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