|
Server : Apache/2.2.22 (Unix) mod_ssl/2.2.22 OpenSSL/1.0.0-fips mod_auth_passthrough/2.1 mod_bwlimited/1.4 System : Linux server.jackjohnson.com 2.6.32-279.5.2.el6.x86_64 #1 SMP Fri Aug 24 01:07:11 UTC 2012 x86_64 User : jackjohn ( 502) PHP Version : 5.3.17 Disable Function : NONE Directory : /home/jackjohn/www/style/javascript/ |
Upload File : |
// ----------------------------------------------------------------------------
// Dynamic Lists - Javascript Library
// Copyright (C) 2003-2004, All Rights Reserved
// ----------------------------------------------------------------------------
// This program is protected by local and international copyright laws. Any
// use of this program is subject to the the terms of the license agreement
// included as part of this distribution archive. Any other uses are stictly
// prohibited without the written permission of the Vendor and all other
// rights are reserved.
// ----------------------------------------------------------------------------
/* ---------------------------------------------------------------------- *\
Function : dlist_init
Description : Loads listdata, clears "rows" list and inserts one row for
each hidden field in listdata (that doesn't have _erased
set), then reset visibility and colors.
Usage : dlist_init(listname, createRowHTML_function)
\* ---------------------------------------------------------------------- */
function dlist_init(listname, createRowHTML) {
// error checking
var isErrors = dlist_errorChecking(listname, createRowHTML);
if (isErrors) { return; }
// set vars
var listdata = _listdata_loadAll(listname);
var rowsContainer = document.getElementById(listname +':rows');
// remove existing list rows
removeChildNodes( rowsContainer );
// add rowHTML to dynamic list
_dlist_appendRowHTML(listname, listdata.rows, createRowHTML)
_dlist_setNodeVisibility(listname);
_dlist_setRowColors(listname);
}
/* ---------------------------------------------------------------------- *\
Function : dlist_errorChecking
Description : Check for required fields and information before creating
dynamic list
Usage : dlist_errorChecking(listname, createRowHTML_function)
\* ---------------------------------------------------------------------- */
function dlist_errorChecking(listname, createRowHTML) {
// basic error checking
if (!listname) { error("no listname specified!"); }
if (typeof(createRowHTML) != 'function') { error("createRowHTML must be a function!"); };
var errorMsg = '';
// check elements exist
var reqElementIdSuffixes = ['listdata','rows','max_rows_reached','empty_list','add_row','tmpHTML'];
for (var n=0; n < reqElementIdSuffixes.length; n++) {
var suffixName = reqElementIdSuffixes[n];
var fullname = listname +':'+ suffixName;
var el = document.getElementById(fullname);
if (!el) {
errorMsg += "required element not defined: "+ fullname + "\n";
}
}
// check config field defined
var reqElementNameSuffixes = ['maximum_rows_allowed','highest_record_number','retain_erased_rows','background_classnames'];
for (n=0; n < reqElementNameSuffixes.length; n++) {
suffixName = reqElementNameSuffixes[n];
fullname = listname +':'+ suffixName;
var matches = document.getElementsByName(fullname);
if (matches.length == 0) {
errorMsg += "required element not defined: "+ fullname + "\n";
}
if (matches.length > 1) {
errorMsg += "Too many elements with same name: "+ fullname + "\n";
}
}
//
// Check createRowHTML output
//
var fields = { '_listname': listname };
var rowHTML = createRowHTML( fields );
var rowNodes = __dlist_createRowNodes(listname, rowHTML);
var firstTR = rowNodes[0];
// check form elements created by createRowHTML have onchange/onclick event handlers
var formFields = getFormFieldNames( firstTR );
for (var fieldName in formFields) {
var fieldElement = formFields[ fieldName ];
var needsOnClickHandler = 0;
var needsOnChangeHandler = 0;
// figure out which elements need which handlers
if (fieldElement.type == 'hidden') { continue; }
else if (fieldElement.type == 'radio' ||
fieldElement.type == 'checkbox') { needsOnClickHandler = 1; }
else if (fieldElement.type == 'text' ||
fieldElement.type == 'password' ||
fieldElement.type == 'textarea' ||
fieldElement.type == 'select' ||
fieldElement.type == 'select-one') { needsOnChangeHandler = 1; }
else { errorMsg += "Unrecognized element type '" +fieldElement.type+ "'"; }
// check handler is defined
var fieldNameParts = fieldName.split(":");
var fieldNameWithoutPrefix = fieldNameParts[ fieldNameParts.length - 1 ];
if (needsOnClickHandler && fieldElement.onclick == undefined) {
errorMsg += "The '" +fieldNameWithoutPrefix+ "' field in the createRowHTML function doesn't have a onclick handler defined!\n";
}
if (needsOnChangeHandler && fieldElement.onchange == undefined) {
errorMsg += "The '" +fieldNameWithoutPrefix+ "' field in the createRowHTML function doesn't have a onchange handler defined!\n";
}
}
// check row created by createRowHTML has id
if (firstTR.id == '') {
errorMsg += "The table row TR tag in the createRowHTML function doesn't have an id value!";
}
// display error message(s)
if (errorMsg) {
alert(errorMsg);
return true;
}
else {
return false;
}
}
/* ---------------------------------------------------------------------- *\
Function : dlist_addNewRow
Description : add a new row to the dynamic list.
formFieldValues is optional
\* ---------------------------------------------------------------------- */
function dlist_addNewRow(listname, createRowHTML, formFieldValues) {
var rowNode = document.getElementById(listname +':add_row');
// get form field values for row
if (typeof(formFieldValues) == 'undefined') {
formFieldValues = new Object();
var formFieldNames = getFormFieldNames(rowNode);
for (var longFieldname in formFieldNames) {
var shortFieldname = longFieldname.replace(listname+':add:', '');
if (longFieldname == '') {
error("rowNode '" +listname+ ":add_row' contains a field with a blank name!\n\n" + rowNode.innerHTML);
}
formFieldValues[ shortFieldname ] = getFormFieldValueByName( longFieldname );
}
}
var rowfields = _listdata_addRow(listname, formFieldValues);
// add row HTML to dynamic list table
_dlist_appendRowHTML(listname, [ rowfields ], createRowHTML)
// reset visibility and colors
_dlist_setNodeVisibility(listname);
_dlist_setRowColors(listname);
}
/* ---------------------------------------------------------------------- *\
Function : dlist_removeRow
Description : Remove a row from the list and mark it as _erased in the
listdata.
\* ---------------------------------------------------------------------- */
function dlist_removeRow(listname, rownum) {
_listdata_eraseRow(listname, rownum);
// remove HTML Row from list
var rowNode = document.getElementById(listname +':'+ rownum);
rowNode.parentNode.removeChild( rowNode );
_dlist_setNodeVisibility(listname);
_dlist_setRowColors(listname);
}
/* ---------------------------------------------------------------------- *\
Function : dlist_moveRow
Description : Move a specified row up or down in list, then reset
visibility and colors. Note, when a row is moved off the
top of the list it gets added to the bottom and all the
other rows move up one (and vice-versa when it's moved off
the bottom).
\* ---------------------------------------------------------------------- */
function dlist_moveRow(listname, rownum, direction) {
// error checking
if (direction != 'up' && direction != 'down') { error("direction must be 'up' or 'down'"); }
// define vars
var rowsContainer = document.getElementById(listname +':rows');
// switch _order values in listdata (and save)
_listdata_moveRow(listname, rownum, direction);
// backup form elements state
var elementStates = _backupFormElementStates(rowsContainer);
//
// switch row order in table
//
var thisRow = document.getElementById(listname +':'+ rownum);
if (direction == 'up') {
if (thisRow.previousSibling) {
swapNode(thisRow.previousSibling, thisRow);
}
else { // move to bottom of list if no row above
var parentNode = thisRow.parentNode;
parentNode.removeChild(thisRow);
parentNode.appendChild(thisRow)
}
}
if (direction == 'down') {
if (thisRow.nextSibling) { swapNode(thisRow.nextSibling, thisRow); }
else { // move to top of list if no row below thisRow
parentNode = thisRow.parentNode;
parentNode.removeChild(thisRow);
parentNode.insertBefore(thisRow, parentNode.firstChild);
}
}
// restore form state
_restoreFormElementStates(elementStates);
_dlist_setNodeVisibility(listname);
_dlist_setRowColors(listname);
return true;
}
/* ---------------------------------------------------------------------- *\
Function : dlist_saveRowOnChange
Description : update row after it's form elements have been modified.
Usage : call with onclick="" for radios and checkboxes
and onchange="" for all other elements
\* ---------------------------------------------------------------------- */
function dlist_saveRowOnChange(listname, rownum) {
var rowNode = document.getElementById(listname +':'+ rownum);
var formfields = getFormFieldNames(rowNode);
var rowfields = new Object();
// get form field values for row
for (var longFieldname in formfields) {
var shortFieldname = longFieldname.replace(listname+':'+rownum+':', '');
rowfields[ shortFieldname ] = getFormFieldValueByName( longFieldname );
}
// save row data
_listdata_saveRow(listname, rownum, rowfields);
}
/* ---------------------------------------------------------------------- *\
Function : dlist_debugger
Description : display a textarea with the realtime contents of the
datalist node.
Usage : <script> dlist_debugger('listname'); </script>
\* ---------------------------------------------------------------------- */
function dlist_debugger(listname) {
var debugfield = document.getElementById(listname + ':debugger');
var listdata = document.getElementById(listname +':listdata');
if (!listdata) { error("Can't start debug viewer without: " +listname+ ':listdata'); }
if (!debugfield) {
document.write('<p><b>listdata Contents</b><br>');
document.write('<textarea id="' +listname+ ':debugger" cols=120 rows=25 style="width: 100%"></textarea></p>');
debugfield = document.getElementById(listname + ':debugger');
// note: setInterval is picky in safari, but this works
window.setInterval( 'dlist_debugger("'+listname+'")', 500); // refresh ourselves
}
var listdataHTML = listdata.innerHTML;
listdataHTML = listdataHTML.replace(/>/g, ">\n");
listdataHTML = listdataHTML.replace(/\n\s+/g, "\n");
listdataHTML = listdataHTML.replace(/&/g, "&");
listdataHTML = listdataHTML.replace(/&/g, "&\n");
debugfield.value = listdataHTML;
return true;
}
/* ---------------------------------------------------------------------- *\
Function : _dlist_appendRowHTML
Description : Append one or more rows to the HTML list. Note, this does
NOT add anything to listdata. It just updates the HTML.
\* ---------------------------------------------------------------------- */
function _dlist_appendRowHTML(listname, rowDataArray, createRowHTML) {
// create new rows
var rowsHTML = '';
for (n=0; n < rowDataArray.length; n++) {
var rowFields = rowDataArray[n];
if (parseInt(rowFields._erased)) { continue; }
rowsHTML += createRowHTML( rowFields );
}
// create row nodes
var rowNodes = __dlist_createRowNodes(listname, rowsHTML);
// copy rows over to rowsContainer
var rowsContainer = document.getElementById(listname +':rows');
for (var n=0; n < rowNodes.length; n++) {
var thisRow = rowNodes[n];
rowsContainer.appendChild( thisRow );
}
}
/* ---------------------------------------------------------------------- *\
Function : _dlist_setNodeVisibility
Description : Toggle the visibility on the following elements as
appropriate: max_records_reached, empty_list, and add_row.
\* ---------------------------------------------------------------------- */
function _dlist_setNodeVisibility(listname) {
var listdata = _listdata_loadAll(listname);
var visibleRowCount = _dlist_getVisibleRowCount(listdata);
//
// set display attribute
//
var VISIBLE = ''; // set to blank for default visibility setting
var NONE = 'none';
// rows
var listrowss = document.getElementById(listname +':rows');
listrowss.style.display = VISIBLE;
// empty list
var empty_list = document.getElementById(listname +':empty_list');
if (visibleRowCount == 0) { empty_list.style.display = VISIBLE; }
else { empty_list.style.display = NONE; }
// max records & add row
var max_records = document.getElementById(listname +':max_rows_reached');
var add_row = document.getElementById(listname +':add_row');
if (listdata.config.maximum_rows_allowed <= visibleRowCount) {
max_records.style.display = VISIBLE;
add_row.style.display = NONE;
} else {
max_records.style.display = NONE;
add_row.style.display = VISIBLE;
}
}
/* ---------------------------------------------------------------------- *\
Function : _dlist_getVisibleRowCount
Description :
Usage : visibleRowCount = _dlist_getVisibleRowCount(listdata);
\* ---------------------------------------------------------------------- */
function _dlist_getVisibleRowCount(listdata) {
// get not-erased row count
var visibleRowCount = 0;
for (var n=0; n < listdata.rows.length; n++) {
var thisRow = listdata.rows[n];
if (parseInt(thisRow._erased)) { continue; }
visibleRowCount++;
}
return visibleRowCount;
}
/* ---------------------------------------------------------------------- *\
Function : _dlist_setRowColors
Description : Reset the background colors on all the rows on the ":rows"
tbody cell.
\* ---------------------------------------------------------------------- */
function _dlist_setRowColors(listname) {
var listdata = _listdata_loadAll(listname);
var rowsContainer = document.getElementById(listname +':rows');
if (listdata.config.background_classnames.length == 0) { return; } // 0 colors
if (!isArray(listdata.config.background_classnames)) {
listdata.config.background_classnames = [ listdata.config.background_classnames ];
}
// Set row colors on dynamic list rows
var parentNodeStack = [ rowsContainer ];
var tableRows = new Array();
var counter = 0;
for (var x=0; x < parentNodeStack.length; x++) {
var thisParent = parentNodeStack[x];
var bgclass_idx, bgclass;
// set background color for row's cells
if (thisParent.nodeName == 'TR') {
bgclass_idx = counter % listdata.config.background_classnames.length;
bgclass = listdata.config.background_classnames[ bgclass_idx ];
counter++;
}
for (var y=0; y < thisParent.childNodes.length; y++) {
var thisNode = thisParent.childNodes[y];
if (thisNode.nodeName == 'TABLE') { parentNodeStack.push(thisNode); } // add to stack
if (thisNode.nodeName == 'TBODY') { parentNodeStack.push(thisNode); } // add to stack
if (thisNode.nodeName == 'TR') { parentNodeStack.push(thisNode); } // add to stack
// set class for all child TD's in TR row
if (thisNode.nodeName == 'TD' && bgclass) {
thisNode.className = bgclass;
}
}
}
}
/* ---------------------------------------------------------------------- *\
Function : _dlist_redrawRow
Description : regenerate a row with (presumably) updated listdata, then
reset visibility and colors.
\* ---------------------------------------------------------------------- */
function _dlist_redrawRow(listname, rownum, createRowHTML) {
var rowfields = _listdata_loadRow(listname, rownum);
var oldRow = document.getElementById(listname +':'+ rownum);
// create new row
var newRowHTML = createRowHTML(rowfields);
var newRowNodes = __dlist_createRowNodes(listname, newRowHTML);
var newRow = newRowNodes[0];
// swap it with old
swapNode(oldRow, newRow);
_dlist_setNodeVisibility(listname);
_dlist_setRowColors(listname);
}
/* ---------------------------------------------------------------------- *\
Function : __dlist_createRowNodes
Description : Takes some rowHTML "<tr>...</tr><tr>...</tr>", inserts it
into an invisible table, and returns an array of row nodes.
Usage : rowNodes = __dlist_createRowNodes(listname, rowsHTML);
\* ---------------------------------------------------------------------- */
function __dlist_createRowNodes(listname, rowsHTML) {
// insert row HTML into temporary table to generate DOM elements
var tmpTable = document.getElementById(listname + ':tmpHTML');
tmpTable.innerHTML = '<table border=1 style="display: none">' + rowsHTML + '</table>';
// Get a list of all rows in tmpTable (non-recursive version)
var parentNodeStack = [ tmpTable ];
var rowNodes = new Array();
for (var x=0; x < parentNodeStack.length; x++) {
var thisParent = parentNodeStack[x];
for (var y=0; y < thisParent.childNodes.length; y++) {
var thisNode = thisParent.childNodes[y];
if (thisNode.nodeName == 'TABLE') { parentNodeStack.push(thisNode); } // add to stack
if (thisNode.nodeName == 'TBODY') { parentNodeStack.push(thisNode); } // add to stack
if (thisNode.nodeName == 'TR') { rowNodes.push(thisNode); }
}
}
// erase child nodes from DOM (so multiple IDs with the same name don't conflict)
removeChildNodes(tmpTable);
// return array of row nodes
return rowNodes;
}
/* ---------------------------------------------------------------------- *\
Function : _listdata_loadAll
Description : Return the listdata data structure. Structure:
var listdata = {
config: {
maximum_rows_allowed: X,
highest_record_number: X,
retain_erased_rows: X,
background_classnames: X
}
rows: [
'... querystring encoded list of rows fields ...',
'... querystring encoded list of rows fields ...',
'... querystring encoded list of rows fields ...'
]
};
\* ---------------------------------------------------------------------- */
function _listdata_loadAll(listname) {
var listdataNode = document.getElementById(listname+':listdata');
var listdata = {
config: {},
rows: []
};
// load config data
var formfields = getFormFieldNames(listdataNode);
for (var fieldname in formfields) {
var thisField = formfields[fieldname];
var fieldvalue = thisField.value;
var isConfigField = thisField.name && (thisField.name.lastIndexOf(listname+':') > -1);
var configField = fieldname.replace(listname+':', '');
if (isConfigField) {
var isCommaSeperatedList = (fieldvalue.lastIndexOf(',') > -1);
if (isCommaSeperatedList) {
var valuesCSV = fieldvalue.replace(/\s*,\s*/g, ',');
var valuesArray = valuesCSV.split(',');
listdata.config[ configField ] = valuesArray;
}
else {
listdata.config[ configField ] = fieldvalue;
}
}
}
// error checking
if (isNaN(listdata.config.highest_record_number)) { error(listname+":highest_record_number must be a number not '" +listdata.config.highest_record_number+ "'"); }
// load rows
var rowsArray = document.getElementsByName(listname);
for (var n=0; n < rowsArray.length; n++) {
var thisRow = rowsArray[n];
var rowfields = query2obj(thisRow.value);
rowfields['_listname'] = listname;
listdata.rows.push( rowfields );
}
// sort array by "_order" field
listdata.rows.sort( __listdata_sortRows );
// return listdata object
return listdata;
}
/* ---------------------------------------------------------------------- *\
Function : _listdata_saveAll
Description : Re-generates all the hidden fields in the listdataNode to
represent the current state of the listdata.
\* ---------------------------------------------------------------------- */
function _listdata_saveAll(listname, listdataOriginal) {
// clone obj because we modify values below and referenced object is used in calling function
var listdataCopy = cloneObject(listdataOriginal);
var listdataNode = document.getElementById(listname + ":listdata");
if (listdataNode == null) { error("Can't find: " +listname+ ':listdata'); }
// Remove old contents of listdata
removeChildNodes( listdataNode );
// Append Config Fields
for (var shortFieldname in listdataCopy.config) {
var fieldvalue = listdataCopy.config[ shortFieldname ];
var longFieldname = listname +':'+ shortFieldname;
var newTag = __listdata_createHiddenElement(longFieldname, fieldvalue)
listdataNode.appendChild(newTag)
}
// Append List Row Fields
for (var n=0; n < listdataCopy.rows.length; n++) {
delete listdataCopy.rows[n]['_listname']; // don't save dynamic field (set by _listdata_loadAll)
var rowQueryString = obj2query( listdataCopy.rows[n] );
newTag = __listdata_createHiddenElement(listname, rowQueryString)
listdataNode.appendChild(newTag)
}
return true;
}
/* ---------------------------------------------------------------------- *\
Function : _listdata_loadRow
\* ---------------------------------------------------------------------- */
function _listdata_loadRow(listname, rownum) {
var listdata = _listdata_loadAll(listname);
// find matching row
var matchingRow;
for (var n=0; n < listdata.rows.length; n++) {
var thisRow = listdata.rows[n];
if (thisRow._num == rownum) { matchingRow = thisRow; }
}
if (!matchingRow) { error("unable to find row " + rownum); }
return matchingRow;
}
/* ---------------------------------------------------------------------- *\
Function : _listdata_saveRow
Description : Updates field values of a specified row. Note, fields
that are not specified will maintain their original value
\* ---------------------------------------------------------------------- */
function _listdata_saveRow(listname, rownum, newValues) {
var listdata = _listdata_loadAll(listname);
// find matching row
var matchingRow;
for (var n=0; n < listdata.rows.length; n++) {
var thisRow = listdata.rows[n];
if (thisRow._num == rownum) { matchingRow = thisRow; }
}
if (!matchingRow) { error("unable to find row " + rownum); }
// update row values
for (var fieldname in newValues) {
matchingRow[fieldname] = newValues[fieldname];
}
// save listdata
_listdata_saveAll(listname, listdata);
return true;
}
/* ---------------------------------------------------------------------- *\
Function : _listdata_addRow
Description : Add a row to the listdata and a hash of it's field & values
\* ---------------------------------------------------------------------- */
function _listdata_addRow(listname, newRowFields) {
var listdata = _listdata_loadAll(listname);
// get new row number
var highestRowNumber = listdata.config.highest_record_number;
var newRowNumber = parseInt(highestRowNumber)+1;
listdata.config.highest_record_number = newRowNumber;
// get new order number
var highestOrderNumber = 0;
for (var n=0; n < listdata.rows.length; n++) {
var thisRow = listdata.rows[n];
if (thisRow._order > parseInt(highestOrderNumber)) { highestOrderNumber = thisRow._order; }
}
var newOrderNumber = Math.max( parseInt(highestOrderNumber)+1, newRowNumber);
// create new row object
var newRow = {
_num: newRowNumber,
_order: newOrderNumber,
_erased: 0,
_listname: listname
};
for (var rowField in newRowFields) {
newRow[ rowField ] = newRowFields[ rowField ];
}
// add to listdata
listdata.rows.push(newRow);
// save to HTML
_listdata_saveAll(listname, listdata);
// return row reference
return newRow;
}
/* ---------------------------------------------------------------------- *\
Function : _listdata_eraseRow
Description : Mark a row as erased by setting _erased flag
\* ---------------------------------------------------------------------- */
function _listdata_eraseRow(listname, rownum) {
var listdataObj = _listdata_loadAll(listname);
// flag erased rows
var rowFound = 0;
for (var n=0; n < listdataObj.rows.length; n++) {
var thisRow = listdataObj.rows[n];
if (thisRow._num == rownum) {
thisRow._erased = 1;
thisRow._order = 0;
rowFound = 1;
}
}
if (!rowFound) { error("_listdata_eraseRow: Couldn't find record #" + rownum); }
// erase flagged rows
var retain_erased_rows = parseInt(listdataObj.config.retain_erased_rows);
if (!retain_erased_rows) {
for (var idx=0; idx < listdataObj.rows.length; null) {
thisRow = listdataObj.rows[idx];
if (parseInt(thisRow._erased)) {
listdataObj.rows.splice(idx, 1); // remove row
continue; // next element is now at same index
}
idx++; // check next element
}
}
// save to listdata HTML
_listdata_saveAll(listname, listdataObj);
return true;
}
/* ---------------------------------------------------------------------- *\
Function : _listdata_moveRow
Description : move a row up or down, adjusting other row values as
required. The top and bottom of lists wrap/connect.
\* ---------------------------------------------------------------------- */
function _listdata_moveRow(listname, rownum, direction) {
var listdata = _listdata_loadAll(listname);
var rowArray = listdata.rows;
// split rowArray into hidden and visible arrays
var hiddenRows = [];
var visibleRows = [];
var sourceIndex;
for (var n=0; n < rowArray.length; n++) {
var thisRow = rowArray[n];
var isHidden = parseInt(thisRow._erased);
if (isHidden) {
hiddenRows.push( thisRow );
thisRow._order = 0;
}
else {
visibleRows.push( thisRow );
if (thisRow._num == rownum) { sourceIndex = visibleRows.length - 1; }
}
}
if (sourceIndex == null) { error("Unable to find row number " + rownum); }
if (direction != 'down' && direction != 'up') { error("Invalid direction '"+direction+"', must be 'up' or 'down'"); }
// define vars
var sourceIsFirstRow = (sourceIndex == 0);
var sourceIsLastRow = (sourceIndex == (visibleRows.length-1));
var sourceValue = visibleRows[sourceIndex];
// re-order rows
if (direction == 'up' && !sourceIsFirstRow) { // row above us
var targetIndex = sourceIndex - 1;
visibleRows[sourceIndex] = visibleRows[targetIndex];
visibleRows[targetIndex] = sourceValue;
}
else if (direction == 'down' && !sourceIsLastRow) { // row below us
targetIndex = sourceIndex + 1;
visibleRows[sourceIndex] = visibleRows[targetIndex];
visibleRows[targetIndex] = sourceValue;
}
else if (direction == 'up' && sourceIsFirstRow) { // none above us
visibleRows.push(visibleRows.shift()); // first becomes last
}
else if (direction == 'down' && sourceIsLastRow) { // none below us
visibleRows.unshift(visibleRows.pop()); // last becomes first
}
// reset all order values
for (var idx=0; idx < visibleRows.length; idx++) {
thisRow = visibleRows[idx];
thisRow._order = idx + 1;
}
// merge arrays into rowArray
rowArray = hiddenRows.concat(visibleRows);
// save to listdata HTML
_listdata_saveAll(listname, listdata);
return true;
}
/* ---------------------------------------------------------------------- *\
Function : __listdata_sortRows
Description : sort rows by _order field
Usage : listdata.rows.sort( __listdata_sortRows );
\* ---------------------------------------------------------------------- */
function __listdata_sortRows(obj1, obj2) {
var order1 = parseInt(obj1._order) || 0;
var order2 = parseInt(obj2._order) || 0;
if (order1 < order2) { return -1; }
else if (order1 == order2) { return 0; }
else if (order1 > order2) { return 1; }
return true;
}
/* ---------------------------------------------------------------------- *\
Function : __listdata_createHiddenElement
Description : Create a new hidden input field element and return a
reference to it.
\* ---------------------------------------------------------------------- */
function __listdata_createHiddenElement(elName, elValue) {
var browserEngine = whatBrowserEngine();
if (browserEngine == 'msie') { // setAttribute('name') broken in IE6
var newTag = document.createElement('<input type="hidden" name="' +elName+ '" id="' +elName+ '">');
newTag.setAttribute('value', elValue);
}
else {
newTag = document.createElement('input');
newTag.setAttribute('type', 'hidden');
newTag.setAttribute('name', elName);
newTag.setAttribute('id', elName);
newTag.setAttribute('value', elValue);
}
return newTag;
}
/* ---------------------------------------------------------------------- *\
Function : *formElementStates
Description : Get or set the form element states (value, checked, and
selected specifically) for all the form elements below
the current node.
This function is to workaround a common browser bug that
resets form element states when a node is moved or manipulated.
IE 6 resets checkboxes/radios to pageload values on move.
Usage : var elementStates = backupFormElementStates(parentNode);
restoreFormElementStates(elementStates);
\* ---------------------------------------------------------------------- */
function _backupFormElementStates(parentNode) {
// get element lists
var inputs = parentNode.getElementsByTagName('input'); // hidden, checkbox, radio, text, password
var selects = parentNode.getElementsByTagName('select'); // select-one, select-multi
var textareas = parentNode.getElementsByTagName('textarea'); // textareas
// merge element lists
var elements = new Array();
for (var n=0; n < inputs.length; n++) { elements.push( inputs[n] ); }
for (n=0; n < selects.length; n++) { elements.push( selects[n] ); }
for (n=0; n < textareas.length; n++) { elements.push( textareas[n] ); }
// create array to save element states in
var elementStates = new Array();
// save value for each element
for (n=0; n < elements.length; n++) {
var thisElement = elements[n];
var backupState = new Object();
var eType = thisElement.type;
backupState.node = thisElement;
backupState.type = thisElement.type; // for debug use only
// hidden, textarea, password, and text fields
if (eType == 'hidden' || eType == 'textarea' || eType == 'password' || eType == 'text') {
backupState.value = thisElement.value;
}
// checkboxes & radios
else if (eType == 'checkbox' || eType == 'radio' ) {
backupState.checked = thisElement.checked;
}
// selects
else if (eType == 'select-one' || eType == 'select-multiple') {
backupState.selectedIndexes = "";
for (var idx=0; idx < thisElement.options.length; idx++) {
var thisOption = thisElement.options[idx];
if (thisOption.selected) {
if (backupState.selectedIndexes.length != 0) {
backupState.selectedIndexes += ",";
}
backupState.selectedIndexes += idx
}
}
}
// skip these elements
else if (eType == 'button' || eType == 'submit' || eType == 'reset' || eType == 'image') { continue; }
// unknown elements
else { error("Unknown element type: " + eType); }
// add this elements state to list
elementStates.push( backupState );
}
return elementStates;
}
// ----------------------------------------------------------------------------
function _restoreFormElementStates(elementStates) {
for (var n=0; n < elementStates.length; n++) {
var thisElement = elementStates[n].node;
var backupState = elementStates[n];
var eType = thisElement.type;
// hidden, textarea, password, and text fields
if (eType == 'hidden' || eType == 'textarea' || eType == 'password' || eType == 'text') {
thisElement.value = backupState.value;
}
// checkboxes & radios
else if (eType == 'checkbox' || eType == 'radio' ) {
thisElement.checked = backupState.checked;
}
// selects
else if (eType == 'select-one' || eType == 'select-multiple') {
// create lookup table for selected Indexes
var wasSelectedIndex = new Object();
var indexArray = backupState.selectedIndexes.split(",");
for (var i=0; i < indexArray.length; i++) {
var indexNumber = indexArray[i];
wasSelectedIndex[ indexNumber ] = true;
}
// mark options as selected or not
for (var idx=0; idx < thisElement.options.length; idx++) {
var thisOption = thisElement.options[idx];
var selectedBoolValue = (typeof wasSelectedIndex[idx] == 'undefined') ? false : true;
thisOption.selected = selectedBoolValue;
}
}
// skip these elements
else if (eType == 'button' || eType == 'submit' || eType == 'reset' || eType == 'image') { continue; }
// unknown elements
else { error("Unknown element type: " + eType); }
}
return true;
}
// ----------------------------------------------------------------------------