[ Index ] |
PHP Cross Reference of phpwcms V1.4.3 _r380 (23.11.09) |
[Summary view] [Print] [Text view]
1 /*=================================================================== 2 Author: Matt Kruse 3 4 View documentation, examples, and source code at: 5 http://www.JavascriptToolbox.com/ 6 7 NOTICE: You may use this code for any purpose, commercial or 8 private, without any further permission from the author. You may 9 remove this notice from your final code if you wish, however it is 10 appreciated by the author if at least the web site address is kept. 11 12 This code may NOT be distributed for download from script sites, 13 open source CDs or sites, or any other distribution method. If you 14 wish you share this code with others, please direct them to the 15 web site above. 16 17 Pleae do not link directly to the .js files on the server above. Copy 18 the files to your own server for use with your site or webapp. 19 ===================================================================*/ 20 // Global objects to keep track of DynamicOptionList objects created on the page 21 var dynamicOptionListCount=0; 22 var dynamicOptionListObjects = new Array(); 23 24 // Init call to setup lists after page load. One call to this function sets up all lists. 25 function initDynamicOptionLists() { 26 // init each DynamicOptionList object 27 for (var i=0; i<dynamicOptionListObjects.length; i++) { 28 var dol = dynamicOptionListObjects[i]; 29 30 // Find the form associated with this list 31 if (dol.formName!=null) { 32 dol.form = document.forms[dol.formName]; 33 } 34 else if (dol.formIndex!=null) { 35 dol.form = document.forms[dol.formIndex]; 36 } 37 else { 38 // Form wasn't set manually, so go find it! 39 // Search for the first form element name in the lists 40 var name = dol.fieldNames[0][0]; 41 for (var f=0; f<document.forms.length; f++) { 42 if (typeof(document.forms[f][name])!="undefined") { 43 dol.form = document.forms[f]; 44 break; 45 } 46 } 47 if (dol.form==null) { 48 alert("ERROR: Couldn't find form element "+name+" in any form on the page! Init aborted"); return; 49 } 50 } 51 52 // Form is found, now set the onchange attributes of each dependent select box 53 for (var j=0; j<dol.fieldNames.length; j++) { 54 // For each set of field names... 55 for (var k=0; k<dol.fieldNames[j].length-1; k++) { 56 // For each field in the set... 57 var selObj = dol.form[dol.fieldNames[j][k]]; 58 if (typeof(selObj)=="undefined") { alert("Select box named "+dol.fieldNames[j][k]+" could not be found in the form. Init aborted"); return; } 59 // Map the HTML options in the first select into the options we created 60 if (k==0) { 61 if (selObj.options!=null) { 62 for (l=0; l<selObj.options.length; l++) { 63 var sopt = selObj.options[l]; 64 var m = dol.findMatchingOptionInArray(dol.options,sopt.text,sopt.value,false); 65 if (m!=null) { 66 var reselectForNN6 = sopt.selected; 67 var m2 = new Option(sopt.text, sopt.value, sopt.defaultSelected, sopt.selected); 68 m2.selected = sopt.selected; // For some reason I need to do this to make NN4 happy 69 m2.defaultSelected = sopt.defaultSelected; 70 m2.DOLOption = m; 71 selObj.options[l] = m2; 72 selObj.options[l].selected = reselectForNN6; // Reselect this option for NN6 to be happy. Yuck. 73 } 74 } 75 } 76 } 77 if (selObj.onchange==null) { 78 // We only modify the onChange attribute if it's empty! Otherwise do it yourself in your source! 79 selObj.onchange = new Function("dynamicOptionListObjects["+dol.index+"].change(this)"); 80 } 81 } 82 } 83 } 84 // Set the preselectd options on page load 85 resetDynamicOptionLists(); 86 } 87 88 // This function populates lists with the preselected values. 89 // It's pulled out into a separate function so it can be hooked into a 'reset' button on a form 90 // Optionally passed a form object which should be the only form reset 91 function resetDynamicOptionLists(theform) { 92 // reset each DynamicOptionList object 93 for (var i=0; i<dynamicOptionListObjects.length; i++) { 94 var dol = dynamicOptionListObjects[i]; 95 if (typeof(theform)=="undefined" || theform==null || theform==dol.form) { 96 for (var j=0; j<dol.fieldNames.length; j++) { 97 dol.change(dol.form[dol.fieldNames[j][0]],true); // Second argument says to use preselected values rather than default values 98 } 99 } 100 } 101 } 102 103 // An object to represent an Option() but just for data-holding 104 function DOLOption(text,value,defaultSelected,selected) { 105 this.text = text; 106 this.value = value; 107 this.defaultSelected = defaultSelected; 108 this.selected = selected; 109 this.options = new Array(); // To hold sub-options 110 return this; 111 } 112 113 // DynamicOptionList CONSTRUCTOR 114 function DynamicOptionList() { 115 this.form = null;// The form this list belongs to 116 this.options = new Array();// Holds the options of dependent lists 117 this.longestString = new Array();// Longest string that is currently a potential option (for Netscape) 118 this.numberOfOptions = new Array();// The total number of options that might be displayed, to build dummy options (for Netscape) 119 this.currentNode = null;// The current node that has been selected with forValue() or forText() 120 this.currentField = null;// The current field that is selected to be used for setValue() 121 this.currentNodeDepth = 0;// How far down the tree the currentNode is 122 this.fieldNames = new Array();// Lists of dependent fields which use this object 123 this.formIndex = null;// The index of the form to associate with this list 124 this.formName = null;// The name of the form to associate with this list 125 this.fieldListIndexes = new Object();// Hold the field lists index where fields exist 126 this.fieldIndexes = new Object();// Hold the index within the list where fields exist 127 this.selectFirstOption = true;// Whether or not to select the first option by default if no options are default or preselected, otherwise set the selectedIndex = -1 128 this.numberOfOptions = new Array();// Store the max number of options for a given option list 129 this.longestString = new Array();// Store the longest possible string 130 this.values = new Object(); // Will hold the preselected values for fields, by field name 131 132 // Method mappings 133 this.forValue = DOL_forValue; 134 this.forText = DOL_forText; 135 this.forField = DOL_forField; 136 this.forX = DOL_forX; 137 this.addOptions = DOL_addOptions; 138 this.addOptionsTextValue = DOL_addOptionsTextValue; 139 this.setDefaultOptions = DOL_setDefaultOptions; 140 this.setValues = DOL_setValues; 141 this.setValue = DOL_setValues; 142 this.setFormIndex = DOL_setFormIndex; 143 this.setFormName = DOL_setFormName; 144 this.printOptions = DOL_printOptions; 145 this.addDependentFields = DOL_addDependentFields; 146 this.change = DOL_change; 147 this.child = DOL_child; 148 this.selectChildOptions = DOL_selectChildOptions; 149 this.populateChild = DOL_populateChild; 150 this.change = DOL_change; 151 this.addNewOptionToList = DOL_addNewOptionToList; 152 this.findMatchingOptionInArray = DOL_findMatchingOptionInArray; 153 154 // Optionally pass in the dependent field names 155 if (arguments.length > 0) { 156 // Process arguments and add dependency groups 157 for (var i=0; i<arguments.length; i++) { 158 this.fieldListIndexes[arguments[i].toString()] = this.fieldNames.length; 159 this.fieldIndexes[arguments[i].toString()] = i; 160 } 161 this.fieldNames[this.fieldNames.length] = arguments; 162 } 163 164 // Add this object to the global array of dynamicoptionlist objects 165 this.index = window.dynamicOptionListCount++; 166 window["dynamicOptionListObjects"][this.index] = this; 167 } 168 169 // Given an array of Option objects, search for an existing option that matches value, text, or both 170 function DOL_findMatchingOptionInArray(a,text,value,exactMatchRequired) { 171 if (a==null || typeof(a)=="undefined") { return null; } 172 var value_match = null; // Whether or not a value has been matched 173 var text_match = null; // Whether or not a text has been matched 174 for (var i=0; i<a.length; i++) { 175 var opt = a[i]; 176 // If both value and text match, return it right away 177 if (opt.value==value && opt.text==text) { return opt; } 178 if (!exactMatchRequired) { 179 // If value matches, store it until we complete scanning the list 180 if (value_match==null && value!=null && opt.value==value) { 181 value_match = opt; 182 } 183 // If text matches, store it for later 184 if (text_match==null && text!=null && opt.text==text) { 185 text_match = opt; 186 } 187 } 188 } 189 return (value_match!=null)?value_match:text_match; 190 } 191 192 // Util function used by forValue and forText 193 function DOL_forX(s,type) { 194 if (this.currentNode==null) { this.currentNodeDepth=0; } 195 var useNode = (this.currentNode==null)?this:this.currentNode; 196 var o = this.findMatchingOptionInArray(useNode["options"],(type=="text")?s:null,(type=="value")?s:null,false); 197 if (o==null) { 198 o = new DOLOption(null,null,false,false); 199 o[type] = s; 200 useNode.options[useNode.options.length] = o; 201 } 202 this.currentNode = o; 203 this.currentNodeDepth++; 204 return this; 205 } 206 207 // Set the portion of the list structure that is to be used by a later operation like addOptions 208 function DOL_forValue(s) { return this.forX(s,"value"); } 209 210 // Set the portion of the list structure that is to be used by a later operation like addOptions 211 function DOL_forText(s) { return this.forX(s,"text"); } 212 213 // Set the field to be used for setValue() calls 214 function DOL_forField(f) { this.currentField = f; return this; } 215 216 // Create and add an option to a list, avoiding duplicates 217 function DOL_addNewOptionToList(a, text, value, defaultSelected) { 218 var o = new DOLOption(text,value,defaultSelected,false); 219 // Add the option to the array 220 if (a==null) { a = new Array(); } 221 for (var i=0; i<a.length; i++) { 222 if (a[i].text==o.text && a[i].value==o.value) { 223 if (o.selected) { 224 a[i].selected=true; 225 } 226 if (o.defaultSelected) { 227 a[i].defaultSelected = true; 228 } 229 return a; 230 } 231 } 232 a[a.length] = o; 233 } 234 235 // Add sub-options to the currently-selected node, with the same text and value for each option 236 function DOL_addOptions() { 237 if (this.currentNode==null) { this.currentNode = this; } 238 if (this.currentNode["options"] == null) { this.currentNode["options"] = new Array(); } 239 for (var i=0; i<arguments.length; i++) { 240 var text = arguments[i]; 241 this.addNewOptionToList(this.currentNode.options,text,text,false); 242 if (typeof(this.numberOfOptions[this.currentNodeDepth])=="undefined") { 243 this.numberOfOptions[this.currentNodeDepth]=0; 244 } 245 if (this.currentNode.options.length > this.numberOfOptions[this.currentNodeDepth]) { 246 this.numberOfOptions[this.currentNodeDepth] = this.currentNode.options.length; 247 } 248 if (typeof(this.longestString[this.currentNodeDepth])=="undefined" || (text.length > this.longestString[this.currentNodeDepth].length)) { 249 this.longestString[this.currentNodeDepth] = text; 250 } 251 } 252 this.currentNode = null; 253 this.currentNodeDepth = 0; 254 } 255 256 // Add sub-options to the currently-selected node, specifying separate text and values for each option 257 function DOL_addOptionsTextValue() { 258 if (this.currentNode==null) { this.currentNode = this; } 259 if (this.currentNode["options"] == null) { this.currentNode["options"] = new Array(); } 260 for (var i=0; i<arguments.length; i++) { 261 var text = arguments[i++]; 262 var value = arguments[i]; 263 this.addNewOptionToList(this.currentNode.options,text,value,false); 264 if (typeof(this.numberOfOptions[this.currentNodeDepth])=="undefined") { 265 this.numberOfOptions[this.currentNodeDepth]=0; 266 } 267 if (this.currentNode.options.length > this.numberOfOptions[this.currentNodeDepth]) { 268 this.numberOfOptions[this.currentNodeDepth] = this.currentNode.options.length; 269 } 270 if (typeof(this.longestString[this.currentNodeDepth])=="undefined" || (text.length > this.longestString[this.currentNodeDepth].length)) { 271 this.longestString[this.currentNodeDepth] = text; 272 } 273 } 274 this.currentNode = null; 275 this.currentNodeDepth = 0; 276 } 277 278 // Find the first dependent list of a select box 279 // If it's the last list in a chain, return null because there are no children 280 function DOL_child(obj) { 281 var listIndex = this.fieldListIndexes[obj.name]; 282 var index = this.fieldIndexes[obj.name]; 283 if (index < (this.fieldNames[listIndex].length-1)) { 284 return this.form[this.fieldNames[listIndex][index+1]]; 285 } 286 return null; 287 } 288 289 // Set the options which should be selected by default for a certain value in the parent 290 function DOL_setDefaultOptions() { 291 if (this.currentNode==null) { this.currentNode = this; } 292 for (var i=0; i<arguments.length; i++) { 293 var o = this.findMatchingOptionInArray(this.currentNode.options,null,arguments[i],false); 294 if (o!=null) { 295 o.defaultSelected = true; 296 } 297 } 298 this.currentNode = null; 299 } 300 301 // Set the options which should be selected when the page loads. This is different than the default value and ONLY applies when the page LOADS 302 function DOL_setValues() { 303 if (this.currentField==null) { 304 alert("Can't call setValues() without using forField() first!"); 305 return; 306 } 307 if (typeof(this.values[this.currentField])=="undefined") { 308 this.values[this.currentField] = new Object(); 309 } 310 for (var i=0; i<arguments.length; i++) { 311 this.values[this.currentField][arguments[i]] = true; 312 } 313 this.currentField = null; 314 } 315 316 // Manually set the form for the object using an index 317 function DOL_setFormIndex(i) { 318 this.formIndex = i; 319 } 320 321 // Manually set the form for the object using a form name 322 function DOL_setFormName(n) { 323 this.formName = n; 324 } 325 326 // Print blank <option> objects for Netscape4, since it refuses to grow or shrink select boxes for new options 327 function DOL_printOptions(name) { 328 // Only need to write out "dummy" options for Netscape4 329 if ((navigator.appName == 'Netscape') && (parseInt(navigator.appVersion) <= 4)){ 330 var index = this.fieldIndexes[name]; 331 var ret = ""; 332 if (typeof(this.numberOfOptions[index])!="undefined") { 333 for (var i=0; i<this.numberOfOptions[index]; i++) { 334 ret += "<OPTION>"; 335 } 336 } 337 ret += "<OPTION>"; 338 if (typeof(this.longestString[index])!="undefined") { 339 for (var i=0; i<this.longestString[index].length; i++) { 340 ret += "_"; 341 } 342 } 343 document.writeln(ret); 344 } 345 } 346 347 // Add a list of field names which use this option-mapping object. 348 // A single mapping object may be used by multiple sets of fields 349 function DOL_addDependentFields() { 350 for (var i=0; i<arguments.length; i++) { 351 this.fieldListIndexes[arguments[i].toString()] = this.fieldNames.length; 352 this.fieldIndexes[arguments[i].toString()] = i; 353 } 354 this.fieldNames[this.fieldNames.length] = arguments; 355 } 356 357 // Called when a parent select box is changed. It populates its direct child, then calls change on the child object to continue the population. 358 function DOL_change(obj, usePreselected) { 359 if (usePreselected==null || typeof(usePreselected)=="undefined") { usePreselected = false; } 360 var changedListIndex = this.fieldListIndexes[obj.name]; 361 var changedIndex = this.fieldIndexes[obj.name]; 362 var child = this.child(obj); 363 if (child == null) { return; } // No child, no need to continue 364 if (obj.type == "select-one") { 365 // Treat single-select differently so we don't have to scan the entire select list, which could potentially speed things up 366 if (child.options!=null) { 367 child.options.length=0; // Erase all the options from the child so we can re-populate 368 } 369 if (obj.options!=null && obj.options.length>0 && obj.selectedIndex>=0) { 370 var o = obj.options[obj.selectedIndex]; 371 this.populateChild(o.DOLOption,child,usePreselected); 372 this.selectChildOptions(child,usePreselected); 373 } 374 } 375 else if (obj.type == "select-multiple") { 376 // For each selected value in the parent, find the options to fill in for this list 377 // Loop through the child list and keep track of options that are currently selected 378 var currentlySelectedOptions = new Array(); 379 if (!usePreselected) { 380 for (var i=0; i<child.options.length; i++) { 381 var co = child.options[i]; 382 if (co.selected) { 383 this.addNewOptionToList(currentlySelectedOptions, co.text, co.value, co.defaultSelected); 384 } 385 } 386 } 387 child.options.length=0; 388 if (obj.options!=null) { 389 var obj_o = obj.options; 390 // For each selected option in the parent... 391 for (var i=0; i<obj_o.length; i++) { 392 if (obj_o[i].selected) { 393 // if option is selected, add its children to the list 394 this.populateChild(obj_o[i].DOLOption,child,usePreselected); 395 } 396 } 397 // Now go through and re-select any options which were selected before 398 var atLeastOneSelected = false; 399 if (!usePreselected) { 400 for (var i=0; i<child.options.length; i++) { 401 var m = this.findMatchingOptionInArray(currentlySelectedOptions,child.options[i].text,child.options[i].value,true); 402 if (m!=null) { 403 child.options[i].selected = true; 404 atLeastOneSelected = true; 405 } 406 } 407 } 408 if (!atLeastOneSelected) { 409 this.selectChildOptions(child,usePreselected); 410 } 411 } 412 } 413 // Change all the way down the chain 414 this.change(child,usePreselected); 415 } 416 function DOL_populateChild(dolOption,childSelectObj,usePreselected) { 417 // If this opton has sub-options, populate the child list with them 418 if (dolOption!=null && dolOption.options!=null) { 419 for (var j=0; j<dolOption.options.length; j++) { 420 var srcOpt = dolOption.options[j]; 421 if (childSelectObj.options==null) { childSelectObj.options = new Array(); } 422 // Put option into select list 423 var duplicate = false; 424 var preSelectedExists = false; 425 for (var k=0; k<childSelectObj.options.length; k++) { 426 var csi = childSelectObj.options[k]; 427 if (csi.text==srcOpt.text && csi.value==srcOpt.value) { 428 duplicate = true; 429 break; 430 } 431 } 432 if (!duplicate) { 433 var newopt = new Option(srcOpt.text, srcOpt.value, false, false); 434 newopt.selected = false; // Again, we have to do these two statements for NN4 to work 435 newopt.defaultSelected = false; 436 newopt.DOLOption = srcOpt; 437 childSelectObj.options[childSelectObj.options.length] = newopt; 438 } 439 } 440 } 441 } 442 443 // Once a child select is populated, go back over it to select options which should be selected 444 function DOL_selectChildOptions(obj,usePreselected) { 445 // Look to see if any options are preselected=true. If so, then set then selected if usePreselected=true, otherwise set defaults 446 var values = this.values[obj.name]; 447 var preselectedExists = false; 448 if (usePreselected && values!=null && typeof(values)!="undefined") { 449 for (var i=0; i<obj.options.length; i++) { 450 var v = obj.options[i].value; 451 if (v!=null && values[v]!=null && typeof(values[v])!="undefined") { 452 preselectedExists = true; 453 break; 454 } 455 } 456 } 457 // Go back over all the options to do the selection 458 var atLeastOneSelected = false; 459 for (var i=0; i<obj.options.length; i++) { 460 var o = obj.options[i]; 461 if (preselectedExists && o.value!=null && values[o.value]!=null && typeof(values[o.value])!="undefined") { 462 o.selected = true; 463 atLeastOneSelected = true; 464 } 465 else if (!preselectedExists && o.DOLOption!=null && o.DOLOption.defaultSelected) { 466 o.selected = true; 467 atLeastOneSelected = true; 468 } 469 else { 470 o.selected = false; 471 } 472 } 473 // If nothing else was selected, select the first one by default 474 if (this.selectFirstOption && !atLeastOneSelected && obj.options.length>0) { 475 obj.options[0].selected = true; 476 } 477 else if (!atLeastOneSelected && obj.type=="select-one") { 478 obj.selectedIndex = -1; 479 } 480 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Dec 30 05:55:15 2009 | Cross-referenced by PHPXref 0.7 |