Changeset 27130 for main


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

Some code tidying and well as adding more documentation

Location:
main/trunk/greenstone3/web/interfaces/default/js
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • main/trunk/greenstone3/web/interfaces/default/js/debug_scripts.js

    r27129 r27130  
    44    //Private member variables
    55    //************************
    6    
     6
    77    //The this variable
    88    var _greenbug = this;
    9    
     9
    1010    //Debugger state-keeping variables
    1111    var _debugOn = false;
     
    1515    var _editModeText = false;
    1616    var _selectedTemplate;
    17    
     17
    1818    //Page elements
    1919    var _mainDiv;
    20    
     20
    2121    var _textEditor;
    2222    var _vEditor;
    23    
     23
    2424    var _navArea;
    2525    var _fileSelector;
     
    2727    var _editor;
    2828    var _editingDiv;
    29     var _unpauseButton;
     29    var _selectNewElementButton;
    3030    var _closeEditorButton;
    3131    var _xmlStatusBar;
    3232    var _saveButton;
    3333    var _swapEditorButton;
    34    
     34
    3535    //Editor state-keeping variables
    3636    var _currentFileName;
     
    4141    var _currentNamespace;
    4242    var _isVisualEditor = true;
    43    
     43
    4444    var _styleFunctions = new Array();
    45    
     45
     46    //Used to reload the page while keeping the state of the editor
    4647    var partialPageReload = function(callback)
    4748    {
     
    5354            var bodyEndIndex = response.indexOf("</body>");
    5455            var bodyText = response.substring(bodyStartIndex, bodyEndIndex + 7);
    55            
     56
    5657            //Get the current top area and container
    5758            var topLevelTopArea = $("#topArea");
    5859            var topLevelContainer = $("#container");
    59            
     60
    6061            //Create a temporary div and put the html into it
    6162            var tempDiv = $("<div>");
    6263            tempDiv.html(bodyText);
    63            
     64
    6465            //Replace the contents of the old elements with the new elements
    6566            var topArea = tempDiv.find("#topArea");
     
    6768            topLevelTopArea.html(topArea.html());
    6869            topLevelContainer.html(container.html());
    69            
     70
    7071            //Update the events for the debug elements that currently don't have events associated with them
    7172            var debugElems = $('debug, [debug="true"]').filter(function(){return (!($.data(this, "events"))) ? true : false});
     
    7677            alert("There was an error reloading the page, please reload manually.");
    7778        });
    78        
     79
    7980        if(callback)
    8081        {
     
    8283        }
    8384    }
    84    
     85
     86    //Some functions need to be called after an element is added to the page. So we store them and call them later.
    8587    var callStyleFunctions = function()
    8688    {
     
    9193        }
    9294    }
    93    
     95
     96    //Create the area where the buttons are stored
    9497    var createButtonDiv = function(buttonDiv)
    9598    {
    96         var pickElementButton = $("<button>Enable selector</button>");
    97         pickElementButton.click(function()
     99        //Used to enable the selector to get the templates of a particular area of the page
     100        var enableSelectorButton = $("<button>Enable selector</button>");
     101        enableSelectorButton.click(function()
    98102        {
    99103            if(!_debugOn)
    100104            {
    101                 pickElementButton.button("option", "label", "Disable selector");
     105                enableSelectorButton.button("option", "label", "Disable selector");
    102106                $("a").click(function(e)
    103107                {
     
    108112            else
    109113            {
    110                 pickElementButton.button("option", "label", "Enable selector");
     114                enableSelectorButton.button("option", "label", "Enable selector");
    111115                $("a").off("click");
    112116                clearAll();
    113                 _unpauseButton.button("option", "disabled", true);
     117                _selectNewElementButton.button("option", "disabled", true);
    114118                _pauseSelector = false;
    115119                _debugOn = false;
    116120            }
    117121        });
    118         _styleFunctions.push(function(){pickElementButton.button({icons:{primary:"ui-icon-power"}})});
    119 
    120         _unpauseButton = $("<button>Select new element</button>");
    121         _unpauseButton.click(function()
     122        _styleFunctions.push(function(){enableSelectorButton.button({icons:{primary:"ui-icon-power"}})});
     123
     124        //Used to change what is currently selected
     125        _selectNewElementButton = $("<button>Select new element</button>");
     126        _selectNewElementButton.click(function()
    122127        {
    123128            if(_pauseSelector)
    124129            {
    125130                _pauseSelector = false;
    126                 _unpauseButton.button("option", "disabled", true);
    127             }
    128         });
    129         _styleFunctions.push(function(){_unpauseButton.button({icons:{primary:"ui-icon-pencil"}, disabled:true})});
    130        
     131                _selectNewElementButton.button("option", "disabled", true);
     132            }
     133        });
     134        _styleFunctions.push(function(){_selectNewElementButton.button({icons:{primary:"ui-icon-pencil"}, disabled:true})});
     135
     136        //Used to minimise/restore the editor
    131137        _closeEditorButton = $("<button>Close editor</button>");
    132138        _closeEditorButton.click(function()
     
    145151        _closeEditorButton.css("float", "right");
    146152        _styleFunctions.push(function(){_closeEditorButton.button({icons:{secondary:"ui-icon-newwin"}, disabled:true})});
    147        
     153
     154        //Used to save any changes that have been made to this template
    148155        _saveButton = $("<button>Save changes</button>");
    149156        _saveButton.click(function()
     
    162169                }
    163170                xmlString = xmlString.replace(/&/g, "&amp;");
    164                
     171
    165172                try
    166173                {
     
    172179                    return;
    173180                }
    174                
     181
    175182                var url = gs.xsltParams.library_name;
    176183                var parameters = {"a":"g", "rt":"r", "s":"SaveXMLTemplateToFile", "s1.locationName":_currentLocation, "s1.fileName":_currentFileName, "s1.interfaceName":gs.xsltParams.interface_name, "s1.siteName":gs.xsltParams.site_name, "s1.collectionName":gs.cgiParams.c, "s1.namespace":_currentNamespace, "s1.nodename":_currentNodename, "s1.xml":xmlString};
     
    207214        });
    208215        _styleFunctions.push(function(){_saveButton.button({icons:{primary:"ui-icon-disk"}, disabled:true})});
    209        
     216
     217        //Used to switch between the XML and Visual editors
    210218        _swapEditorButton = $("<button>Switch to XML editor</button>");
    211219        _swapEditorButton.button().click(function()
     
    253261        });
    254262        _styleFunctions.push(function(){_swapEditorButton.button({icons:{primary:"ui-icon-refresh"}})});
    255        
     263
    256264        undoButton = $("<button>Undo</button>");
    257265        undoButton.click(function()
     
    267275        });
    268276        _styleFunctions.push(function(){undoButton.button({icons:{primary:"ui-icon-arrowreturnthick-1-w"}})});
    269        
    270         buttonDiv.append(pickElementButton);
    271         buttonDiv.append(_unpauseButton);
     277
     278        buttonDiv.append(enableSelectorButton);
     279        buttonDiv.append(_selectNewElementButton);
    272280        buttonDiv.append(_closeEditorButton);
    273281        buttonDiv.append(_saveButton);
     
    275283        buttonDiv.append(undoButton);
    276284    }
    277    
     285
     286    //Used to monitor the state of the XML in the XML editor and will notify the user if there is an error
    278287    var createXMLStatusBar = function(buttonDiv)
    279288    {
     
    282291        _xmlStatusBar.addClass("ui-corner-all");
    283292        _styleFunctions.push(function(){_xmlStatusBar.hide();});
    284        
     293
    285294        //Check the XML for errors every 2 seconds
    286295        setInterval(function()
     
    304313                    return;
    305314                }
    306                
     315
    307316                _xmlStatusBar.text("XML OK!");
    308317                _xmlStatusBar.addClass("ui-state-active");
     
    318327                }
    319328            }
    320            
    321329        }, 2000);
    322330        buttonDiv.append(_xmlStatusBar);
    323331    }
    324    
     332
     333    //Create the elements that allow
    325334    var createFileAndTemplateSelectors = function(buttonDiv)
    326335    {
     
    338347        });
    339348        _templateSelector.append(templateSelectBox);
    340         _fileSelector = $("<div>", {"id":"veFileSelector", "class":"ui-state-default ui-corner-all"});
     349        _fileSelector = $("<div>", {"id":"veFileSelector"});
    341350        buttonDiv.append(_fileSelector);
    342351        buttonDiv.append(_templateSelector);
    343     }
    344    
     352
     353        //Populate the file selector
     354        var url = gs.xsltParams.library_name + "?a=g&rt=r&s=GetXSLTFilesForCollection&s1.interfaceName=" + gs.xsltParams.interface_name + "&s1.siteName=" + gs.xsltParams.site_name + "&s1.collectionName=" + gs.cgiParams.c;
     355        $.ajax(url)
     356        .success(function(response)
     357        {
     358            var listStartIndex = response.indexOf("<fileListJSON>") + "<fileListJSON>".length;
     359            var listEndIndex = response.indexOf("</fileListJSON>");
     360
     361            var listString = response.substring(listStartIndex, listEndIndex).replace(/&quot;/g, "\"").replace(/\\/g, "/");
     362            var list = eval(listString);
     363
     364            var selectBox = $("<select>");
     365            selectBox.append($("<option>-- Select a file --</option>", {value:"none"}));
     366            _fileSelector.addClass("ui-state-default");
     367            _fileSelector.addClass("ui-corner-all");
     368            _fileSelector.append("<span>Files: </span>");
     369            _fileSelector.append(selectBox);
     370            for(var i = 0; i < list.length; i++)
     371            {
     372                var item = list[i];
     373                var option = $("<option>" + item.path + " (" + item.location + ")</option>", {value:item.path});
     374                option.data("fileItem", item);
     375                selectBox.append(option);
     376            }
     377
     378            selectBox.change(function()
     379            {
     380                var selectedItem = selectBox.find(":selected");
     381
     382                if(!selectedItem.data("fileItem"))
     383                {
     384                    return;
     385                }
     386
     387                var getURL = gs.xsltParams.library_name + "?a=g&rt=r&s=GetTemplateListFromFile&s1.fileName=" + selectedItem.data("fileItem").path + "&s1.locationName=" + selectedItem.data("fileItem").location + "&s1.interfaceName=" + gs.xsltParams.interface_name + "&s1.siteName=" + gs.xsltParams.site_name + "&s1.collectionName=" + gs.cgiParams.c;
     388                $.ajax(getURL)
     389                .success(function(templateResponse)
     390                {
     391                    var templateListStart = templateResponse.indexOf("<templateList>") + "<templateList>".length;
     392                    var templateListEnd = templateResponse.indexOf("</templateList>");
     393                    var templateListString = templateResponse.substring(templateListStart, templateListEnd).replace(/&quot;/g, "\"");
     394                    var templateList = eval(templateListString);
     395
     396                    clearAll();
     397
     398                    _templateSelector.children("select").empty();
     399                    if(templateList.length == 0)
     400                    {
     401                        _templateSelector.children("select").append("<option>-- No templates --</option>");
     402                    }
     403                    else
     404                    {
     405                        _templateSelector.children("select").append("<option>-- Select a template --</option>");
     406                    }
     407
     408                    for(var i = 0; i < templateList.length; i++)
     409                    {
     410                        var fileName = selectedItem.data("fileItem").path;
     411                        var location = selectedItem.data("fileItem").location;
     412                        var namespace = templateList[i].namespace;
     413                        var nodename = "template";
     414                        var name = templateList[i].name;
     415                        var match = templateList[i].match;
     416
     417                        if(name)
     418                        {
     419                            name = templateList[i].name.replace(/&apos;/g, "'").replace(/&quot;/g, "\"").replace(/&amp;/g, "&");
     420                        }
     421                        if(match)
     422                        {
     423                            match = templateList[i].match.replace(/&apos;/g, "'").replace(/&quot;/g, "\"").replace(/&amp;/g, "&");
     424                        }
     425
     426                        var infoContainer = $("<option>");
     427
     428                        _elements.push(infoContainer);
     429
     430                        addChangeEventToInfoContainer(infoContainer, fileName, location, nodename, namespace, name, match);
     431
     432                        if(name && name.length > 0)
     433                        {
     434                            infoContainer.text(name);
     435                        }
     436                        if(match && match.length > 0)
     437                        {
     438                            infoContainer.text(match);
     439                        }
     440
     441                        _templateSelector.children("select").append(infoContainer);
     442                    }
     443                });
     444            });
     445        })
     446        .error(function()
     447        {
     448            console.log("Error retrieving XSLT files");
     449        });
     450    }
     451
     452    //The function that creates all the necessary elements for Greenbug
    345453    var createDebugDiv = function()
    346454    {
     
    368476        createFileAndTemplateSelectors(buttonDiv);
    369477        createXMLStatusBar(buttonDiv);
    370        
    371         //Populate the file selector
    372         var url = gs.xsltParams.library_name + "?a=g&rt=r&s=GetXSLTFilesForCollection&s1.interfaceName=" + gs.xsltParams.interface_name + "&s1.siteName=" + gs.xsltParams.site_name + "&s1.collectionName=" + gs.cgiParams.c;
    373         $.ajax(url)
    374         .success(function(response)
    375         {
    376             var listStartIndex = response.indexOf("<fileListJSON>") + "<fileListJSON>".length;
    377             var listEndIndex = response.indexOf("</fileListJSON>");
    378            
    379             var listString = response.substring(listStartIndex, listEndIndex).replace(/&quot;/g, "\"").replace(/\\/g, "/");
    380             var list = eval(listString);
    381            
    382             var selectBox = $("<select>");
    383             selectBox.append($("<option>-- Select a file --</option>", {value:"none"}));
    384             _fileSelector.append("<span>Files: </span>");
    385             _fileSelector.append(selectBox);
    386             for(var i = 0; i < list.length; i++)
    387             {
    388                 var item = list[i];
    389                 var option = $("<option>" + item.path + " (" + item.location + ")</option>", {value:item.path});
    390                 option.data("fileItem", item);
    391                 selectBox.append(option);
    392             }
    393 
    394             selectBox.change(function()
    395             {
    396                 var selectedItem = selectBox.find(":selected");
    397                
    398                 if(!selectedItem.data("fileItem"))
    399                 {
    400                     return;
    401                 }
    402                
    403                 var getURL = gs.xsltParams.library_name + "?a=g&rt=r&s=GetTemplateListFromFile&s1.fileName=" + selectedItem.data("fileItem").path + "&s1.locationName=" + selectedItem.data("fileItem").location + "&s1.interfaceName=" + gs.xsltParams.interface_name + "&s1.siteName=" + gs.xsltParams.site_name + "&s1.collectionName=" + gs.cgiParams.c;
    404                 $.ajax(getURL)
    405                 .success(function(templateResponse)
    406                 {
    407                     var templateListStart = templateResponse.indexOf("<templateList>") + "<templateList>".length;
    408                     var templateListEnd = templateResponse.indexOf("</templateList>");
    409                     var templateListString = templateResponse.substring(templateListStart, templateListEnd).replace(/&quot;/g, "\"");
    410                     var templateList = eval(templateListString);
    411                    
    412                     clearAll();
    413                    
    414                     _templateSelector.children("select").empty();
    415                     if(templateList.length == 0)
    416                     {
    417                         _templateSelector.children("select").append("<option>-- No templates --</option>");
    418                     }
    419                     else
    420                     {
    421                         _templateSelector.children("select").append("<option>-- Select a template --</option>");
    422                     }
    423                    
    424                     for(var i = 0; i < templateList.length; i++)
    425                     {
    426                         var fileName = selectedItem.data("fileItem").path;
    427                         var location = selectedItem.data("fileItem").location;
    428                         var namespace = templateList[i].namespace;
    429                         var nodename = "template";
    430                         var name = templateList[i].name;
    431                         var match = templateList[i].match;
    432                        
    433                         if(name)
    434                         {
    435                             name = templateList[i].name.replace(/&apos;/g, "'").replace(/&quot;/g, "\"").replace(/&amp;/g, "&");
    436                         }
    437                         if(match)
    438                         {
    439                             match = templateList[i].match.replace(/&apos;/g, "'").replace(/&quot;/g, "\"").replace(/&amp;/g, "&");
    440                         }
    441                        
    442                         var infoContainer = $("<option>");
    443                        
    444                         _elements.push(infoContainer);
    445                        
    446                         addMouseEventsToInfoContainer(infoContainer, fileName, location, nodename, namespace, name, match);
    447                        
    448                         if(name && name.length > 0)
    449                         {
    450                             infoContainer.text(name);
    451                         }
    452                         if(match && match.length > 0)
    453                         {
    454                             infoContainer.text(match);
    455                         }
    456                        
    457                         if(_templateSelector.children("div").length > 0)
    458                         {/*
    459                             var spacer = $("<div>&gt;&gt;</div>");
    460                             spacer.addClass("gbSpacer");
    461 
    462                             _templateSelector.prepend(spacer);
    463                             _elements.push(spacer);
    464                             */
    465                         }
    466                        
    467                         _templateSelector.children("select").append(infoContainer);
    468                        
    469                         //resizeContainers();
    470                     }
    471                 });
    472             });
    473         })
    474         .error(function()
    475         {
    476             console.log("Error retrieving XSLT files");
    477         });
    478        
     478
    479479        _styleFunctions.push(function(){$(".ui-button").css({"margin-right":"0.5em"});});
    480        
     480
    481481        _mainDiv.append(toolBarDiv);
    482482        _mainDiv.append(_editingDiv);
    483483        _mainDiv.append(_navArea);
    484484    }
    485    
     485
     486    //Clear all selected elements on the page
    486487    var clearAll = function()
    487488    {
     
    492493        });
    493494    }
    494    
     495
     496    //Put a border around the given element
    495497    var highlightElement = function(e)
    496498    {
     
    512514        _elements.push(rightBorderDiv);
    513515    }
    514    
     516
     517    //Change the current template in the XML and Visual editor
    515518    this.changeCurrentTemplate = function(location, fileName, nodename, namespace, name, match)
    516519    {
    517520        var responseName = "requestedNameTemplate";
    518        
     521
    519522        var url = gs.xsltParams.library_name + "?a=g&rt=r&s=GetXMLTemplateFromFile&s1.fileName=" + fileName + "&s1.interfaceName=" + gs.xsltParams.interface_name + "&s1.siteName=" + gs.xsltParams.site_name + "&s1.collectionName=" + gs.cgiParams.c + "&s1.locationName=" + location + "&s1.namespace=" + namespace + "&s1.nodename=" + nodename;
    520523        if(match && match.length > 0){url += "&s1.match=" + match; responseName = "requestedMatchTemplate";}
     
    535538                return;
    536539            }
    537        
     540
    538541            _textEditor = $("<div>", {"id":"textEditor"});
    539542            _textEditor.css({"width":"100%", "height":"300px"});
    540543            _textEditor.val(template);
    541            
     544
    542545            if(_isVisualEditor)
    543546            {
    544547                _textEditor.hide();
    545548            }
    546            
     549
    547550            _editingDiv.empty();
    548551            _editingDiv.append($("<p>Location: " + location + " <br/>Filename: " + fileName + "</p>"));
    549552            _editingDiv.append(_textEditor);
    550            
     553
    551554            _vEditor = new visualXMLEditor(template);
    552555            _editingDiv.append(_vEditor.getMainDiv());
    553556            _vEditor.setGreenbug(_greenbug);
    554557            _vEditor.selectRootElement();
    555            
     558
    556559            if(!_isVisualEditor)
    557560            {
    558561                _vEditor.getMainDiv().hide();
    559562            }
    560            
     563
    561564            _editor = ace.edit("textEditor");
    562565            _editor.getSession().setMode("ace/mode/xml");
     
    566569            var UndoManager = require("ace/undomanager").UndoManager;
    567570            _editor.getSession().setUndoManager(new UndoManager());
    568            
     571
    569572            _textEditor.css({"min-height":"200px", "border-top":"5px solid #444"});
    570573            _textEditor.resizable({handles: 'n', resize:function()
     
    583586        .error(function()
    584587        {
    585             console.log("ERROR");
    586         });
    587     }
    588    
    589     var addMouseEventsToInfoContainer = function(infoContainer, fileName, location, nodename, namespace, name, match)
     588            console.log("Error getting the XML template from the file");
     589        });
     590    }
     591
     592    //Store the function that is called when this template is selected from the list
     593    var addChangeEventToInfoContainer = function(infoContainer, fileName, location, nodename, namespace, name, match)
    590594    {
    591595        infoContainer.data("changeFunction", function()
     
    598602            _selectedTemplate.prevBorder = _selectedTemplate.css("border");
    599603            _selectedTemplate.css("border", "red 1px solid");
    600        
     604
    601605            _currentFileName = fileName;
    602606            _currentLocation = location;
     
    605609            _currentName = name;
    606610            _currentMatch = match;
    607        
     611
    608612            _greenbug.changeCurrentTemplate(location, fileName, nodename, namespace, name, match);
    609613        });
    610         /*
    611         infoContainer.mouseover(function()
    612         {
    613             $(this).removeClass("ui-state-default");
    614             $(this).addClass("ui-state-active");
    615         });
    616         infoContainer.mouseout(function()
    617         {
    618             $(this).addClass("ui-state-default");
    619             $(this).removeClass("ui-state-active");
    620         });
    621         */
    622     }
    623 
     614    }
     615
     616    //Add the mouse events to the <debug> elemetns that are called when the selector is anabled
    624617    var addMouseEventsToDebugElements = function(debugElems)
    625618    {
     
    629622            {
    630623                _pauseSelector = true;
    631                 _unpauseButton.button("option", "disabled", false);
     624                _selectNewElementButton.button("option", "disabled", false);
    632625            }
    633626        });
     
    680673                    var location;
    681674                    var fileName;
     675                    //Use the filepath to work out where this file is from
    682676                    if(filepath.search(/[\/\\]interfaces[\/\\]/) != -1)
    683677                    {
     
    705699                    _elements.push(infoContainer);
    706700
    707                     addMouseEventsToInfoContainer(infoContainer, fileName, location, nodename, namespace, name, match);
     701                    addChangeEventToInfoContainer(infoContainer, fileName, location, nodename, namespace, name, match);
    708702
    709703                    if(name && name.length > 0)
     
    716710                    }
    717711
    718                     if(_templateSelector.children("div").length > 0)
    719                     {
    720                         /*
    721                         var spacer = $("<div>&gt;&gt;</div>");
    722                         spacer.addClass("gbSpacer");
    723 
    724                         _templateSelector.prepend(spacer);
    725                         _elements.push(spacer);
    726                         */
    727                     }
    728 
    729712                    _templateSelector.children("select").append(infoContainer);
    730 
    731                     //resizeContainers();
    732713                });
    733714               
     
    750731        });
    751732    }
    752    
     733
     734    //Remove <debug> elements from the title
    753735    var fixTitle = function()
    754736    {
    755737        $("title").text($("title").text().replace(/<[^>]*>/g, ""));
    756738    }
    757    
    758     /*
    759     var resizeContainers = function()
    760     {
    761         var templates = _templateSelector.children(".gbTemplateContainer");
    762         var spacers = _templateSelector.children(".gbSpacer");
    763        
    764         var templateWidth = (79/templates.length) + "%";
    765         templates.css("width", templateWidth);
    766        
    767         if(spacers.length > 0)
    768         {
    769             var spacersWidth = (19/spacers.length) + "%";
    770             spacers.css("width", spacersWidth);
    771         }
    772     }
    773     */
    774    
     739
     740    //Initialise Greenbug
    775741    this.init = function()
    776742    {
     
    805771        createDebugDiv();
    806772        $("body").append(_mainDiv);
    807        
     773
    808774        callStyleFunctions();
    809775
     
    811777        fixTitle();
    812778    }
    813    
    814779}
    815780
     781//The code entry point
    816782$(window).load(function()
    817783{
  • 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.