Skip to content
This repository
Browse code

Update to MooTools 1.4.1

  • Loading branch information...
commit d72c8bfccbac5301d9097baca25cf0d4f3f381a7 1 parent 9ea99da
Arian Stolwijk arian authored
1,064 Source/mootools-core-1.3-full.js → Source/mootools-core-1.4-full.js
@@ -3,10 +3,10 @@
3 3 MooTools: the javascript framework
4 4
5 5 web build:
6   - - http://mootools.net/core/7c56cfef9dddcf170a5d68e3fb61cfd7
  6 + - http://mootools.net/core/76bf47062d6c1983d66ce47ad66aa0e0
7 7
8 8 packager build:
9   - - packager build Core/Core Core/Array Core/String Core/Number Core/Function Core/Object Core/Event Core/Browser Core/Class Core/Class.Extras Core/Slick.Parser Core/Slick.Finder Core/Element Core/Element.Style Core/Element.Event Core/Element.Dimensions Core/Fx Core/Fx.CSS Core/Fx.Tween Core/Fx.Morph Core/Fx.Transitions Core/Request Core/Request.HTML Core/Request.JSON Core/Cookie Core/JSON Core/DOMReady Core/Swiff
  9 + - packager build Core/Core Core/Array Core/String Core/Number Core/Function Core/Object Core/Event Core/Browser Core/Class Core/Class.Extras Core/Slick.Parser Core/Slick.Finder Core/Element Core/Element.Style Core/Element.Event Core/Element.Delegation Core/Element.Dimensions Core/Fx Core/Fx.CSS Core/Fx.Tween Core/Fx.Morph Core/Fx.Transitions Core/Request Core/Request.HTML Core/Request.JSON Core/Cookie Core/JSON Core/DOMReady Core/Swiff
10 10
11 11 /*
12 12 ---
@@ -33,8 +33,8 @@ provides: [Core, MooTools, Type, typeOf, instanceOf, Native]
33 33 (function(){
34 34
35 35 this.MooTools = {
36   - version: '1.3.2',
37   - build: 'c9f1ff10e9e7facb65e9481049ed1b450959d587'
  36 + version: '1.4.1',
  37 + build: 'd1fb25710e3c5482a219ab9dc675a4e0ad2176b6'
38 38 };
39 39
40 40 // typeOf, instanceOf
@@ -265,7 +265,7 @@ var force = function(name, object, methods){
265 265
266 266 force('String', String, [
267 267 'charAt', 'charCodeAt', 'concat', 'indexOf', 'lastIndexOf', 'match', 'quote', 'replace', 'search',
268   - 'slice', 'split', 'substr', 'substring', 'toLowerCase', 'toUpperCase'
  268 + 'slice', 'split', 'substr', 'substring', 'trim', 'toLowerCase', 'toUpperCase'
269 269 ])('Array', Array, [
270 270 'pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift', 'concat', 'join', 'slice',
271 271 'indexOf', 'lastIndexOf', 'filter', 'forEach', 'every', 'map', 'some', 'reduce', 'reduceRight'
@@ -421,7 +421,7 @@ Array.implement({
421 421
422 422 /*<!ES5>*/
423 423 every: function(fn, bind){
424   - for (var i = 0, l = this.length; i < l; i++){
  424 + for (var i = 0, l = this.length >>> 0; i < l; i++){
425 425 if ((i in this) && !fn.call(bind, this[i], i, this)) return false;
426 426 }
427 427 return true;
@@ -429,30 +429,30 @@ Array.implement({
429 429
430 430 filter: function(fn, bind){
431 431 var results = [];
432   - for (var i = 0, l = this.length; i < l; i++){
  432 + for (var i = 0, l = this.length >>> 0; i < l; i++){
433 433 if ((i in this) && fn.call(bind, this[i], i, this)) results.push(this[i]);
434 434 }
435 435 return results;
436 436 },
437 437
438 438 indexOf: function(item, from){
439   - var len = this.length;
440   - for (var i = (from < 0) ? Math.max(0, len + from) : from || 0; i < len; i++){
  439 + var length = this.length >>> 0;
  440 + for (var i = (from < 0) ? Math.max(0, length + from) : from || 0; i < length; i++){
441 441 if (this[i] === item) return i;
442 442 }
443 443 return -1;
444 444 },
445 445
446 446 map: function(fn, bind){
447   - var results = [];
448   - for (var i = 0, l = this.length; i < l; i++){
  447 + var length = this.length >>> 0, results = Array(length);
  448 + for (var i = 0; i < length; i++){
449 449 if (i in this) results[i] = fn.call(bind, this[i], i, this);
450 450 }
451 451 return results;
452 452 },
453 453
454 454 some: function(fn, bind){
455   - for (var i = 0, l = this.length; i < l; i++){
  455 + for (var i = 0, l = this.length >>> 0; i < l; i++){
456 456 if ((i in this) && fn.call(bind, this[i], i, this)) return true;
457 457 }
458 458 return false;
@@ -596,37 +596,37 @@ String.implement({
596 596 },
597 597
598 598 contains: function(string, separator){
599   - return (separator) ? (separator + this + separator).indexOf(separator + string + separator) > -1 : this.indexOf(string) > -1;
  599 + return (separator) ? (separator + this + separator).indexOf(separator + string + separator) > -1 : String(this).indexOf(string) > -1;
600 600 },
601 601
602 602 trim: function(){
603   - return this.replace(/^\s+|\s+$/g, '');
  603 + return String(this).replace(/^\s+|\s+$/g, '');
604 604 },
605 605
606 606 clean: function(){
607   - return this.replace(/\s+/g, ' ').trim();
  607 + return String(this).replace(/\s+/g, ' ').trim();
608 608 },
609 609
610 610 camelCase: function(){
611   - return this.replace(/-\D/g, function(match){
  611 + return String(this).replace(/-\D/g, function(match){
612 612 return match.charAt(1).toUpperCase();
613 613 });
614 614 },
615 615
616 616 hyphenate: function(){
617   - return this.replace(/[A-Z]/g, function(match){
  617 + return String(this).replace(/[A-Z]/g, function(match){
618 618 return ('-' + match.charAt(0).toLowerCase());
619 619 });
620 620 },
621 621
622 622 capitalize: function(){
623   - return this.replace(/\b[a-z]/g, function(match){
  623 + return String(this).replace(/\b[a-z]/g, function(match){
624 624 return match.toUpperCase();
625 625 });
626 626 },
627 627
628 628 escapeRegExp: function(){
629   - return this.replace(/([-.*+?^${}()|[\]\/\\])/g, '\\$1');
  629 + return String(this).replace(/([-.*+?^${}()|[\]\/\\])/g, '\\$1');
630 630 },
631 631
632 632 toInt: function(base){
@@ -638,17 +638,17 @@ String.implement({
638 638 },
639 639
640 640 hexToRgb: function(array){
641   - var hex = this.match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/);
  641 + var hex = String(this).match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/);
642 642 return (hex) ? hex.slice(1).hexToRgb(array) : null;
643 643 },
644 644
645 645 rgbToHex: function(array){
646   - var rgb = this.match(/\d{1,3}/g);
  646 + var rgb = String(this).match(/\d{1,3}/g);
647 647 return (rgb) ? rgb.rgbToHex(array) : null;
648 648 },
649 649
650 650 substitute: function(object, regexp){
651   - return this.replace(regexp || (/\\?\{([^{}]+)\}/g), function(match, name){
  651 + return String(this).replace(regexp || (/\\?\{([^{}]+)\}/g), function(match, name){
652 652 if (match.charAt(0) == '\\') return match.slice(1);
653 653 return (object[name] != null) ? object[name] : '';
654 654 });
@@ -750,18 +750,26 @@ Function.implement({
750 750 return null;
751 751 },
752 752
753   - /*<!ES5>*/
754   - bind: function(bind){
  753 + /*<!ES5-bind>*/
  754 + bind: function(that){
755 755 var self = this,
756   - args = (arguments.length > 1) ? Array.slice(arguments, 1) : null;
757   -
758   - return function(){
759   - if (!args && !arguments.length) return self.call(bind);
760   - if (args && arguments.length) return self.apply(bind, args.concat(Array.from(arguments)));
761   - return self.apply(bind, args || arguments);
  756 + args = arguments.length > 1 ? Array.slice(arguments, 1) : null,
  757 + F = function(){};
  758 +
  759 + var bound = function(){
  760 + var context = that, length = arguments.length;
  761 + if (this instanceof bound){
  762 + F.prototype = self.prototype;
  763 + context = new F;
  764 + }
  765 + var result = (!args && !length)
  766 + ? self.call(context)
  767 + : self.apply(context, args && length ? args.concat(Array.slice(arguments)) : args || arguments);
  768 + return context == that ? result : context;
762 769 };
  770 + return bound;
763 771 },
764   - /*</!ES5>*/
  772 + /*</!ES5-bind>*/
765 773
766 774 pass: function(args, bind){
767 775 var self = this;
@@ -1118,7 +1126,7 @@ try {
1118 1126
1119 1127 name: Event
1120 1128
1121   -description: Contains the Event Class, to make the event object cross-browser.
  1129 +description: Contains the Event Type, to make the event object cross-browser.
1122 1130
1123 1131 license: MIT-style license.
1124 1132
@@ -1129,52 +1137,54 @@ provides: Event
1129 1137 ...
1130 1138 */
1131 1139
1132   -var Event = new Type('Event', function(event, win){
  1140 +(function() {
  1141 +
  1142 +var _keys = {};
  1143 +
  1144 +var DOMEvent = this.DOMEvent = new Type('DOMEvent', function(event, win){
1133 1145 if (!win) win = window;
1134   - var doc = win.document;
1135 1146 event = event || win.event;
1136 1147 if (event.$extended) return event;
  1148 + this.event = event;
1137 1149 this.$extended = true;
1138   - var type = event.type,
1139   - target = event.target || event.srcElement,
1140   - page = {},
1141   - client = {},
1142   - related = null,
1143   - rightClick, wheel, code, key;
  1150 + this.shift = event.shiftKey;
  1151 + this.control = event.ctrlKey;
  1152 + this.alt = event.altKey;
  1153 + this.meta = event.metaKey;
  1154 + var type = this.type = event.type;
  1155 + var target = event.target || event.srcElement;
1144 1156 while (target && target.nodeType == 3) target = target.parentNode;
  1157 + this.target = document.id(target);
1145 1158
1146   - if (type.indexOf('key') != -1){
1147   - code = event.which || event.keyCode;
1148   - key = Object.keyOf(Event.Keys, code);
  1159 + if (type.indexOf('key') == 0){
  1160 + var code = this.code = (event.which || event.keyCode);
  1161 + this.key = _keys[code];
1149 1162 if (type == 'keydown'){
1150   - var fKey = code - 111;
1151   - if (fKey > 0 && fKey < 13) key = 'f' + fKey;
  1163 + if (code > 111 && code < 124) this.key = 'f' + (code - 111);
  1164 + else if (code > 95 && code < 106) this.key = code - 96;
1152 1165 }
1153   - if (!key) key = String.fromCharCode(code).toLowerCase();
1154   - } else if ((/click|mouse|menu/i).test(type)){
  1166 + if (this.key == null) this.key = String.fromCharCode(code).toLowerCase();
  1167 + } else if (type == 'click' || type == 'dblclick' || type == 'contextmenu' || type == 'DOMMouseScroll' || type.indexOf('mouse') == 0){
  1168 + var doc = win.document;
1155 1169 doc = (!doc.compatMode || doc.compatMode == 'CSS1Compat') ? doc.html : doc.body;
1156   - page = {
  1170 + this.page = {
1157 1171 x: (event.pageX != null) ? event.pageX : event.clientX + doc.scrollLeft,
1158 1172 y: (event.pageY != null) ? event.pageY : event.clientY + doc.scrollTop
1159 1173 };
1160   - client = {
  1174 + this.client = {
1161 1175 x: (event.pageX != null) ? event.pageX - win.pageXOffset : event.clientX,
1162 1176 y: (event.pageY != null) ? event.pageY - win.pageYOffset : event.clientY
1163 1177 };
1164   - if ((/DOMMouseScroll|mousewheel/).test(type)){
1165   - wheel = (event.wheelDelta) ? event.wheelDelta / 120 : -(event.detail || 0) / 3;
1166   - }
1167   - rightClick = (event.which == 3) || (event.button == 2);
1168   - if ((/over|out/).test(type)){
1169   - related = event.relatedTarget || event[(type == 'mouseover' ? 'from' : 'to') + 'Element'];
1170   - var testRelated = function(){
1171   - while (related && related.nodeType == 3) related = related.parentNode;
1172   - return true;
1173   - };
1174   - var hasRelated = (Browser.firefox2) ? testRelated.attempt() : testRelated();
1175   - related = (hasRelated) ? related : null;
  1178 + if (type == 'DOMMouseScroll' || type == 'mousewheel')
  1179 + this.wheel = (event.wheelDelta) ? event.wheelDelta / 120 : -(event.detail || 0) / 3;
  1180 +
  1181 + this.rightClick = (event.which == 3 || event.button == 2);
  1182 + if (type == 'mouseover' || type == 'mouseout'){
  1183 + var related = event.relatedTarget || event[(type == 'mouseover' ? 'from' : 'to') + 'Element'];
  1184 + while (related && related.nodeType == 3) related = related.parentNode;
  1185 + this.relatedTarget = document.id(related);
1176 1186 }
1177   - } else if ((/gesture|touch/i).test(type)){
  1187 + } else if (type.indexOf('touch') == 0 || type.indexOf('gesture') == 0){
1178 1188 this.rotation = event.rotation;
1179 1189 this.scale = event.scale;
1180 1190 this.targetTouches = event.targetTouches;
@@ -1182,53 +1192,19 @@ var Event = new Type('Event', function(event, win){
1182 1192 var touches = this.touches = event.touches;
1183 1193 if (touches && touches[0]){
1184 1194 var touch = touches[0];
1185   - page = {x: touch.pageX, y: touch.pageY};
1186   - client = {x: touch.clientX, y: touch.clientY};
  1195 + this.page = {x: touch.pageX, y: touch.pageY};
  1196 + this.client = {x: touch.clientX, y: touch.clientY};
1187 1197 }
1188 1198 }
1189 1199
1190   - return Object.append(this, {
1191   - event: event,
1192   - type: type,
1193   -
1194   - page: page,
1195   - client: client,
1196   - rightClick: rightClick,
1197   -
1198   - wheel: wheel,
1199   -
1200   - relatedTarget: document.id(related),
1201   - target: document.id(target),
1202   -
1203   - code: code,
1204   - key: key,
1205   -
1206   - shift: event.shiftKey,
1207   - control: event.ctrlKey,
1208   - alt: event.altKey,
1209   - meta: event.metaKey
1210   - });
  1200 + if (!this.client) this.client = {};
  1201 + if (!this.page) this.page = {};
1211 1202 });
1212 1203
1213   -Event.Keys = {
1214   - 'enter': 13,
1215   - 'up': 38,
1216   - 'down': 40,
1217   - 'left': 37,
1218   - 'right': 39,
1219   - 'esc': 27,
1220   - 'space': 32,
1221   - 'backspace': 8,
1222   - 'tab': 9,
1223   - 'delete': 46
1224   -};
1225   -
1226   -
1227   -
1228   -Event.implement({
  1204 +DOMEvent.implement({
1229 1205
1230 1206 stop: function(){
1231   - return this.stopPropagation().preventDefault();
  1207 + return this.preventDefault().stopPropagation();
1232 1208 },
1233 1209
1234 1210 stopPropagation: function(){
@@ -1245,6 +1221,25 @@ Event.implement({
1245 1221
1246 1222 });
1247 1223
  1224 +DOMEvent.defineKey = function(code, key){
  1225 + _keys[code] = key;
  1226 + return this;
  1227 +};
  1228 +
  1229 +DOMEvent.defineKeys = DOMEvent.defineKey.overloadSetter(true);
  1230 +
  1231 +DOMEvent.defineKeys({
  1232 + '38': 'up', '40': 'down', '37': 'left', '39': 'right',
  1233 + '27': 'esc', '32': 'space', '8': 'backspace', '9': 'tab',
  1234 + '46': 'delete', '13': 'enter'
  1235 +});
  1236 +
  1237 +})();
  1238 +
  1239 +
  1240 +
  1241 +
  1242 +
1248 1243
1249 1244 /*
1250 1245 ---
@@ -2280,7 +2275,7 @@ local.matchNode = function(node, selector){
2280 2275 if (!parsed) return true;
2281 2276
2282 2277 // simple (single) selectors
2283   - var expressions = parsed.expressions, reversedExpressions, simpleExpCounter = 0, i;
  2278 + var expressions = parsed.expressions, simpleExpCounter = 0, i;
2284 2279 for (i = 0; (currentExpression = expressions[i]); i++){
2285 2280 if (currentExpression.length == 1){
2286 2281 var exp = currentExpression[0];
@@ -2575,7 +2570,7 @@ for (var p in pseudos) local['pseudo:' + p] = pseudos[p];
2575 2570
2576 2571 // attributes methods
2577 2572
2578   -local.attributeGetters = {
  2573 +var attributeGetters = local.attributeGetters = {
2579 2574
2580 2575 'class': function(){
2581 2576 return this.getAttribute('class') || this.className;
@@ -2600,15 +2595,22 @@ local.attributeGetters = {
2600 2595
2601 2596 'type': function(){
2602 2597 return this.getAttribute('type');
  2598 + },
  2599 +
  2600 + 'maxlength': function(){
  2601 + var attributeNode = this.getAttributeNode('maxLength');
  2602 + return (attributeNode && attributeNode.specified) ? attributeNode.nodeValue : null;
2603 2603 }
2604 2604
2605 2605 };
2606 2606
  2607 +attributeGetters.MAXLENGTH = attributeGetters.maxLength = attributeGetters.maxlength;
  2608 +
2607 2609 // Slick
2608 2610
2609 2611 var Slick = local.Slick = (this.Slick || {});
2610 2612
2611   -Slick.version = '1.1.5';
  2613 +Slick.version = '1.1.6';
2612 2614
2613 2615 // Slick finder
2614 2616
@@ -2630,9 +2632,15 @@ Slick.contains = function(container, node){
2630 2632 // Slick attribute getter
2631 2633
2632 2634 Slick.getAttribute = function(node, name){
  2635 + local.setDocument(node);
2633 2636 return local.getAttribute(node, name);
2634 2637 };
2635 2638
  2639 +Slick.hasAttribute = function(node, name){
  2640 + local.setDocument(node);
  2641 + return local.hasAttribute(node, name);
  2642 +};
  2643 +
2636 2644 // Slick matcher
2637 2645
2638 2646 Slick.match = function(node, selector){
@@ -2697,7 +2705,7 @@ description: One of the most important items in MooTools. Contains the dollar fu
2697 2705
2698 2706 license: MIT-style license.
2699 2707
2700   -requires: [Window, Document, Array, String, Function, Number, Slick.Parser, Slick.Finder]
  2708 +requires: [Window, Document, Array, String, Function, Object, Number, Slick.Parser, Slick.Finder]
2701 2709
2702 2710 provides: [Element, Elements, $, $$, Iframe, Selectors]
2703 2711
@@ -2717,8 +2725,8 @@ var Element = function(tag, props){
2717 2725 if (parsed.id && props.id == null) props.id = parsed.id;
2718 2726
2719 2727 var attributes = parsed.attributes;
2720   - if (attributes) for (var i = 0, l = attributes.length; i < l; i++){
2721   - var attr = attributes[i];
  2728 + if (attributes) for (var attr, i = 0, l = attributes.length; i < l; i++){
  2729 + attr = attributes[i];
2722 2730 if (props[attr.key] != null) continue;
2723 2731
2724 2732 if (attr.value != null && attr.operator == '=') props[attr.key] = attr.value;
@@ -2862,9 +2870,9 @@ var splice = Array.prototype.splice, object = {'0': 0, '1': 1, length: 2};
2862 2870 splice.call(object, 1, 1);
2863 2871 if (object[1] == 1) Elements.implement('splice', function(){
2864 2872 var length = this.length;
2865   - splice.apply(this, arguments);
  2873 + var result = splice.apply(this, arguments);
2866 2874 while (length >= this.length) delete this[length--];
2867   - return this;
  2875 + return result;
2868 2876 }.protect());
2869 2877
2870 2878 Elements.implement(Array.prototype);
@@ -2984,6 +2992,79 @@ Window.implement({
2984 2992
2985 2993 });
2986 2994
  2995 +var contains = {contains: function(element){
  2996 + return Slick.contains(this, element);
  2997 +}};
  2998 +
  2999 +if (!document.contains) Document.implement(contains);
  3000 +if (!document.createElement('div').contains) Element.implement(contains);
  3001 +
  3002 +
  3003 +
  3004 +// tree walking
  3005 +
  3006 +var injectCombinator = function(expression, combinator){
  3007 + if (!expression) return combinator;
  3008 +
  3009 + expression = Object.clone(Slick.parse(expression));
  3010 +
  3011 + var expressions = expression.expressions;
  3012 + for (var i = expressions.length; i--;)
  3013 + expressions[i][0].combinator = combinator;
  3014 +
  3015 + return expression;
  3016 +};
  3017 +
  3018 +Object.forEach({
  3019 + getNext: '~',
  3020 + getPrevious: '!~',
  3021 + getParent: '!'
  3022 +}, function(combinator, method){
  3023 + Element.implement(method, function(expression){
  3024 + return this.getElement(injectCombinator(expression, combinator));
  3025 + });
  3026 +});
  3027 +
  3028 +Object.forEach({
  3029 + getAllNext: '~',
  3030 + getAllPrevious: '!~',
  3031 + getSiblings: '~~',
  3032 + getChildren: '>',
  3033 + getParents: '!'
  3034 +}, function(combinator, method){
  3035 + Element.implement(method, function(expression){
  3036 + return this.getElements(injectCombinator(expression, combinator));
  3037 + });
  3038 +});
  3039 +
  3040 +Element.implement({
  3041 +
  3042 + getFirst: function(expression){
  3043 + return document.id(Slick.search(this, injectCombinator(expression, '>'))[0]);
  3044 + },
  3045 +
  3046 + getLast: function(expression){
  3047 + return document.id(Slick.search(this, injectCombinator(expression, '>')).getLast());
  3048 + },
  3049 +
  3050 + getWindow: function(){
  3051 + return this.ownerDocument.window;
  3052 + },
  3053 +
  3054 + getDocument: function(){
  3055 + return this.ownerDocument;
  3056 + },
  3057 +
  3058 + getElementById: function(id){
  3059 + return document.id(Slick.find(this, '#' + ('' + id).replace(/(\W)/g, '\\$1')));
  3060 + },
  3061 +
  3062 + match: function(expression){
  3063 + return !expression || Slick.match(this, expression);
  3064 + }
  3065 +
  3066 +});
  3067 +
2987 3068
2988 3069
2989 3070 if (window.$$ == null) Window.implement('$$', function(selector){
@@ -2996,48 +3077,7 @@ if (window.$$ == null) Window.implement('$$', function(selector){
2996 3077
2997 3078 (function(){
2998 3079
2999   -var collected = {}, storage = {};
3000   -var formProps = {input: 'checked', option: 'selected', textarea: 'value'};
3001   -
3002   -var get = function(uid){
3003   - return (storage[uid] || (storage[uid] = {}));
3004   -};
3005   -
3006   -var clean = function(item){
3007   - var uid = item.uid;
3008   - if (item.removeEvents) item.removeEvents();
3009   - if (item.clearAttributes) item.clearAttributes();
3010   - if (uid != null){
3011   - delete collected[uid];
3012   - delete storage[uid];
3013   - }
3014   - return item;
3015   -};
3016   -
3017   -var camels = ['defaultValue', 'accessKey', 'cellPadding', 'cellSpacing', 'colSpan', 'frameBorder', 'maxLength', 'readOnly',
3018   - 'rowSpan', 'tabIndex', 'useMap'
3019   -];
3020   -var bools = ['compact', 'nowrap', 'ismap', 'declare', 'noshade', 'checked', 'disabled', 'readOnly', 'multiple', 'selected',
3021   - 'noresize', 'defer', 'defaultChecked'
3022   -];
3023   - var attributes = {
3024   - 'html': 'innerHTML',
3025   - 'class': 'className',
3026   - 'for': 'htmlFor',
3027   - 'text': (function(){
3028   - var temp = document.createElement('div');
3029   - return (temp.textContent == null) ? 'innerText' : 'textContent';
3030   - })()
3031   -};
3032   -var readOnly = ['type'];
3033   -var expandos = ['value', 'defaultValue'];
3034   -var uriAttrs = /^(?:href|src|usemap)$/i;
3035   -
3036   -bools = bools.associate(bools);
3037   -camels = camels.associate(camels.map(String.toLowerCase));
3038   -readOnly = readOnly.associate(readOnly);
3039   -
3040   -Object.append(attributes, expandos.associate(expandos));
  3080 +// Inserters
3041 3081
3042 3082 var inserters = {
3043 3083
@@ -3065,42 +3105,92 @@ inserters.inside = inserters.bottom;
3065 3105
3066 3106
3067 3107
3068   -var injectCombinator = function(expression, combinator){
3069   - if (!expression) return combinator;
  3108 +// getProperty / setProperty
3070 3109
3071   - expression = Object.clone(Slick.parse(expression));
  3110 +var propertyGetters = {}, propertySetters = {};
3072 3111
3073   - var expressions = expression.expressions;
3074   - for (var i = expressions.length; i--;)
3075   - expressions[i][0].combinator = combinator;
  3112 +// properties
3076 3113
3077   - return expression;
3078   -};
  3114 +var properties = {};
  3115 +Array.forEach([
  3116 + 'type', 'value', 'defaultValue', 'accessKey', 'cellPadding', 'cellSpacing', 'colSpan',
  3117 + 'frameBorder', 'readOnly', 'rowSpan', 'tabIndex', 'useMap'
  3118 +], function(property){
  3119 + properties[property.toLowerCase()] = property;
  3120 +});
3079 3121
3080   -Element.implement({
  3122 +Object.append(properties, {
  3123 + 'html': 'innerHTML',
  3124 + 'text': (function(){
  3125 + var temp = document.createElement('div');
  3126 + return (temp.textContent == null) ? 'innerText': 'textContent';
  3127 + })()
  3128 +});
3081 3129
3082   - set: function(prop, value){
3083   - var property = Element.Properties[prop];
3084   - (property && property.set) ? property.set.call(this, value) : this.setProperty(prop, value);
3085   - }.overloadSetter(),
  3130 +Object.forEach(properties, function(real, key){
  3131 + propertySetters[key] = function(node, value){
  3132 + node[real] = value;
  3133 + };
  3134 + propertyGetters[key] = function(node){
  3135 + return node[real];
  3136 + };
  3137 +});
3086 3138
3087   - get: function(prop){
3088   - var property = Element.Properties[prop];
3089   - return (property && property.get) ? property.get.apply(this) : this.getProperty(prop);
3090   - }.overloadGetter(),
  3139 +// Booleans
3091 3140
3092   - erase: function(prop){
3093   - var property = Element.Properties[prop];
3094   - (property && property.erase) ? property.erase.apply(this) : this.removeProperty(prop);
3095   - return this;
  3141 +var bools = [
  3142 + 'compact', 'nowrap', 'ismap', 'declare', 'noshade', 'checked',
  3143 + 'disabled', 'readOnly', 'multiple', 'selected', 'noresize',
  3144 + 'defer', 'defaultChecked', 'autofocus', 'controls', 'autoplay',
  3145 + 'loop'
  3146 +];
  3147 +
  3148 +var booleans = {};
  3149 +Array.forEach(bools, function(bool){
  3150 + var lower = bool.toLowerCase();
  3151 + booleans[lower] = bool;
  3152 + propertySetters[lower] = function(node, value){
  3153 + node[bool] = !!value;
  3154 + };
  3155 + propertyGetters[lower] = function(node){
  3156 + return !!node[bool];
  3157 + };
  3158 +});
  3159 +
  3160 +// Special cases
  3161 +
  3162 +Object.append(propertySetters, {
  3163 +
  3164 + 'class': function(node, value){
  3165 + ('className' in node) ? node.className = value : node.setAttribute('class', value);
  3166 + },
  3167 +
  3168 + 'for': function(node, value){
  3169 + ('htmlFor' in node) ? node.htmlFor = value : node.setAttribute('for', value);
3096 3170 },
3097 3171
3098   - setProperty: function(attribute, value){
3099   - attribute = camels[attribute] || attribute;
3100   - if (value == null) return this.removeProperty(attribute);
3101   - var key = attributes[attribute];
3102   - (key) ? this[key] = value :
3103   - (bools[attribute]) ? this[attribute] = !!value : this.setAttribute(attribute, '' + value);
  3172 + 'style': function(node, value){
  3173 + (node.style) ? node.style.cssText = value : node.setAttribute('style', value);
  3174 + }
  3175 +
  3176 +});
  3177 +
  3178 +/* getProperty, setProperty */
  3179 +
  3180 +Element.implement({
  3181 +
  3182 + setProperty: function(name, value){
  3183 + var lower = name.toLowerCase();
  3184 + if (value == null){
  3185 + if (!booleans[lower]){
  3186 + this.removeAttribute(name);
  3187 + return this;
  3188 + }
  3189 + value = false;
  3190 + }
  3191 + var setter = propertySetters[lower];
  3192 + if (setter) setter(this, value);
  3193 + else this.setAttribute(name, value);
3104 3194 return this;
3105 3195 },
3106 3196
@@ -3109,13 +3199,11 @@ Element.implement({
3109 3199 return this;
3110 3200 },
3111 3201
3112   - getProperty: function(attribute){
3113   - attribute = camels[attribute] || attribute;
3114   - var key = attributes[attribute] || readOnly[attribute];
3115   - return (key) ? this[key] :
3116   - (bools[attribute]) ? !!this[attribute] :
3117   - (uriAttrs.test(attribute) ? this.getAttribute(attribute, 2) :
3118   - (key = this.getAttributeNode(attribute)) ? key.nodeValue : null) || null;
  3202 + getProperty: function(name){
  3203 + var getter = propertyGetters[name.toLowerCase()];
  3204 + if (getter) return getter(this);
  3205 + var result = Slick.getAttribute(this, name);
  3206 + return (!result && !Slick.hasAttribute(this, name)) ? null : result;
3119 3207 },
3120 3208
3121 3209 getProperties: function(){
@@ -3123,12 +3211,8 @@ Element.implement({
3123 3211 return args.map(this.getProperty, this).associate(args);
3124 3212 },
3125 3213
3126   - removeProperty: function(attribute){
3127   - attribute = camels[attribute] || attribute;
3128   - var key = attributes[attribute];
3129   - (key) ? this[key] = '' :
3130   - (bools[attribute]) ? this[attribute] = false : this.removeAttribute(attribute);
3131   - return this;
  3214 + removeProperty: function(name){
  3215 + return this.setProperty(name, null);
3132 3216 },
3133 3217
3134 3218 removeProperties: function(){
@@ -3136,6 +3220,22 @@ Element.implement({
3136 3220 return this;
3137 3221 },
3138 3222
  3223 + set: function(prop, value){
  3224 + var property = Element.Properties[prop];
  3225 + (property && property.set) ? property.set.call(this, value) : this.setProperty(prop, value);
  3226 + }.overloadSetter(),
  3227 +
  3228 + get: function(prop){
  3229 + var property = Element.Properties[prop];
  3230 + return (property && property.get) ? property.get.apply(this) : this.getProperty(prop);
  3231 + }.overloadGetter(),
  3232 +
  3233 + erase: function(prop){
  3234 + var property = Element.Properties[prop];
  3235 + (property && property.erase) ? property.erase.apply(this) : this.removeProperty(prop);
  3236 + return this;
  3237 + },
  3238 +
3139 3239 hasClass: function(className){
3140 3240 return this.className.clean().contains(className, ' ');
3141 3241 },
@@ -3194,58 +3294,6 @@ Element.implement({
3194 3294 return this.replaces(el).grab(el, where);
3195 3295 },
3196 3296
3197   - getPrevious: function(expression){
3198   - return document.id(Slick.find(this, injectCombinator(expression, '!~')));
3199   - },
3200   -
3201   - getAllPrevious: function(expression){
3202   - return Slick.search(this, injectCombinator(expression, '!~'), new Elements);
3203   - },
3204   -
3205   - getNext: function(expression){
3206   - return document.id(Slick.find(this, injectCombinator(expression, '~')));
3207   - },
3208   -
3209   - getAllNext: function(expression){
3210   - return Slick.search(this, injectCombinator(expression, '~'), new Elements);
3211   - },
3212   -
3213   - getFirst: function(expression){
3214   - return document.id(Slick.search(this, injectCombinator(expression, '>'))[0]);
3215   - },
3216   -
3217   - getLast: function(expression){
3218   - return document.id(Slick.search(this, injectCombinator(expression, '>')).getLast());
3219   - },
3220   -
3221   - getParent: function(expression){
3222   - return document.id(Slick.find(this, injectCombinator(expression, '!')));
3223   - },
3224   -
3225   - getParents: function(expression){
3226   - return Slick.search(this, injectCombinator(expression, '!'), new Elements);
3227   - },
3228   -
3229   - getSiblings: function(expression){
3230   - return Slick.search(this, injectCombinator(expression, '~~'), new Elements);
3231   - },
3232   -
3233   - getChildren: function(expression){
3234   - return Slick.search(this, injectCombinator(expression, '>'), new Elements);
3235   - },
3236   -
3237   - getWindow: function(){
3238   - return this.ownerDocument.window;
3239   - },
3240   -
3241   - getDocument: function(){
3242   - return this.ownerDocument;
3243   - },
3244   -
3245   - getElementById: function(id){
3246   - return document.id(Slick.find(this, '#' + ('' + id).replace(/(\W)/g, '\\$1')));
3247   - },
3248   -
3249 3297 getSelected: function(){
3250 3298 this.selectedIndex; // Safari 3.2.1
3251 3299 return new Elements(Array.from(this.options).filter(function(option){
@@ -3269,7 +3317,30 @@ Element.implement({
3269 3317 });
3270 3318 });
3271 3319 return queryString.join('&');
3272   - },
  3320 + }
  3321 +
  3322 +});
  3323 +
  3324 +var collected = {}, storage = {};
  3325 +
  3326 +var get = function(uid){
  3327 + return (storage[uid] || (storage[uid] = {}));
  3328 +};
  3329 +
  3330 +var clean = function(item){
  3331 + var uid = item.uid;
  3332 + if (item.removeEvents) item.removeEvents();
  3333 + if (item.clearAttributes) item.clearAttributes();
  3334 + if (uid != null){
  3335 + delete collected[uid];
  3336 + delete storage[uid];
  3337 + }
  3338 + return item;
  3339 +};
  3340 +
  3341 +var formProps = {input: 'checked', option: 'selected', textarea: 'value'};
  3342 +
  3343 +Element.implement({
3273 3344
3274 3345 destroy: function(){
3275 3346 var children = clean(this).getElementsByTagName('*');
@@ -3287,55 +3358,44 @@ Element.implement({
3287 3358 return (this.parentNode) ? this.parentNode.removeChild(this) : this;
3288 3359 },
3289 3360
3290   - match: function(expression){
3291   - return !expression || Slick.match(this, expression);
3292   - }
3293   -
3294   -});
  3361 + clone: function(contents, keepid){
  3362 + contents = contents !== false;
  3363 + var clone = this.cloneNode(contents), ce = [clone], te = [this], i;
3295 3364
3296   -var cleanClone = function(node, element, keepid){
3297   - if (!keepid) node.setAttributeNode(document.createAttribute('id'));
3298   - if (node.clearAttributes){
3299   - node.clearAttributes();
3300   - node.mergeAttributes(element);
3301   - node.removeAttribute('uid');
3302   - if (node.options){
3303   - var no = node.options, eo = element.options;
3304   - for (var i = no.length; i--;) no[i].selected = eo[i].selected;
  3365 + if (contents){
  3366 + ce.append(Array.from(clone.getElementsByTagName('*')));
  3367 + te.append(Array.from(this.getElementsByTagName('*')));
3305 3368 }
3306   - }
3307   -
3308   - var prop = formProps[element.tagName.toLowerCase()];
3309   - if (prop && element[prop]) node[prop] = element[prop];
3310   -};
3311 3369
3312   -Element.implement('clone', function(contents, keepid){
3313   - contents = contents !== false;
3314   - var clone = this.cloneNode(contents), i;
  3370 + for (i = ce.length; i--;){
  3371 + var node = ce[i], element = te[i];
  3372 + if (!keepid) node.removeAttribute('id');
  3373 + /*<ltIE9>*/
  3374 + if (node.clearAttributes){
  3375 + node.clearAttributes();
  3376 + node.mergeAttributes(element);
  3377 + node.removeAttribute('uid');
  3378 + if (node.options){
  3379 + var no = node.options, eo = element.options;
  3380 + for (var j = no.length; j--;) no[j].selected = eo[j].selected;
  3381 + }
  3382 + }
  3383 + /*</ltIE9>*/
  3384 + var prop = formProps[element.tagName.toLowerCase()];
  3385 + if (prop && element[prop]) node[prop] = element[prop];
  3386 + }
3315 3387
3316   - if (contents){
3317   - var ce = clone.getElementsByTagName('*'), te = this.getElementsByTagName('*');
3318   - for (i = ce.length; i--;) cleanClone(ce[i], te[i], keepid);
  3388 + /*<ltIE9>*/
  3389 + if (Browser.ie){
  3390 + var co = clone.getElementsByTagName('object'), to = this.getElementsByTagName('object');
  3391 + for (i = co.length; i--;) co[i].outerHTML = to[i].outerHTML;
  3392 + }
  3393 + /*</ltIE9>*/
  3394 + return document.id(clone);
3319 3395 }
3320 3396
3321   - cleanClone(clone, this, keepid);
3322   -
3323   - if (Browser.ie){
3324   - var co = clone.getElementsByTagName('object'), to = this.getElementsByTagName('object');
3325   - for (i = co.length; i--;) co[i].outerHTML = to[i].outerHTML;
3326   - }
3327   - return document.id(clone);
3328 3397 });
3329 3398
3330   -var contains = {contains: function(element){
3331   - return Slick.contains(this, element);
3332   -}};
3333   -
3334   -if (!document.contains) Document.implement(contains);
3335   -if (!document.createElement('div').contains) Element.implement(contains);
3336   -
3337   -
3338   -
3339 3399 [Element, Window, Document].invoke('implement', {
3340 3400
3341 3401 addListener: function(type, fn){
@@ -3386,8 +3446,6 @@ if (window.attachEvent && !window.addEventListener) window.addListener('unload',
3386 3446 });
3387 3447 /*</ltIE9>*/
3388 3448
3389   -})();
3390   -
3391 3449 Element.Properties = {};
3392 3450
3393 3451
@@ -3416,17 +3474,6 @@ Element.Properties.tag = {
3416 3474
3417 3475 };
3418 3476
3419   -/*<ltIE9>*/
3420   -(function(maxLength){
3421   - if (maxLength != null) Element.Properties.maxlength = Element.Properties.maxLength = {
3422   - get: function(){
3423   - var maxlength = this.getAttribute('maxLength');
3424   - return maxlength == maxLength ? null : maxlength;
3425   - }
3426   - };
3427   -})(document.createElement('input').getAttribute('maxLength'));
3428   -/*</ltIE9>*/
3429   -
3430 3477 /*<!webkit>*/
3431 3478 Element.Properties.html = (function(){
3432 3479
@@ -3445,10 +3492,26 @@ Element.Properties.html = (function(){
3445 3492 };
3446 3493 translations.thead = translations.tfoot = translations.tbody;
3447 3494
  3495 + /*<ltIE9>*/
  3496 + // technique by jdbarlett - http://jdbartlett.com/innershiv/
  3497 + wrapper.innerHTML = '<nav></nav>';
  3498 + var HTML5Test = wrapper.childNodes.length == 1;
  3499 + if (!HTML5Test){
  3500 + var tags = 'abbr article aside audio canvas datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video'.split(' '),
  3501 + fragment = document.createDocumentFragment(), l = tags.length;
  3502 + while (l--) fragment.createElement(tags[l]);
  3503 + fragment.appendChild(wrapper);
  3504 + }
  3505 + /*</ltIE9>*/
  3506 +
3448 3507 var html = {
3449   - set: function(){
3450   - var html = Array.flatten(arguments).join('');
  3508 + set: function(html){
  3509 + if (typeOf(html) == 'array') html = html.join('');
  3510 +
3451 3511 var wrap = (!tableTest && translations[this.get('tag')]);
  3512 + /*<ltIE9>*/
  3513 + if (!wrap && !HTML5Test) wrap = [0, '', ''];
  3514 + /*</ltIE9>*/
3452 3515 if (wrap){
3453 3516 var first = wrapper;
3454 3517 first.innerHTML = wrap[1] + html + wrap[2];
@@ -3466,6 +3529,40 @@ Element.Properties.html = (function(){
3466 3529 })();
3467 3530 /*</!webkit>*/
3468 3531
  3532 +/*<ltIE9>*/
  3533 +var testForm = document.createElement('form');
  3534 +testForm.innerHTML = '<select><option>s</option></select>';
  3535 +
  3536 +if (testForm.firstChild.value != 's') Element.Properties.value = {
  3537 +
  3538 + set: function(value){
  3539 + var tag = this.get('tag');
  3540 + if (tag != 'select') return this.setProperty('value', value);
  3541 + var options = this.getElements('option');
  3542 + for (var i = 0; i < options.length; i++){
  3543 + var option = options[i],
  3544 + attr = option.getAttributeNode('value'),
  3545 + optionValue = (attr && attr.specified) ? option.value : option.get('text');
  3546 + if (optionValue == value) return option.selected = true;
  3547 + }
  3548 + },
  3549 +
  3550 + get: function(){
  3551 + var option = this, tag = option.get('tag');
  3552 +
  3553 + if (tag != 'select' && tag != 'option') return this.getProperty('value');
  3554 +
  3555 + if (tag == 'select' && !(option = option.getSelected()[0])) return '';
  3556 +
  3557 + var attr = option.getAttributeNode('value');
  3558 + return (attr && attr.specified) ? option.value : option.get('text');
  3559 + }
  3560 +
  3561 +};
  3562 +/*</ltIE9>*/
  3563 +
  3564 +})();
  3565 +
3469 3566
3470 3567 /*
3471 3568 ---
@@ -3491,41 +3588,38 @@ Element.Properties.styles = {set: function(styles){
3491 3588 this.setStyles(styles);
3492 3589 }};
3493 3590
3494   -var hasOpacity = (html.style.opacity != null);
3495   -var reAlpha = /alpha\(opacity=([\d.]+)\)/i;
  3591 +var hasOpacity = (html.style.opacity != null),
  3592 + hasFilter = (html.style.filter != null),
  3593 + reAlpha = /alpha\(opacity=([\d.]+)\)/i;
3496 3594
3497   -var setOpacity = function(element, opacity){
3498   - if (!element.currentStyle || !element.currentStyle.hasLayout) element.style.zoom = 1;
3499   - if (hasOpacity){
3500   - element.style.opacity = opacity;
3501   - } else {
3502   - opacity = (opacity * 100).limit(0, 100).round();
3503   - opacity = (opacity == 100) ? '' : 'alpha(opacity=' + opacity + ')';
3504   - var filter = element.style.filter || element.getComputedStyle('filter') || '';
3505   - element.style.filter = reAlpha.test(filter) ? filter.replace(reAlpha, opacity) : filter + opacity;
3506   - }
  3595 +var setVisibility = function(element, opacity){
  3596 + element.store('$opacity', opacity);
  3597 + element.style.visibility = opacity > 0 ? 'visible' : 'hidden';
3507 3598 };
3508 3599
3509   -Element.Properties.opacity = {
3510   -
3511   - set: function(opacity){
3512   - var visibility = this.style.visibility;
3513   - if (opacity == 0 && visibility != 'hidden') this.style.visibility = 'hidden';
3514   - else if (opacity != 0 && visibility != 'visible') this.style.visibility = 'visible';
3515   -
3516   - setOpacity(this, opacity);
3517   - },
3518   -
3519   - get: (hasOpacity) ? function(){
3520   - var opacity = this.style.opacity || this.getComputedStyle('opacity');
3521   - return (opacity == '') ? 1 : opacity;
3522   - } : function(){
3523   - var opacity, filter = (this.style.filter || this.getComputedStyle('filter'));
3524   - if (filter) opacity = filter.match(reAlpha);
3525   - return (opacity == null || filter == null) ? 1 : (opacity[1] / 100);
3526   - }
3527   -
3528   -};
  3600 +var setOpacity = (hasOpacity ? function(element, opacity){
  3601 + element.style.opacity = opacity;
  3602 +} : (hasFilter ? function(element, opacity){
  3603 + if (!element.currentStyle || !element.currentStyle.hasLayout) element.style.zoom = 1;
  3604 + opacity = (opacity * 100).limit(0, 100).round();
  3605 + opacity = (opacity == 100) ? '' : 'alpha(opacity=' + opacity + ')';
  3606 + var filter = element.style.filter || element.getComputedStyle('filter') || '';
  3607 + element.style.filter = reAlpha.test(filter) ? filter.replace(reAlpha, opacity) : filter + opacity;
  3608 +} : setVisibility));
  3609 +
  3610 +var getOpacity = (hasOpacity ? function(element){
  3611 + var opacity = element.style.opacity || element.getComputedStyle('opacity');
  3612 + return (opacity == '') ? 1 : opacity.toFloat();
  3613 +} : (hasFilter ? function(element){
  3614 + var filter = (element.style.filter || element.getComputedStyle('filter')),
  3615 + opacity;
  3616 + if (filter) opacity = filter.match(reAlpha);
  3617 + return (opacity == null || filter == null) ? 1 : (opacity[1] / 100);
  3618 +} : function(element){
  3619 + var opacity = element.retrieve('$opacity');
  3620 + if (opacity == null) opacity = (element.style.visibility == 'hidden' ? 0 : 1);
  3621 + return opacity;
  3622 +}));
3529 3623
3530 3624 var floatName = (html.style.cssFloat == null) ? 'styleFloat' : 'cssFloat';
3531 3625
@@ -3538,21 +3632,12 @@ Element.implement({
3538 3632 return (computed) ? computed.getPropertyValue((property == floatName) ? 'float' : property.hyphenate()) : null;
3539 3633 },
3540 3634
3541   - setOpacity: function(value){
3542   - setOpacity(this, value);
3543   - return this;
3544   - },
3545   -
3546   - getOpacity: function(){
3547   - return this.get('opacity');
3548   - },
3549   -
3550 3635 setStyle: function(property, value){
3551   - switch (property){
3552   - case 'opacity': return this.set('opacity', parseFloat(value));
3553   - case 'float': property = floatName;
  3636 + if (property == 'opacity'){
  3637 + setOpacity(this, parseFloat(value));
  3638 + return this;
3554 3639 }
3555   - property = property.camelCase();
  3640 + property = (property == 'float' ? floatName : property).camelCase();
3556 3641 if (typeOf(value) != 'string'){
3557 3642 var map = (Element.Styles[property] || '@').split(' ');
3558 3643 value = Array.from(value).map(function(val, i){
@@ -3567,11 +3652,8 @@ Element.implement({
3567 3652 },
3568 3653
3569 3654 getStyle: function(property){
3570   - switch (property){
3571   - case 'opacity': return this.get('opacity');
3572   - case 'float': property = floatName;
3573   - }
3574   - property = property.camelCase();
  3655 + if (property == 'opacity') return getOpacity(this);
  3656 + property = (property == 'float' ? floatName : property).camelCase();
3575 3657 var result = this.style[property];
3576 3658 if (!result || property == 'zIndex'){
3577 3659 result = [];
@@ -3628,6 +3710,8 @@ Element.Styles = {
3628 3710
3629