// dollarsign.js v0.3pre // A jQuery clone with less features, more bugs and less speed // by Jeffery To // Guvf urycf jjjvaf / vfbone / Nrtvf znxr fb zhpu $ gung rira gur pbzcrgrag rzcyblrrf trg fbzr (function () { var win = window, doc = win.document, _$ = win.$, undef, ds; var PROP = 'dollarsign' + (new Date()).getTime(), ELID = 1, store = {}; function makeArray(o) { var l, a, i; if (o == null) { return []; } if (o instanceof Array) { return o.concat(); } if (typeof o == 'string' || o instanceof String) { return o.split(''); } l = parseInt(o.length, 10); if (isNaN(l) || !isFinite(l) || l <= 0) { return []; } try { a = Array.prototype.concat.call(o); } catch (e) { a = null; } // sometimes a is an array but all of its members are undefined // strings in ie // nodelists in safari 2 // so we need to check // sigh if (a) { // find a non-member of o and compare // can't use the in operator because it doesn't work with // nodelists in safari 2 for (i = l - 1; i >= 0; i--) { if (o[i] != null) { if (a[i] !== o[i]) { a = null; } break; } } } if (!a) { a = []; for (i = l - 1; i >= 0; i--) { a[i] = o[i]; } } return a; }; function extend() { var args = makeArray(arguments), deep = false, o, p, q, l, i, j; if (args[0] === true) { deep = args.shift(); } l = args.length; if (l == 1) { o = ds; } else { o = args.shift(); l--; } for (i = 0; i < l; i++) { p = args[i]; for (j in p) { q = p[j]; if (typeof q != 'undefined') { o[j] = (deep && typeof q == 'object' && q) ? arguments.callee(true, (o[j] || ((q instanceof Array) ? [] : {})), q) : q; } } } return o; }; function tester(s) { var fns = [], id = '', tag, next, a, b, c, l, i; // hierarchy a = s.match(/^([>+~]*)(.*)$/); next = a[1].charAt(0); s = a[2]; // tag a = s.match(/^(\*|\w*)(.*)$/); tag = a[1].toLowerCase(); s = a[2]; // everything else if (a = s.match(/[#.:](?:\w|\\\.|\\:|\\\[|\\\])+/g)) { l = a.length; for (i = 0; i < l; i++) { b = a[i]; c = b.substring(1); switch (b.charAt(0)) { case '#': // id id = c; if (id.indexOf('\\') > -1) { id = id.replace(/\\([.:\[\]])/g, '$1'); } break; case '.': // class (function () { var re = new RegExp('\\b' + c + '\\b'); fns.push(function (el) { return (re.test(el.className)); }); })() break; case ':': // pseudo-class break; } } } if (tag !== '' && tag !== '*') { fns.unshift(function (el) { return (el.nodeName.toLowerCase() === tag); }); } if (id !== '') { fns.unshift(function (el) { return (el.id === id); }); } return function (el, pos) { var l = fns.length, r = true, i; for (i = 0; i < l; i++) { if (!fns[i](el, pos)) { r = false; break; } } return { pass: r, next: (next == '' || next == '>') ? 'parentNode' : 'previousSibling', stopNext: (next == '>' || next == '+') }; }; } var DOM = { isElement: function (o) { return !!(o && o.nodeType == 1); }, isDocument: function (o) { return !!(o && o.nodeType == 9); }, contains: function (a, d) { if (a && d) { if (a.contains) { return a.contains(d); } else if (a.compareDocumentPosition) { // based on http://www.quirksmode.org/blog/archives/2006/01/contains_for_mo.html return !!(a.compareDocumentPosition(d) & 0x10); } else { for (d = d.parentNode; d; d = d.parentNode) { if (d == a) { return true; } } } } return false; }, nextElement: function(el, next, all) { var p = el[next], r; if (!all) { while (p && p.nodeType != 1 && p.nodeType != 9) { p = p[next]; } r = p; } else { r = []; while (p) { if (p.nodeType == 1) { r.push(p); } p = p[next]; } } return r; }, // from http://www.quirksmode.org/dom/getElementsByTagNames.html sort: function (els) { var sorted = true; if (els.length > 0) { if (els[0].sourceIndex != null) { els.sort(function (a, b) { return a.sourceIndex - b.sourceIndex; }); } else if (els[0].compareDocumentPosition) { els.sort(function (a, b) { return 3 - (a.compareDocumentPosition(b) & 0x06); }); } else { sorted = false; } } return sorted; } }; // XXX todo: use querySelectorAll function sel(s, doc, root, els) { var D = DOM, result = [], canId, sorted, a, l, i; // split and normalize s // e.g. " body , div span, ul>li, label+ input " becomes // ["body", "div span", "ul >li", "label +input"] s = ds.map(s.split(','), function (v) { var w = ds.trim(v.replace(/([>+~])\s*/g, ' $1')).replace(/\s+/, ' '); return (w !== '') ? w : null; }); // check to make sure doc exists and is a document node if (!D.isDocument(doc)) { doc = ((root && root.ownerDocument) || win.document); } if (!root) { root = doc; } if (!D.isElement(root) && !D.isDocument(root)) { return result; } if (els) { // filter given list for elements els = ds.grep(makeArray(els), function (el) { return D.isElement(el); }); } else { // check if we can use doc.getElementById canId = ((root == doc || D.contains(doc, root)) && doc.getElementById); } // for each selector ds.each(s, function (i, v) { var f = v.split(' ').reverse(), list, id, tag, el; // find starting list of elements, if necessary if (els) { list = els.concat(); } else { if (canId) { id = f[0].match(/#((?:\w|\\\.|\\:|\\\[|\\\])+)/); if (id) { id = id[1]; if (id.indexOf('\\') > -1) { id = id.replace(/\\([.:\[\]])/g, '$1'); } el = doc.getElementById(id); if (!el) { return result; } // getElementById in ie is broken // e.g. for id "foo", it returns any element with name="foo" or id="FOO" // so we need to test for it if (el.id == id && D.contains(root, el)) { list = [el]; } } } if (!list) { tag = f[0].match(/^\w+/); // XXX todo: check ds.support.objectAll list = makeArray(root.getElementsByTagName((tag) ? tag[0] : '*')); } } // convert selector into test functions f = ds.map(f, function (w) { return tester(w); }); // test each element list = ds.map(list, function (el, i) { var fns = f.concat(), fn = fns.shift(), pass = true, next, stopNext, p, r; // run first test on actual element r = fn(el, i); if (!r.pass) { return null; } // run remaining tests on parents / siblings fn = fns[0]; next = r.next; stopNext = r.stopNext; p = D.nextElement(el, next); while (p && p != root && fns.length > 0) { r = fn(p, i); if (r.pass) { fns.shift(); fn = fns[0]; next = r.next; stopNext = r.stopNext; } else if (stopNext) { break; } p = D.nextElement(p, next); } // make sure the node we end on is also okay // (for selectors that start with > or + if (fns.length == 0 && !stopNext) { while (p && p != root) { p = D.nextElement(p, next); } } if (fns.length > 0 || p != root) { pass = false; } return (pass) ? el : null; }); result = result.concat(list); }); // sort elements by dom order sorted = D.sort(result); // remove duplicates // only for multiple selectors if (s.length > 1) { if (sorted) { a = result; l = a.length; result = []; for (i = 0; i < l; i++) { if (a[i] != a[i + 1]) { result.push(a[i]); } } } else { result = ds.unique(result); } } return result; } function DS(a, s) { var l, i; if (a) { l = a.length; for (i = 0; i < l; i++) { this[i] = a[i]; } } this.length = (l || 0); this.selector = (s || ''); } /* * core */ ds = function (o, node) { var me = arguments.callee, ds, tag, div, wrapper, serialize; if (o instanceof DS) { // dollar sign object ds = extend(new DS(o, o.selector), { context: o.context, prevObject: o.prevObject }); return ds; } if (me.isFunction(o)) { // document ready listener return me(doc).ready(o); } if (me.isArray(o)) { // array of elements return new DS(o); } if (o == null) { o = ''; } if (o === '') { o = doc; } if (typeof o != 'string') { // element or null (document) ds = new DS([o]); ds.context = o; return ds; } if (o.indexOf('<') > -1) { // html o = o.replace(/^[^<]+/, '').replace(/[^>]+$/, ''); tag = o.match(/^<(\w+)/)[1].toLowerCase(); wrapper = []; switch (tag) { case 'li': wrapper.push('ul'); break; case 'option': wrapper.push('select'); break; case 'thead': case 'tbody': case 'tfoot': case 'tr': wrapper.push('table'); break; case 'td': case 'th': wrapper.push('table', 'tr'); break; case 'fieldset': wrapper.push('form'); break; case 'legend': wrapper.push('form', 'fieldset'); break; case 'link': case 'style': case 'script': // for style see http://social.msdn.microsoft.com/forums/en-US/iewebdevelopment/thread/33fd33f7-e857-4f6f-978e-fd486eba7174/ if (!me.support.htmlSerialize) { o = '
' + o; serialize = true; } break; } node = me(node)[0]; div = me(((DOM.isDocument(node)) ? node : node.ownerDocument).createElement('div')) .html( me.map(wrapper, function (t) { return ['<', t, '>']; }).join('') + o + me.map(wrapper.reverse(), function (t) { return ['']; }).join('') ); me.each(wrapper, function () { div = div.children().eq(0); }); ds = new DS(div.contents().get().slice((serialize) ? 1 : 0)); // can't do div.html('') as that clears child node text in ie div = div[0]; ds.each(function () { div.removeChild(this); }); return ds; } // selector return me(node || doc).find(o); }; ds.fn = DS.prototype = { // make DS look like an array push: [].push, sort: [].sort, splice: [].splice, // object accessors get: function (i) { return (arguments.length == 0) ? makeArray(this) : this[i]; }, each: function (fn) { ds.each(makeArray(this), fn); return this; }, size: function () { return this.length; }, index: function (el) { return ds.inArray(makeArray(this)); }, // plugins extend: function () { var args = makeArray(arguments); if (args.length > 0) { args.unshift(ds.fn); extend.apply(ds, args); } return ds; }, // data data: function (n, v) { var P = PROP, s = store, l = arguments.length; if (l == 0) { return this; } if (l == 1) { if (this.length == 0) { return undef; } return (s[(this[0][P] || '')] || {})[n]; } this.each(function () { var id = (this[P] || (this[P] = ELID++)); (s[id] || (s[id] = {}))[n] = v; }); return this; }, removeData: function (n) { var P = PROP, s = store; this.each(function () { delete (s[(this[P] || '')] || {})[n]; }); return this; }, queue: function (n, o) { switch (arguments.length) { case 0: n = 'fx'; case 1: if (typeof n == 'string') { return (this.data(n) || []); } o = n; n = 'fx'; default: if (!o) { return this; } if (!ds.isArray(o)) { this.each(function () { var el = $(this), q = el.data(n); if (!q) { el.data(n, q = []); } q.push(o); }); } else { this.each(function () { $(this).data(n, o.concat()); }); } this.each(function () { var q = $(this).data(n); if (q.length == 1) { q[0].call(this); } }); } return this; }, dequeue: function (n) { n = (typeof n == 'string') ? n : 'fx'; this.each(function () { var q = $(this).queue(n); q.shift(); if (q.length > 0) { q[0].call(this); } }); return this; } }; // interoperability ds.noConflict = function () { win.$ = _$; return ds; } /* * utilities */ extend({ // array and object operations makeArray: makeArray, extend: extend, each: function (o, cb) { var l, i; if (this.isArray(o)) { l = o.length; for (i = 0; i < l; i++) { if (cb.call(o[i], i, o[i]) === false) { break; } } } else { for (i in o) { if (cb.call(o[i], i, o[i]) === false) { break; } } } return o; }, grep: function (a, cb, invert) { var b = []; this.each(a, function (i, v) { var r = cb.call(win, v, i); if ((!invert && r) || (invert && !r)) { b.push(v); } }); return b; }, map: function (a, cb) { var b = [], me = this; this.each(a, function (i, v) { var r = cb.call(win, v, i); if (me.isArray(r)) { b = b.concat(r); } else if (r != null) { b.push(r); } }); return b; }, inArray: function (v, a) { var r = -1; this.each(a, function (i, w) { if (w === v) { r = i; return false; } return true; }); return r; }, merge: function (a, b) { this.each(b, function (i, v) { a.push(v); }); return a; }, unique: function (a) { var b = [], me = this; this.each(a, function (i, v) { if (me.inArray(v, b) == -1) { b.push(v); } }); return b; }, // test operations isArray: function (o) { return (o instanceof Array); }, isFunction: function (o) { return (typeof o == 'function'); }, // string operations trim: function (s) { return String(s).replace(/^\s+/, '').replace(/\s+$/, ''); } }); // browser and feature detection (function () { var div = doc.createElement('div'), o; div.innerHTML = ' a'; o = div.getElementsByTagName('a')[0]; ds.support = { cssFloat: (typeof div.style.cssFloat == 'string'), hrefNormalized: (o.getAttribute('href') == '#'), leadingWhitespace: (div.firstChild != o), noCloneEvent: true, opacity: (typeof div.style.opacity == 'string'), style: (typeof o.getAttribute('style') == 'string') }; if (o.attachEvent && o.fireEvent) { o.attachEvent('onclick', function () { ds.support.noCloneEvent = false; o.detachEvent('onclick', arguments.callee); }); o.cloneNode(true).fireEvent('onclick'); } div.innerHTML = ''; ds.support.htmlSerialize = (div.getElementsByTagName('link').length == 1); div.innerHTML = ''; o = div.getElementsByTagName('object')[0]; ds.support.objectAll = (o.getElementsByTagName('*').length == 1); o = doc.createElement('script'); try { o.appendChild(doc.createTextNode('')); ds.support.scriptEval = true; } catch (e) { ds.support.scriptEval = false; } div.innerHTML = '
'; ds.support.tbody = (div.getElementsByTagName('tbody').length == 0); div = o = null; })(); function boxModelTest() { ds.boxModel = ds.support.boxModel = (doc.compatMode == 'CSS1Compat'); } // distilled from http://www.quirksmode.org/js/detect.html ds.browser = { safari: false, opera: false, msie: false, mozilla: false, version: '' }; ds.each([ { flag: 'safari', str: 'AppleWebKit' }, { flag: 'opera', prop: win.opera, ver: 'Opera' }, { flag: 'msie', str: 'MSIE' }, { flag: 'mozilla', str: 'Gecko', ver: 'rv' } ], function () { var ua = navigator.userAgent, str = this.str, i = ua.indexOf(this.ver || str); if (!this.prop && ua.indexOf(str) == -1) { return true; } ds.browser[this.flag] = true; if (i > -1) { ds.browser.version = ua.substring(i).match(/[\d.]+/)[0]; } return false; }); /* * attributes */ var attrMap = (ds.browser.msie) ? // list from http://webbugtrack.blogspot.com/2007/08/bug-242-setattribute-doesnt-always-work.html { acceptcharset: 'acceptCharset', accesskey: 'accessKey', allowtransparency: 'allowTransparency', bgcolor: 'bgColor', cellpadding: 'cellPadding', cellspacing: 'cellSpacing', 'class': 'className', colspan: 'colSpan', defaultchecked: 'defaultChecked', defaultselected: 'defaultSelected', defaultvalue: 'defaultValue', 'for': 'htmlFor', frameborder: 'frameBorder', hspace: 'hSpace', longdesc: 'longDesc', maxlength: 'maxLength', marginwidth: 'marginWidth', marginheight: 'marginHeight', noresize: 'noResize', noshade: 'noShade', readonly: 'readOnly', rowspan: 'rowSpan', tabindex: 'tabIndex', valign: 'vAlign', vspace: 'vSpace' } : { className: 'class', htmlFor: 'for' }; extend(ds.fn, { // attr attr: function (o, v) { var self = this, l = arguments.length, el; if (l == 0) { return this; } if (typeof o != 'string') { ds.each(o, function (i, v) { self.attr(i, v); }); return this; } if (l == 1 && this.length == 0) { return undef; } el = this[0]; o = (attrMap[o]) ? attrMap[o] : o; if (o != 'style' || ds.support.style) { if (l == 1) { v = el.getAttribute(o); return (v != null) ? v : el[o]; } else { this.each((ds.isFunction(v)) ? function (i) { this.setAttribute(o, v.call(this, i)); } : function () { this.setAttribute(o, v); }); } } else { if (l == 1) { return el.style.cssText; } else { this.each((ds.isFunction(v)) ? function (i) { this.style.cssText = v.call(this, i); } : function () { this.style.cssText = v; }); } } return this; }, removeAttr: function (n) { n = (attrMap[n]) ? attrMap[n] : n; this.each(function () { this.removeAttribute(n); }); return this; }, // class addClass: function (c) { c = ds.unique(ds.trim(String(c)).replace(/\s+/, ' ').split(' ')); this.each(function () { var el = ds(this), cn = this.className; ds.each(c, function (i, v) { if (!el.hasClass(v)) { cn += ' ' + v; } }); this.className = cn; }); return this; }, hasClass: function (c) { var re = new RegExp('\\b' + c + '\\b'), r = false; this.each(function () { if (re.test(this.className)) { r = true; return false; } return true; }); return r; }, removeClass: function (c) { var res = ds.map(ds.unique(ds.trim(String(c)).replace(/\s+/, ' ').split(' ')), function (v) { return new RegExp('(?:^|\\s+)' + v + '(?:$|\\s+)'); }); this.each(function () { var cn = this.className; ds.each(res, function () { cn = cn.replace(this, ' '); }); this.className = ds.trim(cn); }); return this; }, toggleClass: function (c, s) { var l = arguments.length; this.each(function () { var el = ds(this), add = (l > 1) ? s : !el.hasClass(c); el[(add) ? 'addClass' : 'removeClass'](c); }); return this; }, // html html: function (s) { if (arguments.length == 0) { return (this.length > 0) ? this[0].innerHTML : null; } this.each(function () { this.innerHTML = s; }); return this; }, // text text: function (s) { if (arguments.length > 0) { return this.html(String(s).replace(/&/g, '&').replace(//g, '>')); } s = ''; this.each(function () { s += ds(this).html().replace(/<[^>]*>/g, '').replace(/&/g, '&'); }); return s; }, // val val: function (o) { var el, a; if (arguments.length == 0) { if (this.length == 0) { return undef; } el = this[0]; return (el.nodeName.toLowerCase() == 'select' && el.multiple) ? ds.map(makeArray(el.options), function (o) { return (o.selected) ? o.value : null; }) : el.value; } a = (ds.isArray(o)) ? o : null; this.each(function () { switch(this.nodeName.toLowerCase()) { case 'select': ds.each(makeArray(this.options), (a) ? function () { this.selected = (ds.inArray(this.value, a) > -1); } : function () { this.selected = (this.value == o); }); break; case 'input': if ((this.type == 'radio' || this.type == 'checkbox') && a) { this.checked = (ds.inArray(this.value, a) > -1); break; } default: this.value = o; break; } }); return this; } }); /* * traversing */ // this is also used for intermediate DS objects so that they have enough context to perform computations function prep(n, o, s) { return extend((n instanceof DS) ? n : ds(n), { selector: (s != null) ? ds.trim(o.selector + s) : '', context: o.context, prevObject: o }); } function rel(f, rel, all, s) { var o = prep(ds.unique(ds.map(this.get(), function (el) { return DOM.nextElement(el, rel, all); })), this, '.' + f + '()'); return (arguments.length > 3) ? prep(o.filter(String(s)), this, '.' + f + '(' + s + ')') : o; } var useChildren; // test if we can use the .children collection // broken in safari 2, see https://bugs.webkit.org/show_bug.cgi?id=3330 (function () { var div = document.createElement('div'); div.innerHTML = ''; useChildren = (!!div.children && (div.children.length == 1)); div = null; })(); extend(ds.fn, { // filtering is: function (s) { return (this.filter(s).length > 0); }, hasClass: function (c) { return this.is('.' + c); }, not: function (o) { var self = this, l = this.get(); if (o instanceof DS) { o = o.get(); } l = ds.grep(l, (typeof o == 'string') ? function (el) { return !prep(el, self).is(o); } : (ds.isArray(o)) ? function (el) { return (ds.inArray(el, o) == -1); } : function (el) { return (el != o); }); return prep(l, this, (typeof o == 'string') ? '.not(' + o + ')' : null); }, slice: function () { return prep(Array.prototype.slice.apply(this.get(), arguments), this, '.slice(' + makeArray(arguments).join(',') + ')'); }, eq: function (i) { return prep((i >= 0 && i < this.length) ? this[i] : [], this, '.eq(' + i + ')'); }, filter: function (o) { var c = this.context, doc = (c) ? (DOM.isDocument(c)) ? c : c.ownerDocument : win.doc; return (ds.isFunction(o)) ? this.map(function () { return (o.apply(this, arguments)) ? this : null; }) : prep(sel(o, doc, doc, this.get()), this, '.filter(' + o + ')'); }, map: function (fn) { // note args reversed return prep(ds.map(this.get(), function (el, i) { return fn.call(el, i, el); }), this, '.map(' + fn + ')'); // XXX }, // finding next: function () { return rel.apply(this, ['next', 'nextSibling', false].concat(makeArray(arguments))); }, nextAll: function () { return rel.apply(this, ['next', 'nextSibling', true ].concat(makeArray(arguments))); }, prev: function () { return rel.apply(this, ['prev', 'previousSibling', false].concat(makeArray(arguments))); }, prevAll: function () { return rel.apply(this, ['prev', 'previousSibling', true ].concat(makeArray(arguments))); }, parent: function () { return rel.apply(this, ['parent', 'parentNode', false].concat(makeArray(arguments))); }, parents: function () { return rel.apply(this, ['parent', 'parentNode', true ].concat(makeArray(arguments))); }, siblings: function (s) { var self = this, o = prep(ds.unique(ds.map(this.get(), function (el) { var n = prep(el, self); return n.prevAll().get().concat(n.nextAll().get()); })), this, '.siblings()'); return (arguments.length > 0) ? prep(o.filter(String(s)), this, '.siblings(' + s + ')') : o; }, children: function (s) { var D = DOM, o = prep(ds.unique(ds.map(this.get(), function (el) { var c = el.children; if (c && useChildren) { return makeArray(c); } if (!(c = el.childNodes)) { return null; } return ds.grep(makeArray(c), function (n) { return D.isElement(n); }); })), this, '.children()'); return (arguments.length > 0) ? prep(o.filter(String(s)), this, '.children(' + s + ')') : o; }, closest: function (s) { var self = this; // jQuery doesn't do unique() across all result elements return prep(ds.map(this.get(), function (el) { var o = prep(el, self), a = o.parents(s); return (o.is(s)) ? el : (((a = o.parents(s)).length > 0) ? a[0] : null); }), this); }, add: function (o) { var c = this.content; return prep(ds.unique(this.get().concat(ds(o, c).get())), this, (typeof o == 'string') ? ', ' + o : null); }, find: function (s) { var c = this.context; return prep(ds.unique(ds.map(this.get(), function (el) { return sel(s, c, el); })), this, ' ' + s); }, offsetParent: function () { return prep((this.length > 0) ? this[0].offsetParent : [], this); }, contents: function () { return prep(ds.unique(ds.map(this.get(), function (el) { return (el.nodeName.toLowerCase() == 'iframe') ? el.contentDocument : ((el.childNodes) ? makeArray(el.childNodes) : null); })), this, '.contents()'); }, // chaining andSelf: function () { return prep(ds.unique(ds.merge(this.get(), (this.prevObject) ? this.prevObject.get() : [])), this); }, end: function () { return (this.prevObject || ds([])); } }); /* * Manipulation */ function insertNodes(nodes, parent, next) { var f = (parent.ownerDocument || doc).createDocumentFragment(); ds.each(nodes, function () { f.appendChild(this); }); parent.insertBefore(f, next); } function innerNodes(outer) { var D = DOM; return ds.map(outer, function (el) { var cur = el, next = cur.firstChild; while (next) { if (!D.isElement(next)) { next = D.nextElement(next, 'nextSibling'); } if (next) { cur = next; next = next.firstChild; } } return cur; }); } extend(ds.fn, { // copying clone: function (e) { var P = PROP, h = handleEvent, els = prep(ds.map(this.get(), function (el) { return el.cloneNode(true); }), this), copy = els.find('*').andSelf().get(), orig; ds.each(copy, function () { this[P] = null; }); // XXX todo: if noCloneEvent == false then ? if (e) { orig = this.find('*').andSelf().get(); ds.each(orig, function (i) { var events = ds(this).data('events'), c; if (!events) { return; } c = copy[i]; ds.each(events, function (type, ed) { if (ed && ed.order && ed.order.length > 0) { c['on' + type] = h; } }); ds(c).data('events', extend({}, events)); }); } return els; }, // removing empty: function () { this.each(function () { var el = this; ds(el).find('*').unbind(); ds.each(makeArray(el.childNodes).reverse(), function () { el.removeChild(this); }); }); return this; }, remove: function (s) { ((arguments.length > 0) ? this.filter(String(s)) : this).each(function () { var p = this.parentNode; ds(this).find('*').andSelf().unbind(); if (p) { p.removeChild(this); } }); return this; }, // inserting inside append: function (o) { var ins = insertNodes, l = this.length; if (l == 0) { return this; } o = ds(o); if (l == 1) { ins(o.get(), this[0], null); } else { this.each(function () { ins(o.clone(true).get(), this, null); }); o.remove(); } return this; }, prepend: function (o) { var ins = insertNodes, l = this.length; if (l == 0) { return this; } o = ds(o); if (l == 1) { ins(o.get(), this[0], this[0].firstChild); } else { this.each(function () { ins(o.clone(true).get(), this, this.firstChild); }); o.remove(); } return this; }, // inserting outside after: function (o) { var ins = insertNodes, l = this.length; if (l == 0) { return this; } o = ds(o); if (l == 1) { ins(o.get(), this[0].parentNode, this[0].nextSibling); } else { this.each(function () { ins(o.clone(true).get(), this.parentNode, this.nextSibling); }); o.remove(); } return this; }, before: function (o) { var ins = insertNodes, l = this.length; if (l == 0) { return this; } o = ds(o); if (l == 1) { ins(o.get(), this[0].parentNode, this[0]); } else { this.each(function () { ins(o.clone(true).get(), this.parentNode, this); }); o.remove(); } return this; }, // inserting around wrap: function (o) { var inn = innerNodes, ins = insertNodes; o = ds(o); this.each(function () { var w = o.clone(true).get(), p = this.parentNode, s = this.nextSibling; ds(inn(w)).append(this); ins(w, p, s); }); return this; }, wrapAll: function (o) { var inn = innerNodes, ins = insertNodes, w, p, s; if (this.length == 0) { return this; } w = ds(o).get(), p = this[0].parentNode; s = this[0].nextSibling; ds(inn(w)).append(this); ins(w, p, s); return this; }, wrapInner: function (o) { var inn = innerNodes, ins = insertNodes; o = ds(o); this.each(function () { var w = o.clone(this).get(); ds(inn(w)).append(makeArray(this.childNodes)); ins(w, this, null); }); return this; }, // replacing replaceWith: function (o) { return this.after(o).remove(); }, replaceAll: function (s) { var self = this, orig = ds(s).get(), els = []; if (orig.length > 0) { ds(orig.shift()).replaceWith(this); els = els.concat(this.get()); ds.each(orig, function () { var o = self.clone(true); ds(this).replaceWith(o); els = els.concat(o.get()); }); } return prep(els, this, '.replaceAll(' + s + ')'); } }); ds.each([ { name: 'appendTo', fn: 'append' }, { name: 'prependTo', fn: 'prepend' }, { name: 'insertAfter', fn: 'after' }, { name: 'insertBefore', fn: 'before' } ], function () { var fn = this.fn; ds.fn[this.name] = function (s) { ds(s)[fn](this); return this; }; }); /* * css */ function toCamelCase(s) { return String(s).replace(/-./g, function (s) { return s.charAt(1).toUpperCase(); }); } function toCSSCase(s) { return String(s).replace(/[A-Z]/g, function (s) { return '-' + s.toLowerCase(); }); } function toPixelValue(el, prop, v) { var a = /^(-?)(\d*\.?\d*)(em|ex|in|cm|mm|pt|pc|%)$/.exec(v), sign, val, unit, s, rs, fs; if (!a) { return v; } sign = a[1]; val = parseFloat(a[2]); unit = a[3]; if (prop == 'fontSize') { // font size of el is relative to font size of el's parent el = el.parentNode; } if (unit == '%') { // can't compute percentages since we're setting 'left' val *= 0.01; unit = 'em'; } // adapted from http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 s = el.style.left; rs = el.runtimeStyle.left; el.runtimeStyle.left = el.currentStyle.left; el.style.left = '1' + unit; fs = parseFloat(el.style.pixelLeft); el.style.left = s; el.runtimeStyle.left = rs; return sign + (val * fs) + 'px'; } var numProps = { zIndex: true, lineHeight: true, opacity: true }, ieProgid = /\bprogid:DXImageTransform\.Microsoft\.Alpha\([^)]*\)/gi, ieAlpha = /\balpha\([^)]*\)/gi, ieOpacity = /opacity=([\d.]+)/i; function getBoxDetails(el, width) { var o = ds(el), l = (width) ? 'left' : 'top', r = (width) ? 'right' : 'bottom', a = [ o.css('margin-' + l), (o.css('border-' + l + '-style') != 'none') ? o.css('border-' + l + '-width') : 0, o.css('padding-' + l), (width) ? el.offsetWidth : el.offsetHeight, o.css('padding-' + r), (o.css('border-' + r + '-style') != 'none') ? o.css('border-' + r + '-width') : 0, o.css('margin-' + r) ]; a = ds.map(a, function (v) { return parseFloat(v); }); a[3] = a[3] - a[1] - a[2] - a[4] - a[5]; return a; } function dim(width, v) { var s = (width) ? 'Width' : 'Height', el, w; if (arguments.length == 1) { if (this.length == 0) { return null; } el = this[0]; if (el == win) { return (el['inner' + s] || (doc.documentElement && doc.documentElement['client' + s]) || (doc.body && doc.body['client' + s]) || 0); } else if (DOM.isDocument(el)) { return ((el.documentElement && el.documentElement['scroll' + s]) || (el.body && el.body['scroll' + s]) || 0); } return getBoxDetails(el, width)[3]; } v = ds.trim(String(v)); if (/[\d.]$/.test(v)) { v += 'px'; } s = s.toLowerCase(); if (ds.support.boxModel) { this.each(function () { ds(this).css(s, v); }); } else { w = parseFloat(v); this.each(function () { var el = ds(this), a; el.css(s, v); a = getBoxDetails(this, width); el.css(s, (w - a[3] + w) + 'px'); }); } return this; } function innerDim(width) { var a = getBoxDetails(this, width); return a[2] + a[3] + a[4]; } function outerDim(width, margin) { var a = getBoxDetails(this, width); return a[1] + a[2] + a[3] + a[4] + a[5] + ((margin) ? a[0] + a[6] : 0); } function scrollPos(left, v) { var s = (left) ? 'Left' : 'Top'; if (arguments.length == 1) { return (this.length > 0) ? this[0]['scroll' + s] : null; } this.each(function () { this['scroll' + s] = v; }); return this; } extend(ds.fn, { // css css: function (o, v) { var self = this, l = arguments.length, el, dv, progid, alpha, opacity, f; if (l == 0) { return this; } if (typeof o != 'string') { ds.each(o, function (i, v) { self.css(i, v); }); return this; } if (l == 1 && this.length == 0) { return undef; } if (o != 'opacity' || ds.support.opacity) { if (l == 1) { // adapted from http://www.quirksmode.org/dom/getstyles.html el = this[0]; dv = (el.ownerDocument || doc).defaultView; if (dv && dv.getComputedStyle) { return dv.getComputedStyle(el, null).getPropertyValue(toCSSCase(o)); } if (el.currentStyle) { o = (o == 'float') ? (ds.support.cssFloat) ? 'cssFloat' : 'styleFloat' : toCamelCase(o); return toPixelValue(el, o, el.currentStyle[o]); } return undef; } else { o = (o == 'float') ? (ds.support.cssFloat) ? 'cssFloat' : 'styleFloat' : toCamelCase(o); v = String(v); if (!numProps[o] && /^-?\d*\.?\d*$/.test(v) && /\d/.test(v)) { v += 'px'; } this.each(function () { this.style[o] = v; }); } } else { progid = ieProgid; alpha = ieAlpha; opacity = ieOpacity; if (l == 1) { el = this[0]; v = 100; // search for the lowest opacity value f = el.style.filter; ds.each([progid, alpha], function () { var a = f.match(this); ds.each(a, function (i, s) { var b = s.match(opacity), op = parseFloat((b || [])[1]); if (op < v) { v = op; } }); f = f.replace(this, ''); }); return v / 100; } else { v = ' alpha(opacity=' + (parseFloat(v) * 100) + ')'; this.each(function () { var s = this.style; s.filter = ds.trim(s.filter.replace(progid, '').replace(alpha, '') + v).replace(/\s+/g, ' '); s.zoom = '1'; // force hasLayout to apply filter }); } } return this; }, // height and width width: function () { return dim.apply(this, [true ].concat(makeArray(arguments))); }, height: function () { return dim.apply(this, [false].concat(makeArray(arguments))); }, innerWidth: function () { return (this.length > 0) ? innerDim.call(this[0], true ) : null; }, innerHeight: function () { return (this.length > 0) ? innerDim.call(this[0], false) : null; }, outerWidth: function () { return (this.length > 0) ? outerDim.apply(this[0], [true ].concat(makeArray(arguments))) : null; }, outerHeight: function () { return (this.length > 0) ? outerDim.apply(this[0], [false].concat(makeArray(arguments))) : null; }, // positioning scrollLeft: function () { return scrollPos.apply(this, [true ].concat(makeArray(arguments))); }, scrollTop: function () { return scrollPos.apply(this, [false].concat(makeArray(arguments))); } }); /* * events * adapted from Dean Edwards * http://dean.edwards.name/weblog/2005/10/add-event/ * http://dean.edwards.name/weblog/2005/10/add-event2/ */ // a counter used to create unique IDs var FNID = 1; ds.Event = function (o, el) { var me = arguments.callee, e = this; if (e == win) { return new me(o); } if (o instanceof me) { return extend(e, o); } if (typeof o == 'string') { e.type = o; e.target = el; return e; } ds.each([ 'type', 'currentTarget', 'keyCode', 'charCode', 'which', 'altKey', 'ctrlKey', 'metaKey', 'shiftKey', 'button', 'clientX', 'clientY', 'screenX', 'screenY', 'result' ], function (i, v) { e[v] = o[v]; }); extend(e, { originalEvent: o, target: (o.target) ? (DOM.isElement(o.target)) ? o.target : o.target.parentNode : o.srcElement, relatedTarget: (o.relatedTarget || ((o.type == 'mouseover') ? o.fromElement : o.toElement)), timeStamp: (o.timeStamp || (new Date()).getTime()), // pageX / pageY from http://www.quirksmode.org/js/events_properties.html pageX: (o.pageX || o.pageY) ? o.pageX : (o.clientX || o.clientY) ? o.clientX + doc.body.scrollLeft + doc.documentElement.scrollLeft : 0, pageY: (o.pageX || o.pageY) ? o.pageY : (o.clientX || o.clientY) ? o.clientY + doc.body.scrollTop + doc.documentElement.scrollTop : 0, cancelled: (o.returnValue === false), stopped: (o.cancelBubble === true), halted: (o.halted === true) }); return e; }; ds.Event.prototype = { cancelled: false, stopped: false, halted: false, preventDefault: function () { var oe = this.originalEvent; this.cancelled = true; if (!oe) { return; } oe.returnValue = false; if (oe.preventDefault) { oe.preventDefault(); } }, isDefaultPrevented: function () { return this.cancelled; }, stopPropagation: function () { var oe = this.originalEvent; this.stopped = true; if (!oe) { return; } oe.cancelBubble = true; if (oe.stopPropagation) { oe.stopPropagation(); } }, isPropagationStopped: function () { return this.stopped; }, stopImmediatePropagation: function () { this.stopPropagation(); this.halted = true; if (!oe) { return; } oe.halted = true; }, isImmediatePropagationStopped: function () { return this.halted; } }; function handleEvent(e) { var el = this, args = makeArray(arguments), type, isbeforeunload, events, ed, fns, order, ret; // grab the event object (IE uses a global event object) e = (e || win.event); if (!e.currentTarget) { e.currentTarget = el; } if (e.timeStamp == null) { e.timeStamp = (new Date()).getTime(); } e = new ds.Event(e); args[0] = e; type = e.type; isbeforeunload = (this == win && type == 'beforeunload'); if (!isbeforeunload) { ret = true; } // get a reference to the hash table of event handlers if (!(events = ds(this).data('events')) || !(ed = events[type])) { return ret; } fns = ed.fns; order = ed.order; // execute each event handler ds.each(order, function (i, id) { var f = fns[id], r; e.data = f.data; r = f.fn.apply(el, args); if (!isbeforeunload) { if (e.isDefaultPrevented()) { ret = false; } if (r === false) { e.preventDefault(); e.stopPropagation(); ret = false; } } else { if (typeof r == 'string') { ret = e.returnValue = r; } } if (typeof r != 'undefined') { e.result = r; e.originalEvent.result = r; } return !e.isImmediatePropagationStopped(); }); return ret; } function triggerEvent(els, doDefault, o, d) { var t, ont; if (!(o instanceof ds.Event) && typeof o != 'string') { o = extend(new ds.Event(), o); } d = (d || []); t = (typeof o == 'string') ? o : o.type; ont = 'on' + t; els.each(function () { var el = this, e = new ds.Event(o, el), a = [e].concat(d), r; if (t == 'click' && doDefault && el.click) { // this bubbles on its own el.click(); return; } while (el) { r = true; if (el[ont]) { r = el[ont].apply(el, a); } if (r === false) { break; } if (doDefault && !e.isDefaultPrevented() && el[t]) { el[t](); } if (e.isPropagationStopped()) { break; } el = el.parentNode; } }); return els; } function mouseenter(e) { var contains = DOM.contains, from = e.relatedTarget, to = e.target, o, d; if ((from == this || contains(this, from)) || !(to == this || contains(this, to))) { return; } o = extend(new ds.Event(e), { type: 'mouseenter', originalEvent: null }); o.stopPropagation(); d = makeArray(arguments); d.shift(); ds(this).trigger(o, d); } function mouseleave(e) { var contains = DOM.contains, from = e.target, to = e.relatedTarget, o, d; if (!(from == this || contains(this, from)) || (to == this || contains(this, to))) { return; } o = extend(new ds.Event(e), { type: 'mouseleave', originalEvent: null }); o.stopPropagation(); d = makeArray(arguments); d.shift(); ds(this).trigger(o, d); } var nativeMouseenter; // based on http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/ (function () { var div = document.createElement('div'); nativeMouseenter = ('onmouseenter' in div); if (!nativeMouseenter) { div.setAttribute('onmouseenter', 'return;'); nativeMouseenter = ds.isFunction(div.onmouseenter); } div = null; })(); // document ready based on // http://dean.edwards.name/weblog/2006/06/again/ // http://javascript.nwbox.com/ContentLoaded/ // we'll stick with browser detects for now, since to feature detect these feels dangerous function setupReady() { var fn = ready; if (ds._readying) { return; } // mozilla, newer webkit, opera if (doc.addEventListener) { doc.addEventListener('DOMContentLoaded', fn, false); } // older webkit if (ds.browser.safari && parseFloat(ds.browser.version) < 525.13) { ds._readyTimer = setInterval(function () { if (/loaded|complete/.test(document.readyState)) { fn(); // call the onload handler } }, 0); } // ie if (ds.browser.msie) { ds._readyRSC = function (e) { if (doc.readyState == 'complete') { fn(); } }; doc.attachEvent('onreadystatechange', ds._readyRSC); if (win == win.top) { ds._readyTimer = setInterval(function () { var done = false; try { doc.documentElement.doScroll('left'); done = true; } catch (e) { done = false; } if (done) { fn(); } }, 0); } } // fallback ds(window).load(fn); ds._readying = true; } function ready() { var fn = arguments.callee; if (ds._readied) { return; } // mozilla, newer webkit, opera if (doc.addEventListener) { doc.removeEventListener('DOMContentLoaded', fn, false); } // older webkit if (ds.browser.safari && parseFloat(ds.browser.version) < 525.13) { clearInterval(ds._readyTimer); ds._readyTimer = null; } // ie if (ds.browser.msie) { doc.detachEvent('onreadystatechange', ds._readyRSC); ds._readyRSC = null; if (win == win.top) { clearInterval(ds._readyTimer); ds._readyTimer = null; } } // fallback ds(window).unbind('load', fn); ds._readied = true; // note: we pass an event object instead of the dollar sign object // this is different that with jQuery ds(doc).trigger('ready'); } ds.fn.extend({ // event handling bind: function (t, o, fn) { var P = PROP, h = handleEvent, u = {}, hasDoc = false, id; ds.each(ds.trim(String(t)).replace(/\s+/, ' ').split(' '), function (i, v) { u[v] = true; }); if (arguments.length < 3) { fn = o; o = undef; } // assign each event handler a unique ID id = (fn[P] || (fn[P] = FNID++)); this.each(function () { var elem = this, el = ds(this), events = el.data('events'); // create a hash table of event types for the element if (!events) { el.data('events', (events = {})); } ds.each(u, function (type) { // create a hash table of event handlers for each element/event pair var ed = (events[type] || (events[type] = { fns: {}, order: [] })), fns = ed.fns, order = ed.order, g = elem['on' + type], i; if (g != h) { // store the existing event handler (if there is one) if (g) { i = (g[P] || (g[P] = FNID++)); if (!fns[i]) { fns[i] = { fn: g }; order.push(i); } } // assign a global event handler to do all the work elem['on' + type] = h; } // store the event handler in the hash table if (!fns[id]) { fns[id] = { fn: fn, data: o }; order.push(id); } }); if (this == doc) { hasDoc = true; } }); if (!nativeMouseenter) { if (u.mouseenter) { this.bind('mouseover', mouseenter); } if (u.mouseleave) { this.bind('mouseout', mouseleave); } } if (hasDoc && u.ready) { setupReady(); } return this; }, one: function () { var args = makeArray(arguments), fn = args.pop(); args.push(function (e) { ds(this).unbind(e.type, arguments.callee); return fn.apply(this, arguments); }); return this.bind.apply(this, args); }, unbind: function (t, fn) { var h = handleEvent, enter = mouseenter, leave = mouseleave, u = {}, els, id; ds.each(ds.trim(String(t)).replace(/\s+/, ' ').split(' '), function (i, v) { u[v] = true; }); switch (arguments.length) { case 0: this.each(function () { var el = ds(this), events = el.data('events'), type; if (!events) { return; } for (type in events) { if (this['on' + type] == h) { this['on' + type] = null; } } el.removeData('events'); }); break; case 1: els = []; this.each(function () { var elem = this, el = ds(this), events = el.data('events'); if (!events) { return; } ds.each(u, function (type) { if (elem['on' + type] == h) { elem['on' + type] = null; } delete events[type]; }); els.push(this); }); if (!nativeMouseenter) { if (u.mouseover && !u.mouseenter) { ds.each(els, function () { var el = ds(this), events = el.data('events'); if (events.mouseenter && events.mouseenter.order.length > 0) { el.bind('mouseover', enter); } }); } if (u.mouseout && !u.mouseleave) { ds.each(els, function () { var el = ds(this), events = el.data('events'); if (events.mouseleave && events.mouseleave.order.length > 0) { el.bind('mouseout', leave); } }); } } break; default: if (!(id = fn[PROP])) { break; } this.each(function () { var el = ds(this), events = el.data('events'); if (!events) { return; } ds.each(u, function (type) { var ed = events[type], fns, order, i; if (!ed) { return; } fns = ed.fns; order = ed.order; if (!fns[id] || (i = ds.inArray(id, order)) == -1) { return; } // delete the event handler from the hash table delete fns[id]; order.splice(i, 1); }); }); break; } return this; }, trigger: function (e, d) { return triggerEvent(this, true, e, d); }, triggerHandler: function (e, d) { return triggerEvent(this, false, e, d); }, // interaction helpers hover: function (over, out) { return this.mouseenter(over).mouseleave(out); }, toggle: function () { var fns = makeArray(arguments), l = fns.length, i = 0; if (l == 0) { return this; } return this.click(function () { fns[i].apply(this, arguments); i = (i + 1) % l; }); } }); // event helpers ds.each([ 'blur', 'change', 'click', 'dblclick', 'error', 'focus', 'keydown', 'keypress', 'keyup', 'select', 'submit' ], function (i, type) { ds.fn[type] = function () { return (arguments.length == 0) ? this.trigger(type) : this.bind(type, arguments[0]); }; }); ds.each([ 'load', 'mousedown', 'mouseenter', 'mouseleave', 'mousemove', 'mouseout', 'mouseover', 'mouseup', 'ready', 'resize', 'scroll', 'unload' ], function (i, type) { ds.fn[type] = function (fn) { return this.bind(type, fn); }; }); // XXX todo: clear cache on page unload ds(boxModelTest); win.$ = ds; })();