Ignore:
Timestamp:
2013-03-27T12:04:48+13:00 (11 years ago)
Author:
sjm84
Message:

Some code tidying and well as adding more documentation

File:
1 edited

Legend:

Unmodified
Added
Removed
  • main/trunk/greenstone3/web/interfaces/default/js/visual-xml-editor.js

    r27110 r27130  
    33// This class represents an editor that allows you to modify XML visually //
    44// ********************************************************************** //
    5 
    65function visualXMLEditor(xmlString)
    76{
     7    //Variables that store the visual editor and a link to the DebugWidget
    88    var _thisEditor = this;
    99    var _greenbug;
    1010
     11    //Stores what id we are up to (used to compare VEElements)
    1112    var _globalID = 0;
    1213
     14    //Stores the current state of the XML
    1315    var _xml;
    14    
     16
     17    //Elements of the editor
    1518    var _mainDiv = $("<div>", {"id":"veMainDiv"});
    1619    var _toolboxDiv = $("<div>", {"id":"veToolboxDiv"});
     
    1821    var _editorDiv = $("<div>", {"id":"veEditorDiv"});
    1922    var _infoDiv = $("<div>", {"id":"veInfoDiv"});
     23
     24    //State-keeping variables
    2025    var _rootElement;
    2126    var _selectedElement;
    22 
    2327    var _overTrash = false;
    24    
    2528    var _validDropSpot = false;
    2629    var _validDropType;
    2730    var _validDropElem;
    28    
    2931    var _origDDParent;
    3032    var _origDDPosition;
    31    
     33
     34    //Keep track of what is currently being edited
    3235    var _editingNodes = new Array();
    33    
     36
     37    //Stores what elements we are currently over while dragging (necessary to find the deepest element)
    3438    var _overList = new Array();
    3539    _overList.freeSpaces = new Array();
    36    
     40
     41    //Keep a list of what has been changed so that it can be undone
    3742    var _transactions = new Array();
    38    
     43
     44    //A list of "ready-made" attributes for certain elements
    3945    var _validAttrList =
    4046    {
     
    5864        }
    5965    }
    60    
     66
     67    //The list of elements that show up in the toolbox (gslib is added dynamically later)
    6168    var _elemList =
    6269    {
     
    8087        ]
    8188    };
    82    
     89
     90    //Restricts what elements can be added to a given element
    8391    var _childRestrictions =
    8492    {
     
    8997        }
    9098    };
    91    
     99
     100    //Get a connection to the DebugWidget
    92101    this.setGreenbug = function(gb)
    93102    {
    94103        _greenbug = gb;
    95104    }
    96    
     105
     106    //Get the XML in its current state
    97107    this.getXML = function()
    98108    {
    99109        return _xml;
    100110    }
    101    
     111
     112    //Undo a transation
    102113    this.undo = function()
    103114    {
     
    118129                var pos = t.vElemPos;
    119130                var elem = t.vElem;
    120                
     131
    121132                elem.detach();
    122133                if(pos == 0)
     
    188199        }
    189200    }
    190    
     201
     202    //Check if an element is allowed as a child to another element
    191203    var checkRestricted = function(child, parent)
    192204    {
     
    205217            pNodeName = pFullNodename.substring(pFullNodename.indexOf(":") + 1);
    206218        }
    207        
     219
    208220        var namespaceList = _childRestrictions[pNamespace];
    209221        if(namespaceList)
     
    222234            }
    223235        }
    224        
     236
    225237        return true;
    226238    }
    227    
     239
     240    //Add the trash bin to the editor
    228241    var placeTrashBin = function()
    229242    {
     
    246259        _editorContainer.append(bin);
    247260    }
    248    
     261
     262    //Dynamically retrieve the gslib elements from the gslib.xsl file to put into the toolbox
    249263    var retrieveGSLIBTemplates = function(callback)
    250264    {
     
    256270            startIndex = response.search("<templateList>") + "<templateList>".length;
    257271            endIndex = response.search("</templateList>");
    258            
     272
    259273            var listString = response.substring(startIndex, endIndex);
    260274            var list = eval(listString.replace(/&quot;/g, "\""));
    261275            var modifiedList = new Array();
    262            
     276
    263277            for(var i = 0; i < list.length; i++)
    264278            {
     
    269283                }
    270284            }
    271            
     285
    272286            _elemList["gslib"] = modifiedList;
    273            
     287
    274288            if(callback)
    275289            {
     
    282296        });
    283297    }
    284    
     298
     299    //Create the toolbar
    285300    var populateToolbar = function()
    286301    {
     
    316331            _toolboxDiv.append(tabDiv);
    317332        }
    318        
     333
    319334        var otherTab = $("<li>");
    320335        var otherTabLink = $("<a>", {"href":"#veother"});
     
    323338        otherTab.append(otherTabLink);
    324339        tabHolder.append(otherTab);
    325        
     340
    326341        var otherTabDiv = $("<div>", {"id":"veother"});
    327342        var textNode = _xml.createTextNode("text");
     
    331346        textDiv.data("toolbar", true);
    332347        otherTabDiv.append(textDiv);
    333        
     348
    334349        var customInput = $("<input type=\"text\">");
    335350        var customElemHolder = $("<div>");
     
    352367        otherTabDiv.append(customCreateButton);
    353368        otherTabDiv.append(customElemHolder);
    354        
     369
    355370        _toolboxDiv.append(otherTabDiv);
    356371
    357372        _toolboxDiv.tabs();
    358        
     373
    359374        customCreateButton.button();
    360375    }
    361376
     377    //Turns the given XML into the nice visual structure recursively
    362378    var constructDivsRecursive = function(currentDiv, currentParent, level)
    363379    {
     
    370386        container.addClass("veContainerElement");
    371387        currentDiv.append(container);
    372        
     388
    373389        var allowedList = new Array();
    374390        var counter = currentParent.firstChild;
     
    394410            var elementDiv = veElement.getDiv();
    395411            veElement.setWidth(width);
    396            
     412
    397413            if(!_rootElement)
    398414            {
     
    411427        container.append($("<div>", {"style":"clear:both;"}));
    412428    }
    413    
     429
     430    //Fake a click on the root element
    414431    this.selectRootElement = function()
    415432    {
    416433        var height = _editorDiv.height() + 10;
    417434        if(height < 300){height = 300;}
    418        
     435
    419436        _editorContainer.css("height", height + "px");
    420437        _infoDiv.css("height", height + "px");
    421438        _rootElement.trigger("click");
    422439    }
    423    
     440
     441    //Return the main visual editor div
    424442    this.getMainDiv = function()
    425443    {
    426444        return _mainDiv;
    427445    }
    428    
     446
     447    //Save any unfinished edits
    429448    this.savePendingEdits = function()
    430449    {
     
    435454        }
    436455    }
    437    
     456
     457    //Add the given VEElement to the list of VEElements we are currently dragging over
    438458    var addToOverList = function(veElement)
    439459    {
     
    442462            return;
    443463        }
    444    
     464
    445465        for(var i = 0; i < _overList.length; i++)
    446466        {
     
    449469                continue;
    450470            }
    451        
     471
    452472            if(_overList[i].getID() == veElement.getID())
    453473            {
     
    455475            }
    456476        }
    457        
     477
    458478        if(_overList.freeSpaces.length > 0)
    459479        {
     
    465485        }
    466486    }
    467    
     487
     488    //Remove the given VEElement from the list of VElements we are currently dragging over
    468489    var removeFromOverList = function(veElement)
    469490    {
     
    474495                continue;
    475496            }
    476        
     497
    477498            if(_overList[i].getID() == veElement.getID())
    478499            {
     
    482503        }
    483504    }
    484    
     505
     506    //Get the deepest VEElement we are currently dragging over
    485507    var getDeepestOverElement = function()
    486508    {
     
    512534        return deepestElem;
    513535    }
    514    
     536
     537    //Resize all the VEElements
    515538    var resizeAll = function()
    516539    {
     
    519542            var toolbarStatus = $(this).data("toolbar");
    520543            var beingDraggedStatus = $(this).data("dragging");
    521            
     544
    522545            if(beingDraggedStatus || !toolbarStatus)
    523546            {
    524547                return true;
    525548            }
    526            
     549
    527550            return false;
    528551        }
    529    
     552
    530553        var allElems = $(".veElement").filter(filterFunction).each(function()
    531554        {
     
    550573    }
    551574
     575    //Initialise the visual editor
    552576    var initVXE = function()
    553577    {
     
    573597        _mainDiv.append($("<div>", {"style":"clear:both;"}));       
    574598    }
    575    
     599
    576600    // *********************************************************************** //
    577601    // Visual Editor Text                                                      //
    578602    // This inner class represents a single xml text node in the visual editor //
    579603    // *********************************************************************** //
    580 
    581604    var VEText = function(node)
    582605    {
     606        //Constructor code
    583607        var _thisNode = this;
    584608        var _xmlNode = node;
    585    
     609
    586610        var _textEditor = $("<div>");
    587611        var _nodeText = $("<div>");
     
    589613
    590614        _textEditor.append(_nodeText);
    591        
     615
    592616        var _editButton = $("<button>Edit text</button>");
    593617        _editButton.click(function()
     
    603627        });
    604628        _textEditor.append(_editButton);
    605        
     629
     630        //Enable editing of this text node
    606631        this.editMode = function()
    607632        {
     
    615640        }
    616641
     642        //Save edits to this text node
    617643        this.saveEdits = function()
    618644        {
     
    625651                }
    626652            }
    627        
     653
    628654            _transactions.push({type:"editText", elem:_xmlNode, vElem: _nodeText, value:_nodeText.data("prevTextValue")});
    629655            var textArea = _nodeText.find("textarea");
     
    635661        }
    636662
     663        //Create a text node editor
    637664        this.getDiv = function()
    638665        {
     
    642669        }
    643670    }
    644    
     671
    645672    // *********************************************************************** //
    646673    // Visual Editor Attribute                                                 //
    647674    // This inner class represents a single xml attribute in the visual editor //
    648675    // *********************************************************************** //
    649 
    650676    var VEAttribute = function(attrElem, xmlElem, name, value)
    651677    {
     678        //Constructor code
    652679        var _name;
    653680        if(name)
     
    659686            _name = attrElem.name;
    660687        }
    661        
     688
    662689        var _value;
    663690        if(value)
     
    673700
    674701        var _thisAttr = this;
    675        
     702
     703        //Get the attribute name
    676704        this.getName = function()
    677705        {
     
    679707        }
    680708
     709        //Get the attribute value
    681710        this.getValue = function()
    682711        {
     
    684713        }
    685714
     715        //Get the name cell of the attribute table
    686716        var createNameCell = function()
    687717        {
     
    691721        }
    692722
     723        //Get the value cell of the attribute table
    693724        var createValueCell = function()
    694725        {
     
    698729        }
    699730
     731        //Get the edit cell of the attribute table
    700732        var createEditCell = function()
    701733        {
    702734            var cell = $("<td>", {"class":"veEditCell"});
    703735            var link = $("<a href=\"javascript:;\">edit</a>");
    704            
     736
    705737            link.click(function()
    706738            {
     
    711743        }
    712744
     745        //Get the delete cell of the attribute table
    713746        var createDeleteCell = function()
    714747        {
     
    725758        }
    726759
     760        //Create a table row from this attribute
    727761        this.getAsTableRow = function()
    728762        {
     
    745779            return tableRow;
    746780        }
    747        
     781
     782        //Enable editing of this attribute
    748783        this.editMode = function(editValue)
    749784        {
    750785            _editingNodes.push(_thisAttr);
    751        
     786
    752787            var nameCell = _row.children("td").eq(0);
    753788            var valueCell = _row.children("td").eq(1);
     
    784819            }
    785820        }
    786        
     821
     822        //Save edits to this attribute
    787823        this.saveEdits = function()
    788824        {
     
    799835            var valueCell = _row.children("td").eq(1);
    800836            var editLink = _row.children("td").eq(2).find("a");
    801        
     837
    802838            editLink.text("edit");
    803839            editLink.off("click");
     
    809845            var nameInput = nameCell.children("input");
    810846            var valueInput = valueCell.children("input");
    811            
     847
    812848            nameInput.blur();
    813849            valueInput.blur();
     
    815851            var name = nameInput.val();
    816852            var value = valueInput.val();
    817            
     853
    818854            if(name.length == 0 || name.search(/\w/g) == -1)
    819855            {
     
    821857                return;
    822858            }
    823            
     859
    824860            nameCell.empty();
    825861            nameCell.text(name);
     
    827863            valueCell.empty();
    828864            valueCell.text(value);
    829            
     865
    830866            if(nameCell.data("prevName") != "")
    831867            {
     
    833869            }
    834870            _xmlElem.setAttribute(name, value);
    835            
     871
    836872            _transactions.push({type:"editAttr", elem:_xmlElem, row:_row, newName:name, name:_name, value:_value});
    837            
     873
    838874            _name = name;
    839875            _value = value;
     
    853889        _div.data("parentVEElement", this);
    854890        _div.data("expanded", "normal");
    855        
     891
     892        //Add the necessary functions to make this VEElement draggable
    856893        var makeDraggable = function()
    857894        {
    858895            _div.draggable(
    859896            {
     897                "distance":"20",
    860898                "revert":"true",
    861899                "helper":function()
     
    864902                    var height = _div.children(".veTitleElement").height();
    865903                    _div.draggable("option", "cursorAt", {top:(height / 2), left:(_div.width() / 2)});
    866                
     904
    867905                    var tempVEE = new VEElement(_xmlNode);
    868906                    var tempDiv = tempVEE.getDiv();
     
    952990                                }
    953991                                var pos = Math.floor(overChildrenLength * posPercent);
    954                                
     992
    955993                                if(pos < overChildrenLength - 1)
    956994                                {
     
    9821020                {
    9831021                    var transactionType = (_div.data("toolbar")) ? "addElem" : "remMvElem";
    984                    
     1022
    9851023                    if(_div.data("toolbar"))
    9861024                    {
     
    9901028                    _div.css("border", "1px solid black");
    9911029                    _div.css("background", _div.data("prevBackground"));
    992                    
     1030
    9931031                    //If the element was not dropped in a valid place then put it back
    9941032                    if(!_validDropSpot && !_div.data("toolbar"))
     
    10071045                            _origDDParent.children(".veElement").eq(_origDDPosition).before(_div);
    10081046                        }
    1009                        
     1047
    10101048                        if(_overTrash)
    10111049                        {
     
    10341072                        _transactions.push({type:transactionType, vElemParent:_origDDParent, vElemPos:_origDDPosition, vElem:_div});
    10351073                    }
    1036                    
     1074
    10371075                    _div.data("dragging", false);
    10381076                    _div.data("toolbar", false);
    1039                    
     1077
    10401078                    _overList = new Array();
    10411079                    _overList.freeSpaces = new Array();
     
    10431081            });
    10441082
     1083            //Also make this element a drop-zone for other elements
    10451084            _div.droppable(
    10461085            {
     
    10571096            });
    10581097        }
    1059        
     1098
     1099        //Get the underlying div
    10601100        this.getDiv = function()
    10611101        {
    10621102            return _div;
    10631103        }
    1064        
     1104
     1105        //Get the XML for this element
    10651106        this.getXMLNode = function()
    10661107        {
    10671108            return _xmlNode;
    10681109        }
    1069        
     1110
     1111        //Get the unique ID of this VEElement
    10701112        this.getID = function()
    10711113        {
     
    10731115        }
    10741116
    1075         var createTableHeader = function()
    1076         {
    1077             var tableHeader = $("<tr>");
    1078             tableHeader.html("<td class=\"veNameCell\">Name</td><td class=\"veValueCell\">Value</td>");
    1079             return tableHeader;
    1080         }
    1081        
     1117        //Fill the information area with details about this element
    10821118        this.populateInformationDiv = function()
    10831119        {
     
    11041140                attributeTable.addClass("veAttributeTableContainer");
    11051141
    1106                 attributeTable.append(createTableHeader());
     1142                attributeTable.append($("<tr>").html("<td class=\"veNameCell\">Name</td><td class=\"veValueCell\">Value</td>"));
    11071143
    11081144                $(_xmlNode.attributes).each(function()
     
    11141150                _infoDiv.append(attributeTableTitle);
    11151151                _infoDiv.append(attributeTable);
    1116                
     1152
    11171153                var addDiv = $("<div>", {"class":"veInfoDivTitle"});
    11181154                var addSelect = $("<select>");
     
    11441180                    }
    11451181                }
    1146                
     1182
    11471183                var addButton = $("<button>Add attribute</button>");
    11481184                addButton.click(function()
     
    11701206                _infoDiv.append(addDiv);
    11711207                addButton.button();
    1172                
     1208
    11731209                /*
    11741210                if(_xmlNode.tagName == "xsl:call-template" && _xmlNode.getAttribute("name").length > 0)
     
    12461282        }
    12471283
     1284        //Add mouseover/out and click events to this element
    12481285        var addMouseEvents = function()
    12491286        {
     
    12911328            });
    12921329        }
    1293        
     1330
     1331        //Check if we need to expand an element before we do
    12941332        var checkResizeNecessary = function()
    12951333        {
     
    13151353            return false;
    13161354        }
    1317        
     1355
     1356        //Remove this from the editor
    13181357        this.remove = function()
    13191358        {
     
    13241363            _div.detach();
    13251364            _infoDiv.empty();
    1326            
     1365
    13271366            if(divParent.length)
    13281367            {
    13291368                divParent.first().trigger("click");
    13301369            }
    1331            
     1370
    13321371            $("#veTrash").children("img").attr("src", gs.imageURLs.trashFull);
    13331372        }
    13341373
     1374        //Expend this element horizontally
    13351375        this.expand = function()
    13361376        {
     
    13441384                    $(this).data("expanded", "small");
    13451385                });
    1346                
     1386
    13471387                _div.animate({width:"80%"}, 1000);
    13481388                _div.data("expanded", "expanded");
     
    13501390        }
    13511391
     1392        //Evenly distribute the children of this node evenly
    13521393        this.evenlyDistributeChildren = function()
    13531394        {
     
    13611402        }
    13621403
     1404        //Expand this node and any parents and evenly distribute its children
    13631405        this.focus = function()
    13641406        {
     
    13661408            {
    13671409                _div.data("parentVEElement").expand();
    1368                
     1410
    13691411                var parents = _div.parents(".veElement");
    13701412                parents.each(function()
     
    13761418            _div.data("parentVEElement").evenlyDistributeChildren();
    13771419        }
    1378        
     1420
     1421        //Set whether to use the short name for this element (i.e. without the namespace)
    13791422        this.setShortName = function(short)
    13801423        {
     
    13891432        }
    13901433
     1434        //Set the width of this element
    13911435        this.setWidth = function(width)
    13921436        {
    13931437            _div.css("width", width + "%");
    13941438        }
    1395        
     1439
    13961440        //Visual Editor Element constructor
    13971441        var initVEE = function()
     
    14001444            _div.addClass("ui-corner-all");
    14011445            makeDraggable();
    1402            
     1446
    14031447            var titleText;
    14041448            if(_xmlNode.nodeType == 3 && _xmlNode.nodeValue.search(/\S/) != -1)
     
    14271471                titleText = _xmlNode.tagName;
    14281472            }
    1429            
     1473
    14301474            addMouseEvents();
    1431            
     1475
    14321476            _div.append("<div class=\"veTitleElement\">" + titleText + "</div>");
    14331477        }
     
    14351479        initVEE();
    14361480    }
    1437    
     1481
    14381482    //Call the constructor
    14391483    initVXE();
Note: See TracChangeset for help on using the changeset viewer.