1/* 2 * Copyright 2005 Joe Walker 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17/** 18 * Declare an object to which we can add real functions. 19 */ 20if (window['dojo']) dojo.provide('dwr.util'); 21if (typeof window['dwr'] == 'undefined') window.dwr = {}; 22if (typeof dwr['util'] == 'undefined') dwr.util = {}; 23//if (typeof window['DWRUtil'] == 'undefined') window.DWRUtil = dwr.util; 24 25/** @private The flag we use to decide if we should escape html */ 26dwr.util._escapeHtml = true; 27 28/** 29 * Set the global escapeHtml flag 30 */ 31dwr.util.setEscapeHtml = function(escapeHtml) { 32 dwr.util._escapeHtml = escapeHtml; 33}; 34 35/** @private Work out from an options list and global settings if we should be esccaping */ 36dwr.util._shouldEscapeHtml = function(options) { 37 if (options && options.escapeHtml != null) { 38 return options.escapeHtml; 39 } 40 return dwr.util._escapeHtml; 41}; 42 43/** 44 * Return a string with &, < and > replaced with their entities 45 * @see TODO 46 */ 47dwr.util.escapeHtml = function(original) { 48 return original.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/"/g,'"').replace(/'/g,'''); 49}; 50 51/** 52 * Replace common XML entities with characters (see dwr.util.escapeHtml()) 53 * @see TODO 54 */ 55dwr.util.unescapeHtml = function(original) { 56 return original.replace(/</g,'<').replace(/>/g,'>').replace(/"/g,'"').replace(/'/g,"'").replace(/&/g,'&'); 57}; 58 59/** 60 * Replace characters dangerous for XSS reasons with visually similar characters 61 * @see TODO 62 */ 63dwr.util.replaceXmlCharacters = function(original) { 64 original = original.replace("&", "+"); 65 original = original.replace("<", "\u2039"); 66 original = original.replace(">", "\u203A"); 67 original = original.replace("\'", "\u2018"); 68 original = original.replace("\"", "\u201C"); 69 return original; 70}; 71 72/** 73 * Return true iff the input string contains any XSS dangerous characters 74 * @see TODO 75 */ 76dwr.util.containsXssRiskyCharacters = function(original) { 77 return (original.indexOf('&') != -1 78 || original.indexOf('<') != -1 79 || original.indexOf('>') != -1 80 || original.indexOf('\'') != -1 81 || original.indexOf('\"') != -1); 82}; 83 84/** 85 * Enables you to react to return being pressed in an input 86 * @see http://getahead.org/dwr/browser/util/selectrange 87 */ 88dwr.util.onReturn = function(event, action) { 89 if (!event) event = window.event; 90 if (event && event.keyCode && event.keyCode == 13) action(); 91}; 92 93/** 94 * Select a specific range in a text box. Useful for 'google suggest' type functions. 95 * @see http://getahead.org/dwr/browser/util/selectrange 96 */ 97dwr.util.selectRange = function(ele, start, end) { 98 ele = dwr.util._getElementById(ele, "selectRange()"); 99 if (ele == null) return; 100 if (ele.setSelectionRange) { 101 ele.setSelectionRange(start, end); 102 } 103 else if (ele.createTextRange) { 104 var range = ele.createTextRange(); 105 range.moveStart("character", start); 106 range.moveEnd("character", end - ele.value.length); 107 range.select(); 108 } 109 ele.focus(); 110}; 111 112/** 113 * Find the element in the current HTML document with the given id or ids 114 * @see http://getahead.org/dwr/browser/util/$ 115 */ 116dwr.util.byId = function() { 117 var elems = []; 118 for (var i = 0; i < arguments.length; i++) { 119 var idOrElem = arguments[i]; 120 var elem; 121 if (typeof idOrElem == 'string') { 122 var elem = document.getElementById(idOrElem); 123 // Workaround for IE and Opera that may return element based on name 124 // (note use of elem.attributes.id.value due to IE bug for elem.getAttribute) 125 if (document.all && elem && elem.attributes.id.value != idOrElem) { 126 elem = null; 127 var maybeElems = document.all[idOrElem]; 128 if (maybeElems.tagName) maybeElems = [maybeElems]; 129 for (var j = 0; j < maybeElems.length; j++) { 130 if (maybeElems[j].attributes.id.value == idOrElem) { 131 elem = maybeElems[j]; 132 break; 133 } 134 } 135 } 136 } 137 else { 138 elem = idOrElem; 139 } 140 if (arguments.length == 1) { 141 return elem; 142 } 143 elems.push(elem); 144 } 145 return elems; 146} 147 148/** 149 * Alias $ to dwr.util.byId 150 * @see http://getahead.org/dwr/browser/util/$ 151 */ 152if (window['$'] == null) { 153 window['$'] = dwr.util.byId; 154} 155 156/** 157 * This function pretty-prints simple data or whole object graphs, f ex as an aid in debugging. 158 * @see http://getahead.org/dwr/browser/util/todescriptivestring 159 */ 160dwr.util.toDescriptiveString = function(data, showLevels, options) { 161 if (showLevels === undefined) showLevels = 1; 162 var opt = {}; 163 if (dwr.util._isObject(options)) opt = options; 164 var defaultoptions = { 165 escapeHtml:false, 166 baseIndent: "", 167 childIndent: "\u00A0\u00A0", 168 lineTerminator: "\n", 169 oneLineMaxItems: 5, 170 shortStringMaxLength: 13, 171 propertyNameMaxLength: 30 172 }; 173 for (var p in defaultoptions) { 174 if (!(p in opt)) { 175 opt[p] = defaultoptions[p]; 176 } 177 } 178 179 var skipDomProperties = { 180 document:true, ownerDocument:true, 181 all:true, 182 parentElement:true, parentNode:true, offsetParent:true, 183 children:true, firstChild:true, lastChild:true, 184 previousSibling:true, nextSibling:true, 185 innerHTML:true, outerHTML:true, 186 innerText:true, outerText:true, textContent:true, 187 attributes:true, 188 style:true, currentStyle:true, runtimeStyle:true, 189 parentTextEdit:true 190 }; 191 192 function recursive(data, showLevels, indentDepth, options) { 193 var reply = ""; 194 try { 195 // string 196 if (dwr.util._isString(data)) { 197 var str = data; 198 if (showLevels == 0 && str.length > options.shortStringMaxLength) 199 str = str.substring(0, options.shortStringMaxLength-3) + "..."; 200 if (options.escapeHtml) { 201 // Do the escape separately for every line as escapeHtml() on some 202 // browsers (IE) will strip line breaks and we want to preserve them 203 var lines = str.split("\n"); 204 for (var i = 0; i < lines.length; i++) lines[i] = dwr.util.escapeHtml(lines[i]); 205 str = lines.join("\n"); 206 } 207 if (showLevels == 0) { // Short format 208 str = str.replace(/\n|\r|\t/g, function(ch) { 209 switch (ch) { 210 case "\n": return "\\n"; 211 case "\r": return ""; 212 case "\t": return "\\t"; 213 } 214 }); 215 } 216 else { // Long format 217 str = str.replace(/\n|\r|\t/g, function(ch) { 218 switch (ch) { 219 case "\n": return options.lineTerminator + indent(indentDepth+1, options); 220 case "\r": return ""; 221 case "\t": return "\\t"; 222 } 223 }); 224 } 225 reply = '"' + str + '"'; 226 } 227 228 // function 229 else if (dwr.util._isFunction(data)) { 230 reply = "function"; 231 } 232 233 // Array 234 else if (dwr.util._isArrayLike(data)) { 235 if (showLevels == 0) { // Short format (don't show items) 236 if (data.length > 0) 237 reply = "[...]"; 238 else 239 reply = "[]"; 240 } 241 else { // Long format (show items) 242 var strarr = []; 243 strarr.push("["); 244 var count = 0; 245 for (var i = 0; i < data.length; i++) { 246 if (!(i in data) && data != "[object NodeList]") continue; 247 var itemvalue = data[i]; 248 if (count > 0) strarr.push(", "); 249 if (showLevels == 1) { // One-line format 250 if (count == options.oneLineMaxItems) { 251 strarr.push("..."); 252 break; 253 } 254 } 255 else { // Multi-line format 256 strarr.push(options.lineTerminator + indent(indentDepth+1, options)); 257 } 258 if (i != count) { 259 strarr.push(i); 260 strarr.push(":"); 261 } 262 strarr.push(recursive(itemvalue, showLevels-1, indentDepth+1, options)); 263 count++; 264 } 265 if (showLevels > 1) strarr.push(options.lineTerminator + indent(indentDepth, options)); 266 strarr.push("]"); 267 reply = strarr.join(""); 268 } 269 } 270 271 // Objects except Date 272 else if (dwr.util._isObject(data) && !dwr.util._isDate(data)) { 273 if (showLevels == 0) { // Short format (don't show properties) 274 reply = dwr.util._detailedTypeOf(data); 275 } 276 else { // Long format (show properties) 277 var strarr = []; 278 if (dwr.util._detailedTypeOf(data) != "Object") { 279 strarr.push(dwr.util._detailedTypeOf(data)); 280 if (typeof data.valueOf() != "object") { 281 strarr.push(":"); 282 strarr.push(recursive(data.valueOf(), 1, indentDepth, options)); 283 } 284 strarr.push(" "); 285 } 286 strarr.push("{"); 287 var isDomObject = dwr.util._isHTMLElement(data); 288 var count = 0; 289 for (var prop in data) { 290 var propvalue = data[prop]; 291 if (isDomObject) { 292 if (!propvalue) continue; 293 if (typeof propvalue == "function") continue; 294 if (skipDomProperties[prop]) continue; 295 if (prop.toUpperCase() == prop) continue; 296 } 297 if (count > 0) strarr.push(", "); 298 if (showLevels == 1) { // One-line format 299 if (count == options.oneLineMaxItems) { 300 strarr.push("..."); 301 break; 302 } 303 } 304 else { // Multi-line format 305 strarr.push(options.lineTerminator + indent(indentDepth+1, options)); 306 } 307 strarr.push(prop.length > options.propertyNameMaxLength ? prop.substring(0, options.propertyNameMaxLength-3) + "..." : prop); 308 strarr.push(":"); 309 strarr.push(recursive(propvalue, showLevels-1, indentDepth+1, options)); 310 count++; 311 } 312 if (showLevels > 1 && count > 0) strarr.push(options.lineTerminator + indent(indentDepth, options)); 313 strarr.push("}"); 314 reply = strarr.join(""); 315 } 316 } 317 318 // undefined, null, number, boolean, Date 319 else { 320 reply = "" + data; 321 } 322 323 return reply; 324 } 325 catch(err) { 326 return (err.message ? err.message : ""+err); 327 } 328 } 329 330 function indent(count, options) { 331 var strarr = []; 332 strarr.push(options.baseIndent); 333 for (var i=0; i<count; i++) { 334 strarr.push(options.childIndent); 335 } 336 return strarr.join(""); 337 }; 338 339 return recursive(data, showLevels, 0, opt); 340}; 341 342/** 343 * Setup a GMail style loading message. 344 * @see http://getahead.org/dwr/browser/util/useloadingmessage 345 */ 346dwr.util.useLoadingMessage = function(message) { 347 var loadingMessage; 348 if (message) loadingMessage = message; 349 else loadingMessage = "Loading"; 350 dwr.engine.setPreHook(function() { 351 var disabledZone = dwr.util.byId('disabledZone'); 352 if (!disabledZone) { 353 disabledZone = document.createElement('div'); 354 disabledZone.setAttribute('id', 'disabledZone'); 355 disabledZone.style.position = "absolute"; 356 disabledZone.style.zIndex = "1000";
357 disabledZone.style.left = "0px"; 358 disabledZone.style.top = "0px"; 359 disabledZone.style.width = "100%"; 360 disabledZone.style.height = "100%"; 361 // IE need a background color to block click. Use an invisible background. 362 if (window.ActiveXObject) { 363 disabledZone.style.background = "white"; 364 disabledZone.style.filter = "alpha(opacity=0)"; 365 } 366 document.body.appendChild(disabledZone); 367 var messageZone = document.createElement('div'); 368 messageZone.setAttribute('id', 'messageZone'); 369 messageZone.style.position = "absolute"; 370 messageZone.style.top = "0px"; 371 messageZone.style.right = "0px"; 372 messageZone.style.background = "red"; 373 messageZone.style.color = "white"; 374 messageZone.style.fontFamily = "Arial,Helvetica,sans-serif"; 375 messageZone.style.padding = "4px"; 376 document.body.appendChild(messageZone); 377 var text = document.createTextNode(loadingMessage); 378 messageZone.appendChild(text); 379 dwr.util._disabledZoneUseCount = 1; 380 } 381 else { 382 dwr.util.byId('messageZone').innerHTML = loadingMessage; 383 disabledZone.style.visibility = 'visible'; 384 dwr.util._disabledZoneUseCount++; 385 dwr.util.byId('messageZone').style.visibility = 'visible'; 386 } 387 }); 388 dwr.engine.setPostHook(function() { 389 dwr.util._disabledZoneUseCount--; 390 if (dwr.util._disabledZoneUseCount == 0) { 391 dwr.util.byId('disabledZone').style.visibility = 'hidden'; 392 dwr.util.byId('messageZone').style.visibility = 'hidden'; 393 } 394 }); 395}; 396 397/** 398 * Set a global highlight handler 399 */ 400dwr.util.setHighlightHandler = function(handler) { 401 dwr.util._highlightHandler = handler; 402}; 403 404/** 405 * An example highlight handler 406 */ 407dwr.util.yellowFadeHighlightHandler = function(ele) { 408 dwr.util._yellowFadeProcess(ele, 0); 409}; 410dwr.util._yellowFadeSteps = [ "d0", "b0", "a0", "90", "98", "a0", "a8", "b0", "b8", "c0", "c8", "d0", "d8", "e0", "e8", "f0", "f8" ]; 411dwr.util._yellowFadeProcess = function(ele, colorIndex) { 412 ele = dwr.util.byId(ele); 413 if (colorIndex < dwr.util._yellowFadeSteps.length) { 414 ele.style.backgroundColor = "#ffff" + dwr.util._yellowFadeSteps[colorIndex]; 415 setTimeout("dwr.util._yellowFadeProcess('" + ele.id + "'," + (colorIndex + 1) + ")", 200); 416 } 417 else { 418 ele.style.backgroundColor = "transparent"; 419 } 420}; 421 422/** 423 * An example highlight handler 424 */ 425dwr.util.borderFadeHighlightHandler = function(ele) { 426 ele.style.borderWidth = "2px"; 427 ele.style.borderStyle = "solid"; 428 dwr.util._borderFadeProcess(ele, 0); 429}; 430dwr.util._borderFadeSteps = [ "d0", "b0", "a0", "90", "98", "a0", "a8", "b0", "b8", "c0", "c8", "d0", "d8", "e0", "e8", "f0", "f8" ]; 431dwr.util._borderFadeProcess = function(ele, colorIndex) { 432 ele = dwr.util.byId(ele); 433 if (colorIndex < dwr.util._borderFadeSteps.length) { 434 ele.style.borderColor = "#ff" + dwr.util._borderFadeSteps[colorIndex] + dwr.util._borderFadeSteps[colorIndex]; 435 setTimeout("dwr.util._borderFadeProcess('" + ele.id + "'," + (colorIndex + 1) + ")", 200); 436 } 437 else { 438 ele.style.backgroundColor = "transparent"; 439 } 440}; 441 442/** 443 * A focus highlight handler 444 */ 445dwr.util.focusHighlightHandler = function(ele) { 446 try { 447 ele.focus(); 448 } 449 catch (ex) { /* ignore */ } 450}; 451 452/** @private the current global highlight style */ 453dwr.util._highlightHandler = null; 454 455/** 456 * Highlight that an element has changed 457 */ 458dwr.util.highlight = function(ele, options) { 459 if (options && options.highlightHandler) { 460 options.highlightHandler(dwr.util.byId(ele)); 461 } 462 else if (dwr.util._highlightHandler != null) { 463 dwr.util._highlightHandler(dwr.util.byId(ele)); 464 } 465}; 466 467/** 468 * Set the value an HTML element to the specified value. 469 * @see http://getahead.org/dwr/browser/util/setvalue 470 */ 471dwr.util.setValue = function(ele, val, options) { 472 if (val == null) val = ""; 473 if (options == null) options = {}; 474 475 var orig = ele; 476 ele = dwr.util.byId(ele); // Returns null if argument is a name, even on IE 477 var nodes = null; 478 if (ele == null) { 479 // Now it is time to look by name 480 nodes = document.getElementsByName(orig); 481 if (nodes.length >= 1) ele = nodes.item(0); 482 } 483 484 if (ele == null) { 485 dwr.util._debug("setValue() can't find an element with id/name: " + orig + "."); 486 return; 487 } 488 489 // All paths now lead to some update so we highlight a change 490 dwr.util.highlight(ele, options); 491 492 if (dwr.util._isHTMLElement(ele, "select")) { 493 if (ele.type == "select-multiple" && dwr.util._isArray(val)) dwr.util._selectListItems(ele, val); 494 else dwr.util._selectListItem(ele, val); 495 return; 496 } 497 498 if (dwr.util._isHTMLElement(ele, "input")) { 499 if (ele.type == "radio" || ele.type == "checkbox") { 500 if (nodes && nodes.length >= 1) { 501 for (var i = 0; i < nodes.length; i++) { 502 var node = nodes.item(i); 503 if (node.type != ele.type) continue; 504 if (dwr.util._isArray(val)) { 505 node.checked = false;
506 for (var j = 0; j < val.length; j++) 507 if (val[j] == node.value) node.checked = true; 508 } 509 else { 510 node.checked = (node.value == val); 511 } 512 } 513 } 514 else { 515 ele.checked = (val == true); 516 } 517 } 518 else ele.value = val; 519 520 return; 521 } 522 523 if (dwr.util._isHTMLElement(ele, "textarea")) { 524 ele.value = val; 525 return; 526 } 527 528 if (dwr.util._isHTMLElement(ele, "img")) { 529 ele.src = val; 530 return; 531 } 532 533 // If the value to be set is a DOM object then we try importing the node 534 // rather than serializing it out 535 if (val.nodeType) { 536 if (val.nodeType == 9 /*Node.DOCUMENT_NODE*/) val = val.documentElement; 537 val = dwr.util._importNode(ele.ownerDocument, val, true); 538 ele.appendChild(val); 539 return; 540 } 541 542 // Fall back to innerHTML and friends 543 if (dwr.util._shouldEscapeHtml(options)) { 544 if ("textContent" in ele) ele.textContent = val.toString(); 545 else if ("innerText" in ele) ele.innerText = val.toString(); 546 else ele.innerHTML = dwr.util.escapeHtml(val.toString()); 547 } 548 else { 549 ele.innerHTML = val; 550 } 551}; 552 553/** 554 * @private Find multiple items in a select list and select them. Used by setValue() 555 * @param ele The select list item 556 * @param val The array of values to select 557 */ 558dwr.util._selectListItems = function(ele, val) { 559 // We deal with select list elements by selecting the matching option 560 // Begin by searching through the values 561 var found = 0; 562 var i; 563 var j; 564 for (i = 0; i < ele.options.length; i++) { 565 ele.options[i].selected = false; 566 for (j = 0; j < val.length; j++) { 567 if (ele.options[i].value == val[j]) { 568 ele.options[i].selected = true; 569 found++; 570 } 571 } 572 } 573 // If that fails then try searching through the visible text 574 if (found == val.length) return; 575 576 for (i = 0; i < ele.options.length; i++) { 577 for (j = 0; j < val.length; j++) { 578 if (ele.options[i].text == val[j]) { 579 ele.options[i].selected = true; 580 } 581 } 582 } 583}; 584 585/** 586 * @private Find an item in a select list and select it. Used by setValue() 587 * @param ele The select list item 588 * @param val The value to select 589 */ 590dwr.util._selectListItem = function(ele, val) { 591 // We deal with select list elements by selecting the matching option 592 // Begin by searching through the values 593 var found = false; 594 var i; 595 for (i = 0; i < ele.options.length; i++) { 596 if (ele.options[i].value == val) { 597 ele.options[i].selected = true; 598 found = true; 599 } 600 else { 601 ele.options[i].selected = false; 602 } 603 } 604 605 // If that fails then try searching through the visible text 606 if (found) return; 607 608 for (i = 0; i < ele.options.length; i++) { 609 ele.options[i].selected = (ele.options[i].text == val); 610 } 611}; 612 613/** 614 * Read the current value for a given HTML element. 615 * @see http://getahead.org/dwr/browser/util/getvalue 616 */ 617dwr.util.getValue = function(ele, options) { 618 if (options == null) options = {}; 619 var orig = ele; 620 ele = dwr.util.byId(ele); // Returns null if argument is a name, even on IE 621 var nodes = null; 622 if (ele == null) { 623 // Now it is time to look by name 624 nodes = document.getElementsByName(orig); 625 if (nodes.length >= 1) ele = nodes.item(0); 626 } 627 if (ele == null) { 628 dwr.util._debug("getValue() can't find an element with id/name: " + orig + "."); 629 return ""; 630 } 631 632 if (dwr.util._isHTMLElement(ele, "select")) { 633 // Using "type" property instead of "multiple" as "type" is an official 634 // client-side property since JS 1.1 635 if (ele.type == "select-multiple") { 636 var reply = new Array(); 637 for (var i = 0; i < ele.options.length; i++) { 638 var item = ele.options[i]; 639 if (item.selected) { 640 var valueAttr = item.getAttributeNode("value"); 641 if (valueAttr && valueAttr.specified) { 642 reply.push(item.value); 643 } 644 else { 645 reply.push(item.text); 646 } 647 } 648 } 649 return reply; 650 } 651 else { 652 var sel = ele.selectedIndex; 653 if (sel != -1) { 654 var item = ele.options[sel]; 655 var valueAttr = item.getAttributeNode("value"); 656 if (valueAttr && valueAttr.specified) { 657 return item.value; 658 } 659 return item.text; 660 } 661 else { 662 return ""; 663 } 664 } 665 } 666 667 if (dwr.util._isHTMLElement(ele, "input")) { 668 if (ele.type == "radio") { 669 if (nodes && nodes.length >= 1) { 670 for (var i = 0; i < nodes.length; i++) { 671 var node = nodes.item(i); 672 if (node.type == ele.type) { 673 if (node.checked) return node.value; 674 } 675 } 676 } 677 return ele.checked; 678 } 679 if (ele.type == "checkbox") { 680 if (nodes && nodes.length >= 1) { 681 var reply = []; 682 for (var i = 0; i < nodes.length; i++) { 683 var node = nodes.item(i); 684 if (node.type == ele.type) { 685 if (node.checked) reply.push(node.value); 686 } 687 } 688 return reply; 689 } 690 return ele.checked; 691 } 692 if (ele.type == "file") { 693 return ele; 694 } 695 return ele.value; 696 } 697 698 if (dwr.util._isHTMLElement(ele, "textarea")) { 699 return ele.value; 700 } 701 702 if (dwr.util._shouldEscapeHtml(options)) { 703 if (ele.textContent) return ele.textContent; 704 else if (ele.innerText) return ele.innerText; 705 } 706 return ele.innerHTML; 707}; 708 709/** 710 * getText() is like getValue() except that it reads the text (and not the value) from select elements 711 * @see http://getahead.org/dwr/browser/util/gettext 712 */ 713dwr.util.getText = function(ele) { 714 ele = dwr.util._getElementById(ele, "getText()"); 715 if (ele == null) return null; 716 if (!dwr.util._isHTMLElement(ele, "select")) { 717 dwr.util._debug("getText() can only be used with select elements. Attempt to use: " + dwr.util._detailedTypeOf(ele) + " from id: " + orig + "."); 718 return ""; 719 } 720 721 // This is a bit of a scam because it assumes single select 722 // but I'm not sure how we should treat multi-select. 723 var sel = ele.selectedIndex; 724 if (sel != -1) { 725 return ele.options[sel].text; 726 } 727 else { 728 return ""; 729 } 730}; 731 732/** 733 * Given a map, or a recursive structure consisting of arrays and maps, call 734 * setValue() for all leaf entries and use intermediate levels to form nested 735 * element ids. 736 * @see http://getahead.org/dwr/browser/util/setvalues 737 */ 738dwr.util.setValues = function(data, options) { 739 var prefix = ""; 740 var depth = 100; 741 if (options && options.prefix) prefix = options.prefix; 742 if (options && options.idPrefix) prefix = options.idPrefix; 743 if (options && "depth" in options) depth = options.depth; 744 dwr.util._setValuesRecursive(data, prefix, depth, options); 745}; 746 747/** 748 * @private Recursive helper for setValues() 749 */ 750dwr.util._setValuesRecursive = function(data, idpath, depth, options) { 751 if (depth == 0) return; 752 // Array containing objects -> add "[n]" to prefix and make recursive call 753 // for each item object 754 if (dwr.util._isArray(data) && data.length > 0 && dwr.util._isObject(data[0])) { 755 for (var i = 0; i < data.length; i++) { 756 dwr.util._setValuesRecursive(data[i], idpath+"["+i+"]", depth-1, options); 757 } 758 } 759 // Object (not array) -> handle nested object properties 760 else if (dwr.util._isObject(data) && !dwr.util._isArray(data)) { 761 for (var prop in data) { 762 var subidpath = idpath ? idpath+"."+prop : prop; 763 // Object (not array), or array containing objects -> call ourselves recursively 764 if (dwr.util._isObject(data[prop]) && !dwr.util._isArray(data[prop]) && !dwr.util._isDate(data[prop]) 765 || dwr.util._isArray(data[prop]) && data[prop].length > 0 && dwr.util._isObject(data[prop][0])) { 766 dwr.util._setValuesRecursive(data[prop], subidpath, depth-1, options); 767 } 768 // Functions -> skip 769 else if (typeof data[prop] == "function") { 770 // NOP 771 } 772 // Only simple values left (or array of simple values, or empty array) 773 // -> call setValue() 774 else { 775 // Are there any elements with that id or name 776 if (dwr.util.byId(subidpath) != null || document.getElementsByName(subidpath).length >= 1) { 777 dwr.util.setValue(subidpath, data[prop], options); 778 } 779 } 780 } 781 } 782}; 783 784/** 785 * Given a map, or a recursive structure consisting of arrays and maps, call 786 * getValue() for all leaf entries and use intermediate levels to form nested 787 * element ids. 788 * Given a string or element that refers to a form, create an object from the 789 * elements of the form. 790 * @see http://getahead.org/dwr/browser/util/getvalues 791 */ 792dwr.util.getValues = function(data, options) { 793 if (typeof data == "string" || dwr.util._isHTMLElement(data)) { 794 return dwr.util.getFormValues(data); 795 } 796 else { 797 var prefix = ""; 798 var depth = 100; 799 if (options != null && options.prefix) prefix = options.prefix; 800 if (options != null && options.idPrefix) prefix = options.idPrefix; 801 if (options != null && "depth" in options) depth = options.depth; 802 dwr.util._getValuesRecursive(data, prefix, depth, options); 803 return data; 804 } 805}; 806 807/** 808 * Given a string or element that refers to a form, create an object from the 809 * elements of the form. 810 * @see http://getahead.org/dwr/browser/util/getvalues 811 */ 812dwr.util.getFormValues = function(eleOrNameOrId) { 813 var ele = null; 814 if (typeof eleOrNameOrId == "string") { 815 ele = document.forms[eleOrNameOrId]; // arg is name 816 if (ele == null) ele = dwr.util.byId(eleOrNameOrId); // arg is id 817 } 818 else if (dwr.util._isHTMLElement(eleOrNameOrId)) { 819 ele = eleOrNameOrId; // arg is element 820 } 821 if (ele != null) { 822 if (ele.elements == null) { 823 alert("getFormValues() requires an object or reference to a form element."); 824 return null; 825 } 826 var reply = {}; 827 var name; 828 var value; 829 for (var i = 0; i < ele.elements.length; i++) { 830 if (ele[i].type in {button:0,submit:0,reset:0,image:0,file:0}) continue; 831 if (ele[i].name) { 832 name = ele[i].name; 833 value = dwr.util.getValue(name); 834 } 835 else { 836 if (ele[i].id) name = ele[i].id; 837 else name = "element" + i; 838 value = dwr.util.getValue(ele[i]); 839 } 840 reply[name] = value; 841 } 842 return reply; 843 } 844}; 845 846/** 847 * @private Recursive helper for getValues(). 848 */ 849dwr.util._getValuesRecursive = function(data, idpath, depth, options) { 850 if (depth == 0) return; 851 // Array containing objects -> add "[n]" to idpath and make recursive call 852 // for each item object 853 if (dwr.util._isArray(data) && data.length > 0 && dwr.util._isObject(data[0])) { 854 for (var i = 0; i < data.length; i++) { 855 dwr.util._getValuesRecursive(data[i], idpath+"["+i+"]", depth-1, options); 856 } 857 } 858 // Object (not array) -> handle nested object properties 859 else if (dwr.util._isObject(data) && !dwr.util._isArray(data)) { 860 for (var prop in data) { 861 var subidpath = idpath ? idpath+"."+prop : prop; 862 // Object, or array containing objects -> call ourselves recursively 863 if (dwr.util._isObject(data[prop]) && !dwr.util._isArray(data[prop]) 864 || dwr.util._isArray(data[prop]) && data[prop].length > 0 && dwr.util._isObject(data[prop][0])) { 865 dwr.util._getValuesRecursive(data[prop], subidpath, depth-1, options); 866 } 867 // Functions -> skip 868 else if (typeof data[prop] == "function") { 869 // NOP 870 } 871 // Only simple values left (or array of simple values, or empty array) 872 // -> call getValue() 873 else { 874 // Are there any elements with that id or name 875 if (dwr.util.byId(subidpath) != null || document.getElementsByName(subidpath).length >= 1) { 876 data[prop] = dwr.util.getValue(subidpath); 877 } 878 } 879 } 880 } 881}; 882 883/** 884 * Add options to a list from an array or map.
885 * @see http://getahead.org/dwr/browser/lists 886 */ 887dwr.util.addOptions = function(ele, data/*, options*/) { 888 ele = dwr.util._getElementById(ele, "addOptions()"); 889 if (ele == null) return; 890 var useOptions = dwr.util._isHTMLElement(ele, "select"); 891 var useLi = dwr.util._isHTMLElement(ele, ["ul", "ol"]); 892 if (!useOptions && !useLi) { 893 dwr.util._debug("addOptions() can only be used with select/ul/ol elements. Attempt to use: " + dwr.util._detailedTypeOf(ele)); 894 return; 895 } 896 if (data == null) return; 897 898 var argcount = arguments.length; 899 var options = {}; 900 var lastarg = arguments[argcount - 1]; 901 if (argcount > 2 && dwr.util._isObject(lastarg)) { 902 options = lastarg; 903 argcount--; 904 } 905 var arg3 = null; if (argcount >= 3) arg3 = arguments[2]; 906 var arg4 = null; if (argcount >= 4) arg4 = arguments[3]; 907 if (!options.optionCreator && useOptions) options.optionCreator = dwr.util._defaultOptionCreator; 908 if (!options.optionCreator && useLi) options.optionCreator = dwr.util._defaultListItemCreator; 909 options.document = ele.ownerDocument; 910 911 var text, value, li; 912 if (dwr.util._isArray(data)) { 913 // Loop through the data that we do have 914 for (var i = 0; i < data.length; i++) { 915 options.data = data[i]; 916 options.text = null; 917 options.value = null; 918 if (useOptions) { 919 if (arg3 != null) { 920 if (arg4 != null) { 921 options.text = dwr.util._getValueFrom(data[i], arg4); 922 options.value = dwr.util._getValueFrom(data[i], arg3); 923 } 924 else options.text = options.value = dwr.util._getValueFrom(data[i], arg3); 925 } 926 else options.text = options.value = dwr.util._getValueFrom(data[i]); 927 928 if (options.text != null || options.value) { 929 var opt = options.optionCreator(options); 930 opt.text = options.text; 931 opt.value = options.value; 932 ele.options[ele.options.length] = opt; 933 } 934 } 935 else { 936 options.value = dwr.util._getValueFrom(data[i], arg3); 937 if (options.value != null) { 938 li = options.optionCreator(options); 939 if (dwr.util._shouldEscapeHtml(options)) { 940 options.value = dwr.util.escapeHtml(options.value); 941 } 942 li.innerHTML = options.value; 943 ele.appendChild(li); 944 } 945 } 946 } 947 } 948 else if (arg4 != null) { 949 if (!useOptions) { 950 alert("dwr.util.addOptions can only create select lists from objects."); 951 return; 952 } 953 for (var prop in data) { 954 options.data = data[prop]; 955 options.value = dwr.util._getValueFrom(data[prop], arg3); 956 options.text = dwr.util._getValueFrom(data[prop], arg4); 957 958 if (options.text != null || options.value) { 959 var opt = options.optionCreator(options); 960 opt.text = options.text; 961 opt.value = options.value; 962 ele.options[ele.options.length] = opt; 963 } 964 } 965 } 966 else { 967 if (!useOptions) { 968 dwr.util._debug("dwr.util.addOptions can only create select lists from objects."); 969 return; 970 } 971 for (var prop in data) { 972 if (typeof data[prop] == "function") continue; 973 options.data = data[prop]; 974 if (!arg3) { 975 options.value = prop; 976 options.text = data[prop]; 977 } 978 else { 979 options.value = data[prop]; 980 options.text = prop; 981 } 982 if (options.text != null || options.value) { 983 var opt = options.optionCreator(options); 984 opt.text = options.text; 985 opt.value = options.value; 986 ele.options[ele.options.length] = opt; 987 } 988 } 989 } 990 991 // All error routes through this function result in a return, so highlight now 992 dwr.util.highlight(ele, options); 993}; 994 995/** 996 * @private Get the data from an array function for dwr.util.addOptions 997 */ 998dwr.util._getValueFrom = function(data, method) { 999 if (method == null) return data; 1000 else if (typeof method == 'function') return method(data); 1001 else return data[method]; 1002}; 1003 1004/** 1005 * @private Default option creation function 1006 */ 1007dwr.util._defaultOptionCreator = function(options) { 1008 return options.document.createElement("option"); 1009}; 1010 1011/** 1012 * @private Default list item creation function 1013 */ 1014dwr.util._defaultListItemCreator = function(options) { 1015 return options.document.createElement("li"); 1016}; 1017 1018/** 1019 * Remove all the options from a select list (specified by id) 1020 * @see http://getahead.org/dwr/browser/lists 1021 */ 1022dwr.util.removeAllOptions = function(ele) { 1023 ele = dwr.util._getElementById(ele, "removeAllOptions()"); 1024 if (ele == null) return; 1025 var useOptions = dwr.util._isHTMLElement(ele, "select"); 1026 var useLi = dwr.util._isHTMLElement(ele, ["ul", "ol"]); 1027 if (!useOptions && !useLi) { 1028 dwr.util._debug("removeAllOptions() can only be used with select, ol and ul elements. Attempt to use: " + dwr.util._detailedTypeOf(ele)); 1029 return; 1030 } 1031 if (useOptions) { 1032 ele.options.length = 0; 1033 } 1034 else { 1035 while (ele.childNodes.length > 0) { 1036 ele.removeChild(ele.firstChild); 1037 } 1038 } 1039}; 1040 1041/** 1042 * Create rows inside a the table, tbody, thead or tfoot element (given by id).
1043 * @see http://getahead.org/dwr/browser/tables 1044 */ 1045dwr.util.addRows = function(ele, data, cellFuncs, options) { 1046 ele = dwr.util._getElementById(ele, "addRows()"); 1047 if (ele == null) return; 1048 if (!dwr.util._isHTMLElement(ele, ["table", "tbody", "thead", "tfoot"])) { 1049 dwr.util._debug("addRows() can only be used with table, tbody, thead and tfoot elements. Attempt to use: " + dwr.util._detailedTypeOf(ele)); 1050 return; 1051 } 1052 if (!options) options = {}; 1053 if (!options.rowCreator) options.rowCreator = dwr.util._defaultRowCreator; 1054 if (!options.cellCreator) options.cellCreator = dwr.util._defaultCellCreator; 1055 options.document = ele.ownerDocument; 1056 var tr, rowNum; 1057 if (dwr.util._isArray(data)) { 1058 for (rowNum = 0; rowNum < data.length; rowNum++) { 1059 options.rowData = data[rowNum]; 1060 options.rowIndex = rowNum; 1061 options.rowNum = rowNum; 1062 options.data = null; 1063 options.cellNum = -1; 1064 tr = dwr.util._addRowInner(cellFuncs, options); 1065 if (tr != null) ele.appendChild(tr); 1066 } 1067 } 1068 else if (typeof data == "object") { 1069 rowNum = 0; 1070 for (var rowIndex in data) { 1071 options.rowData = data[rowIndex]; 1072 options.rowIndex = rowIndex; 1073 options.rowNum = rowNum; 1074 options.data = null; 1075 options.cellNum = -1; 1076 tr = dwr.util._addRowInner(cellFuncs, options); 1077 if (tr != null) ele.appendChild(tr); 1078 rowNum++; 1079 } 1080 } 1081 1082 dwr.util.highlight(ele, options); 1083}; 1084 1085/** 1086 * @private The contents we put in empty table cells to workaround IE's border bug. 1087 */ 1088dwr.util._emptyTableCellReplacement = "<div style='width:0;height:0;overflow:hidden;'></div>"; 1089 1090/** 1091 * @private Internal function to draw a single row of a table. 1092 */ 1093dwr.util._addRowInner = function(cellFuncs, options) { 1094 var tr = options.rowCreator(options); 1095 if (tr == null) return null; 1096 for (var cellNum = 0; cellNum < cellFuncs.length; cellNum++) { 1097 var func = cellFuncs[cellNum]; 1098 if (typeof func == 'function') options.data = func(options.rowData, options); 1099 else options.data = func || ""; 1100 options.cellNum = cellNum; 1101 var td = options.cellCreator(options); 1102 if (td != null) { 1103 if (options.data) { 1104 if (dwr.util._isHTMLElement(options.data)) td.appendChild(options.data); 1105 else { 1106 if (dwr.util._shouldEscapeHtml(options) && typeof(options.data) == "string") { 1107 td.innerHTML = dwr.util.escapeHtml(options.data); 1108 } 1109 else { 1110 td.innerHTML = options.data; 1111 } 1112 } 1113 } 1114 else { 1115 td.innerHTML = dwr.util._emptyTableCellReplacement; 1116 } 1117 tr.appendChild(td); 1118 } 1119 } 1120 return tr; 1121}; 1122 1123/** 1124 * @private Default row creation function 1125 */ 1126dwr.util._defaultRowCreator = function(options) { 1127 return options.document.createElement("tr"); 1128}; 1129 1130/** 1131 * @private Default cell creation function 1132 */ 1133dwr.util._defaultCellCreator = function(options) { 1134 return options.document.createElement("td"); 1135}; 1136 1137/** 1138 * Remove all the children of a given node. 1139 * @see http://getahead.org/dwr/browser/tables 1140 */ 1141dwr.util.removeAllRows = function(ele, options) { 1142 ele = dwr.util._getElementById(ele, "removeAllRows()"); 1143 if (ele == null) return; 1144 if (!options) options = {}; 1145 if (!options.filter) options.filter = function() { return true; }; 1146 if (!dwr.util._isHTMLElement(ele, ["table", "tbody", "thead", "tfoot"])) { 1147 dwr.util._debug("removeAllRows() can only be used with table, tbody, thead and tfoot elements. Attempt to use: " + dwr.util._detailedTypeOf(ele)); 1148 return; 1149 } 1150 var child = ele.firstChild; 1151 var next; 1152 while (child != null) { 1153 next = child.nextSibling; 1154 if (options.filter(child)) { 1155 ele.removeChild(child); 1156 } 1157 child = next; 1158 } 1159}; 1160 1161/** 1162 * dwr.util.byId(ele).className = "X", that we can call from Java easily. 1163 */ 1164dwr.util.setClassName = function(ele, className) { 1165 ele = dwr.util._getElementById(ele, "setClassName()"); 1166 if (ele == null) return; 1167 ele.className = className; 1168}; 1169 1170/** 1171 * dwr.util.byId(ele).className += "X", that we can call from Java easily. 1172 */ 1173dwr.util.addClassName = function(ele, className) { 1174 ele = dwr.util._getElementById(ele, "addClassName()"); 1175 if (ele == null) return; 1176 ele.className += " " + className; 1177}; 1178 1179/** 1180 * dwr.util.byId(ele).className -= "X", that we can call from Java easily 1181 * From code originally by Gavin Kistner 1182 */ 1183dwr.util.removeClassName = function(ele, className) { 1184 ele = dwr.util._getElementById(ele, "removeClassName()"); 1185 if (ele == null) return; 1186 var regex = new RegExp("(^|\\s)" + className + "(\\s|$)", 'g'); 1187 ele.className = ele.className.replace(regex, ''); 1188}; 1189 1190/** 1191 * dwr.util.byId(ele).className |= "X", that we can call from Java easily. 1192 */ 1193dwr.util.toggleClassName = function(ele, className) { 1194 ele = dwr.util._getElementById(ele, "toggleClassName()"); 1195 if (ele == null) return; 1196 var regex = new RegExp("(^|\\s)" + className + "(\\s|$)"); 1197 if (regex.test(ele.className)) { 1198 ele.className = ele.className.replace(regex, ''); 1199 } 1200 else { 1201 ele.className += " " + className; 1202 } 1203}; 1204 1205/** 1206 * Clone a node and insert it into the document just above the 'template' node 1207 * @see http://getahead.org/dwr/??? 1208 */ 1209dwr.util.cloneNode = function(ele, options) { 1210 ele = dwr.util._getElementById(ele, "cloneNode()"); 1211 if (ele == null) return null; 1212 if (options == null) options = {}; 1213 var clone = ele.cloneNode(true); 1214 if (options.idPrefix || options.idSuffix) { 1215 dwr.util._updateIds(clone, options); 1216 } 1217 else { 1218 dwr.util._removeIds(clone); 1219 } 1220 ele.parentNode.insertBefore(clone, ele); 1221 return clone; 1222}; 1223 1224/** 1225 * @private Update all of the ids in an element tree 1226 */ 1227dwr.util._updateIds = function(ele, options) { 1228 if (options == null) options = {}; 1229 if (ele.id) { 1230 ele.setAttribute("id", (options.idPrefix || "") + ele.id + (options.idSuffix || "")); 1231 } 1232 var children = ele.childNodes; 1233 for (var i = 0; i < children.length; i++) { 1234 var child = children.item(i); 1235 if (child.nodeType == 1 /*Node.ELEMENT_NODE*/) { 1236 dwr.util._updateIds(child, options); 1237 } 1238 } 1239}; 1240 1241/** 1242 * @private Remove all the Ids from an element 1243 */ 1244dwr.util._removeIds = function(ele) { 1245 if (ele.id) ele.removeAttribute("id"); 1246 var children = ele.childNodes; 1247 for (var i = 0; i < children.length; i++) { 1248 var child = children.item(i); 1249 if (child.nodeType == 1 /*Node.ELEMENT_NODE*/) { 1250 dwr.util._removeIds(child); 1251 } 1252 } 1253}; 1254 1255/** 1256 * Clone a template node and its embedded template child nodes according to 1257 * cardinalities (of arrays) in supplied data. 1258 */ 1259dwr.util.cloneNodeForValues = function(templateEle, data, options) { 1260 templateEle = dwr.util._getElementById(templateEle, "cloneNodeForValues()"); 1261 if (templateEle == null) return null; 1262 if (options == null) options = {}; 1263 var idpath; 1264 if (options.idPrefix != null) 1265 idpath = options.idPrefix; 1266 else 1267 idpath = templateEle.id || ""; 1268 return dwr.util._cloneNodeForValuesRecursive(templateEle, data, idpath, options); 1269}; 1270 1271/** 1272 * @private Recursive helper for cloneNodeForValues(). 1273 */ 1274dwr.util._cloneNodeForValuesRecursive = function(templateEle, data, idpath, options) { 1275 // Incoming array -> make an id for each item and call clone of the template 1276 // for each of them 1277 if (dwr.util._isArray(data)) { 1278 var clones = []; 1279 for (var i = 0; i < data.length; i++) { 1280 var item = data[i]; 1281 var clone = dwr.util._cloneNodeForValuesRecursive(templateEle, item, idpath + "[" + i + "]", options); 1282 clones.push(clone); 1283 } 1284 return clones; 1285 } 1286 else 1287 // Incoming object (not array) -> clone the template, add id prefixes, add 1288 // clone to DOM, and then recurse into any array properties if they contain 1289 // objects and there is a suitable template 1290 if (dwr.util._isObject(data) && !dwr.util._isArray(data)) { 1291 var clone = templateEle.cloneNode(true); 1292 if (options.updateCloneStyle && clone.style) { 1293 for (var propname in options.updateCloneStyle) { 1294 clone.style[propname] = options.updateCloneStyle[propname]; 1295 } 1296 } 1297 dwr.util._replaceIds(clone, templateEle.id, idpath); 1298 templateEle.parentNode.insertBefore(clone, templateEle); 1299 dwr.util._cloneSubArrays(data, idpath, options); 1300 return clone; 1301 } 1302 1303 // It is an error to end up here so we return nothing 1304 return null; 1305}; 1306 1307/** 1308 * @private Substitute a leading idpath fragment with another idpath for all 1309 * element ids tree, and remove ids that don't match the idpath. 1310 */ 1311dwr.util._replaceIds = function(ele, oldidpath, newidpath) { 1312 if (ele.id) { 1313 var newId = null; 1314 if (ele.id == oldidpath) { 1315 newId = newidpath; 1316 } 1317 else if (ele.id.length > oldidpath.length) { 1318 if (ele.id.substr(0, oldidpath.length) == oldidpath) { 1319 var trailingChar = ele.id.charAt(oldidpath.length); 1320 if (trailingChar == "." || trailingChar == "[") { 1321 newId = newidpath + ele.id.substr(oldidpath.length); 1322 } 1323 } 1324 } 1325 if (newId) { 1326 ele.setAttribute("id", newId); 1327 } 1328 else { 1329 ele.removeAttribute("id"); 1330 } 1331 } 1332 var children = ele.childNodes; 1333 for (var i = 0; i < children.length; i++) { 1334 var child = children.item(i); 1335 if (child.nodeType == 1 /*Node.ELEMENT_NODE*/) { 1336 dwr.util._replaceIds(child, oldidpath, newidpath); 1337 } 1338 } 1339}; 1340 1341/** 1342 * @private Finds arrays in supplied data and uses any corresponding template 1343 * node to make a clone for each item in the array. 1344 */ 1345dwr.util._cloneSubArrays = function(data, idpath, options) { 1346 for (prop in data) { 1347 var value = data[prop]; 1348 // Look for potential recursive cloning in all array properties 1349 if (dwr.util._isArray(value)) { 1350 // Only arrays with objects are interesting for cloning 1351 if (value.length > 0 && dwr.util._isObject(value[0])) { 1352 var subTemplateId = idpath + "." + prop; 1353 var subTemplateEle = dwr.util.byId(subTemplateId); 1354 if (subTemplateEle != null) { 1355 dwr.util._cloneNodeForValuesRecursive(subTemplateEle, value, subTemplateId, options); 1356 } 1357 } 1358 } 1359 // Continue looking for arrays in object properties 1360 else if (dwr.util._isObject(value)) { 1361 dwr.util._cloneSubArrays(value, idpath + "." + prop, options); 1362 } 1363 } 1364}; 1365 1366/** 1367 * @private Helper to turn a string into an element with an error message 1368 */ 1369dwr.util._getElementById = function(ele, source) { 1370 var orig = ele; 1371 ele = dwr.util.byId(ele); 1372 if (ele == null) { 1373 dwr.util._debug(source + " can't find an element with id: " + orig + "."); 1374 } 1375 return ele; 1376}; 1377 1378/** 1379 * @private Is the given node an HTML element (optionally of a given type)? 1380 * @param ele The element to test 1381 * @param nodeName eg "input", "textarea" - check for node name (optional) 1382 * if nodeName is an array then check all for a match. 1383 */ 1384dwr.util._isHTMLElement = function(ele, nodeName) { 1385 if (ele == null || typeof ele != "object" || ele.nodeName == null) { 1386 return false;
1387 } 1388 if (nodeName != null) { 1389 var test = ele.nodeName.toLowerCase(); 1390 if (typeof nodeName == "string") { 1391 return test == nodeName.toLowerCase(); 1392 } 1393 if (dwr.util._isArray(nodeName)) { 1394 var match = false; 1395 for (var i = 0; i < nodeName.length && !match; i++) { 1396 if (test == nodeName[i].toLowerCase()) { 1397 match = true; 1398 } 1399 } 1400 return match; 1401 } 1402 dwr.util._debug("dwr.util._isHTMLElement was passed test node name that is neither a string or array of strings"); 1403 return false; 1404 } 1405 return true; 1406}; 1407 1408/** 1409 * @private Like typeOf except that more information for an object is returned other than "object" 1410 */ 1411dwr.util._detailedTypeOf = function(x) { 1412 var reply = typeof x; 1413 if (reply == "object") { 1414 reply = Object.prototype.toString.apply(x); // Returns "[object class]" 1415 reply = reply.substring(8, reply.length-1); // Just get the class bit 1416 } 1417 return reply; 1418}; 1419 1420/** 1421 * @private Object detector. Excluding null from objects. 1422 */ 1423dwr.util._isObject = function(data) { 1424 return (data && typeof data == "object"); 1425}; 1426 1427/** 1428 * @private Array detector. Note: instanceof doesn't work with multiple frames. 1429 */ 1430dwr.util._isArray = function(data) { 1431 return (data && Object.prototype.toString.call(data)=="[object Array]"); 1432}; 1433 1434/** 1435 * @private Array like detector. Note: instanceof doesn't work with multiple frames. 1436 */ 1437dwr.util._isArrayLike = function(data) { 1438 return data 1439 && (typeof data.length == "number") // must have .length 1440 && ((data.propertyIsEnumerable && data.propertyIsEnumerable("length")==false) || !data.constructor || data!="[object Object]") // .length must be native prop 1441 && !dwr.util._isString(data) // don't be fooled by string 1442 && !dwr.util._isFunction(data) // don't be fooled by function 1443 && !data.tagName; // don't be fooled by elements 1444}; 1445 1446/** 1447 * @private String detector. 1448 */ 1449dwr.util._isString = function(data) { 1450 return (data && (typeof data == "string" || Object.prototype.toString.call(data) == "[object String]")); 1451}; 1452 1453/** 1454 * @private Function detector. 1455 */ 1456dwr.util._isFunction = function(data) { 1457 return (data && (typeof data == "function" || Object.prototype.toString.call(data) == "[object Function]") 1458 && data != "[object NodeList]"); // need to workaround NodeList on Safari 1459}; 1460 1461/** 1462 * @private Date detector. Note: instanceof doesn't work with multiple frames. 1463 */ 1464dwr.util._isDate = function(data) { 1465 return (data && Object.prototype.toString.call(data)=="[object Date]"); 1466}; 1467 1468/** 1469 * @private Used by setValue. Gets around the missing functionallity in IE. 1470 */ 1471dwr.util._importNode = function(doc, importedNode, deep) { 1472 var newNode; 1473 1474 if (importedNode.nodeType == 1 /*Node.ELEMENT_NODE*/) { 1475 newNode = doc.createElement(importedNode.nodeName); 1476 1477 for (var i = 0; i < importedNode.attributes.length; i++) { 1478 var attr = importedNode.attributes[i]; 1479 if (attr.nodeValue != null && attr.nodeValue != '') { 1480 newNode.setAttribute(attr.name, attr.nodeValue); 1481 } 1482 } 1483 1484 if (importedNode.style != null) { 1485 newNode.style.cssText = importedNode.style.cssText; 1486 } 1487 } 1488 else if (importedNode.nodeType == 3 /*Node.TEXT_NODE*/) { 1489 newNode = doc.createTextNode(importedNode.nodeValue); 1490 } 1491 1492 if (deep && importedNode.hasChildNodes()) { 1493 for (i = 0; i < importedNode.childNodes.length; i++) { 1494 newNode.appendChild(dwr.util._importNode(doc, importedNode.childNodes[i], true)); 1495 } 1496 } 1497 1498 return newNode; 1499}; 1500 1501/** @private Used internally when some message needs to get to the programmer */ 1502dwr.util._debug = function(message, stacktrace) { 1503 var written = false; 1504 try { 1505 if (window.console) { 1506 if (stacktrace && window.console.trace) window.console.trace(); 1507 window.console.log(message); 1508 written = true; 1509 } 1510 else if (window.opera && window.opera.postError) { 1511 window.opera.postError(message); 1512 written = true; 1513 } 1514 } 1515 catch (ex) { /* ignore */ } 1516 1517 if (!written) { 1518 var debug = document.getElementById("dwr-debug"); 1519 if (debug) { 1520 var contents = message + "<br/>" + debug.innerHTML; 1521 if (contents.length > 2048) contents = contents.substring(0, 2048); 1522 debug.innerHTML = contents; 1523 } 1524 } 1525}; 1526
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.