blob: 01e08a2b3aaf70745b101a7db6f136663813fce7 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
dojo.require("dojo.widget.HtmlWidget");
dojo.provide("cocoon.forms.MultiValueDoubleList");
/**
* A free-entry multivalue field editor style double list.
*
* Some functionality that's not visible at first sight:
* - items can be moved around using ctrl+up and ctrl+down.
* - an item can be replaced/updated by pressing ctrl+enter in the input box
*/
dojo.widget.defineWidget(
// widget name and class
"cocoon.forms.MultiValueDoubleList",
// superclass
dojo.widget.HtmlWidget,
function() {
},
// properties and methods
{
isContainer: false,
cformsIdPrefix: "id-prefix-not-set",
resourcesUri: cocoon.resourcesUri,
templatePath: cocoon.resourcesUri + "/forms/js/templates/MultiValueDoubleList.html",
availableListLabel : "Available",
selectedListLabel : "Selected",
size: "5",
styleClass : "",
fillInTemplate: function(args, frag) {
cocoon.forms.MultiValueDoubleList.superclass.fillInTemplate(this, args, frag);
// Available list options.
this.selectLeft.addOption = function(value, text) {
var alreadyInList = false;
for (var i = 0; this.options.length > i && !alreadyInList; i++) {
if (this.options[i].value == value) {
alreadyInList = true;
}
}
if (!alreadyInList) {
this.options[this.options.length] = new Option(text, value);
}
}
// Selected list options.
this.selectRight.addOption = function(value, text) {
var alreadyInList = false;
for (var i = 0; this.options.length > i && !alreadyInList; i++) {
if (this.options[i].value == value) {
alreadyInList = true;
}
}
if (!alreadyInList) {
this.options[this.options.length] = new Option(text, value);
}
}
dojo.event.connect(this.selectRight, "ondblclick", this, "_transferLeft");
dojo.event.connect(this.transferRight, "onclick", this, "_transferRight");
dojo.event.connect(this.selectLeft, "ondblclick", this, "_transferRight");
dojo.event.connect(this.transferAllRight, "onclick", this, "_transferAllRight");
dojo.event.connect(this.transferLeft, "onclick", this, "_transferLeft");
dojo.event.connect(this.transferAllLeft, "onclick", this, "_transferAllLeft");
dojo.event.connect(this, "addedTo", this, "_addOnSubmitHandler");
this._readData(this.getFragNodeRef(frag));
},
_addOnSubmitHandler: function(parent) {
var form = this._getForm(this);
if (form != null) {
dojo.event.connect("before", form,"onsubmit", this, "_selectAll");
} else {
dojo.debug("MultiValueDoubleList is not being added to a form -- no onSubmitHandler then.");
}
},
/**
* Finds the HTML form to which a widget belongs.
* The widget is passed as an argument since this might become a generic
* utility function outside of this wiget.
*/
_getForm: function(widget) {
do {
if (widget.domNode != null && widget.domNode.tagName != null && widget.domNode.tagName.toLowerCase() == "form") {
return widget.domNode;
}
widget = widget.parent;
} while (widget != null)
return null;
},
_readData: function(origFrag) {
// Read data from available list options.
var table = dojo.dom.getFirstChildElement(origFrag, "table");
if (table != null) {
var tbody = dojo.dom.firstElement(table, "tbody");
if (tbody != null) {
var tr = dojo.dom.firstElement(tbody, "tr");
while (tr != null) {
var td = dojo.dom.firstElement(tr, "td");
var value = td != null ? dojo.dom.textContent(td) : null;
var text = td.nextSibling != null ? dojo.dom.textContent(td.nextSibling) : value;
if (value && text) {
this.selectLeft.addOption(value, text);
}
tr = dojo.dom.nextElement(tr, "tr");
}
}
// Read data from selected list options.
var table1 = dojo.dom.getNextSiblingElement(table, "table");
if (table1 != null) {
var tbody1 = dojo.dom.firstElement(table1, "tbody");
if (tbody1 != null) {
var tr1 = dojo.dom.firstElement(tbody1, "tr");
while (tr1 != null) {
var td1 = dojo.dom.firstElement(tr1, "td");
var value1 = td1 != null ? dojo.dom.textContent(td1) : null;
var text1 = td1.nextSibling != null ? dojo.dom.textContent(td1.nextSibling) : value1;
if (value1 && text1) {
this.selectRight.addOption(value1, text1);
}
tr1 = dojo.dom.nextElement(tr1, "tr");
}
}
}
} else {
dojo.debug("MultiValueDoubleList: no data table found");
}
},
_selectAll: function() {
this._selectAllOptions(this.selectRight);
},
_transferLeft: function (event) {
dojo.event.browser.stopEvent(event);
this._moveSelectedOptions(this.selectRight, this.selectLeft);
this._update();
},
_transferRight: function (event) {
dojo.event.browser.stopEvent(event);
this._moveSelectedOptions(this.selectLeft, this.selectRight);
this._update();
},
_transferAllLeft: function (event) {
dojo.event.browser.stopEvent(event);
this._moveAllOptions(this.selectRight, this.selectLeft);
this._update();
},
_transferAllRight: function (event) {
dojo.event.browser.stopEvent(event);
this._moveAllOptions(this.selectLeft, this.selectRight);
this._update();
},
_update: function() {
var removedLeft = new Object();
var removedRight = new Object();
var addedLeft = new Object();
var addedRight = new Object();
var newLeft = new Object();
var newRight = new Object();
var originalLeftValues = new Object();
var originalRightValues = new Object();
var delimiter = ",";
var right = this.selectRight;
var left = this.selectLeft;
var removedLeftField = null;
var removedRightField = null;
var addedLeftField = null;
var addedRightField = null;
var newLeftField = null;
var newRightField = null;
for (var i = 0; i < left.options.length; i++) {
var o = left.options[i];
newLeft[o.value] = 1;
if (typeof(originalLeftValues[o.value]) == "undefined") {
addedLeft[o.value] = 1;
removedRight[o.value] = 1;
}
}
for (var i = 0; i < right.options.length; i++) {
var o = right.options[i];
newRight[o.value] = 1;
if (typeof(originalRightValues[o.value]) == "undefined") {
addedRight[o.value] = 1;
removedLeft[o.value] = 1;
}
}
if (removedLeftField != null) {
removedLeftField.value = this._join(removedLeft, delimiter);
}
if (removedRightField != null) {
removedRightField.value = this._join(removedRight, delimiter);
}
if (addedLeftField != null) {
addedLeftField.value = this._join(addedLeft, delimiter);
}
if (addedRightField != null) {
addedRightField.value = this._join(addedRight, delimiter);
}
if (newLeftField != null) {
newLeftField.value = this._join(newLeft, delimiter);
}
if (newRightField != null) {
newRightField.value = this._join(newRight, delimiter);
}
},
_moveSelectedOptions: function (from, to) {
if (arguments.length > 3) {
var regex = arguments[3];
if(regex != "") {
this._unSelectMatchingOptions(from,regex);
}
}
for(var i = 0; i < from.options.length; i++) {
var o = from.options[i];
if(o.selected) {
to.options[to.options.length] = new Option( o.text, o.value, true, o.selected);
}
}
for (var i = (from.options.length-1); i >= 0; i--) {
var o = from.options[i];
if(o.selected) {
from.options[i] = null;
}
}
if ((arguments.length < 3) || (arguments[2] == true)) {
this._sortSelect(from);
this._sortSelect(to);
}
from.selectedIndex = -1;
to.selectedIndex = -1;
},
_moveAllOptions: function (from, to) {
this._selectAllOptions(from);
if(arguments.length == 2) {
this._moveSelectedOptions(from, to);
} else if(arguments.length == 3) {
this._moveSelectedOptions(from, to, arguments[2]);
} else if(arguments.length == 4) {
this._moveSelectedOptions(from, to, arguments[2], arguments[3]);
}
},
_selectAllOptions: function (obj) {
for(var i = 0; i < obj.options.length; i++) {
obj.options[i].selected = true;
}
},
_unSelectMatchingOptions: function (obj, regex) {
this._selectUnselectMatchingOptions(obj, regex, "unselect", false);
},
_selectUnselectMatchingOptions: function(obj, regex, which, only) {
if (window.RegExp) {
var selected1;
var selected2;
if(which == "select"){
selected1 = true;
selected2 = false;
} else if (which == "unselect") {
selected1 = false;
selected2 = true;
} else {
return;
}
var re = new RegExp(regex);
for (var i = 0;i < obj.options.length; i++) {
if(re.test(obj.options[i].text)) {
obj.options[i].selected = selected1;
} else {
if(only == true) {
obj.options[i].selected = selected2;
}
}
}
}
},
_join: function(o, delimiter) {
var val;
var str="";
for(val in o) {
if (str.length > 0) {
str = str + delimiter;
}
str = str + val;
}
return str;
},
_sortSelect: function(obj) {
var o = new Array();
if(obj.options == null) {
return;
}
for(var i = 0; i < obj.options.length; i++) {
o[o.length] = new Option( obj.options[i].text, obj.options[i].value, obj.options[i].defaultSelected, obj.options[i].selected) ;
}
if (o.length == 0) {
return;
}
o = o.sort( function(a,b) {
if ((a.text + "") < (b.text + "")) {
return -1;
}
if ((a.text + "") > (b.text + "")) {
return 1;
}
return 0;
} );
for(var i = 0; i < o.length; i++) {
obj.options[i] = new Option(o[i].text, o[i].value, o[i].defaultSelected, o[i].selected);
}
}
}
);