pjs/editor/ui/dialogs/content/EdSelectProps.js

709 строки
21 KiB
JavaScript
Исходник Обычный вид История

/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Selection List Properties Dialog.
*
* The Initial Developer of the Original Code is
* Neil Rashbrook.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s): Neil Rashbrook <neil@parkwaycc.co.uk>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
// Global variables
var hasValue;
var oldValue;
var insertNew;
var globalArray;
var selectElement;
var currentObject = null;
var selectedOption = 0;
var selectedOptionCount = 0;
// Utility functions
function GetObjectForTreeItem(treeItem)
{
return globalArray[parseInt(treeItem.getAttribute("index"))];
}
function InsertBefore(parent, before, after)
{
var savedObject = currentObject;
before.parentObject = parent;
parent.element.insertBefore(before.element, after.element);
parent.treeChildren.insertBefore(before.treeItem, after.treeItem);
gDialog.tree.focus();
selectTreeItem(savedObject.treeItem);
gDialog.previousButton.disabled = !savedObject.canMoveUp();
gDialog.nextButton.disabled = !savedObject.canMoveDown();
}
function AppendChild(parent, option)
{
var savedObject = currentObject;
option.parentObject = parent;
parent.treeChildren.appendChild(option.treeItem);
parent.element.appendChild(option.element);
gDialog.tree.focus();
selectTreeItem(savedObject.treeItem);
gDialog.previousButton.disabled = !savedObject.canMoveUp();
gDialog.nextButton.disabled = !savedObject.canMoveDown();
}
function UpdateSelectMultiple()
{
if (selectedOptionCount > 1)
{
gDialog.selectMultiple.checked = true;
gDialog.selectMultiple.disabled = true;
}
else
gDialog.selectMultiple.disabled = false;
}
function createXUL(localName)
{
return document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", localName);
}
// OPTION element wrapper object
function optionObject(parent, option)
{
if (option.hasAttribute("selected"))
selectedOptionCount++;
this.globalIndex = globalArray.length;
globalArray[globalArray.length++] = this;
this.parentObject = parent;
this.element = option;
this.treeItem = createXUL("treeitem");
this.treeRow = createXUL("treerow");
this.treeCellText = createXUL("treecell");
this.treeCellValue = createXUL("treecell");
this.treeCellSelected = createXUL("treecell");
this.treeItem.setAttribute("index", this.globalIndex);
this.treeItem.setAttribute("container", "true");
this.treeItem.setAttribute("empty", "true");
this.treeCellText.setAttribute("class", "treecell-indent");
this.treeCellText.setAttribute("notwisty", "true");
this.treeCellText.setAttribute("label", option.text);
if (option.hasAttribute("value"))
this.treeCellValue.setAttribute("label", option.value);
else
this.treeCellValue.setAttribute("label", option.text);
this.treeCellSelected.setAttribute("properties", "checked-"+option.hasAttribute("selected"));
this.treeRow.appendChild(this.treeCellText);
this.treeRow.appendChild(this.treeCellValue);
this.treeRow.appendChild(this.treeCellSelected);
this.treeItem.appendChild(this.treeRow);
parent.treeChildren.appendChild(this.treeItem);
gDialog.treeItem.setAttribute("open", "true");
}
optionObject.prototype.onSpace = function onSpace()
{
if (this.element.hasAttribute("selected"))
{
selectedOptionCount--;
this.element.removeAttribute("selected");
this.treeCellSelected.setAttribute("properties", "checked-false");
gDialog.optionSelected.setAttribute("checked", "false");
selectedOption = 0;
}
else
{
if (gDialog.selectMultiple.checked || !globalArray[selectedOption].element.hasAttribute("selected"))
selectedOptionCount++;
else
{
globalArray[selectedOption].element.removeAttribute("selected");
globalArray[selectedOption].treeCellSelected.setAttribute("properties", "checked-false");
}
this.element.setAttribute("selected", "");
this.treeCellSelected.setAttribute("properties", "checked-true");
gDialog.optionSelected.setAttribute("checked", "true");
selectedOption = this.globalIndex;
}
UpdateSelectMultiple();
};
optionObject.prototype.onFocus = function onFocus()
{
gDialog.optionText.value = this.element.text;
hasValue = this.element.hasAttribute("value");
oldValue = this.element.value;
gDialog.optionHasValue.checked = hasValue;
gDialog.optionValue.value = hasValue ? this.element.value : this.element.text;
gDialog.optionSelected.checked = this.element.hasAttribute("selected");
gDialog.optionDisabled.checked = this.element.hasAttribute("disabled");
gDialog.selectDeck.setAttribute("selectedIndex", "2");
};
optionObject.prototype.onBlur = function onBlur()
{
this.element.text = gDialog.optionText.value;
if (gDialog.optionHasValue.checked)
this.element.value = gDialog.optionValue.value;
else
this.element.removeAttribute("value");
if (gDialog.optionSelected.checked)
this.element.setAttribute("selected", "");
else
this.element.removeAttribute("selected");
if (gDialog.optionDisabled.checked)
this.element.setAttribute("disabled", "");
else
this.element.removeAttribute("disabled");
};
optionObject.prototype.canDestroy = function canDestroy(prompt)
{
return true;
/*return !prompt ||
ConfirmWithTitle(GetString("DeleteOption"),
GetString("DeleteOptionMsg"),
GetString("DeleteOption"));*/
};
optionObject.prototype.destroy = function destroy()
{
if (this.element.hasAttribute("selected"))
{
selectedOptionCount--;
UpdateSelectMultiple();
}
this.parentObject.removeChild(this);
};
optionObject.prototype.canMoveUp = function canMoveUp()
{
return this.treeItem.previousSibling || this.parentObject != gDialog;
}
optionObject.prototype.moveUp = function moveUp()
{
if (this.treeItem.previousSibling)
GetObjectForTreeItem(this.treeItem.previousSibling).insertAfter(this);
else
InsertBefore(gDialog, this, this.parentObject);
}
optionObject.prototype.insertAfter = function insertAfter(option)
{
InsertBefore(this.parentObject, option, this);
}
optionObject.prototype.canMoveDown = function canMoveDown()
{
return this.treeItem.nextSibling || this.parentObject != gDialog;
}
optionObject.prototype.moveDown = function moveDown()
{
if (this.treeItem.nextSibling)
GetObjectForTreeItem(this.treeItem.nextSibling).insertBefore(this);
else if (this.parentObject.treeItem.nextSibling)
InsertBefore(gDialog, this, GetObjectForTreeItem(this.parentObject.treeItem.nextSibling));
else
AppendChild(gDialog, this);
}
optionObject.prototype.insertBefore = function insertBefore(option)
{
InsertBefore(this.parentObject, this, option);
}
optionObject.prototype.appendChild = function appendChild(child)
{
return this.parentObject.appendChild(child);
};
// OPTGROUP element wrapper object
function optgroupObject(parent, optgroup)
{
this.globalIndex = globalArray.length;
globalArray[globalArray.length++] = this;
this.parentObject = parent;
this.element = optgroup;
this.treeItem = createXUL("treeitem");
this.treeRow = createXUL("treerow");
this.treeCell = createXUL("treecell");
this.treeChildren = createXUL("treechildren");
this.treeItem.setAttribute("index", this.globalIndex);
this.treeItem.setAttribute("container", "true");
this.treeItem.setAttribute("empty", "true");
this.treeItem.setAttribute("open", "true");
this.treeCell.setAttribute("class", "treecell-indent");
this.treeCell.setAttribute("notwisty", "true");
this.treeCell.setAttribute("label", optgroup.label);
this.treeRow.appendChild(this.treeCell);
this.treeItem.appendChild(this.treeRow);
this.treeItem.appendChild(this.treeChildren);
parent.treeChildren.appendChild(this.treeItem);
gDialog.treeItem.setAttribute("open", "true");
for (var child = optgroup.firstChild; child; child = child.nextSibling)
if (child.tagName == "OPTION")
new optionObject(this, child);
}
optgroupObject.prototype.onSpace = function onSpace()
{
};
optgroupObject.prototype.onFocus = function onFocus()
{
gDialog.optgroupLabel.value = this.element.label;
gDialog.optgroupDisabled.checked = this.element.disabled;
gDialog.selectDeck.setAttribute("selectedIndex", "1");
};
optgroupObject.prototype.onBlur = function onBlur()
{
this.element.label = gDialog.optgroupLabel.value;
this.element.disabled = gDialog.optgroupDisabled.checked;
};
optgroupObject.prototype.canDestroy = function canDestroy(prompt)
{
return !this.element.firstChild;
/*return !this.element.firstChild && (!prompt ||
ConfirmWithTitle(GetString("DeleteOptGroup"),
GetString("DeleteOptGroupMsg"),
GetString("DeleteOptGroup")));
*/
};
optgroupObject.prototype.destroy = function destroy()
{
gDialog.removeChild(this);
};
optgroupObject.prototype.canMoveUp = function canMoveUp()
{
return this.treeItem.previousSibling;
}
optgroupObject.prototype.moveUp = function moveUp()
{
InsertBefore(this.parentObject, this, GetObjectForTreeItem(this.treeItem.previousSibling));
}
optgroupObject.prototype.insertBefore = function insertBefore(option)
{
if (this.treeChildren.firstChild)
InsertBefore(this, option, GetObjectForTreeItem(this.treeChildren.firstChild));
else
AppendChild(this, option);
}
optgroupObject.prototype.canMoveDown = function canMoveDown()
{
return this.treeItem.nextSibling;
}
optgroupObject.prototype.moveDown = function moveDown()
{
InsertBefore(this.parentObject, GetObjectForTreeItem(this.treeItem.nextSibling), this);
}
optgroupObject.prototype.insertAfter = function insertAfter(option)
{
AppendChild(this, option);
}
optgroupObject.prototype.appendChild = function appendChild(child)
{
this.element.appendChild(child);
return new optionObject(this, child);
};
optgroupObject.prototype.removeChild = function removeChild(child)
{
this.element.removeChild(child.element);
this.treeChildren.removeChild(child.treeItem);
globalArray[child.globalIndex] = null;
};
// dialog initialization code
function Startup()
{
if (!InitEditorShell())
return;
// Get a single selected select element
var tagName = "select";
selectElement = editorShell.GetSelectedElement(tagName);
if (selectElement)
// We found an element and don't need to insert one
insertNew = false;
else
{
insertNew = true;
// We don't have an element selected,
// so create one with default attributes
selectElement = editorShell.CreateElementWithDefaults(tagName);
if(!selectElement)
{
dump("Failed to get selected element or create a new one!\n");
window.close();
return;
}
}
// SELECT element wrapper object
gDialog = {
accept: document.documentElement.getButton("accept"),
selectDeck: document.getElementById("SelectDeck"),
selectName: document.getElementById("SelectName"),
selectSize: document.getElementById("SelectSize"),
selectMultiple: document.getElementById("SelectMultiple"),
selectDisabled: document.getElementById("SelectDisabled"),
selectTabIndex: document.getElementById("SelectTabIndex"),
optgroupLabel: document.getElementById("OptGroupLabel"),
optgroupDisabled: document.getElementById("OptGroupDisabled"),
optionText: document.getElementById("OptionText"),
optionHasValue: document.getElementById("OptionHasValue"),
optionValue: document.getElementById("OptionValue"),
optionSelected: document.getElementById("OptionSelected"),
optionDisabled: document.getElementById("OptionDisabled"),
removeButton: document.getElementById("RemoveButton"),
previousButton: document.getElementById("PreviousButton"),
nextButton: document.getElementById("NextButton"),
tree: document.getElementById("SelectTree"),
treeCols: document.getElementById("SelectCols"),
treeItem: document.getElementById("SelectItem"),
treeCell: document.getElementById("SelectCell"),
treeChildren: document.getElementById("SelectChildren"),
element: selectElement.cloneNode(false),
globalIndex: 0,
onSpace: function onSpace() {},
onFocus: function onFocus()
{
gDialog.selectName.value = this.element.getAttribute("name");
gDialog.selectSize.value = this.element.getAttribute("size");
gDialog.selectMultiple.checked = this.element.hasAttribute("multiple");
gDialog.selectDisabled.checked = this.element.hasAttribute("disabled");
gDialog.selectTabIndex.value = this.element.getAttribute("tabindex");
this.selectDeck.setAttribute("selectedIndex", "0");
onNameInput();
},
onBlur: function onBlur()
{
this.element.setAttribute("name", gDialog.selectName.value);
if (gDialog.selectSize.value)
this.element.setAttribute("size", gDialog.selectSize.value);
else
this.element.removeAttribute("size");
if (gDialog.selectMultiple.checked)
this.element.setAttribute("multiple", "");
else
this.element.removeAttribute("multiple");
if (gDialog.selectDisabled.checked)
this.element.setAttribute("disabled", "");
else
this.element.removeAttribute("disabled");
if (gDialog.selectTabIndex.value)
this.element.setAttribute("tabindex", gDialog.selectTabIndex.value);
else
this.element.removeAttribute("tabindex");
},
appendChild: function appendChild(child)
{
if (child.tagName == "OPTION")
{
this.element.appendChild(child)
return new optionObject(this, child);
}
if (child.tagName == "OPTGROUP")
{
this.element.appendChild(child)
return new optgroupObject(this, child);
}
return null;
},
removeChild: function removeChild(child)
{
this.treeChildren.removeChild(child.treeItem);
globalArray[child.globalIndex] = null;
},
canDestroy: function canDestroy(prompt)
{
return false;
},
canMoveUp: function canMoveUp()
{
return false;
},
canMoveDown: function canMoveDown()
{
return false;
}
}
globalArray = [gDialog];
// Workaround for tree scrollbar bug
for (var col = gDialog.treeCols.firstChild; col.nextSibling; col = col.nextSibling)
{
col.setAttribute("width", col.boxObject.width);
col.removeAttribute("flex");
}
// We modify the actual option and optgroup elements so clone them first
for (var child = selectElement.firstChild; child; child = child.nextSibling)
gDialog.appendChild(child.cloneNode(true));
UpdateSelectMultiple();
selectTreeItem(gDialog.treeItem);
onNameInput();
SetTextboxFocus(gDialog.selectName);
SetWindowLocation();
}
function InitDialog()
{
currentObject.onFocus();
}
function ValidateData()
{
currentObject.onBlur();
return true;
}
function onAccept()
{
// All values are valid - copy to actual element in doc or
// element created to insert
ValidateData();
try {
// Coalesce into one undo transaction
editorShell.BeginBatchChanges();
editorShell.CloneAttributes(selectElement, gDialog.element);
if (insertNew)
// 'true' means delete the selection before inserting
editorShell.InsertElementAtSelection(selectElement, true);
while (selectElement.firstChild)
editorShell.DeleteElement(selectElement.firstChild);
var newNodes = gDialog.element.childNodes;
for (var offset = 0; offset < newNodes.length; offset++)
editorShell.InsertElement(newNodes[offset], selectElement, offset, true);
} finally {
editorShell.EndBatchChanges();
}
SaveWindowLocation();
return true;
}
// Button actions
function AddOption()
{
var optionElement = editorShell.CreateElementWithDefaults("option");
var optionObject = currentObject.appendChild(optionElement);
selectTreeItem(optionObject.treeItem);
SetTextboxFocus(gDialog.optionText);
}
function AddOptGroup()
{
var optgroupElement = editorShell.CreateElementWithDefaults("optgroup");
var optgroupObject = gDialog.appendChild(optgroupElement);
selectTreeItem(optgroupObject.treeItem);
SetTextboxFocus(gDialog.optgroupLabel);
}
function RemoveElement()
{
if (currentObject.canDestroy(true))
{
var selection = currentObject.treeItem;
selection = selection.nextSibling || selection.previousSibling || selection.parentNode.parentNode;
currentObject.destroy();
selectTreeItem(selection);
gDialog.tree.focus();
}
}
// Event handlers
function onTreeSelect(event)
{
if (currentObject)
currentObject.onBlur();
var selectedItem = gDialog.tree.contentView.getItemAtIndex(gDialog.tree.currentIndex);
if (selectedItem)
{
currentObject = globalArray[parseInt(selectedItem.getAttribute("index"))];
currentObject.onFocus();
}
else
currentObject = gDialog;
gDialog.removeButton.disabled = !currentObject.canDestroy(false);
gDialog.previousButton.disabled = !currentObject.canMoveUp();
gDialog.nextButton.disabled = !currentObject.canMoveDown();
globalElement = currentObject.element;
}
function onTreeKeyUp(event)
{
if (event.keyCode == event.DOM_VK_SPACE)
currentObject.onSpace();
}
function onTreeClicked(event)
{
var row = {}, col = {}, obj = {};
gDialog.tree.treeBoxObject.getCellAt(event.clientX, event.clientY, row, col, obj);
if (col.value == "SelectSelCol") {
var selection = gDialog.tree.contentView.getItemAtIndex(row.value);
currentObject = globalArray[parseInt(selection.getAttribute("index"))];
if ("treeCellSelected" in currentObject) {
selectTreeItem(selection);
currentObject.onSpace();
}
}
gDialog.tree.focus();
}
var timeout = 0;
function copyValue(textbox, treecell, delay)
{
if (timeout) clearTimeout(timeout);
if (delay)
timeout = setTimeout(copyValue, 800, textbox, treecell, false);
else {
timeout = 0;
treecell.setAttribute("label", textbox.value);
}
}
function onNameInput()
{
var disabled = !gDialog.selectName.value;
if (gDialog.accept.disabled != disabled)
gDialog.accept.disabled = disabled;
copyValue(gDialog.selectName, gDialog.treeCell, true);
}
function onNameChange()
{
copyValue(gDialog.selectName, gDialog.treeCell, false);
}
function onLabelInput()
{
copyValue(gDialog.optgroupLabel, currentObject.treeCell, true);
}
function onLabelChange()
{
copyValue(gDialog.optgroupLabel, currentObject.treeCell, false);
}
function copyText(delay)
{
if (timeout) clearTimeout(timeout);
if (delay)
timeout = setTimeout(copyText, 800, false);
else {
timeout = 0;
currentObject.treeCellText.setAttribute("label", gDialog.optionText.value);
if (!hasValue)
{
gDialog.optionValue.value = gDialog.optionText.value;
currentObject.treeCellValue.setAttribute("label", gDialog.optionText.value);
}
}
}
function onTextInput()
{
copyText(true);
}
function onTextChange()
{
copyText(false);
}
function onValueInput()
{
gDialog.optionHasValue.checked = hasValue = true;
oldValue = gDialog.optionValue.value;
copyValue(gDialog.optionValue, currentObject.treeCellValue, true);
}
function onValueChange()
{
copyValue(gDialog.optionValue, currentObject.treeCellValue, false);
}
function onHasValueClick()
{
hasValue = gDialog.optionHasValue.checked;
if (hasValue)
{
gDialog.optionValue.value = oldValue;
}
else
{
oldValue = gDialog.optionValue.value;
gDialog.optionValue.value = gDialog.optionText.value;
}
currentObject.treeCellValue.setAttribute("label", gDialog.optionValue.value);
}
function onSelectMultipleClick()
{
if (!gDialog.selectMultiple.checked && selectedOptionCount == 1 && !selectedOption)
while (!globalArray[selectedOption] || !globalArray[selectedOption].element.hasAttribute("selected"))
selectedOption++;
}
function selectTreeItem(aItem)
{
var itemIndex = gDialog.tree.contentView.getIndexOfItem(aItem);
gDialog.tree.treeBoxObject.selection.select(itemIndex);
gDialog.tree.treeBoxObject.ensureRowIsVisible(itemIndex);
}