[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
1 /* 2 YUI 3.17.2 (build 9c3c78e) 3 Copyright 2014 Yahoo! Inc. All rights reserved. 4 Licensed under the BSD License. 5 http://yuilibrary.com/license/ 6 */ 7 8 YUI.add('dom-base', function (Y, NAME) { 9 10 /** 11 * @for DOM 12 * @module dom 13 */ 14 var documentElement = Y.config.doc.documentElement, 15 Y_DOM = Y.DOM, 16 TAG_NAME = 'tagName', 17 OWNER_DOCUMENT = 'ownerDocument', 18 EMPTY_STRING = '', 19 addFeature = Y.Features.add, 20 testFeature = Y.Features.test; 21 22 Y.mix(Y_DOM, { 23 /** 24 * Returns the text content of the HTMLElement. 25 * @method getText 26 * @param {HTMLElement} element The html element. 27 * @return {String} The text content of the element (includes text of any descending elements). 28 */ 29 getText: (documentElement.textContent !== undefined) ? 30 function(element) { 31 var ret = ''; 32 if (element) { 33 ret = element.textContent; 34 } 35 return ret || ''; 36 } : function(element) { 37 var ret = ''; 38 if (element) { 39 ret = element.innerText || element.nodeValue; // might be a textNode 40 } 41 return ret || ''; 42 }, 43 44 /** 45 * Sets the text content of the HTMLElement. 46 * @method setText 47 * @param {HTMLElement} element The html element. 48 * @param {String} content The content to add. 49 */ 50 setText: (documentElement.textContent !== undefined) ? 51 function(element, content) { 52 if (element) { 53 element.textContent = content; 54 } 55 } : function(element, content) { 56 if ('innerText' in element) { 57 element.innerText = content; 58 } else if ('nodeValue' in element) { 59 element.nodeValue = content; 60 } 61 }, 62 63 CUSTOM_ATTRIBUTES: (!documentElement.hasAttribute) ? { // IE < 8 64 'for': 'htmlFor', 65 'class': 'className' 66 } : { // w3c 67 'htmlFor': 'for', 68 'className': 'class' 69 }, 70 71 /** 72 * Provides a normalized attribute interface. 73 * @method setAttribute 74 * @param {HTMLElement} el The target element for the attribute. 75 * @param {String} attr The attribute to set. 76 * @param {String} val The value of the attribute. 77 */ 78 setAttribute: function(el, attr, val, ieAttr) { 79 if (el && attr && el.setAttribute) { 80 attr = Y_DOM.CUSTOM_ATTRIBUTES[attr] || attr; 81 el.setAttribute(attr, val, ieAttr); 82 } 83 }, 84 85 86 /** 87 * Provides a normalized attribute interface. 88 * @method getAttribute 89 * @param {HTMLElement} el The target element for the attribute. 90 * @param {String} attr The attribute to get. 91 * @return {String} The current value of the attribute. 92 */ 93 getAttribute: function(el, attr, ieAttr) { 94 ieAttr = (ieAttr !== undefined) ? ieAttr : 2; 95 var ret = ''; 96 if (el && attr && el.getAttribute) { 97 attr = Y_DOM.CUSTOM_ATTRIBUTES[attr] || attr; 98 // BUTTON value issue for IE < 8 99 ret = (el.tagName === "BUTTON" && attr === 'value') ? Y_DOM.getValue(el) : el.getAttribute(attr, ieAttr); 100 101 if (ret === null) { 102 ret = ''; // per DOM spec 103 } 104 } 105 return ret; 106 }, 107 108 VALUE_SETTERS: {}, 109 110 VALUE_GETTERS: {}, 111 112 getValue: function(node) { 113 var ret = '', // TODO: return null? 114 getter; 115 116 if (node && node[TAG_NAME]) { 117 getter = Y_DOM.VALUE_GETTERS[node[TAG_NAME].toLowerCase()]; 118 119 if (getter) { 120 ret = getter(node); 121 } else { 122 ret = node.value; 123 } 124 } 125 126 // workaround for IE8 JSON stringify bug 127 // which converts empty string values to null 128 if (ret === EMPTY_STRING) { 129 ret = EMPTY_STRING; // for real 130 } 131 132 return (typeof ret === 'string') ? ret : ''; 133 }, 134 135 setValue: function(node, val) { 136 var setter; 137 138 if (node && node[TAG_NAME]) { 139 setter = Y_DOM.VALUE_SETTERS[node[TAG_NAME].toLowerCase()]; 140 val = (val === null) ? '' : val; 141 if (setter) { 142 setter(node, val); 143 } else { 144 node.value = val; 145 } 146 } 147 }, 148 149 creators: {} 150 }); 151 152 addFeature('value-set', 'select', { 153 test: function() { 154 var node = Y.config.doc.createElement('select'); 155 node.innerHTML = '<option>1</option><option>2</option>'; 156 node.value = '2'; 157 return (node.value && node.value === '2'); 158 } 159 }); 160 161 if (!testFeature('value-set', 'select')) { 162 Y_DOM.VALUE_SETTERS.select = function(node, val) { 163 for (var i = 0, options = node.getElementsByTagName('option'), option; 164 option = options[i++];) { 165 if (Y_DOM.getValue(option) === val) { 166 option.selected = true; 167 //Y_DOM.setAttribute(option, 'selected', 'selected'); 168 break; 169 } 170 } 171 }; 172 } 173 174 Y.mix(Y_DOM.VALUE_GETTERS, { 175 button: function(node) { 176 return (node.attributes && node.attributes.value) ? node.attributes.value.value : ''; 177 } 178 }); 179 180 Y.mix(Y_DOM.VALUE_SETTERS, { 181 // IE: node.value changes the button text, which should be handled via innerHTML 182 button: function(node, val) { 183 var attr = node.attributes.value; 184 if (!attr) { 185 attr = node[OWNER_DOCUMENT].createAttribute('value'); 186 node.setAttributeNode(attr); 187 } 188 189 attr.value = val; 190 } 191 }); 192 193 194 Y.mix(Y_DOM.VALUE_GETTERS, { 195 option: function(node) { 196 var attrs = node.attributes; 197 return (attrs.value && attrs.value.specified) ? node.value : node.text; 198 }, 199 200 select: function(node) { 201 var val = node.value, 202 options = node.options; 203 204 if (options && options.length) { 205 // TODO: implement multipe select 206 if (node.multiple) { 207 } else if (node.selectedIndex > -1) { 208 val = Y_DOM.getValue(options[node.selectedIndex]); 209 } 210 } 211 212 return val; 213 } 214 }); 215 var addClass, hasClass, removeClass; 216 217 Y.mix(Y.DOM, { 218 /** 219 * Determines whether a DOM element has the given className. 220 * @method hasClass 221 * @for DOM 222 * @param {HTMLElement} element The DOM element. 223 * @param {String} className the class name to search for 224 * @return {Boolean} Whether or not the element has the given class. 225 */ 226 hasClass: function(node, className) { 227 var re = Y.DOM._getRegExp('(?:^|\\s+)' + className + '(?:\\s+|$)'); 228 return re.test(node.className); 229 }, 230 231 /** 232 * Adds a class name to a given DOM element. 233 * @method addClass 234 * @for DOM 235 * @param {HTMLElement} element The DOM element. 236 * @param {String} className the class name to add to the class attribute 237 */ 238 addClass: function(node, className) { 239 if (!Y.DOM.hasClass(node, className)) { // skip if already present 240 node.className = Y.Lang.trim([node.className, className].join(' ')); 241 } 242 }, 243 244 /** 245 * Removes a class name from a given element. 246 * @method removeClass 247 * @for DOM 248 * @param {HTMLElement} element The DOM element. 249 * @param {String} className the class name to remove from the class attribute 250 */ 251 removeClass: function(node, className) { 252 if (className && hasClass(node, className)) { 253 node.className = Y.Lang.trim(node.className.replace(Y.DOM._getRegExp('(?:^|\\s+)' + 254 className + '(?:\\s+|$)'), ' ')); 255 256 if ( hasClass(node, className) ) { // in case of multiple adjacent 257 removeClass(node, className); 258 } 259 } 260 }, 261 262 /** 263 * Replace a class with another class for a given element. 264 * If no oldClassName is present, the newClassName is simply added. 265 * @method replaceClass 266 * @for DOM 267 * @param {HTMLElement} element The DOM element 268 * @param {String} oldClassName the class name to be replaced 269 * @param {String} newClassName the class name that will be replacing the old class name 270 */ 271 replaceClass: function(node, oldC, newC) { 272 removeClass(node, oldC); // remove first in case oldC === newC 273 addClass(node, newC); 274 }, 275 276 /** 277 * If the className exists on the node it is removed, if it doesn't exist it is added. 278 * @method toggleClass 279 * @for DOM 280 * @param {HTMLElement} element The DOM element 281 * @param {String} className the class name to be toggled 282 * @param {Boolean} addClass optional boolean to indicate whether class 283 * should be added or removed regardless of current state 284 */ 285 toggleClass: function(node, className, force) { 286 var add = (force !== undefined) ? force : 287 !(hasClass(node, className)); 288 289 if (add) { 290 addClass(node, className); 291 } else { 292 removeClass(node, className); 293 } 294 } 295 }); 296 297 hasClass = Y.DOM.hasClass; 298 removeClass = Y.DOM.removeClass; 299 addClass = Y.DOM.addClass; 300 301 var re_tag = /<([a-z]+)/i, 302 303 Y_DOM = Y.DOM, 304 305 addFeature = Y.Features.add, 306 testFeature = Y.Features.test, 307 308 creators = {}, 309 310 createFromDIV = function(html, tag) { 311 var div = Y.config.doc.createElement('div'), 312 ret = true; 313 314 div.innerHTML = html; 315 if (!div.firstChild || div.firstChild.tagName !== tag.toUpperCase()) { 316 ret = false; 317 } 318 319 return ret; 320 }, 321 322 re_tbody = /(?:\/(?:thead|tfoot|tbody|caption|col|colgroup)>)+\s*<tbody/, 323 324 TABLE_OPEN = '<table>', 325 TABLE_CLOSE = '</table>', 326 327 selectedIndex; 328 329 Y.mix(Y.DOM, { 330 _fragClones: {}, 331 332 _create: function(html, doc, tag) { 333 tag = tag || 'div'; 334 335 var frag = Y_DOM._fragClones[tag]; 336 if (frag) { 337 frag = frag.cloneNode(false); 338 } else { 339 frag = Y_DOM._fragClones[tag] = doc.createElement(tag); 340 } 341 frag.innerHTML = html; 342 return frag; 343 }, 344 345 _children: function(node, tag) { 346 var i = 0, 347 children = node.children, 348 childNodes, 349 hasComments, 350 child; 351 352 if (children && children.tags) { // use tags filter when possible 353 if (tag) { 354 children = node.children.tags(tag); 355 } else { // IE leaks comments into children 356 hasComments = children.tags('!').length; 357 } 358 } 359 360 if (!children || (!children.tags && tag) || hasComments) { 361 childNodes = children || node.childNodes; 362 children = []; 363 while ((child = childNodes[i++])) { 364 if (child.nodeType === 1) { 365 if (!tag || tag === child.tagName) { 366 children.push(child); 367 } 368 } 369 } 370 } 371 372 return children || []; 373 }, 374 375 /** 376 * Creates a new dom node using the provided markup string. 377 * @method create 378 * @param {String} html The markup used to create the element 379 * @param {HTMLDocument} doc An optional document context 380 * @return {HTMLElement|DocumentFragment} returns a single HTMLElement 381 * when creating one node, and a documentFragment when creating 382 * multiple nodes. 383 */ 384 create: function(html, doc) { 385 if (typeof html === 'string') { 386 html = Y.Lang.trim(html); // match IE which trims whitespace from innerHTML 387 388 } 389 390 doc = doc || Y.config.doc; 391 var m = re_tag.exec(html), 392 create = Y_DOM._create, 393 custom = creators, 394 ret = null, 395 creator, tag, node, nodes; 396 397 if (html != undefined) { // not undefined or null 398 if (m && m[1]) { 399 creator = custom[m[1].toLowerCase()]; 400 if (typeof creator === 'function') { 401 create = creator; 402 } else { 403 tag = creator; 404 } 405 } 406 407 node = create(html, doc, tag); 408 nodes = node.childNodes; 409 410 if (nodes.length === 1) { // return single node, breaking parentNode ref from "fragment" 411 ret = node.removeChild(nodes[0]); 412 } else if (nodes[0] && nodes[0].className === 'yui3-big-dummy') { // using dummy node to preserve some attributes (e.g. OPTION not selected) 413 selectedIndex = node.selectedIndex; 414 415 if (nodes.length === 2) { 416 ret = nodes[0].nextSibling; 417 } else { 418 node.removeChild(nodes[0]); 419 ret = Y_DOM._nl2frag(nodes, doc); 420 } 421 } else { // return multiple nodes as a fragment 422 ret = Y_DOM._nl2frag(nodes, doc); 423 } 424 425 } 426 427 return ret; 428 }, 429 430 _nl2frag: function(nodes, doc) { 431 var ret = null, 432 i, len; 433 434 if (nodes && (nodes.push || nodes.item) && nodes[0]) { 435 doc = doc || nodes[0].ownerDocument; 436 ret = doc.createDocumentFragment(); 437 438 if (nodes.item) { // convert live list to static array 439 nodes = Y.Array(nodes, 0, true); 440 } 441 442 for (i = 0, len = nodes.length; i < len; i++) { 443 ret.appendChild(nodes[i]); 444 } 445 } // else inline with log for minification 446 return ret; 447 }, 448 449 /** 450 * Inserts content in a node at the given location 451 * @method addHTML 452 * @param {HTMLElement} node The node to insert into 453 * @param {HTMLElement | Array | HTMLCollection} content The content to be inserted 454 * @param {HTMLElement} where Where to insert the content 455 * If no "where" is given, content is appended to the node 456 * Possible values for "where" 457 * <dl> 458 * <dt>HTMLElement</dt> 459 * <dd>The element to insert before</dd> 460 * <dt>"replace"</dt> 461 * <dd>Replaces the existing HTML</dd> 462 * <dt>"before"</dt> 463 * <dd>Inserts before the existing HTML</dd> 464 * <dt>"before"</dt> 465 * <dd>Inserts content before the node</dd> 466 * <dt>"after"</dt> 467 * <dd>Inserts content after the node</dd> 468 * </dl> 469 */ 470 addHTML: function(node, content, where) { 471 var nodeParent = node.parentNode, 472 i = 0, 473 item, 474 ret = content, 475 newNode; 476 477 478 if (content != undefined) { // not null or undefined (maybe 0) 479 if (content.nodeType) { // DOM node, just add it 480 newNode = content; 481 } else if (typeof content == 'string' || typeof content == 'number') { 482 ret = newNode = Y_DOM.create(content); 483 } else if (content[0] && content[0].nodeType) { // array or collection 484 newNode = Y.config.doc.createDocumentFragment(); 485 while ((item = content[i++])) { 486 newNode.appendChild(item); // append to fragment for insertion 487 } 488 } 489 } 490 491 if (where) { 492 if (newNode && where.parentNode) { // insert regardless of relationship to node 493 where.parentNode.insertBefore(newNode, where); 494 } else { 495 switch (where) { 496 case 'replace': 497 while (node.firstChild) { 498 node.removeChild(node.firstChild); 499 } 500 if (newNode) { // allow empty content to clear node 501 node.appendChild(newNode); 502 } 503 break; 504 case 'before': 505 if (newNode) { 506 nodeParent.insertBefore(newNode, node); 507 } 508 break; 509 case 'after': 510 if (newNode) { 511 if (node.nextSibling) { // IE errors if refNode is null 512 nodeParent.insertBefore(newNode, node.nextSibling); 513 } else { 514 nodeParent.appendChild(newNode); 515 } 516 } 517 break; 518 default: 519 if (newNode) { 520 node.appendChild(newNode); 521 } 522 } 523 } 524 } else if (newNode) { 525 node.appendChild(newNode); 526 } 527 528 // `select` elements are the only elements with `selectedIndex`. 529 // Don't grab the dummy `option` element's `selectedIndex`. 530 if (node.nodeName == "SELECT" && selectedIndex > 0) { 531 node.selectedIndex = selectedIndex - 1; 532 } 533 534 return ret; 535 }, 536 537 wrap: function(node, html) { 538 var parent = (html && html.nodeType) ? html : Y.DOM.create(html), 539 nodes = parent.getElementsByTagName('*'); 540 541 if (nodes.length) { 542 parent = nodes[nodes.length - 1]; 543 } 544 545 if (node.parentNode) { 546 node.parentNode.replaceChild(parent, node); 547 } 548 parent.appendChild(node); 549 }, 550 551 unwrap: function(node) { 552 var parent = node.parentNode, 553 lastChild = parent.lastChild, 554 next = node, 555 grandparent; 556 557 if (parent) { 558 grandparent = parent.parentNode; 559 if (grandparent) { 560 node = parent.firstChild; 561 while (node !== lastChild) { 562 next = node.nextSibling; 563 grandparent.insertBefore(node, parent); 564 node = next; 565 } 566 grandparent.replaceChild(lastChild, parent); 567 } else { 568 parent.removeChild(node); 569 } 570 } 571 } 572 }); 573 574 addFeature('innerhtml', 'table', { 575 test: function() { 576 var node = Y.config.doc.createElement('table'); 577 try { 578 node.innerHTML = '<tbody></tbody>'; 579 } catch(e) { 580 return false; 581 } 582 return (node.firstChild && node.firstChild.nodeName === 'TBODY'); 583 } 584 }); 585 586 addFeature('innerhtml-div', 'tr', { 587 test: function() { 588 return createFromDIV('<tr></tr>', 'tr'); 589 } 590 }); 591 592 addFeature('innerhtml-div', 'script', { 593 test: function() { 594 return createFromDIV('<script></script>', 'script'); 595 } 596 }); 597 598 if (!testFeature('innerhtml', 'table')) { 599 // TODO: thead/tfoot with nested tbody 600 // IE adds TBODY when creating TABLE elements (which may share this impl) 601 creators.tbody = function(html, doc) { 602 var frag = Y_DOM.create(TABLE_OPEN + html + TABLE_CLOSE, doc), 603 tb = Y.DOM._children(frag, 'tbody')[0]; 604 605 if (frag.children.length > 1 && tb && !re_tbody.test(html)) { 606 tb.parentNode.removeChild(tb); // strip extraneous tbody 607 } 608 return frag; 609 }; 610 } 611 612 if (!testFeature('innerhtml-div', 'script')) { 613 creators.script = function(html, doc) { 614 var frag = doc.createElement('div'); 615 616 frag.innerHTML = '-' + html; 617 frag.removeChild(frag.firstChild); 618 return frag; 619 }; 620 621 creators.link = creators.style = creators.script; 622 } 623 624 if (!testFeature('innerhtml-div', 'tr')) { 625 Y.mix(creators, { 626 option: function(html, doc) { 627 return Y_DOM.create('<select><option class="yui3-big-dummy" selected></option>' + html + '</select>', doc); 628 }, 629 630 tr: function(html, doc) { 631 return Y_DOM.create('<tbody>' + html + '</tbody>', doc); 632 }, 633 634 td: function(html, doc) { 635 return Y_DOM.create('<tr>' + html + '</tr>', doc); 636 }, 637 638 col: function(html, doc) { 639 return Y_DOM.create('<colgroup>' + html + '</colgroup>', doc); 640 }, 641 642 tbody: 'table' 643 }); 644 645 Y.mix(creators, { 646 legend: 'fieldset', 647 th: creators.td, 648 thead: creators.tbody, 649 tfoot: creators.tbody, 650 caption: creators.tbody, 651 colgroup: creators.tbody, 652 optgroup: creators.option 653 }); 654 } 655 656 Y_DOM.creators = creators; 657 Y.mix(Y.DOM, { 658 /** 659 * Sets the width of the element to the given size, regardless 660 * of box model, border, padding, etc. 661 * @method setWidth 662 * @param {HTMLElement} element The DOM element. 663 * @param {String|Number} size The pixel height to size to 664 */ 665 666 setWidth: function(node, size) { 667 Y.DOM._setSize(node, 'width', size); 668 }, 669 670 /** 671 * Sets the height of the element to the given size, regardless 672 * of box model, border, padding, etc. 673 * @method setHeight 674 * @param {HTMLElement} element The DOM element. 675 * @param {String|Number} size The pixel height to size to 676 */ 677 678 setHeight: function(node, size) { 679 Y.DOM._setSize(node, 'height', size); 680 }, 681 682 _setSize: function(node, prop, val) { 683 val = (val > 0) ? val : 0; 684 var size = 0; 685 686 node.style[prop] = val + 'px'; 687 size = (prop === 'height') ? node.offsetHeight : node.offsetWidth; 688 689 if (size > val) { 690 val = val - (size - val); 691 692 if (val < 0) { 693 val = 0; 694 } 695 696 node.style[prop] = val + 'px'; 697 } 698 } 699 }); 700 701 702 }, '3.17.2', {"requires": ["dom-core"]});
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |