2
2
Copyright (c) 2008, Yahoo! Inc. All rights reserved.
3
3
Code licensed under the BSD License:
4
4
http://developer.yahoo.net/yui/license.txt
7
7
YUI.add('dom', function(Y) {
79
79
* @return {HTMLElement | null} The first matching child html element.
81
81
firstChild: function(element, fn) {
82
return Y.DOM._childBy(element, null, fn);
82
return Y.DOM._childBy(element, null, fn);
85
85
firstChildByTag: function(element, tag, fn) {
86
return Y.DOM._childBy(element, tag, fn);
86
return Y.DOM._childBy(element, tag, fn);
90
90
* Finds the lastChild of the given HTMLElement.
91
91
* @method lastChild
92
92
* @param {HTMLElement} element The html element.
93
* @param {String} tag The tag to search for.
93
94
* @param {Function} fn optional An optional boolean test to apply.
94
95
* The optional function is passed the current HTMLElement being tested as its only argument.
95
96
* If no function is given, the first found is returned.
96
97
* @return {HTMLElement | null} The first matching child html element.
98
99
lastChild: function(element, fn) {
99
return Y.DOM._childBy(element, null, fn, true);
100
return Y.DOM._childBy(element, null, fn, true);
102
103
lastChildByTag: function(element, tag, fn) {
103
return Y.DOM._childBy(element, tag, fn, true);
104
return Y.DOM._childBy(element, tag, fn, true);
159
160
* @return {Array} The collection of child elements.
161
162
children: function(element, fn) {
162
return Y.DOM.childrenByTag(element, null, fn);
163
return Y.DOM.childrenByTag(element, null, fn);
172
173
* @param {Boolean} all optional Whether all node types should be scanned, or just element nodes.
173
174
* @return {HTMLElement | null} The matching DOM node or null if none found.
175
previous: function(element, fn, all) {
176
previous: function(element, fn) {
176
177
return Y.DOM.elementByAxis(element, PREVIOUS_SIBLING, fn);
211
212
* @param {String} axis The axis to search (parentNode, nextSibling, previousSibling).
212
213
* @param {Function} fn optional An optional boolean test to apply.
213
214
* @param {Boolean} all optional Whether all node types should be returned, or just element nodes.
214
* The optional function is passed the current DOM node being tested as its only argument.
215
* The optional function is passed the current HTMLElement being tested as its only argument.
215
216
* If no function is given, the first element is returned.
216
217
* @return {HTMLElement | null} The matching element or null if none found.
255
256
* @param {HTMLElement} root optional An optional root element to start from.
256
257
* @param {Function} fn optional An optional boolean test to apply.
257
258
* The optional function is passed the current HTMLElement being tested as its only argument.
258
* If no function is given, the first match is returned.
259
* If no function is given, the first match is returned.
259
260
* @return {HTMLElement} The matching element.
261
262
firstByTag: function(tag, root, fn) {
285
286
filterElementsBy: function(elements, fn, firstOnly) {
286
287
var ret = (firstOnly) ? null : [];
287
for (var i = 0, el; el = elements[i++];) {
288
if ( el[TAG_NAME] && (!fn || fn(el)) ) {
288
for (var i = 0, len = elements[LENGTH]; i < len; ++i) {
289
if (elements[i][TAG_NAME] && (!fn || fn(elements[i]))) {
293
ret[ret[LENGTH]] = el;
294
ret[ret[LENGTH]] = elements[i];
308
309
contains: function(element, needle) {
311
if (!needle || !needle[NODE_TYPE] || !element || !element[NODE_TYPE]) {
312
if ( !needle || !element || !needle[NODE_TYPE] || !element[NODE_TYPE]) {
313
314
} else if (element[CONTAINS]) {
314
315
if (Y.UA.opera || needle[NODE_TYPE] === 1) { // IE & SAF contains fail if needle not an ELEMENT_NODE
329
* Returns an HTMLElement for the given string of HTML.
331
* @param {String} html The string of HTML to convert to a DOM element.
332
* @param {Document} document An optional document to create the node with.
333
* @return {HTMLElement} The newly created element.
330
* Determines whether or not the HTMLElement is part of the document.
332
* @param {HTMLElement} element The containing html element.
333
* @param {HTMLElement} doc optional The document to check.
334
* @return {Boolean} Whether or not the element is attached to the document.
336
inDoc: function(element, doc) {
337
doc = doc || Y.config.doc;
338
return Y.DOM.contains(doc.documentElement, element);
335
341
create: function(html, doc) {
336
342
doc = doc || Y.config.doc;
337
343
var m = re_tag.exec(html);
645
653
* @param {String} att The style property to set.
646
654
* @param {String|Number} val The value.
648
setStyle: function(node, att, val) {
649
var style = node[STYLE],
656
setStyle: function(node, att, val, style) {
650
658
CUSTOM_STYLES = Y.DOM.CUSTOM_STYLES;
764
774
var OFFSET_TOP = 'offsetTop',
765
776
DOCUMENT_ELEMENT = 'documentElement',
766
777
COMPAT_MODE = 'compatMode',
767
778
OFFSET_LEFT = 'offsetLeft',
784
795
RE_TABLE = /^t(?:able|d|h)$/i;
788
801
* Returns the inner height of the viewport (exludes scrollbar).
789
802
* @method winHeight
790
* @return {Int} The pixel height of the viewport.
792
805
winHeight: function(node) {
793
806
var h = Y.DOM._getWinSize(node)[HEIGHT];
998
1019
setXY: function(node, xy, noRetry) {
999
1020
var pos = Y.DOM.getStyle(node, POSITION),
1000
1021
setStyle = Y.DOM.setStyle,
1001
1023
delta = [ // assuming pixels; if not we will have to retry
1002
1024
parseInt( Y.DOM[GET_COMPUTED_STYLE](node, LEFT), 10 ),
1003
1025
parseInt( Y.DOM[GET_COMPUTED_STYLE](node, TOP), 10 )
1117
1149
var OFFSET_WIDTH = 'offsetWidth',
1118
1150
OFFSET_HEIGHT = 'offsetHeight',
1119
1155
TAG_NAME = 'tagName';
1121
1157
var getOffsets = function(r1, r2) {
1123
var t = Math.max(r1.top, r2.top ),
1124
r = Math.min(r1.right, r2.right ),
1125
b = Math.min(r1.bottom, r2.bottom),
1126
l = Math.max(r1.left, r2.left );
1158
var t = Math.max(r1[TOP], r2[TOP]),
1159
r = Math.min(r1[RIGHT], r2[RIGHT]),
1160
b = Math.min(r1[BOTTOM], r2[BOTTOM]),
1161
l = Math.max(r1[LEFT], r2[LEFT]),
1171
var DOM = DOM || Y.DOM;
1138
1174
* Returns an Object literal containing the following about this element: (top, right, bottom, left)
1139
1175
* @method region
1169
1205
@return {Object} Object literal containing the following intersection data: (top, right, bottom, left, area, yoff, xoff, inRegion)
1171
1207
intersect: function(node, node2, altRegion) {
1172
var r = altRegion || Y.DOM.region(node), region = {};
1208
var r = altRegion || DOM.region(node), region = {};
1175
1211
if (n[TAG_NAME]) {
1176
region = Y.DOM.region(n);
1212
region = DOM.region(n);
1177
1213
} else if (Y.Lang.isObject(node2)) {
1178
1214
region = node2;
1183
1219
var off = getOffsets(region, r);
1189
area: ((off.bottom - off.top) * (off.right - off.left)),
1190
yoff: ((off.bottom - off.top)),
1191
xoff: (off.right - off.left),
1192
inRegion: Y.DOM.inRegion(node, node2, false, altRegion)
1223
bottom: off[BOTTOM],
1225
area: ((off[BOTTOM] - off[TOP]) * (off[RIGHT] - off[LEFT])),
1226
yoff: ((off[BOTTOM] - off[TOP])),
1227
xoff: (off[RIGHT] - off[LEFT]),
1228
inRegion: DOM.inRegion(node, node2, false, altRegion)
1204
1240
inRegion: function(node, node2, all, altRegion) {
1205
1241
var region = {},
1206
r = altRegion || Y.DOM.region(node);
1242
r = altRegion || DOM.region(node);
1209
1245
if (n[TAG_NAME]) {
1210
region = Y.DOM.region(n);
1246
region = DOM.region(n);
1211
1247
} else if (Y.Lang.isObject(node2)) {
1212
1248
region = node2;
1218
return ( r.left >= region.left &&
1219
r.right <= region.right &&
1220
r.top >= region.top &&
1221
r.bottom <= region.bottom );
1255
r[LEFT] >= region[LEFT] &&
1256
r[RIGHT] <= region[RIGHT] &&
1257
r[TOP] >= region[TOP] &&
1258
r[BOTTOM] <= region[BOTTOM] );
1223
1260
var off = getOffsets(region, r);
1224
if (off.bottom >= off.top && off.right >= off.left) {
1261
if (off[BOTTOM] >= off[TOP] && off[RIGHT] >= off[LEFT]) {
1239
1276
* @return {Boolean} True if in region, false if not.
1241
1278
inViewportRegion: function(node, all, altRegion) {
1242
return Y.DOM.inRegion(node, Y.DOM.viewportRegion(node), all, altRegion);
1279
return DOM.inRegion(node, DOM.viewportRegion(node), all, altRegion);
1251
1288
viewportRegion: function(node) {
1252
1289
node = node || Y.config.doc.documentElement;
1254
top: Y.DOM.docScrollY(node),
1255
right: Y.DOM.winWidth(node) + Y.DOM.docScrollX(node),
1256
bottom: (Y.DOM.docScrollY(node) + Y.DOM.winHeight(node)),
1257
left: Y.DOM.docScrollX(node)
1291
r[TOP] = DOM.docScrollY(node);
1292
r[RIGHT] = DOM.winWidth(node) + DOM.docScrollX(node);
1293
r[BOTTOM] = (DOM.docScrollY(node) + DOM.winHeight(node));
1294
r[LEFT] = DOM.docScrollX(node);
1264
1301
* Add style management functionality to DOM.
1324
1361
if (property === OPACITY) {
1325
1362
value = Y.DOM.CUSTOM_STYLES[OPACITY].get(el);
1326
} else if (!current || current.indexOf(PX) > -1) { // no need to convert
1363
} else if (!current || (current.indexOf && current.indexOf(PX) > -1)) { // no need to convert
1327
1364
value = current;
1328
1365
} else if (Y.DOM.IE.COMPUTED[property]) { // use compute function
1329
1366
value = Y.DOM.IE.COMPUTED[property](el, property);
1774
1812
for (i = 0, len = token[ATTRIBUTES][LENGTH]; i < len; ++i) {
1775
1813
attribute = node.getAttribute(token[ATTRIBUTES][i][0], 2);
1776
1814
if (attribute === undefined) {
1777
attribute = node[token[ATTRIBUTES][i][0]];
1778
if (attribute === undefined) {
1782
1817
if ( ops[token[ATTRIBUTES][i][1]] &&
1783
1818
!ops[token[ATTRIBUTES][i][1]](attribute, token[ATTRIBUTES][i][2])) {
2031
if (Y.UA.ie) { // rewrite class for IE (others use getAttribute('class')
2066
if (Y.UA.ie && Y.UA.ie < 8) { // rewrite class for IE (others use getAttribute('class')
2032
2067
Selector.attrAliases['class'] = 'className';
2033
2068
Selector.attrAliases['for'] = 'htmlFor';