source: main/trunk/greenstone3/web/interfaces/default/js/debug_scripts.js@ 27057

Last change on this file since 27057 was 27057, checked in by sjm84, 11 years ago

Move the "minimise" button to the right side

  • Property svn:executable set to *
File size: 18.4 KB
Line 
1function DebugWidget()
2{
3 //************************
4 //Private member variables
5 //************************
6
7 //Debugger state-keeping variables
8 var _debugOn = false;
9 var _pauseSelector = false;
10 var _elements = new Array();
11 var _itemSelected = false; //Used to prevent multiple elements from being highlighted
12 var _editModeText = false;
13 var _selectedTemplate;
14
15 //Page elements
16 var _mainDiv;
17
18 var _textEditor;
19 var _vEditor;
20
21 var _templateSelector;
22 var _editor;
23 var _editingDiv;
24 var _unpauseButton;
25 var _closeEditorButton;
26 var _xmlStatusBar;
27 var _saveButton;
28 var _swapEditorButton;
29
30 //Editor state-keeping variables
31 var _currentFilepath;
32 var _currentNodename;
33 var _currentName;
34 var _currentMatch;
35 var _currentNamespace;
36 var _isVisualEditor = true;
37
38 var _styleFunctions = new Array();
39
40 var partialPageReload = function(callback)
41 {
42 $.ajax(document.URL)
43 .success(function(response)
44 {
45 //Get the body text from the response
46 var bodyStartIndex = response.indexOf("<body");
47 var bodyEndIndex = response.indexOf("</body>");
48 var bodyText = response.substring(bodyStartIndex, bodyEndIndex + 7);
49
50 //Get the current top area and container
51 var topLevelTopArea = $("#topArea");
52 var topLevelContainer = $("#container");
53
54 //Create a temporary div and put the html into it
55 var tempDiv = $("<div>");
56 tempDiv.html(bodyText);
57
58 //Replace the contents of the old elements with the new elements
59 var topArea = tempDiv.find("#topArea");
60 var container = tempDiv.find("#container");
61 topLevelTopArea.html(topArea.html());
62 topLevelContainer.html(container.html());
63
64 //Update the events for the debug elements that currently don't have events associated with them
65 var debugElems = $('debug, [debug="true"]').filter(function(){return (!($.data(this, "events"))) ? true : false});
66 addMouseEventsToDebugElements(debugElems);
67 })
68 .error(function()
69 {
70 alert("There was an error reloading the page, please reload manually.");
71 });
72
73 if(callback)
74 {
75 callback();
76 }
77 }
78
79 var callStyleFunctions = function()
80 {
81 for(var i = 0; i < _styleFunctions.length; i++)
82 {
83 var sFunction = _styleFunctions[i];
84 sFunction();
85 }
86 }
87
88 var createDebugDiv = function()
89 {
90 _mainDiv = $("<div>", {"id":"debugDiv"});
91 _mainDiv.css(
92 {
93 "position":"fixed",
94 "font-size":"0.8em",
95 "bottom":"0px",
96 "width":"100%",
97 "background":"white",
98 "border":"1px black solid",
99 "padding":"5px",
100 "z-index":100
101 });
102
103 _editingDiv = $("<div>");
104 var toolBarDiv = $("<div>");
105 toolBarDiv.css({"height":"40px"});
106
107 var buttonDiv = $("<div>");
108 toolBarDiv.append(buttonDiv);
109
110 _templateSelector = $("<div>", {"id":"templateSelector"});
111 _templateSelector.css({"overflow":"auto", "width":"100%"});
112
113 var pickElementButton = $("<button>Enable debugging</button>");
114 pickElementButton.click(function()
115 {
116 if(!_debugOn)
117 {
118 pickElementButton.button("option", "label", "Disable debugging");
119 $("a").click(function(e)
120 {
121 e.preventDefault();
122 });
123 _debugOn = true;
124 }
125 else
126 {
127 pickElementButton.button("option", "label", "Enable debugging");
128 $("a").off("click");
129 clearAll();
130 _unpauseButton.button("option", "disabled", true);
131 _pauseSelector = false;
132 _debugOn = false;
133 }
134 });
135 _styleFunctions.push(function(){pickElementButton.button({icons:{primary:"ui-icon-power"}})});
136
137 _unpauseButton = $("<button>Select new element</button>");
138 _unpauseButton.click(function()
139 {
140 if(_pauseSelector)
141 {
142 _pauseSelector = false;
143 _unpauseButton.button("option", "disabled", true);
144 }
145 });
146 _styleFunctions.push(function(){_unpauseButton.button({icons:{primary:"ui-icon-pencil"}, disabled:true})});
147
148 _closeEditorButton = $("<button>Close editor</button>");
149 _closeEditorButton.click(function()
150 {
151 if(_closeEditorButton.button("option", "label") == "Close editor")
152 {
153 _closeEditorButton.button("option", "label", "Open editor");
154 _editingDiv.hide();
155 }
156 else
157 {
158 _closeEditorButton.button("option", "label", "Close editor");
159 _editingDiv.show();
160 }
161 });
162 _closeEditorButton.css("float", "right");
163 _styleFunctions.push(function(){_closeEditorButton.button({icons:{secondary:"ui-icon-newwin"}, disabled:true})});
164
165 _saveButton = $("<button>Save changes</button>");
166 _saveButton.click(function()
167 {
168 if(_editor)
169 {
170 var xmlString;
171 if(_isVisualEditor)
172 {
173 _vEditor.savePendingEdits();
174 xmlString = new XMLSerializer().serializeToString(_vEditor.getXML());
175 }
176 else
177 {
178 xmlString = _editor.getValue();
179 }
180 xmlString = xmlString.replace(/&/g, "&amp;");
181
182 try
183 {
184 var xml = $.parseXML('<testContainer xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:java="http://xml.apache.org/xslt/java" xmlns:util="xalan://org.greenstone.gsdl3.util.XSLTUtil" xmlns:gslib="http://www.greenstone.org/skinning" xmlns:gsf="http://www.greenstone.org/greenstone3/schema/ConfigFormat">' + xmlString + "</testContainer>");
185 }
186 catch(error)
187 {
188 alert("Could not save as there is a problem with the XML.");
189 return;
190 }
191
192 var url = gs.xsltParams.library_name;
193 var parameters = {"a":"g", "rt":"r", "s":"SaveXMLTemplateToFile", "s1.filePath":_currentFilepath, "s1.namespace":_currentNamespace, "s1.nodename":_currentNodename, "s1.xml":xmlString};
194
195 if(_currentName && _currentName.length > 0){parameters["s1.name"] = _currentName;}
196 if(_currentMatch && _currentMatch.length > 0){parameters["s1.match"] = _currentMatch;}
197
198 _saveButton.button("option", "disabled", true);
199 $.blockUI({message:'<div class="ui-state-active">Saving, please wait...</div>'});
200
201 $.post(url, parameters)
202 .success(function()
203 {
204 $.ajax(gs.xsltParams.library_name + "?a=s&sa=c")
205 .success(function()
206 {
207 partialPageReload(function(){$.unblockUI();});
208 })
209 .error(function()
210 {
211 $.unblockUI();
212 alert("Error reloading collection.");
213 })
214 .complete(function()
215 {
216 _saveButton.button("option", "disabled", false);
217 });
218 })
219 .error(function()
220 {
221 alert("There was an error sending the request to the server, please try again.");
222 });
223 }
224 });
225 _styleFunctions.push(function(){_saveButton.button({icons:{primary:"ui-icon-disk"}, disabled:true})});
226
227 _swapEditorButton = $("<button>Switch to XML editor</button>");
228 _swapEditorButton.button().click(function()
229 {
230 if(_vEditor && _textEditor)
231 {
232 if(_isVisualEditor)
233 {
234 _vEditor.savePendingEdits();
235 _vEditor.getMainDiv().hide();
236 var containerNode = _vEditor.getXML().firstChild;
237 var templateNode = containerNode.firstChild;
238 while(templateNode)
239 {
240 if(templateNode.nodeType == 1)
241 {
242 break;
243 }
244 templateNode = templateNode.nextSibling;
245 }
246 var xmlText = new XMLSerializer().serializeToString(templateNode);
247 _editor.setValue(xmlText);
248 _editor.clearSelection();
249 var UndoManager = require("ace/undomanager").UndoManager;
250 _editor.getSession().setUndoManager(new UndoManager());
251 _textEditor.show();
252 _swapEditorButton.button("option", "label", "Switch to visual editor");
253 _isVisualEditor = false;
254 _xmlStatusBar.show();
255 }
256 else
257 {
258 _textEditor.hide();
259 var xmlText = _editor.getValue();
260 _vEditor.getMainDiv().remove();
261 _vEditor = new visualXMLEditor(xmlText);
262 _editingDiv.append(_vEditor.getMainDiv());
263 _vEditor.selectRootElement();
264 _vEditor.getMainDiv().show();
265 _swapEditorButton.button("option", "label", "Switch to XML editor");
266 _isVisualEditor = true;
267 _xmlStatusBar.hide();
268 }
269 }
270 });
271 _styleFunctions.push(function(){_swapEditorButton.button({icons:{primary:"ui-icon-refresh"}})});
272
273 undoButton = $("<button>Undo</button>");
274 undoButton.click(function()
275 {
276 if(_isVisualEditor)
277 {
278 _vEditor.undo();
279 }
280 else
281 {
282 _editor.undo();
283 }
284 });
285 _styleFunctions.push(function(){undoButton.button({icons:{primary:"ui-icon-arrowreturnthick-1-w"}})});
286
287 _xmlStatusBar = $("<span>");
288 _xmlStatusBar.css("padding", "5px");
289 _xmlStatusBar.addClass("ui-corner-all");
290 _styleFunctions.push(function(){_xmlStatusBar.hide();});
291
292 //Check the XML for errors every 2 seconds
293 setInterval(function()
294 {
295 if(_editor)
296 {
297 var xmlString = _editor.getValue();
298 try
299 {
300 var xml = $.parseXML('<testContainer xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:java="http://xml.apache.org/xslt/java" xmlns:util="xalan://org.greenstone.gsdl3.util.XSLTUtil" xmlns:gslib="http://www.greenstone.org/skinning" xmlns:gsf="http://www.greenstone.org/greenstone3/schema/ConfigFormat">' + xmlString + "</testContainer>");
301 }
302 catch(error)
303 {
304 console.log(error);
305 _xmlStatusBar.text("XML ERROR! (Mouse over for details)");
306 _xmlStatusBar.addClass("ui-state-error");
307 _xmlStatusBar.removeClass("ui-state-active");
308 _xmlStatusBar.attr("title", error);
309 _saveButton.button("option", "disabled", true);
310 _swapEditorButton.button("option", "disabled", true);
311 return;
312 }
313
314 _xmlStatusBar.text("XML OK!");
315 _xmlStatusBar.addClass("ui-state-active");
316 _xmlStatusBar.removeClass("ui-state-error");
317 _xmlStatusBar.removeAttr("title");
318 if(_saveButton.button("option", "label") == "Save changes")
319 {
320 _saveButton.button("option", "disabled", false);
321 }
322 if(_swapEditorButton.button("option", "label") == "Switch to visual editor")
323 {
324 _swapEditorButton.button("option", "disabled", false);
325 }
326 }
327
328 }, 2000);
329
330 var clear = $("<span>");
331 clear.css("clear", "both");
332 toolBarDiv.append(clear);
333
334 buttonDiv.append(pickElementButton);
335 buttonDiv.append(_unpauseButton);
336 buttonDiv.append(_closeEditorButton);
337 buttonDiv.append(_saveButton);
338 buttonDiv.append(_swapEditorButton);
339 buttonDiv.append(undoButton);
340 buttonDiv.append(_xmlStatusBar);
341
342 _styleFunctions.push(function(){$(".ui-button").css({"margin-right":"0.5em"});});
343
344 _mainDiv.append(toolBarDiv);
345 _mainDiv.append(_editingDiv);
346 _mainDiv.append("<div>Templates:</div>");
347 _mainDiv.append(_templateSelector);
348 }
349
350 var clearAll = function()
351 {
352 _itemSelected = false;
353 $(_elements).each(function()
354 {
355 $(this).remove();
356 });
357 }
358
359 var highlightElement = function(e)
360 {
361 var topBorderDiv = $("<div>");
362 var bottomBorderDiv = $("<div>");
363 var leftBorderDiv = $("<div>");
364 var rightBorderDiv = $("<div>");
365
366 topBorderDiv.css({"position":"absolute", "top":e.offset().top + "px", "left":e.offset().left + "px", "height":"0px", "width":e.width() + "px", "border":"1px solid red"});
367 bottomBorderDiv.css({"position":"absolute", "top":(e.offset().top + e.height()) + "px", "left":e.offset().left + "px", "height":"0px", "width":e.width() + "px", "border":"1px solid red"});
368 leftBorderDiv.css({"position":"absolute", "top":e.offset().top + "px", "left":e.offset().left + "px", "height":e.height() + "px", "width":"0px", "border":"1px solid red"});
369 rightBorderDiv.css({"position":"absolute", "top":e.offset().top + "px", "left":(e.offset().left + e.width()) + "px", "height":e.height() + "px", "width":"0px", "border":"1px solid red"});
370
371 $("body").append(topBorderDiv, bottomBorderDiv, leftBorderDiv, rightBorderDiv);
372
373 _elements.push(topBorderDiv);
374 _elements.push(bottomBorderDiv);
375 _elements.push(leftBorderDiv);
376 _elements.push(rightBorderDiv);
377 }
378
379 var addMouseEventsToInfoContainer = function(infoContainer, filepath, nodename, namespace, name, match)
380 {
381 infoContainer.click(function()
382 {
383 if(_selectedTemplate)
384 {
385 _selectedTemplate.css("border", _selectedTemplate.prevBorder);
386 }
387 _selectedTemplate = infoContainer;
388 _selectedTemplate.prevBorder = _selectedTemplate.css("border");
389 _selectedTemplate.css("border", "red 1px solid");
390
391 _currentFilepath = filepath;
392 _currentNodename = nodename;
393 _currentNamespace = namespace;
394 _currentName = name;
395 _currentMatch = match;
396
397 var responseName = "requestedNameTemplate";
398
399 var url = gs.xsltParams.library_name + "?a=g&rt=r&s=RetrieveXMLTemplateFromFile&s1.filePath=" + _currentFilepath + "&s1.namespace=" + _currentNamespace + "&s1.nodename=" + _currentNodename;
400 if(_currentMatch && _currentMatch.length > 0){url += "&s1.match=" + _currentMatch; responseName = "requestedMatchTemplate";}
401 if(_currentName && _currentName.length > 0){url += "&s1.name=" + _currentName;}
402 $.ajax(url)
403 .success(function(response)
404 {
405 var template;
406 if(response.search(responseName) != -1)
407 {
408 var startIndex = response.indexOf("<" + responseName + ">") + responseName.length + 2;
409 var endIndex = response.indexOf("</" + responseName + ">");
410 template = response.substring(startIndex, endIndex);
411 }
412 else
413 {
414 return;
415 }
416
417 _textEditor = $("<div>", {"id":"textEditor"});
418 _textEditor.css({"width":"100%", "height":"300px"});
419 _textEditor.val(template);
420
421 if(_isVisualEditor)
422 {
423 _textEditor.hide();
424 }
425
426 _editingDiv.empty();
427 _editingDiv.append($("<p>" + filepath + "</p>"));
428 _editingDiv.append(_textEditor);
429
430 _vEditor = new visualXMLEditor(template);
431 _editingDiv.append(_vEditor.getMainDiv());
432 _vEditor.selectRootElement();
433
434 if(!_isVisualEditor)
435 {
436 _vEditor.getMainDiv().hide();
437 }
438
439 _editor = ace.edit("textEditor");
440 _editor.getSession().setMode("ace/mode/xml");
441 _editor.getSession().setUseSoftTabs(false);
442 _editor.setValue(template);
443 _editor.clearSelection();
444 var UndoManager = require("ace/undomanager").UndoManager;
445 _editor.getSession().setUndoManager(new UndoManager());
446
447 _textEditor.css({"min-height":"200px", "border-top":"5px solid #444"});
448 _textEditor.resizable({handles: 'n', resize:function()
449 {
450 _textEditor.css({top:"0px"});
451 _editor.resize();
452 }});
453
454 _closeEditorButton.button("option", "disabled", false);
455 if(_closeEditorButton.button("option", "label") == "Open editor")
456 {
457 _closeEditorButton.button("option", "label", "Close editor");
458 _editingDiv.show();
459 }
460 })
461 .error(function()
462 {
463 console.log("ERROR");
464 });
465 });
466 infoContainer.mouseover(function()
467 {
468 $(this).data("background", $(this).css("background"));
469 $(this).css("background", "yellow");
470 });
471 infoContainer.mouseout(function()
472 {
473 $(this).css("background", $(this).data("background"));
474 });
475 }
476
477 var addMouseEventsToDebugElements = function(debugElems)
478 {
479 debugElems.click(function()
480 {
481 if(_debugOn)
482 {
483 _pauseSelector = true;
484 _unpauseButton.button("option", "disabled", false);
485 }
486 });
487
488 debugElems.mouseover(function()
489 {
490 if(_debugOn && !_pauseSelector)
491 {
492 var nodes = new Array();
493 if($(this).is("table, tr"))
494 {
495 var size = parseInt($(this).attr("debugSize"));
496 for(var i = 0; i < size; i++)
497 {
498 var tempNode = $("<div>");
499 tempNode.tempAttrs = new Array();
500 $(this.attributes).each(function()
501 {
502 if(this.value.charAt(0) == '[')
503 {
504 var values = eval(this.value);
505 if(values[i] == "")
506 {
507 return;
508 }
509 tempNode.attr(this.name, values[i]);
510 tempNode.tempAttrs.push({name:this.name, value:values[i]});
511 }
512 });
513 nodes.push(tempNode);
514 }
515 }
516 else
517 {
518 nodes.push(this);
519 }
520
521 $(nodes).each(function()
522 {
523 var filepath = $(this).attr("filename");
524 var fullNodename = $(this).attr("nodename");
525 var colonIndex = fullNodename.indexOf(":");
526 var namespace = fullNodename.substring(0, colonIndex);
527 var nodename = fullNodename.substring(colonIndex + 1);
528 var name = $(this).attr("name");
529 var match = $(this).attr("match");
530
531 var infoContainer = $("<div>");
532 infoContainer.addClass("gbTemplateContainer");
533
534 _elements.push(infoContainer);
535
536 addMouseEventsToInfoContainer(infoContainer, filepath, nodename, namespace, name, match);
537
538 /*
539 var attrstr = "";
540 var illegalNames = ["nodename", "filename", "style", "debug", "id", "class"];
541
542 var attributes = ((this.tempAttrs) ? this.tempAttrs : this.attributes);
543
544 $(attributes).each(function()
545 {
546 for(var i = 0; i < illegalNames.length; i++)
547 {
548 if(this.name == illegalNames[i]){return;}
549 }
550 attrstr += this.name + "=\"" + this.value + "\" ";
551 });
552
553 infoContainer.text("<" + fullNodename + " " + attrstr + ">");
554 */
555
556 if(name && name.length > 0)
557 {
558 infoContainer.text(name);
559 }
560 if(match && match.length > 0)
561 {
562 infoContainer.text(match);
563 }
564
565 if(_templateSelector.children("div").length > 0)
566 {
567 var spacer = $("<div>&gt;&gt;</div>");
568 spacer.addClass("gbSpacer");
569
570 _templateSelector.prepend(spacer);
571 _elements.push(spacer);
572 }
573
574 _templateSelector.prepend(infoContainer);
575
576 resizeContainers();
577 });
578
579 if(!_itemSelected)
580 {
581 _itemSelected = true;
582 highlightElement($(this));
583 }
584 }
585 });
586
587 debugElems.mouseout(function()
588 {
589 if(_debugOn && !_pauseSelector)
590 {
591 clearAll();
592 }
593 });
594 }
595
596 var fixTitle = function()
597 {
598 $("title").text($("title").text().replace(/<[^>]*>/g, ""));
599 }
600
601 var resizeContainers = function()
602 {
603 var templates = _templateSelector.children(".gbTemplateContainer");
604 var spacers = _templateSelector.children(".gbSpacer");
605
606 var templateWidth = (79/templates.length) + "%";
607 templates.css("width", templateWidth);
608
609 if(spacers.length > 0)
610 {
611 var spacersWidth = (19/spacers.length) + "%";
612 spacers.css("width", spacersWidth);
613 }
614 }
615
616 this.init = function()
617 {
618 //We only want this on if we have debug elements in the page
619 var debugElems = $('debug, [debug="true"]');
620 if(!debugElems.length)
621 {
622 console.log("No debug tags present, debugging disabled.");
623 return;
624 }
625
626 createDebugDiv();
627 $("body").append(_mainDiv);
628
629 callStyleFunctions();
630
631 addMouseEventsToDebugElements(debugElems);
632 fixTitle();
633 }
634
635}
636
637$(window).load(function()
638{
639 var debugWidget = new DebugWidget();
640 debugWidget.init();
641});
Note: See TracBrowser for help on using the repository browser.