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

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

Make sure angle brackets in attributes are properly escaped

  • Property svn:executable set to *
File size: 12.6 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
13 //Page elements
14 var _mainDiv;
15 var _textDiv;
16 var _editingDiv;
17 var _unpauseButton;
18 var _closeEditorButtonButton;
19 var _xmlStatusBar;
20 var _saveButton;
21
22 //Editor state-keeping variables
23 var _currentFilepath;
24 var _currentNodename;
25 var _currentName;
26 var _currentMatch;
27 var _currentNamespace;
28
29 var createDebugDiv = function()
30 {
31 _mainDiv = $("<div>", {"id":"debugDiv"});
32 _mainDiv.css(
33 {
34 "position":"fixed",
35 "font-size":"0.7em",
36 "bottom":"0px",
37 "height":"300px",
38 "width":"100%",
39 "background":"white",
40 "border":"1px black solid",
41 "padding":"5px",
42 "z-index":100
43 });
44
45 _editingDiv = $("<div>");
46 var toolBarDiv = $("<div>");
47 toolBarDiv.css({"height":"40px"});
48 var buttonDiv = $("<div>");
49 buttonDiv.css("float", "left");
50 toolBarDiv.append(buttonDiv);
51 _textDiv = $("<div>");
52 _textDiv.css({"overflow":"auto", "width":"100%", "height":"260px"});
53
54 var pickElementButton = $("<input type=\"button\" value=\"Enable debugging\">");
55 pickElementButton.click(function()
56 {
57 if(!_debugOn)
58 {
59 pickElementButton.attr("value", "Disable debugging");
60 $("a").click(function(e)
61 {
62 e.preventDefault();
63 });
64 _debugOn = true;
65 }
66 else
67 {
68 pickElementButton.attr("value", "Enable debugging");
69 $("a").off("click");
70 clearAll();
71 _unpauseButton.attr("disabled", "disabled");
72 _pauseSelector = false;
73 _debugOn = false;
74 }
75 });
76
77 _unpauseButton = $("<input type=\"button\" value=\"Select new element\" disabled=\"disabled\">");
78 _unpauseButton.click(function()
79 {
80 if(_pauseSelector)
81 {
82 _pauseSelector = false;
83 $(this).attr("disabled", "disabled");
84 }
85 });
86
87 _closeEditorButton = $("<input type=\"button\" value=\"Close editor\" disabled=\"disabled\">");
88 _closeEditorButton.click(function()
89 {
90 if($(this).val() == "Close editor")
91 {
92 $(this).val("Open editor");
93 _editingDiv.hide();
94 _mainDiv.css("height", (_mainDiv.height() - 200) + "px");
95 }
96 else
97 {
98 $(this).val("Close editor");
99 _editingDiv.show();
100 _mainDiv.css("height", (_mainDiv.height() + 200) + "px");
101 }
102 });
103
104 _xmlStatusBar = $("<span>");
105 _xmlStatusBar.css("padding", "5px");
106
107 //Check the XML for errors every 2 seconds
108 setInterval(function()
109 {
110 var editor = _editingDiv.find("textarea");
111 if(editor.length)
112 {
113 var xmlString = editor.val();
114 try
115 {
116 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>");
117 }
118 catch(error)
119 {
120 console.log(error);
121 _xmlStatusBar.text("XML ERROR! (Mouse over for details)");
122 _xmlStatusBar.css({"color":"white", "background":"red"});
123 _xmlStatusBar.attr("title", error);
124 _saveButton.attr("disabled", "disabled");
125 return;
126 }
127
128 _xmlStatusBar.text("XML OK!");
129 _xmlStatusBar.css({"color":"white", "background": "green"});
130 _xmlStatusBar.removeAttr("title");
131 if(_saveButton.val() == "Save changes")
132 {
133 _saveButton.removeAttr("disabled");
134 }
135 }
136
137 }, 2000);
138
139 _saveButton = $("<input type=\"button\" value=\"Save changes\" disabled=\"disabled\">");
140 _saveButton.click(function()
141 {
142 var editor = _editingDiv.find("textarea");
143 if(editor.length)
144 {
145 var xmlString = editor.val().replace(/&/g, "&amp;");
146 try
147 {
148 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>");
149 }
150 catch(error)
151 {
152 alert("Could not save as there is a problem with the XML.");
153 return;
154 }
155
156 var url = gs.xsltParams.library_name;
157 var parameters = {"a":"g", "rt":"r", "s":"SaveXMLTemplateToFile", "s1.filePath":_currentFilepath, "s1.namespace":_currentNamespace, "s1.nodename":_currentNodename, "s1.xml":xmlString};
158
159 if(_currentName && _currentName.length > 0){parameters["s1.name"] = _currentName;}
160 if(_currentMatch && _currentMatch.length > 0){parameters["s1.match"] = _currentMatch;}
161
162 _saveButton.val("Saving...");
163 _saveButton.attr("disabled", "disabled");
164
165 $.post(url, parameters)
166 .success(function()
167 {
168 $.ajax(gs.xsltParams.library_name + "?a=s&sa=c")
169 .success(function()
170 {
171 alert("The template has been saved successfully.");
172 })
173 .error(function()
174 {
175 alert("Error reloading collection.");
176 })
177 .complete(function()
178 {
179 _saveButton.val("Save changes");
180 _saveButton.removeAttr("disabled");
181 });
182 })
183 .error(function()
184 {
185 alert("There was an error sending the request to the server, please try again.");
186 });
187 }
188 });
189
190 var minimiseButton = $("<img>", {"src":gs.imageURLs.collapse});
191 minimiseButton.css({"cursor":"pointer", "float":"right", "margin-right":"20px"});
192 minimiseButton.click(function()
193 {
194 if($(this).attr("src") == gs.imageURLs.collapse)
195 {
196 _textDiv.hide();
197 $(this).attr("src", gs.imageURLs.expand);
198 _mainDiv.css("height", (_mainDiv.height() - 260) + "px");
199 }
200 else
201 {
202 _textDiv.show();
203 $(this).attr("src", gs.imageURLs.collapse);
204 _mainDiv.css("height", (_mainDiv.height() + 260) + "px");
205 }
206 });
207
208 var clear = $("<span>");
209 clear.css("clear", "both");
210
211 toolBarDiv.append(minimiseButton);
212 toolBarDiv.append(clear);
213
214 buttonDiv.append(pickElementButton);
215 buttonDiv.append(_unpauseButton);
216 buttonDiv.append(_closeEditorButton);
217 buttonDiv.append(_xmlStatusBar);
218 buttonDiv.append(_saveButton);
219 _mainDiv.append(_editingDiv);
220 _mainDiv.append(toolBarDiv);
221 _mainDiv.append(_textDiv);
222 }
223
224 var clearAll = function()
225 {
226 _itemSelected = false;
227 $(_elements).each(function()
228 {
229 $(this).remove();
230 });
231 }
232
233 var highlightElement = function(e)
234 {
235 var topBorderDiv = $("<div>");
236 var bottomBorderDiv = $("<div>");
237 var leftBorderDiv = $("<div>");
238 var rightBorderDiv = $("<div>");
239
240 topBorderDiv.css({"position":"absolute", "top":e.offset().top + "px", "left":e.offset().left + "px", "height":"0px", "width":e.width() + "px", "border":"1px solid red"});
241 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"});
242 leftBorderDiv.css({"position":"absolute", "top":e.offset().top + "px", "left":e.offset().left + "px", "height":e.height() + "px", "width":"0px", "border":"1px solid red"});
243 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"});
244
245 $("body").append(topBorderDiv, bottomBorderDiv, leftBorderDiv, rightBorderDiv);
246
247 _elements.push(topBorderDiv);
248 _elements.push(bottomBorderDiv);
249 _elements.push(leftBorderDiv);
250 _elements.push(rightBorderDiv);
251 }
252
253 var addMouseEventsToInfoContainer = function(infoContainer, filepath, nodename, namespace, name, match)
254 {
255 infoContainer.click(function()
256 {
257 _currentFilepath = filepath;
258 _currentNodename = nodename;
259 _currentNamespace = namespace;
260 _currentName = name;
261 _currentMatch = match;
262
263 var responseName = "requestedNameTemplate";
264
265 var url = gs.xsltParams.library_name + "?a=g&rt=r&s=RetrieveXMLTemplateFromFile&s1.filePath=" + _currentFilepath + "&s1.namespace=" + _currentNamespace + "&s1.nodename=" + _currentNodename;
266 if(_currentMatch && _currentMatch.length > 0){url += "&s1.match=" + _currentMatch; responseName = "requestedMatchTemplate";}
267 if(_currentName && _currentName.length > 0){url += "&s1.name=" + _currentName;}
268 $.ajax(url)
269 .success(function(response)
270 {
271 var template;
272 if(response.search(responseName) != -1)
273 {
274 var startIndex = response.indexOf("<" + responseName + ">") + responseName.length + 2;
275 var endIndex = response.indexOf("</" + responseName + ">");
276 template = response.substring(startIndex, endIndex);
277 }
278 else
279 {
280 return;
281 }
282
283 var editArea = $("<textarea>");
284 editArea.css({"width":"98%", "height":"180px"});
285 editArea.val(template);
286
287 _editingDiv.empty();
288 _editingDiv.append(editArea);
289 _editingDiv.css({"height":"190px"});
290
291 _mainDiv.css({"height":"500px"});
292
293 _closeEditorButton.removeAttr("disabled");
294 })
295 .error(function()
296 {
297 console.log("ERROR");
298 });
299 });
300 infoContainer.mouseover(function()
301 {
302 $(this).data("background", $(this).css("background"));
303 $(this).css("background", "yellow");
304 });
305 infoContainer.mouseout(function()
306 {
307 $(this).css("background", $(this).data("background"));
308 });
309 }
310
311 var addMouseEventsToDebugElements = function(debugElems)
312 {
313 debugElems.click(function()
314 {
315 if(_debugOn)
316 {
317 _pauseSelector = true;
318 _unpauseButton.removeAttr("disabled");
319 }
320 });
321
322 debugElems.mouseover(function()
323 {
324 if(_debugOn && !_pauseSelector)
325 {
326 var nodes = new Array();
327 if($(this).is("table, tr"))
328 {
329 var size = parseInt($(this).attr("debugSize"));
330 for(var i = 0; i < size; i++)
331 {
332 var tempNode = $("<div>");
333 tempNode.tempAttrs = new Array();
334 $(this.attributes).each(function()
335 {
336 if(this.value.charAt(0) == '[')
337 {
338 var values = eval(this.value);
339 if(values[i] == "")
340 {
341 return;
342 }
343 tempNode.attr(this.name, values[i]);
344 tempNode.tempAttrs.push({name:this.name, value:values[i]});
345 }
346 });
347 nodes.push(tempNode);
348 }
349 }
350 else
351 {
352 nodes.push(this);
353 }
354
355 $(nodes).each(function()
356 {
357 var filepath = $(this).attr("filename");
358 var fullNodename = $(this).attr("nodename");
359 var colonIndex = fullNodename.indexOf(":");
360 var namespace = fullNodename.substring(0, colonIndex);
361 var nodename = fullNodename.substring(colonIndex + 1);
362 var name = $(this).attr("name");
363 var match = $(this).attr("match");
364
365 var infoContainer = $("<div>");
366 infoContainer.css({"cursor":"pointer", "border":"1px dashed #AAAAAA", "margin":"5px"});
367 var fromDIV = $("<div>");
368 var elementDIV = $("<div>");
369
370 elementDIV.css("font-size", "1.1em");
371 fromDIV.css("font-size", "0.9em");
372
373 infoContainer.append(fromDIV);
374 infoContainer.append(elementDIV);
375
376 _elements.push(infoContainer);
377
378 addMouseEventsToInfoContainer(infoContainer, filepath, nodename, namespace, name, match);
379
380 var attrstr = "";
381 var illegalNames = ["nodename", "filename", "style", "debug", "id", "class"];
382
383 var attributes = ((this.tempAttrs) ? this.tempAttrs : this.attributes);
384
385 $(attributes).each(function()
386 {
387 for(var i = 0; i < illegalNames.length; i++)
388 {
389 if(this.name == illegalNames[i]){return;}
390 }
391 attrstr += this.name + "=\"" + this.value + "\" ";
392 });
393
394 fromDIV.text("From " + filepath + ":");
395 elementDIV.text("<" + fullNodename + " " + attrstr + ">");
396
397 _textDiv.prepend(infoContainer);
398 });
399
400 if(!_itemSelected)
401 {
402 _itemSelected = true;
403 highlightElement($(this));
404 }
405 }
406 });
407
408 debugElems.mouseout(function()
409 {
410 if(_debugOn && !_pauseSelector)
411 {
412 clearAll();
413 }
414 });
415 }
416
417 this.init = function()
418 {
419 //We only want this on if we have debug elements in the page
420 var debugElems = $('debug, [debug="true"]');
421 if(!debugElems.length)
422 {
423 console.log("No debug tags present, debugging disabled.");
424 return;
425 }
426
427 createDebugDiv();
428 $("body").append(_mainDiv);
429
430 addMouseEventsToDebugElements(debugElems);
431 }
432
433}
434
435$(window).load(function()
436{
437 var debugWidget = new DebugWidget();
438 debugWidget.init();
439});
Note: See TracBrowser for help on using the repository browser.