source: main/trunk/greenstone3/web/interfaces/default/js/visual-xml-editor.js@ 26972

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

Changed "save edit" to "done" and a few other minor changes

File size: 26.7 KB
Line 
1// ********************************************************************** //
2// Visual XML Editor //
3// This class represents an editor that allows you to modify XML visually //
4// ********************************************************************** //
5
6function visualXMLEditor(xmlString)
7{
8 var _globalID = 0;
9
10 var _xml;
11
12 var _mainDiv = $("<div>", {"id":"veMainDiv"});
13 var _toolboxDiv = $("<div>", {"id":"veToolboxDiv"});
14 var _editorContainer = $("<div>", {"id":"veEditorContainer"});
15 var _editorDiv = $("<div>", {"id":"veEditorDiv"});
16 var _infoDiv = $("<div>", {"id":"veInfoDiv"});
17 var _rootElement;
18 var _selectedElement;
19
20 var _validDropSpot = false;
21 var _validDropType;
22 var _validDropElem;
23
24 var _origDDParent;
25 var _origDDPosition;
26
27 var _overList = new Array();
28 _overList.freeSpaces = new Array();
29
30 var _transactions = new Array();
31
32 var _childRestrictions =
33 {
34 gsf:
35 {
36 "choose-metadata":["gsf:metadata", "gsf:default"],
37 "metadata":[]
38 }
39 };
40
41 this.getXML = function()
42 {
43 return _xml;
44 }
45
46 this.undo = function()
47 {
48 if(_transactions.length > 0)
49 {
50 var t = _transactions.pop();
51 //Undo an added element
52 if(t.type == "addElem")
53 {
54 $(t.vElem.data("parentVEElement").getXMLNode()).remove();
55 t.vElem.remove();
56 resizeAll();
57 }
58 //Undo a removed or moved element
59 else if(t.type == "remMvElem")
60 {
61 var parent = t.vElemParent;
62 var pos = t.vElemPos;
63 var elem = t.vElem;
64
65 elem.detach();
66 if(pos == 0)
67 {
68 parent.prepend(elem);
69 $(parent.parent().data("parentVEElement").getXMLNode()).prepend(elem.data("parentVEElement").getXMLNode());
70 }
71 else if(pos == parent.children(".veElement").length)
72 {
73 $(parent.children(".veElement").eq(pos - 1).data("parentVEElement").getXMLNode()).after(elem.data("parentVEElement").getXMLNode());
74 parent.children(".veElement").eq(pos - 1).after(elem);
75 }
76 else
77 {
78 $(parent.children(".veElement").eq(pos).data("parentVEElement").getXMLNode()).before(elem.data("parentVEElement").getXMLNode());
79 parent.children(".veElement").eq(pos).before(elem);
80 }
81 resizeAll();
82 }
83 //Undo an added attribute
84 else if(t.type == "addAttr")
85 {
86 if(t.row)
87 {
88 t.row.remove();
89 }
90 }
91 //Undo a removed or edited attribute
92 else if(t.type == "editAttr")
93 {
94 t.elem.removeAttribute(t.newName);
95 t.elem.setAttribute(t.name, t.value);
96 if(t.row)
97 {
98 t.row.children("td").eq(0).text(t.name);
99 t.row.children("td").eq(1).text(t.value);
100 }
101 }
102 //Undo a removed or edited attribute
103 else if(t.type == "remAttr")
104 {
105 t.elem.setAttribute(t.name, t.value);
106 if(t.rowParent)
107 {
108 t.rowParent.append(t.row);
109 }
110 }
111 //Undo edited text
112 else if(t.type == "editText")
113 {
114 t.elem.nodeValue = t.value;
115 if(t.vElem)
116 {
117 t.vElem.text(t.value);
118 }
119 }
120 }
121 }
122
123 var checkRestricted = function(child, parent)
124 {
125 var pFullNodename = parent.tagName;
126 var cFullNodename = child.tagName;
127 var pNamespace;
128 var pNodeName;
129 if(pFullNodename.indexOf(":") == -1)
130 {
131 pNamespace = "no namespace";
132 pNodeName = pFullNodename;
133 }
134 else
135 {
136 pNamespace = pFullNodename.substring(0, pFullNodename.indexOf(":"));
137 pNodeName = pFullNodename.substring(pFullNodename.indexOf(":") + 1);
138 }
139
140 var namespaceList = _childRestrictions[pNamespace];
141 if(namespaceList)
142 {
143 var childList = namespaceList[pNodeName];
144 if(childList)
145 {
146 for(var i = 0; i < childList.length; i++)
147 {
148 if(childList[i] == cFullNodename)
149 {
150 return true;
151 }
152 }
153 return false;
154 }
155 }
156
157 return true;
158 }
159
160 var populateToolbar = function()
161 {
162 var elemList =
163 {
164 html:["a", "br", "div", "li", "link", "script", "span", "table", "td", "tr", "ul"],
165 xsl:
166 [
167 "apply-imports", "apply-templates", "attribute", "attribute-set", "call-template",
168 "choose", "copy", "copy-of", "decimal-format", "element",
169 "fallback", "for-each", "if", "import", "include",
170 "key", "message", "namespace-alias", "number", "otherwise",
171 "output", "param", "preserve-space", "processing-instruction", "sort",
172 "strip-space", "stylesheet", "template", "text", "transform",
173 "value-of", "variable", "when", "with-param"
174 ],
175 gsf:
176 [
177 "cgi-param", "choose-metadata", "collectionText", "displayItem", "displayText",
178 "equivlinkgs3", "foreach-metadata", "icon", "if-metadata-exists", "image",
179 "interfaceText", "link", "meta-value", "metadata", "script",
180 "style", "switch", "template", "text", "variable"
181 ]
182 };
183
184 var tabHolder = $("<ul>");
185 _toolboxDiv.append(tabHolder);
186
187 for(var key in elemList)
188 {
189 var currentList = elemList[key];
190
191 var tab = $("<li>");
192 var tabLink = $("<a>", {"href":"#ve" + key});
193 tabLink.css({"font-size":"0.9em", "padding":"5px"});
194 tabLink.text(key);
195 tab.append(tabLink);
196 tabHolder.append(tab);
197
198 var tabDiv = $("<div>", {"id":"ve" + key});
199 for(var j = 0; j < currentList.length; j++)
200 {
201 var elemName = currentList[j];
202
203 var ns = (key == "html") ? "" : (key + ":");
204
205 var newElem = _xml.createElement(ns + elemName);
206 var veElement = new VEElement(newElem);
207 var veDiv = veElement.getDiv();
208 veDiv.css("float", "none");
209 veDiv.data("toolbar", true);
210 tabDiv.append(veDiv);
211 }
212
213 _toolboxDiv.append(tabDiv);
214 }
215
216 var otherTab = $("<li>");
217 var otherTabLink = $("<a>", {"href":"#veother"});
218 otherTabLink.css({"font-size":"0.9em", "padding":"5px"});
219 otherTabLink.text("other");
220 otherTab.append(otherTabLink);
221 tabHolder.append(otherTab);
222
223 var otherTabDiv = $("<div>", {"id":"veother"});
224 var textNode = _xml.createTextNode("text");
225 var textVEElement = new VEElement(textNode);
226 var textDiv = textVEElement.getDiv();
227 textDiv.css("float", "none");
228 textDiv.data("toolbar", true);
229 otherTabDiv.append(textDiv);
230
231 var customInput = $("<input type=\"text\">");
232 var customElemHolder = $("<div>");
233 var customCreateButton = $("<button>Create element</button>");
234 customCreateButton.click(function()
235 {
236 var elemName = customInput.val();
237 if(elemName.length)
238 {
239 var elem = _xml.createElement(elemName);
240 var veElement = new VEElement(elem);
241 var customElemDiv = veElement.getDiv();
242 customElemDiv.css("float", "none");
243 customElemDiv.data("toolbar", true);
244 customElemHolder.empty();
245 customElemHolder.append(customElemDiv);
246 }
247 });
248 otherTabDiv.append(customInput);
249 otherTabDiv.append(customCreateButton);
250 otherTabDiv.append(customElemHolder);
251
252 _toolboxDiv.append(otherTabDiv);
253
254 _toolboxDiv.tabs();
255 }
256
257 var constructDivsRecursive = function(currentDiv, currentParent, level)
258 {
259 if(!level)
260 {
261 level = 1;
262 }
263
264 var container = $("<div>");
265 container.addClass("veContainerElement");
266 currentDiv.append(container);
267
268 var allowedList = new Array();
269 var counter = currentParent.firstChild;
270 while(counter)
271 {
272 if(counter.nodeType == 1)
273 {
274 allowedList.push(counter)
275 }
276 else if(counter.nodeType == 3 && counter.nodeValue.search(/\S/) != -1)
277 {
278 allowedList.push(counter)
279 }
280 counter = counter.nextSibling;
281 }
282
283 var width = 100 / allowedList.length;
284 for(var i = 0; i < allowedList.length; i++)
285 {
286 var currentElement = allowedList[i];
287
288 var veElement = new VEElement(currentElement);
289 var elementDiv = veElement.getDiv();
290 veElement.setWidth(width);
291
292 if(!_rootElement)
293 {
294 _rootElement = elementDiv;
295 }
296
297 container.append(elementDiv);
298 if(currentElement.firstChild)
299 {
300 constructDivsRecursive(elementDiv, currentElement, level + 1);
301 }
302
303 currentElement = currentElement.nextSibling;
304 }
305
306 container.append($("<div>", {"style":"clear:both;"}));
307 }
308
309 this.selectRootElement = function()
310 {
311 var height = _editorDiv.height() + 10;
312 if(height < 300){height = 300;}
313
314 _editorContainer.css("height", height + "px");
315 _infoDiv.css("height", height + "px");
316 _rootElement.trigger("click");
317 }
318
319 this.getMainDiv = function()
320 {
321 return _mainDiv;
322 }
323
324 var addToOverList = function(veElement)
325 {
326 for(var i = 0; i < _overList.length; i++)
327 {
328 if(!_overList[i])
329 {
330 continue;
331 }
332
333 if(_overList[i].getID() == veElement.getID())
334 {
335 return false;
336 }
337 }
338
339 if(_overList.freeSpaces.length > 0)
340 {
341 _overList[_overList.freeSpaces.pop()] = veElement;
342 }
343 else
344 {
345 _overList.push(veElement);
346 }
347 }
348
349 var removeFromOverList = function(veElement)
350 {
351 for(var i = 0; i < _overList.length; i++)
352 {
353 if(!_overList[i])
354 {
355 continue;
356 }
357
358 if(_overList[i].getID() == veElement.getID())
359 {
360 delete _overList[i];
361 _overList.freeSpaces.push(i);
362 }
363 }
364 }
365
366 var getDeepestOverElement = function()
367 {
368 if(_overList.length == 0)
369 {
370 return null;
371 }
372
373 var deepestVal = 0;
374 var deepestElem = _overList[0];
375
376 for(var i = 0; i < _overList.length; i++)
377 {
378 if(!_overList[i])
379 {
380 continue;
381 }
382
383 var depth = _overList[i].getDiv().parents(".veElement").length;
384 depth = (depth) ? depth : 0;
385
386 if (depth > deepestVal)
387 {
388 deepestVal = depth;
389 deepestElem = _overList[i];
390 }
391 }
392
393 return deepestElem;
394 }
395
396 var resizeAll = function()
397 {
398 var filterFunction = function()
399 {
400 var toolbarStatus = $(this).data("toolbar");
401 var beingDraggedStatus = $(this).data("dragging");
402
403 if(beingDraggedStatus || !toolbarStatus)
404 {
405 return true;
406 }
407
408 return false;
409 }
410
411 var allElems = $(".veElement").filter(filterFunction).each(function()
412 {
413 if($(this).data("helper")){return;}
414
415 var size = $(this).data("expanded");
416 if(size == "small")
417 {
418 var width = (10 / ($(this).siblings(".veElement").filter(function(){return !($(this).data("helper"))}).length - 1));
419 $(this).css("width", width + "%");
420 }
421 else if(size == "normal")
422 {
423 var width = (100 / ($(this).siblings(".veElement").filter(function(){return !($(this).data("helper"))}).length + 1));
424 $(this).css("width", width + "%");
425 }
426 else if(size == "expanded")
427 {
428 $(this).css("width", "90%");
429 }
430 });
431 }
432
433 var initVXE = function()
434 {
435 try
436 {
437 _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>");
438 constructDivsRecursive(_editorDiv, _xml.firstChild);
439 }
440 catch(error)
441 {
442 console.log(error);
443 return null;
444 }
445
446 populateToolbar();
447
448 _editorContainer.append(_editorDiv);
449 _mainDiv.append(_toolboxDiv);
450 _mainDiv.append(_editorContainer);
451 _mainDiv.append($("<div>", {"id":"veSpacerDiv"}));
452 _mainDiv.append(_infoDiv);
453 _mainDiv.append($("<div>", {"style":"clear:both;"}));
454 }
455
456 // *********************************************************************** //
457 // Visual Editor Attribute //
458 // This inner class represents a single xml attribute in the visual editor //
459 // *********************************************************************** //
460
461 var VEAttribute = function(attrElem, xmlElem, name, value)
462 {
463 var _name;
464 if(name)
465 {
466 _name = name;
467 }
468 else if(attrElem && attrElem.name)
469 {
470 _name = attrElem.name;
471 }
472
473 var _value;
474 if(value)
475 {
476 _value = value;
477 }
478 else if(attrElem && attrElem.value)
479 {
480 _value = attrElem.value;
481 }
482
483 var _xmlElem = xmlElem;
484 var _row;
485
486 this.getName = function()
487 {
488 return _name;
489 }
490
491 this.getValue = function()
492 {
493 return _value;
494 }
495
496 var createNameCell = function()
497 {
498 var cell = $("<td>", {"class":"veNameCell"});
499 cell.text(_name);
500 return cell;
501 }
502
503 var createValueCell = function()
504 {
505 var cell = $("<td>", {"class":"veValueCell"});
506 cell.text(_value);
507 return cell;
508 }
509
510 var createEditCell = function()
511 {
512 var cell = $("<td>", {"class":"veEditCell"});
513 var link = $("<a href=\"javascript:;\">edit</a>");
514 link.click(function()
515 {
516 var nameCell = _row.children("td").eq(0);
517 var valueCell = _row.children("td").eq(1);
518 if(link.text() == "edit")
519 {
520 link.text("done");
521
522 var nameInput = $("<input type=\"text\">");
523 nameInput.width(nameCell.width() - 5);
524 nameInput.val(_name);
525
526 var valueInput = $("<input type=\"text\">");
527 valueInput.width(valueCell.width() - 5);
528 valueInput.val(_value);
529
530 nameCell.text("");
531 valueCell.text("");
532
533 nameCell.append(nameInput);
534 valueCell.append(valueInput);
535 }
536 else
537 {
538 link.text("edit");
539
540 var nameInput = nameCell.children("input");
541 var valueInput = valueCell.children("input");
542
543 var name = nameInput.val();
544 var value = valueInput.val();
545
546 nameCell.empty();
547 nameCell.text(name);
548
549 valueCell.empty();
550 valueCell.text(value);
551
552 if(nameCell.data("prevName") != "")
553 {
554 _xmlElem.removeAttribute(_name);
555 }
556 _xmlElem.setAttribute(name, value);
557
558 _transactions.push({type:"editAttr", elem:_xmlElem, row:_row, newName:name, name:_name, value:_value});
559
560 _name = name;
561 _value = value;
562 }
563 });
564 cell.append(link);
565 return cell;
566 }
567
568 var createDeleteCell = function()
569 {
570 var cell = $("<td>", {"class":"veDeleteCell"});
571 var link = $("<a href=\"javascript:;\">delete</a>");
572 link.click(function()
573 {
574 _transactions.push({type:"remAttr", elem:_xmlElem, row:_row, rowParent:_row.parent(), name:_name, value:_value});
575 _xmlElem.removeAttribute(_name);
576 _row.detach();
577 });
578 cell.append(link);
579 return cell;
580 }
581
582 this.getAsTableRow = function()
583 {
584 var tableRow = $("<tr>");
585
586 var attributeName = createNameCell();
587 tableRow.append(attributeName);
588
589 var attributeValue = createValueCell();
590 tableRow.append(attributeValue);
591
592 var editCell = createEditCell()
593 tableRow.append(editCell);
594
595 var deleteCell = createDeleteCell();
596 tableRow.append(deleteCell);
597
598 _row = tableRow;
599
600 return tableRow;
601 }
602 }
603
604 // ********************************************************************************** //
605 // Visual Editor Element //
606 // This inner class represents a single xml element or text node in the visual editor //
607 // ********************************************************************************** //
608 var VEElement = function(xml)
609 {
610 var _div = $("<div>");
611 var _xmlNode = xml;
612 var _id = _globalID++;
613
614 _div.data("parentVEElement", this);
615 _div.data("expanded", "normal");
616
617 var makeDraggable = function()
618 {
619 _div.draggable(
620 {
621 "revert":"true",
622 "helper":function()
623 {
624 //Make sure the cursor is put in the centre of the div
625 var height = _div.children(".veTitleElement").height();
626 _div.draggable("option", "cursorAt", {top:(height / 2), left:(_div.width() / 2)});
627
628 var tempVEE = new VEElement(_xmlNode);
629 var tempDiv = tempVEE.getDiv();
630 tempDiv.css("border", "1px solid orangered");
631 tempDiv.css("background", "orange");
632 tempDiv.width(_div.width());
633 tempDiv.data("helper", true);
634 return tempDiv;
635 },
636 "cursor":"move",
637 "appendTo":_mainDiv,
638 "start":function(event, ui)
639 {
640 _origDDParent = _div.parent();
641 _origDDPosition = _div.index();
642
643 _div.siblings(".veElement").filter(function(){return !($(this).data("helper"))}).data("expanded", "normal");
644 _div.css("border", "1px solid orangered");
645 _div.data("prevBackground", _div.css("background"));
646 _div.css("background", "orange");
647 _div.css("float", "left");
648
649 _div.data("dragging", true);
650 if(_div.data("toolbar"))
651 {
652 var cloneElem = new VEElement(_xmlNode.cloneNode(true));
653 var cloneDiv = cloneElem.getDiv();
654 cloneDiv.css("float", "none");
655 cloneDiv.data("toolbar", true);
656 _div.before(cloneDiv);
657 }
658 _div.detach();
659
660 resizeAll();
661 },
662 "drag":function(event, ui)
663 {
664 var foundDefined = false;
665 for(var i = 0; i < _overList.length; i++)
666 {
667 if(!(_overList[i] === "undefined"))
668 {
669 foundDefined = true;
670 }
671 }
672
673 _validDropSpot = false;
674 if(foundDefined)
675 {
676 var overElement = getDeepestOverElement();
677 if(overElement && overElement.getXMLNode().nodeType != 3 && checkRestricted(_xmlNode, overElement.getXMLNode()))
678 {
679 _validDropSpot = true;
680 var overDiv = overElement.getDiv();
681
682 var overLeft = overDiv.offset().left;
683 var helperLeft = ui.helper.offset().left;
684 var helperMiddle = helperLeft + (ui.helper.width() / 2);
685
686 var overContainers = overDiv.children(".veContainerElement");
687 if(!overContainers.length)
688 {
689 overDiv.append($("<div>", {"class":"veContainerElement"}));
690 overContainers = overDiv.children(".veContainerElement");
691 }
692 var overChildren = overContainers.children(".veElement").filter(function(){return !($(this).data("helper")) && !(_div.data("parentVEElement").getID() == $(this).data("parentVEElement").getID())});
693 var overChildrenLength = overChildren.length + 1;
694
695 if(!overChildren.length)
696 {
697 _validDropElem = overDiv;
698 _validDropType = "into";
699 overContainers.append(_div);
700 }
701 else
702 {
703 var posPercent = (helperMiddle - overLeft) / overDiv.width();
704 if(posPercent < 0)
705 {
706 posPercent = 0;
707 }
708 else if(posPercent > 1)
709 {
710 posPercent = 1;
711 }
712 var pos = Math.floor(overChildrenLength * posPercent);
713
714 if(pos < overChildrenLength - 1)
715 {
716 _validDropElem = overChildren.eq(pos);
717 _validDropType = "before";
718 overChildren.eq(pos).before(_div);
719 }
720 else
721 {
722 _validDropElem = overChildren.eq(pos - 1);
723 //Necessary to fix a rare bug that causes pos to be off by one
724 if(!_validDropElem.length)
725 {
726 _validDropElem = overChildren.eq(pos - 2);
727 }
728 _validDropType = "after";
729 overChildren.eq(pos - 1).after(_div);
730 }
731 }
732
733 overChildren.data("expanded", "normal");
734 _div.data("expanded", "normal");
735
736 resizeAll();
737 }
738 }
739 },
740 "stop":function(event)
741 {
742 var transactionType = (_div.data("toolbar")) ? "addElem" : "remMvElem";
743 _div.data("dragging", false);
744 _div.data("toolbar", false);
745
746 _div.css("border", "1px dashed black");
747 _div.css("background", _div.data("prevBackground"));
748
749 //If the element was not dropped in a valid place then put it back
750 if(!_validDropSpot)
751 {
752 _div.detach();
753 if(_origDDPosition == 0)
754 {
755 _origDDParent.prepend(_div);
756 }
757 else if(_origDDPosition == _origDDParent.children(".veElement").length)
758 {
759 _origDDParent.children(".veElement").eq(_origDDPosition - 1).after(_div);
760 }
761 else
762 {
763 _origDDParent.children(".veElement").eq(_origDDPosition).before(_div);
764 }
765
766 resizeAll();
767 }
768 //Otherwise modify the XML
769 else
770 {
771 var xmlNode = _validDropElem.data("parentVEElement").getXMLNode();
772 if(_validDropType == "before")
773 {
774 $(xmlNode).before(_xmlNode);
775 }
776 else if (_validDropType == "after")
777 {
778 $(xmlNode).after(_xmlNode);
779 }
780 else if (_validDropType == "into")
781 {
782 $(xmlNode).append(_xmlNode);
783 }
784 _transactions.push({type:transactionType, vElemParent:_origDDParent, vElemPos:_origDDPosition, vElem:_div});
785 }
786
787 _overList = new Array();
788 _overList.freeSpaces = new Array();
789 }
790 });
791
792 _div.droppable(
793 {
794 "over":function(event, ui)
795 {
796 addToOverList($(this).data("parentVEElement"));
797 event.stopPropagation();
798 },
799 "out":function(event)
800 {
801 removeFromOverList($(this).data("parentVEElement"));
802 event.stopPropagation();
803 }
804 });
805 }
806
807 this.getDiv = function()
808 {
809 return _div;
810 }
811
812 this.getXMLNode = function()
813 {
814 return _xmlNode;
815 }
816
817 this.getID = function()
818 {
819 return _id;
820 }
821
822 var createTableHeader = function()
823 {
824 var tableHeader = $("<tr>");
825 tableHeader.html("<td class=\"veNameCell\">Name</td><td class=\"veValueCell\">Value</td>");
826 return tableHeader;
827 }
828
829 this.populateInformationDiv = function()
830 {
831 _infoDiv.empty();
832
833 var nameElement = $("<p>");
834 if(_xmlNode.nodeType == 1)
835 {
836 nameElement.text("Name: " + _xmlNode.nodeName);
837 }
838 else
839 {
840 nameElement.text("[text node]");
841 }
842 _infoDiv.append(nameElement);
843
844 if(_xmlNode.nodeType == 1)
845 {
846 var attributeTableTitle = $("<p>Attributes:<p/>");
847 var attributeTable = $("<table>");
848 attributeTable.addClass("veAttributeTableContainer");
849
850 attributeTable.append(createTableHeader());
851
852 $(_xmlNode.attributes).each(function()
853 {
854 var veAttribute = new VEAttribute(this, _xmlNode);
855 attributeTable.append(veAttribute.getAsTableRow());
856 });
857
858 _infoDiv.append(attributeTableTitle);
859 _infoDiv.append(attributeTable);
860
861 var addButton = $("<button>Add attribute</button>");
862 addButton.click(function()
863 {
864 var newAtt = new VEAttribute(null, _xmlNode, "", "");
865 var row = newAtt.getAsTableRow();
866 attributeTable.append(row);
867 _transactions.push({type:"addAttr", row:row})
868 });
869 _infoDiv.append(addButton);
870 }
871
872 if(_xmlNode.nodeType == 3)
873 {
874 var textEditor = $("<div>");
875 var textTitle = $("<div>Text:</div>");
876 var nodeText = $("<div>");
877 nodeText.text(_xmlNode.nodeValue);
878
879 textEditor.append(textTitle);
880 textEditor.append(nodeText);
881
882 _infoDiv.append(textEditor);
883
884 var editButton = $("<button>edit text</button>");
885 editButton.click(function()
886 {
887 if(editButton.text() == "edit text")
888 {
889 nodeText.data("prevTextValue", nodeText.text());
890 var textArea = $("<textarea>");
891 textArea.val(nodeText.text());
892 nodeText.text("");
893 nodeText.append(textArea);
894 editButton.text("done");
895 }
896 else
897 {
898 _transactions.push({type:"editText", elem:_xmlNode, vElem: nodeText, value:nodeText.data("prevTextValue")});
899 var textArea = nodeText.find("textarea");
900 var newValue = textArea.val();
901 _xmlNode.nodeValue = newValue;
902 nodeText.empty();
903 nodeText.text(newValue);
904 editButton.text("edit text");
905 }
906 });
907
908 textEditor.append(editButton);
909 }
910
911 _infoDiv.append($("<br>"));
912 _infoDiv.append($("<br>"));
913
914 var removeButton = $("<button>Delete this element</button>");
915 _infoDiv.append(removeButton);
916 removeButton.click(function()
917 {
918 var divParent = _div.parents(".veElement");
919 _transactions.push({type:"remMvElem", vElemParent:_div.parent(), vElemPos:_div.index(), vElem:_div});
920 _div.data("expanded", "normal");
921 $(_xmlNode).remove();
922 _div.detach();
923 _infoDiv.empty();
924
925 if(divParent.length)
926 {
927 divParent.first().trigger("click");
928 }
929 });
930 }
931
932 var addMouseEvents = function()
933 {
934 _div.mouseover(function(event)
935 {
936 event.stopPropagation();
937 _div.css("border", "1px solid orange");
938 var titleString = " ";
939 if(_xmlNode.nodeType == 1)
940 {
941 for(var i = 0; i < _xmlNode.attributes.length; i++)
942 {
943 var current = _xmlNode.attributes[i];
944 var name = current.name;
945 var value = current.value;
946
947 titleString += name + "=\"" + value + "\" ";
948 }
949 }
950 else if(_xmlNode.nodeType == 3)
951 {
952 titleString = _xmlNode.nodeValue;
953 }
954 _div.attr("title", titleString);
955 });
956 _div.mouseout(function(event)
957 {
958 _div.css("border", "1px dashed black");
959 event.stopPropagation();
960 });
961 _div.click(function(event)
962 {
963 if(_selectedElement)
964 {
965 _selectedElement.css("border", _selectedElement.prevBorder);
966 }
967 _selectedElement = _div;
968 _div.prevBorder = _div.css("border");
969 _div.css("border", "red solid 1px");
970
971 _div.data("parentVEElement").focus();
972 _div.data("parentVEElement").populateInformationDiv();
973
974 event.stopPropagation();
975 });
976 }
977
978 this.expand = function()
979 {
980 var siblings = _div.siblings(".veElement");
981 if(!(_div.data("expanded") == "expanded") && siblings.length && siblings.length > 0)
982 {
983 var sibWidth = 10 / siblings.length;
984 siblings.each(function()
985 {
986 $(this).animate({width:sibWidth + "%"}, 900);
987 $(this).data("expanded", "small");
988 });
989
990 _div.animate({width:"90%"}, 1000);
991 _div.data("expanded", "expanded");
992 }
993 }
994
995 this.evenlyDistributeChildren = function()
996 {
997 var children = _div.find(".veElement")
998 .each(function()
999 {
1000 $(this).data("expanded", "normal");
1001 var length = $(this).siblings(".veElement").filter(function(){return !($(this).data("helper"))}).length + 1;
1002 $(this).css("width", (100 / length) + "%");//$(this).animate({"width":(100 / length) + "%"}, 900);
1003 });
1004 }
1005
1006 this.focus = function()
1007 {
1008 _div.data("parentVEElement").expand();
1009
1010 var parents = _div.parents(".veElement");
1011 parents.each(function()
1012 {
1013 $(this).data("parentVEElement").expand();
1014 });
1015
1016 _div.data("parentVEElement").evenlyDistributeChildren();
1017 }
1018
1019 this.setWidth = function(width)
1020 {
1021 _div.css("width", width + "%");
1022 }
1023
1024 //Visual Editor Element constructor
1025 var initVEE = function()
1026 {
1027 _div.addClass("veElement");
1028 makeDraggable();
1029
1030 var titleText;
1031 if(_xmlNode.nodeType == 3 && _xmlNode.nodeValue.search(/\S/) != -1)
1032 {
1033 _div.addClass("veTextElement");
1034 titleText = "[text]";
1035 }
1036 else if (_xmlNode.nodeType == 1)
1037 {
1038 if(_xmlNode.tagName.search(/^xsl/) != -1)
1039 {
1040 _div.addClass("veXSLElement");
1041 }
1042 else if(_xmlNode.tagName.search(/^gsf/) != -1)
1043 {
1044 _div.addClass("veGSFElement");
1045 }
1046 else if(_xmlNode.tagName.search(/^gslib/) != -1)
1047 {
1048 _div.addClass("veGSLIBElement");
1049 }
1050 else
1051 {
1052 _div.addClass("veHTMLElement");
1053 }
1054 titleText = _xmlNode.tagName;
1055 }
1056
1057 addMouseEvents();
1058
1059 _div.append("<div class=\"veTitleElement\">" + titleText + "</div>");
1060 }
1061
1062 initVEE();
1063 }
1064
1065 //Call the constructor
1066 initVXE();
1067}
Note: See TracBrowser for help on using the repository browser.