home *** CD-ROM | disk | FTP | other *** search
/ ftp.swcp.com / ftp.swcp.com.zip / ftp.swcp.com / mac / mozilla-macos9-1.3.1.sea.bin / Mozilla1.3.1 / Chrome / comm.jar / content / editor / EdSelectProps.js < prev    next >
Text File  |  2003-06-08  |  25KB  |  781 lines

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3.  *
  4.  * The contents of this file are subject to the Mozilla Public License Version
  5.  * 1.1 (the "License"); you may not use this file except in compliance with
  6.  * the License. You may obtain a copy of the License at
  7.  * http://www.mozilla.org/MPL/
  8.  *
  9.  * Software distributed under the License is distributed on an "AS IS" basis,
  10.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  11.  * for the specific language governing rights and limitations under the
  12.  * License.
  13.  *
  14.  * The Original Code is Selection List Properties Dialog.
  15.  *
  16.  * The Initial Developer of the Original Code is
  17.  * Neil Rashbrook.
  18.  * Portions created by the Initial Developer are Copyright (C) 2001
  19.  * the Initial Developer. All Rights Reserved.
  20.  *
  21.  * Contributor(s): Neil Rashbrook <neil@parkwaycc.co.uk>
  22.  *
  23.  * Alternatively, the contents of this file may be used under the terms of
  24.  * either the GNU General Public License Version 2 or later (the "GPL"), or
  25.  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  26.  * in which case the provisions of the GPL or the LGPL are applicable instead
  27.  * of those above. If you wish to allow use of your version of this file only
  28.  * under the terms of either the GPL or the LGPL, and not to allow others to
  29.  * use your version of this file under the terms of the MPL, indicate your
  30.  * decision by deleting the provisions above and replace them with the notice
  31.  * and other provisions required by the GPL or the LGPL. If you do not delete
  32.  * the provisions above, a recipient may use your version of this file under
  33.  * the terms of any one of the MPL, the GPL or the LGPL.
  34.  *
  35.  * ***** END LICENSE BLOCK ***** */
  36.  
  37. // Global variables
  38.  
  39. var atomService = Components.classes["@mozilla.org/atom-service;1"]
  40.                             .getService(Components.interfaces.nsIAtomService);
  41. var checkedAtoms = {
  42.   "false":  atomService.getAtom("checked-false"),
  43.   "true":   atomService.getAtom("checked-true")};
  44.  
  45. var hasValue;
  46. var oldValue;
  47. var insertNew;
  48. var itemArray;
  49. var treeBoxObject;
  50. var treeSelection;
  51. var selectElement;
  52. var currentItem = null;
  53. var selectedOption = null;
  54. var selectedOptionCount = 0;
  55.  
  56. // Utility functions
  57.  
  58. function getParentIndex(index)
  59. {
  60.   switch (itemArray[index].level)
  61.   {
  62.   case 0: return -1;
  63.   case 1: return 0;
  64.   }
  65.   while (itemArray[--index].level > 1);
  66.   return index;
  67. }
  68.  
  69. function UpdateSelectMultiple()
  70. {
  71.   if (selectedOptionCount > 1)
  72.   {
  73.     gDialog.selectMultiple.checked = true;
  74.     gDialog.selectMultiple.disabled = true;
  75.   }
  76.   else
  77.     gDialog.selectMultiple.disabled = false;
  78. }
  79.  
  80. /* wrapper objects:
  81.  * readonly attribute Node element; // DOM node (select/optgroup/option)
  82.  * readonly attribute int level; // tree depth
  83.  * readonly attribute boolean container; // can contain options
  84.  * string getCellText(string col); // tree view helper
  85.  * string cycleCell(int currentIndex); // tree view helper
  86.  * void onFocus(); // load data into deck
  87.  * void onBlur(); // save data from deck
  88.  * boolean canDestroy(boolean prompt); // NB prompt not used
  89.  * void destroy(); // post remove callback
  90.  * void moveUp();
  91.  * boolean canMoveDown();
  92.  * void moveDown();
  93.  * void appendOption(newElement, currentIndex);
  94.  */
  95.  
  96. // OPTION element wrapper object
  97.  
  98. // Create a wrapper for the given element at the given level
  99. function optionObject(option, level)
  100. {
  101.   // select an added option (when loading from document)
  102.   if (option.hasAttribute("selected"))
  103.     selectedOptionCount++;
  104.   this.level = level;
  105.   this.element = option;
  106. }
  107.  
  108. optionObject.prototype.container = false;
  109.  
  110. optionObject.prototype.getCellText = function getCellText(column)
  111. {
  112.   if (column == "SelectSelCol")
  113.     return "";
  114.   if (column == "SelectValCol" && this.element.hasAttribute("value"))
  115.     return this.element.getAttribute("value");
  116.   return this.element.text;
  117. }
  118.  
  119. optionObject.prototype.cycleCell = function cycleCell(index)
  120. {
  121.   if (this.element.hasAttribute("selected"))
  122.   {
  123.     this.element.removeAttribute("selected");
  124.     selectedOptionCount--;
  125.     selectedOption = null;
  126.   }
  127.   else
  128.   {
  129.     // Different handling for multiselect lists
  130.     if (gDialog.selectMultiple.checked || !selectedOption)
  131.       selectedOptionCount++;
  132.     else if (selectedOption)
  133.     {
  134.       selectedOption.removeAttribute("selected");
  135.       treeBoxObject.invalidateColumn("SelectSelCol");
  136.       selectedOption = null;
  137.     }
  138.     this.element.setAttribute("selected", "");
  139.     selectedOption = this.element;
  140.     treeBoxObject.invalidateCell(index, "SelectSelCol");
  141.   }
  142.   if (currentItem == this)
  143.     // Also update the deck
  144.     gDialog.optionSelected.setAttribute("checked", this.element.hasAttribute("selected"));
  145.   UpdateSelectMultiple();
  146. };
  147.  
  148. optionObject.prototype.onFocus = function onFocus()
  149. {
  150.   gDialog.optionText.value = this.element.text;
  151.   hasValue = this.element.hasAttribute("value");
  152.   oldValue = this.element.value;
  153.   gDialog.optionHasValue.checked = hasValue;
  154.   gDialog.optionValue.value = hasValue ? this.element.value : this.element.text;
  155.   gDialog.optionSelected.checked = this.element.hasAttribute("selected");
  156.   gDialog.optionDisabled.checked = this.element.hasAttribute("disabled");
  157.   gDialog.selectDeck.setAttribute("selectedIndex", "2");
  158. };
  159.  
  160. optionObject.prototype.onBlur = function onBlur()
  161. {
  162.   this.element.text = gDialog.optionText.value;
  163.   if (gDialog.optionHasValue.checked)
  164.     this.element.value = gDialog.optionValue.value;
  165.   else
  166.     this.element.removeAttribute("value");
  167.   if (gDialog.optionSelected.checked)
  168.     this.element.setAttribute("selected", "");
  169.   else
  170.     this.element.removeAttribute("selected");
  171.   if (gDialog.optionDisabled.checked)
  172.     this.element.setAttribute("disabled", "");
  173.   else
  174.     this.element.removeAttribute("disabled");
  175. };
  176.  
  177. optionObject.prototype.canDestroy = function canDestroy(prompt)
  178. {
  179.   return true;
  180. /*return !prompt ||
  181.     ConfirmWithTitle(GetString("DeleteOption"),
  182.                      GetString("DeleteOptionMsg"),
  183.                      GetString("DeleteOption"));*/
  184. };
  185.  
  186. optionObject.prototype.destroy = function destroy()
  187. {
  188.   // Deselect a removed option
  189.   if (this.element.hasAttribute("selected"))
  190.   {
  191.     selectedOptionCount--;
  192.     selectedOption = null;
  193.     UpdateSelectMultiple();
  194.   }
  195. };
  196.  
  197. /* 4 cases:
  198.  * a) optgroup -> optgroup
  199.  *      ...         ...
  200.  *    option        option
  201.  * b) optgroup -> option
  202.  *      option    optgroup
  203.  *      ...         ...
  204.  * c) option
  205.  *    option
  206.  * d)   option
  207.  *      option
  208.  */
  209.  
  210. optionObject.prototype.moveUp = function moveUp()
  211. {
  212.   var i;
  213.   var index = treeSelection.currentIndex;
  214.   if (itemArray[index].level < itemArray[index - 1].level + itemArray[index - 1].container)
  215.   {
  216.     // we need to repaint the tree's lines
  217.     treeBoxObject.invalidateRange(getParentIndex(index), index);
  218.     // a) option is just after an optgroup, so it becomes the last child
  219.     itemArray[index].level = 2;
  220.     treeBoxObject.view.selectionChanged();
  221.   }
  222.   else
  223.   {
  224.     // otherwise new option level is now the same as the previous item
  225.     itemArray[index].level = itemArray[index - 1].level;
  226.     // swap the option with the previous item
  227.     itemArray.splice(index, 0, itemArray.splice(--index, 1)[0]);
  228.   }
  229.   selectTreeIndex(index, true);
  230. }
  231.  
  232. optionObject.prototype.canMoveDown = function canMoveDown()
  233. {
  234.   // move down is not allowed on the last option if its level is 1
  235.   return this.level > 1 || itemArray.length - treeSelection.currentIndex > 1;
  236. }
  237.  
  238. optionObject.prototype.moveDown = function moveDown()
  239. {
  240.   var i;
  241.   var index = treeSelection.currentIndex;
  242.   if (index + 1 == itemArray.length || itemArray[index].level > itemArray[index + 1].level)
  243.   {
  244.     // we need to repaint the tree's lines
  245.     treeBoxObject.invalidateRange(getParentIndex(index), index);
  246.     // a) option is last child of an optgroup, so it moves just after
  247.     itemArray[index].level = 1;
  248.     treeBoxObject.view.selectionChanged();
  249.   }
  250.   else
  251.   {
  252.     // level increases if the option was preceding an optgroup
  253.     itemArray[index].level += itemArray[index + 1].container;
  254.     // swap the option with the next item
  255.     itemArray.splice(index, 0, itemArray.splice(++index, 1)[0]);
  256.   }
  257.   selectTreeIndex(index, true);
  258. }
  259.  
  260. optionObject.prototype.appendOption = function appendOption(child, parent)
  261. {
  262.   // special case quick check
  263.   if (this.level == 1)
  264.     return gDialog.appendOption(child, 0);
  265.  
  266.   // append the option to the parent element
  267.   parent = getParentIndex(parent);
  268.   return itemArray[parent].appendOption(child, parent);
  269. };
  270.  
  271. // OPTGROUP element wrapper object
  272.  
  273. // 
  274. function optgroupObject(optgroup)
  275. {
  276.   this.element = optgroup;
  277. }
  278.  
  279. optgroupObject.prototype.level = 1;
  280.  
  281. optgroupObject.prototype.container = true;
  282.  
  283. optgroupObject.prototype.getCellText = function getCellText(column)
  284. {
  285.   return column == "SelectTextCol" ? this.element.label : "";
  286. }
  287.  
  288. optgroupObject.prototype.cycleCell = function cycleCell(index)
  289. {
  290. };
  291.  
  292. optgroupObject.prototype.onFocus = function onFocus()
  293. {
  294.   gDialog.optgroupLabel.value = this.element.label;
  295.   gDialog.optgroupDisabled.checked = this.element.disabled;
  296.   gDialog.selectDeck.setAttribute("selectedIndex", "1");
  297. };
  298.  
  299. optgroupObject.prototype.onBlur = function onBlur()
  300. {
  301.   this.element.label = gDialog.optgroupLabel.value;
  302.   this.element.disabled = gDialog.optgroupDisabled.checked;
  303. };
  304.  
  305. optgroupObject.prototype.canDestroy = function canDestroy(prompt)
  306. {
  307.   // Only removing empty option groups for now
  308.   return gDialog.nextChild(treeSelection.currentIndex) - treeSelection.currentIndex == 1;
  309. /*&& (!prompt ||
  310.     ConfirmWithTitle(GetString("DeleteOptGroup"),
  311.                      GetString("DeleteOptGroupMsg"),
  312.                      GetString("DeleteOptGroup")));
  313. */
  314. };
  315.  
  316. optgroupObject.prototype.destroy = function destroy()
  317. {
  318. };
  319.  
  320. optgroupObject.prototype.moveUp = function moveUp()
  321. {
  322.   // Find the index of the previous and next elements at the same level
  323.   var index = treeSelection.currentIndex;
  324.   var i = index;
  325.   while (itemArray[--index].level > 1);
  326.   var j = gDialog.nextChild(i);
  327.   // Cut out the element, cut the array in two, then join together
  328.   var movedItems = itemArray.splice(i, j - i);
  329.   var endItems = itemArray.splice(index);
  330.   itemArray = itemArray.concat(movedItems).concat(endItems);
  331.   // Repaint the lot
  332.   treeBoxObject.invalidateRange(index, j);
  333.   selectTreeIndex(index, true);
  334. }
  335.  
  336. optgroupObject.prototype.canMoveDown = function canMoveDown()
  337. {
  338.   return gDialog.lastChild() > treeSelection.currentIndex;
  339. }
  340.  
  341. optgroupObject.prototype.moveDown = function moveDown()
  342. {
  343.   // Find the index of the next two elements at the same level
  344.   var index = treeSelection.currentIndex;
  345.   var i = gDialog.nextChild(index);
  346.   var j = gDialog.nextChild(i);
  347.   // Cut out the element, cut the array in two, then join together
  348.   var movedItems = itemArray.splice(i, j - 1);
  349.   var endItems = itemArray.splice(index);
  350.   itemArray = itemArray.concat(movedItems).concat(endItems);
  351.   // Repaint the lot
  352.   treeBoxObject.invalidateRange(index, j);
  353.   index += j - i;
  354.   selectTreeIndex(index, true);
  355. }
  356.  
  357. optgroupObject.prototype.appendOption = function appendOption(child, parent)
  358. {
  359.   var index = gDialog.nextChild(parent);
  360.   // XXX need to repaint the lines, tree won't do this
  361.   treeBoxObject.invalidatePrimaryCell(index - 1);
  362.   // insert the wrapped object as the last child
  363.   itemArray.splice(index, 0, new optionObject(child, 2));
  364.   treeBoxObject.rowCountChanged(index, 1);
  365.   selectTreeIndex(index, false);
  366. };
  367.  
  368. // dialog initialization code
  369.  
  370. function Startup()
  371. {
  372.   var editor = GetCurrentEditor();
  373.   if (!editor)
  374.   {
  375.     dump("Failed to get active editor!\n");
  376.     window.close();
  377.     return;
  378.   }
  379.  
  380.   // Get a single selected select element
  381.   const kTagName = "select";
  382.   try {
  383.     selectElement = editor.getSelectedElement(kTagName);
  384.   } catch (e) {}
  385.  
  386.   if (selectElement)
  387.     // We found an element and don't need to insert one
  388.     insertNew = false;
  389.   else
  390.   {
  391.     insertNew = true;
  392.  
  393.     // We don't have an element selected,
  394.     //  so create one with default attributes
  395.     try {
  396.       selectElement = editor.createElementWithDefaults(kTagName);
  397.     } catch (e) {}
  398.  
  399.     if(!selectElement)
  400.     {
  401.       dump("Failed to get selected element or create a new one!\n");
  402.       window.close();
  403.       return;
  404.     }
  405.   }
  406.  
  407.   // SELECT element wrapper object
  408.   gDialog = {
  409.     // useful elements
  410.     accept:           document.documentElement.getButton("accept"),
  411.     selectDeck:       document.getElementById("SelectDeck"),
  412.     selectName:       document.getElementById("SelectName"),
  413.     selectSize:       document.getElementById("SelectSize"),
  414.     selectMultiple:   document.getElementById("SelectMultiple"),
  415.     selectDisabled:   document.getElementById("SelectDisabled"),
  416.     selectTabIndex:   document.getElementById("SelectTabIndex"),
  417.     optgroupLabel:    document.getElementById("OptGroupLabel"),
  418.     optgroupDisabled: document.getElementById("OptGroupDisabled"),
  419.     optionText:       document.getElementById("OptionText"),
  420.     optionHasValue:   document.getElementById("OptionHasValue"),
  421.     optionValue:      document.getElementById("OptionValue"),
  422.     optionSelected:   document.getElementById("OptionSelected"),
  423.     optionDisabled:   document.getElementById("OptionDisabled"),
  424.     removeButton:     document.getElementById("RemoveButton"),
  425.     previousButton:   document.getElementById("PreviousButton"),
  426.     nextButton:       document.getElementById("NextButton"),
  427.     tree:             document.getElementById("SelectTree"),
  428.     // wrapper methods (except MoveUp and MoveDown)
  429.     element:          selectElement.cloneNode(false),
  430.     level:            0,
  431.     container:        true,
  432.     getCellText:      function getCellText(column)
  433.     {
  434.       return column == "SelectTextCol" ? this.element.getAttribute("name") : "";
  435.     },
  436.     cycleCell:        function cycleCell(index) {},
  437.     onFocus:          function onFocus()
  438.     {
  439.       gDialog.selectName.value = this.element.getAttribute("name");
  440.       gDialog.selectSize.value = this.element.getAttribute("size");
  441.       gDialog.selectMultiple.checked = this.element.hasAttribute("multiple");
  442.       gDialog.selectDisabled.checked = this.element.hasAttribute("disabled");
  443.       gDialog.selectTabIndex.value = this.element.getAttribute("tabindex");
  444.       this.selectDeck.setAttribute("selectedIndex", "0");
  445.       onNameInput();
  446.     },
  447.     onBlur:           function onBlur()
  448.     {
  449.       this.element.setAttribute("name", gDialog.selectName.value);
  450.       if (gDialog.selectSize.value)
  451.         this.element.setAttribute("size", gDialog.selectSize.value);
  452.       else
  453.         this.element.removeAttribute("size");
  454.       if (gDialog.selectMultiple.checked)
  455.         this.element.setAttribute("multiple", "");
  456.       else
  457.         this.element.removeAttribute("multiple");
  458.       if (gDialog.selectDisabled.checked)
  459.         this.element.setAttribute("disabled", "");
  460.       else
  461.         this.element.removeAttribute("disabled");
  462.       if (gDialog.selectTabIndex.value)
  463.         this.element.setAttribute("tabindex", gDialog.selectTabIndex.value);
  464.       else
  465.         this.element.removeAttribute("tabindex");
  466.     },
  467.     appendOption:     function appendOption(child, parent)
  468.     {
  469.       var index = itemArray.length;
  470.       // XXX need to repaint the lines, tree won't do this
  471.       treeBoxObject.invalidateRange(this.lastChild(), index);
  472.       // append the wrapped object
  473.       itemArray.push(new optionObject(child, 1));
  474.       treeBoxObject.rowCountChanged(index, 1);
  475.       selectTreeIndex(index, false);
  476.     },
  477.     canDestroy:       function canDestroy(prompt)
  478.     {
  479.       return false;
  480.     },
  481.     canMoveDown:      function canMoveDown()
  482.     {
  483.       return false;
  484.     },
  485.     // helper methods
  486.     // Find the index of the next immediate child of the select
  487.     nextChild:        function nextChild(index)
  488.     {
  489.       while (++index < itemArray.length && itemArray[index].level > 1);
  490.       return index;
  491.     },
  492.     // Find the index of the last immediate child of the select
  493.     lastChild:        function lastChild()
  494.     {
  495.       var index = itemArray.length;
  496.       while (itemArray[--index].level > 1);
  497.       return index;
  498.     }
  499.   }
  500.   // Start with the <select> wrapper
  501.   itemArray = [gDialog];
  502.  
  503.   // We modify the actual option and optgroup elements so clone them first
  504.   for (var child = selectElement.firstChild; child; child = child.nextSibling)
  505.   {
  506.     if (child.tagName == "OPTION")
  507.       itemArray.push(new optionObject(child.cloneNode(true), 1));
  508.     else if (child.tagName == "OPTGROUP")
  509.     {
  510.       itemArray.push(new optgroupObject(child.cloneNode(false)));
  511.       for (var grandchild = child.firstChild; grandchild; grandchild = grandchild.nextSibling)
  512.         if (grandchild.tagName == "OPTION")
  513.           itemArray.push(new optionObject(grandchild.cloneNode(true), 2));
  514.     }
  515.   }
  516.  
  517.   UpdateSelectMultiple();
  518.  
  519.   // Define a custom view for the tree
  520.   treeBoxObject = gDialog.tree.treeBoxObject;
  521.   treeBoxObject.view = {
  522.     QueryInterface : function QueryInterface(aIID)
  523.     {
  524.       if (aIID.equals(Components.interfaces.nsITreeView) ||
  525.           aIID.equals(Components.interfaces.nsISupportsWeakReference) ||
  526.           aIID.equals(Components.interfaces.nsISupports))
  527.         return this;
  528.       throw Components.results.NS_NOINTERFACE;
  529.     },
  530.     // useful for debugging
  531.     get wrappedJSObject() { return this; },
  532.     get rowCount() { return itemArray.length; },
  533.     get selection() { return treeSelection; },
  534.     set selection(selection) { return treeSelection = selection; },
  535.     getRowProperties: function getRowProperties(index, column, prop) { },
  536.     // could have used a wrapper for this
  537.     getCellProperties: function getCellProperties(index, column, prop)
  538.     {
  539.       if (column == "SelectSelCol" && !itemArray[index].container)
  540.         prop.AppendElement(checkedAtoms[itemArray[index].element.hasAttribute("selected")]);
  541.     },
  542.     getColumnProperties: function getColumnProperties(column, elem, prop) { },
  543.     // get info from wrapper
  544.     isContainer: function isContainer(index) { return itemArray[index].container; },
  545.     isContainerOpen: function isContainerOpen(index) { return true; },
  546.     isContainerEmpty: function isContainerEmpty(index) { return true; },
  547.     isSeparator: function isSeparator(index) { return false; },
  548.     isSorted: function isSorted() { return false; },
  549.     // d&d not implemented yet!
  550.     canDropOn: function canDropOn(index) { return false; },
  551.     canDropBeforeAfter: function canDropBeforeAfter(index, before) { return index >= before; },
  552.     drop: function drop(index, orientation) { alert('drop:' + index + ',' + orientation); },
  553.     // same as the global helper
  554.     getParentIndex: getParentIndex,
  555.     // tree needs to know when to paint lines
  556.     hasNextSibling: function hasNextSibling(index, after)
  557.     {
  558.       if (!index)
  559.         return false;
  560.       var level = itemArray[index].level;
  561.       while (++after < itemArray.length)
  562.         switch (level - itemArray[after].level)
  563.         {
  564.         case 1: return false;
  565.         case 0: return true;
  566.         }
  567.       return false;
  568.     },
  569.     getLevel: function getLevel(index) { return itemArray[index].level; },
  570.     getImageSrc: function getImageSrc(index, column) { },
  571.     getProgressMode : function getProgressMode(index,column) { },
  572.     getCellValue: function getCellValue(index, column) { },
  573.     getCellText: function getCellText(index, column) { return itemArray[index].getCellText(column); },
  574.     setTree: function setTree(tree) { this.tree = tree; },
  575.     toggleOpenState: function toggleOpenState(index) { },
  576.     cycleHeader: function cycleHeader(col, elem) { },
  577.     selectionChanged: function selectionChanged()
  578.     {
  579.       // Save current values and update buttons and deck
  580.       if (currentItem)
  581.         currentItem.onBlur();
  582.       var currentIndex = treeSelection.currentIndex;
  583.       currentItem = itemArray[currentIndex];
  584.       gDialog.removeButton.disabled = !currentItem.canDestroy();
  585.       gDialog.previousButton.disabled = currentIndex < 2;
  586.       gDialog.nextButton.disabled = !currentItem.canMoveDown();
  587.       // For Advanced Edit
  588.       globalElement = currentItem.element;
  589.       currentItem.onFocus();
  590.     },
  591.     cycleCell: function cycleCell(index, column) { itemArray[index].cycleCell(index); },
  592.     isEditable: function isEditable(index, column) { return false; },
  593.     performAction: function performAction(action) { },
  594.     performActionOnCell: function performActionOnCell(action, index, column) { }
  595.   };
  596.   treeSelection.select(0);
  597.   currentItem = gDialog;
  598.   //onNameInput();
  599.  
  600.   SetTextboxFocus(gDialog.selectName);
  601.  
  602.   SetWindowLocation();
  603. }
  604.  
  605. // Called from Advanced Edit
  606. function InitDialog()
  607. {
  608.   currentItem.onFocus();
  609. }
  610.  
  611. // Called from Advanced Edit
  612. function ValidateData()
  613. {
  614.   currentItem.onBlur();
  615.   return true;
  616. }
  617.  
  618. function onAccept()
  619. {
  620.   // All values are valid - copy to actual element in doc or
  621.   //   element created to insert
  622.   ValidateData();
  623.  
  624.   var editor = GetCurrentEditor();
  625.  
  626.   // Coalesce into one undo transaction
  627.   editor.beginTransaction();
  628.  
  629.   try
  630.   {
  631.     editor.cloneAttributes(selectElement, gDialog.element);
  632.  
  633.     if (insertNew)
  634.       // 'true' means delete the selection before inserting
  635.       editor.insertElementAtSelection(selectElement, true);
  636.  
  637.     editor.setShouldTxnSetSelection(false);
  638.  
  639.     while (selectElement.lastChild)
  640.       editor.deleteNode(selectElement.lastChild);
  641.  
  642.     var offset = 0;
  643.     for (var i = 1; i < itemArray.length; i++)
  644.       if (itemArray[i].level > 1)
  645.         selectElement.lastChild.appendChild(itemArray[i].element);
  646.       else
  647.         editor.insertNode(itemArray[i].element, selectElement, offset++, true);
  648.  
  649.     editor.setShouldTxnSetSelection(true);
  650.   }
  651.   finally
  652.   {
  653.     editor.endTransaction();
  654.   }
  655.  
  656.   SaveWindowLocation();
  657.  
  658.   return true;
  659. }
  660.  
  661. // Button actions
  662. function AddOption()
  663. {
  664.   currentItem.appendOption(GetCurrentEditor().createElementWithDefaults("option"), treeSelection.currentIndex);
  665.   SetTextboxFocus(gDialog.optionText);
  666. }
  667.  
  668. function AddOptGroup()
  669. {
  670.   var optgroupElement = GetCurrentEditor().createElementWithDefaults("optgroup");
  671.   var index = itemArray.length;
  672.   // XXX need to repaint the lines, tree won't do this
  673.   treeBoxObject.invalidateRange(gDialog.lastChild(), index);
  674.   // append the wrapped object
  675.   itemArray.push(new optgroupObject(optgroupElement));
  676.   treeBoxObject.rowCountChanged(index, 1);
  677.   selectTreeIndex(index, false);
  678.   SetTextboxFocus(gDialog.optgroupLabel);
  679. }
  680.  
  681. function RemoveElement()
  682. {
  683.   if (currentItem.canDestroy(true))
  684.   {
  685.     // Only removing empty option groups for now
  686.     var index = treeSelection.currentIndex;
  687.     var level = itemArray[index].level;
  688.     // Perform necessary cleanup and remove the wrapper
  689.     itemArray[index].destroy();
  690.     itemArray.splice(index, 1);
  691.     --index;
  692.     // XXX need to repaint the lines, tree won't do this
  693.     if (level == 1) {
  694.       var last = gDialog.lastChild();
  695.       if (index > last)
  696.         treeBoxObject.invalidateRange(last, index);
  697.     }
  698.     selectTreeIndex(index, true);
  699.     treeBoxObject.rowCountChanged(++index, -1);
  700.   }
  701. }
  702.  
  703. // Event handler
  704. function onTreeKeyUp(event)
  705. {
  706.   if (event.keyCode == event.DOM_VK_SPACE)
  707.     currentItem.cycleCell();
  708. }
  709.  
  710. function onNameInput()
  711. {
  712.   var disabled = !gDialog.selectName.value;
  713.   if (gDialog.accept.disabled != disabled)
  714.     gDialog.accept.disabled = disabled;
  715.   gDialog.element.setAttribute("name", gDialog.selectName.value);
  716.   // repaint the tree
  717.   treeBoxObject.invalidatePrimaryCell(treeSelection.currentIndex);
  718. }
  719.  
  720. function onLabelInput()
  721. {
  722.   currentItem.element.setAttribute("label", gDialog.optgroupLabel.value);
  723.   // repaint the tree
  724.   treeBoxObject.invalidatePrimaryCell(treeSelection.currentIndex);
  725. }
  726.  
  727. function onTextInput()
  728. {
  729.   currentItem.element.text = gDialog.optionText.value;
  730.   // repaint the tree
  731.   if (hasValue)
  732.     treeBoxObject.invalidatePrimaryCell(treeSelection.currentIndex);
  733.   else
  734.   {
  735.     gDialog.optionValue.value = gDialog.optionText.value;
  736.     treeBoxObject.invalidateRow(treeSelection.currentIndex);
  737.   }
  738. }
  739.  
  740. function onValueInput()
  741. {
  742.   gDialog.optionHasValue.checked = hasValue = true;
  743.   oldValue = gDialog.optionValue.value;
  744.   currentItem.element.setAttribute("value", oldValue);
  745.   // repaint the tree
  746.   treeBoxObject.invalidateCell(treeSelection.currentIndex, "SelectValCol");
  747. }
  748.  
  749. function onHasValueClick()
  750. {
  751.   hasValue = gDialog.optionHasValue.checked;
  752.   if (hasValue)
  753.   {
  754.     gDialog.optionValue.value = oldValue;
  755.     currentItem.element.setAttribute("value", oldValue);
  756.   }
  757.   else
  758.   {
  759.     oldValue = gDialog.optionValue.value;
  760.     gDialog.optionValue.value = gDialog.optionText.value;
  761.     currentItem.element.removeAttribute("value");
  762.   }
  763.   // repaint the tree
  764.   treeBoxObject.invalidateCell(treeSelection.currentIndex, "SelectValCol");
  765. }
  766.  
  767. function onSelectMultipleClick()
  768. {
  769.   // Recalculate the unique selected option if we need it and have lost it
  770.   if (!gDialog.selectMultiple.checked && selectedOptionCount == 1 && !selectedOption)
  771.     for (var i = 1; !(selectedOption = itemArray[i].element).hasAttribute("selected"); i++);
  772. }
  773.  
  774. function selectTreeIndex(index, focus)
  775. {
  776.   treeSelection.select(index);
  777.   treeBoxObject.ensureRowIsVisible(index);
  778.   if (focus)
  779.     gDialog.tree.focus();
  780. }
  781.