Mercurial > hg > soundsoftware-site
comparison public/javascripts/prototype.js @ 524:1248a47e81b3 feature_36
Merge from branch "luisf"
author | luisf <luis.figueira@eecs.qmul.ac.uk> |
---|---|
date | Mon, 25 Jul 2011 14:39:38 +0100 |
parents | cbce1fd3b1b7 |
children |
comparison
equal
deleted
inserted
replaced
519:3be6bc3c2a17 | 524:1248a47e81b3 |
---|---|
1 /* Prototype JavaScript framework, version 1.6.0.3 | 1 /* Prototype JavaScript framework, version 1.7 |
2 * (c) 2005-2008 Sam Stephenson | 2 * (c) 2005-2010 Sam Stephenson |
3 * | 3 * |
4 * Prototype is freely distributable under the terms of an MIT-style license. | 4 * Prototype is freely distributable under the terms of an MIT-style license. |
5 * For details, see the Prototype web site: http://www.prototypejs.org/ | 5 * For details, see the Prototype web site: http://www.prototypejs.org/ |
6 * | 6 * |
7 *--------------------------------------------------------------------------*/ | 7 *--------------------------------------------------------------------------*/ |
8 | 8 |
9 var Prototype = { | 9 var Prototype = { |
10 Version: '1.6.0.3', | 10 |
11 | 11 Version: '1.7', |
12 Browser: { | 12 |
13 IE: !!(window.attachEvent && | 13 Browser: (function(){ |
14 navigator.userAgent.indexOf('Opera') === -1), | 14 var ua = navigator.userAgent; |
15 Opera: navigator.userAgent.indexOf('Opera') > -1, | 15 var isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]'; |
16 WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1, | 16 return { |
17 Gecko: navigator.userAgent.indexOf('Gecko') > -1 && | 17 IE: !!window.attachEvent && !isOpera, |
18 navigator.userAgent.indexOf('KHTML') === -1, | 18 Opera: isOpera, |
19 MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/) | 19 WebKit: ua.indexOf('AppleWebKit/') > -1, |
20 }, | 20 Gecko: ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') === -1, |
21 MobileSafari: /Apple.*Mobile/.test(ua) | |
22 } | |
23 })(), | |
21 | 24 |
22 BrowserFeatures: { | 25 BrowserFeatures: { |
23 XPath: !!document.evaluate, | 26 XPath: !!document.evaluate, |
27 | |
24 SelectorsAPI: !!document.querySelector, | 28 SelectorsAPI: !!document.querySelector, |
25 ElementExtensions: !!window.HTMLElement, | 29 |
26 SpecificElementExtensions: | 30 ElementExtensions: (function() { |
27 document.createElement('div')['__proto__'] && | 31 var constructor = window.Element || window.HTMLElement; |
28 document.createElement('div')['__proto__'] !== | 32 return !!(constructor && constructor.prototype); |
29 document.createElement('form')['__proto__'] | 33 })(), |
34 SpecificElementExtensions: (function() { | |
35 if (typeof window.HTMLDivElement !== 'undefined') | |
36 return true; | |
37 | |
38 var div = document.createElement('div'), | |
39 form = document.createElement('form'), | |
40 isSupported = false; | |
41 | |
42 if (div['__proto__'] && (div['__proto__'] !== form['__proto__'])) { | |
43 isSupported = true; | |
44 } | |
45 | |
46 div = form = null; | |
47 | |
48 return isSupported; | |
49 })() | |
30 }, | 50 }, |
31 | 51 |
32 ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>', | 52 ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>', |
33 JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/, | 53 JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/, |
34 | 54 |
35 emptyFunction: function() { }, | 55 emptyFunction: function() { }, |
56 | |
36 K: function(x) { return x } | 57 K: function(x) { return x } |
37 }; | 58 }; |
38 | 59 |
39 if (Prototype.Browser.MobileSafari) | 60 if (Prototype.Browser.MobileSafari) |
40 Prototype.BrowserFeatures.SpecificElementExtensions = false; | 61 Prototype.BrowserFeatures.SpecificElementExtensions = false; |
41 | 62 |
42 | 63 |
43 /* Based on Alex Arnell's inheritance implementation. */ | |
44 var Class = { | |
45 create: function() { | |
46 var parent = null, properties = $A(arguments); | |
47 if (Object.isFunction(properties[0])) | |
48 parent = properties.shift(); | |
49 | |
50 function klass() { | |
51 this.initialize.apply(this, arguments); | |
52 } | |
53 | |
54 Object.extend(klass, Class.Methods); | |
55 klass.superclass = parent; | |
56 klass.subclasses = []; | |
57 | |
58 if (parent) { | |
59 var subclass = function() { }; | |
60 subclass.prototype = parent.prototype; | |
61 klass.prototype = new subclass; | |
62 parent.subclasses.push(klass); | |
63 } | |
64 | |
65 for (var i = 0; i < properties.length; i++) | |
66 klass.addMethods(properties[i]); | |
67 | |
68 if (!klass.prototype.initialize) | |
69 klass.prototype.initialize = Prototype.emptyFunction; | |
70 | |
71 klass.prototype.constructor = klass; | |
72 | |
73 return klass; | |
74 } | |
75 }; | |
76 | |
77 Class.Methods = { | |
78 addMethods: function(source) { | |
79 var ancestor = this.superclass && this.superclass.prototype; | |
80 var properties = Object.keys(source); | |
81 | |
82 if (!Object.keys({ toString: true }).length) | |
83 properties.push("toString", "valueOf"); | |
84 | |
85 for (var i = 0, length = properties.length; i < length; i++) { | |
86 var property = properties[i], value = source[property]; | |
87 if (ancestor && Object.isFunction(value) && | |
88 value.argumentNames().first() == "$super") { | |
89 var method = value; | |
90 value = (function(m) { | |
91 return function() { return ancestor[m].apply(this, arguments) }; | |
92 })(property).wrap(method); | |
93 | |
94 value.valueOf = method.valueOf.bind(method); | |
95 value.toString = method.toString.bind(method); | |
96 } | |
97 this.prototype[property] = value; | |
98 } | |
99 | |
100 return this; | |
101 } | |
102 }; | |
103 | |
104 var Abstract = { }; | 64 var Abstract = { }; |
105 | 65 |
106 Object.extend = function(destination, source) { | |
107 for (var property in source) | |
108 destination[property] = source[property]; | |
109 return destination; | |
110 }; | |
111 | |
112 Object.extend(Object, { | |
113 inspect: function(object) { | |
114 try { | |
115 if (Object.isUndefined(object)) return 'undefined'; | |
116 if (object === null) return 'null'; | |
117 return object.inspect ? object.inspect() : String(object); | |
118 } catch (e) { | |
119 if (e instanceof RangeError) return '...'; | |
120 throw e; | |
121 } | |
122 }, | |
123 | |
124 toJSON: function(object) { | |
125 var type = typeof object; | |
126 switch (type) { | |
127 case 'undefined': | |
128 case 'function': | |
129 case 'unknown': return; | |
130 case 'boolean': return object.toString(); | |
131 } | |
132 | |
133 if (object === null) return 'null'; | |
134 if (object.toJSON) return object.toJSON(); | |
135 if (Object.isElement(object)) return; | |
136 | |
137 var results = []; | |
138 for (var property in object) { | |
139 var value = Object.toJSON(object[property]); | |
140 if (!Object.isUndefined(value)) | |
141 results.push(property.toJSON() + ': ' + value); | |
142 } | |
143 | |
144 return '{' + results.join(', ') + '}'; | |
145 }, | |
146 | |
147 toQueryString: function(object) { | |
148 return $H(object).toQueryString(); | |
149 }, | |
150 | |
151 toHTML: function(object) { | |
152 return object && object.toHTML ? object.toHTML() : String.interpret(object); | |
153 }, | |
154 | |
155 keys: function(object) { | |
156 var keys = []; | |
157 for (var property in object) | |
158 keys.push(property); | |
159 return keys; | |
160 }, | |
161 | |
162 values: function(object) { | |
163 var values = []; | |
164 for (var property in object) | |
165 values.push(object[property]); | |
166 return values; | |
167 }, | |
168 | |
169 clone: function(object) { | |
170 return Object.extend({ }, object); | |
171 }, | |
172 | |
173 isElement: function(object) { | |
174 return !!(object && object.nodeType == 1); | |
175 }, | |
176 | |
177 isArray: function(object) { | |
178 return object != null && typeof object == "object" && | |
179 'splice' in object && 'join' in object; | |
180 }, | |
181 | |
182 isHash: function(object) { | |
183 return object instanceof Hash; | |
184 }, | |
185 | |
186 isFunction: function(object) { | |
187 return typeof object == "function"; | |
188 }, | |
189 | |
190 isString: function(object) { | |
191 return typeof object == "string"; | |
192 }, | |
193 | |
194 isNumber: function(object) { | |
195 return typeof object == "number"; | |
196 }, | |
197 | |
198 isUndefined: function(object) { | |
199 return typeof object == "undefined"; | |
200 } | |
201 }); | |
202 | |
203 Object.extend(Function.prototype, { | |
204 argumentNames: function() { | |
205 var names = this.toString().match(/^[\s\(]*function[^(]*\(([^\)]*)\)/)[1] | |
206 .replace(/\s+/g, '').split(','); | |
207 return names.length == 1 && !names[0] ? [] : names; | |
208 }, | |
209 | |
210 bind: function() { | |
211 if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this; | |
212 var __method = this, args = $A(arguments), object = args.shift(); | |
213 return function() { | |
214 return __method.apply(object, args.concat($A(arguments))); | |
215 } | |
216 }, | |
217 | |
218 bindAsEventListener: function() { | |
219 var __method = this, args = $A(arguments), object = args.shift(); | |
220 return function(event) { | |
221 return __method.apply(object, [event || window.event].concat(args)); | |
222 } | |
223 }, | |
224 | |
225 curry: function() { | |
226 if (!arguments.length) return this; | |
227 var __method = this, args = $A(arguments); | |
228 return function() { | |
229 return __method.apply(this, args.concat($A(arguments))); | |
230 } | |
231 }, | |
232 | |
233 delay: function() { | |
234 var __method = this, args = $A(arguments), timeout = args.shift() * 1000; | |
235 return window.setTimeout(function() { | |
236 return __method.apply(__method, args); | |
237 }, timeout); | |
238 }, | |
239 | |
240 defer: function() { | |
241 var args = [0.01].concat($A(arguments)); | |
242 return this.delay.apply(this, args); | |
243 }, | |
244 | |
245 wrap: function(wrapper) { | |
246 var __method = this; | |
247 return function() { | |
248 return wrapper.apply(this, [__method.bind(this)].concat($A(arguments))); | |
249 } | |
250 }, | |
251 | |
252 methodize: function() { | |
253 if (this._methodized) return this._methodized; | |
254 var __method = this; | |
255 return this._methodized = function() { | |
256 return __method.apply(null, [this].concat($A(arguments))); | |
257 }; | |
258 } | |
259 }); | |
260 | |
261 Date.prototype.toJSON = function() { | |
262 return '"' + this.getUTCFullYear() + '-' + | |
263 (this.getUTCMonth() + 1).toPaddedString(2) + '-' + | |
264 this.getUTCDate().toPaddedString(2) + 'T' + | |
265 this.getUTCHours().toPaddedString(2) + ':' + | |
266 this.getUTCMinutes().toPaddedString(2) + ':' + | |
267 this.getUTCSeconds().toPaddedString(2) + 'Z"'; | |
268 }; | |
269 | 66 |
270 var Try = { | 67 var Try = { |
271 these: function() { | 68 these: function() { |
272 var returnValue; | 69 var returnValue; |
273 | 70 |
281 | 78 |
282 return returnValue; | 79 return returnValue; |
283 } | 80 } |
284 }; | 81 }; |
285 | 82 |
83 /* Based on Alex Arnell's inheritance implementation. */ | |
84 | |
85 var Class = (function() { | |
86 | |
87 var IS_DONTENUM_BUGGY = (function(){ | |
88 for (var p in { toString: 1 }) { | |
89 if (p === 'toString') return false; | |
90 } | |
91 return true; | |
92 })(); | |
93 | |
94 function subclass() {}; | |
95 function create() { | |
96 var parent = null, properties = $A(arguments); | |
97 if (Object.isFunction(properties[0])) | |
98 parent = properties.shift(); | |
99 | |
100 function klass() { | |
101 this.initialize.apply(this, arguments); | |
102 } | |
103 | |
104 Object.extend(klass, Class.Methods); | |
105 klass.superclass = parent; | |
106 klass.subclasses = []; | |
107 | |
108 if (parent) { | |
109 subclass.prototype = parent.prototype; | |
110 klass.prototype = new subclass; | |
111 parent.subclasses.push(klass); | |
112 } | |
113 | |
114 for (var i = 0, length = properties.length; i < length; i++) | |
115 klass.addMethods(properties[i]); | |
116 | |
117 if (!klass.prototype.initialize) | |
118 klass.prototype.initialize = Prototype.emptyFunction; | |
119 | |
120 klass.prototype.constructor = klass; | |
121 return klass; | |
122 } | |
123 | |
124 function addMethods(source) { | |
125 var ancestor = this.superclass && this.superclass.prototype, | |
126 properties = Object.keys(source); | |
127 | |
128 if (IS_DONTENUM_BUGGY) { | |
129 if (source.toString != Object.prototype.toString) | |
130 properties.push("toString"); | |
131 if (source.valueOf != Object.prototype.valueOf) | |
132 properties.push("valueOf"); | |
133 } | |
134 | |
135 for (var i = 0, length = properties.length; i < length; i++) { | |
136 var property = properties[i], value = source[property]; | |
137 if (ancestor && Object.isFunction(value) && | |
138 value.argumentNames()[0] == "$super") { | |
139 var method = value; | |
140 value = (function(m) { | |
141 return function() { return ancestor[m].apply(this, arguments); }; | |
142 })(property).wrap(method); | |
143 | |
144 value.valueOf = method.valueOf.bind(method); | |
145 value.toString = method.toString.bind(method); | |
146 } | |
147 this.prototype[property] = value; | |
148 } | |
149 | |
150 return this; | |
151 } | |
152 | |
153 return { | |
154 create: create, | |
155 Methods: { | |
156 addMethods: addMethods | |
157 } | |
158 }; | |
159 })(); | |
160 (function() { | |
161 | |
162 var _toString = Object.prototype.toString, | |
163 NULL_TYPE = 'Null', | |
164 UNDEFINED_TYPE = 'Undefined', | |
165 BOOLEAN_TYPE = 'Boolean', | |
166 NUMBER_TYPE = 'Number', | |
167 STRING_TYPE = 'String', | |
168 OBJECT_TYPE = 'Object', | |
169 FUNCTION_CLASS = '[object Function]', | |
170 BOOLEAN_CLASS = '[object Boolean]', | |
171 NUMBER_CLASS = '[object Number]', | |
172 STRING_CLASS = '[object String]', | |
173 ARRAY_CLASS = '[object Array]', | |
174 DATE_CLASS = '[object Date]', | |
175 NATIVE_JSON_STRINGIFY_SUPPORT = window.JSON && | |
176 typeof JSON.stringify === 'function' && | |
177 JSON.stringify(0) === '0' && | |
178 typeof JSON.stringify(Prototype.K) === 'undefined'; | |
179 | |
180 function Type(o) { | |
181 switch(o) { | |
182 case null: return NULL_TYPE; | |
183 case (void 0): return UNDEFINED_TYPE; | |
184 } | |
185 var type = typeof o; | |
186 switch(type) { | |
187 case 'boolean': return BOOLEAN_TYPE; | |
188 case 'number': return NUMBER_TYPE; | |
189 case 'string': return STRING_TYPE; | |
190 } | |
191 return OBJECT_TYPE; | |
192 } | |
193 | |
194 function extend(destination, source) { | |
195 for (var property in source) | |
196 destination[property] = source[property]; | |
197 return destination; | |
198 } | |
199 | |
200 function inspect(object) { | |
201 try { | |
202 if (isUndefined(object)) return 'undefined'; | |
203 if (object === null) return 'null'; | |
204 return object.inspect ? object.inspect() : String(object); | |
205 } catch (e) { | |
206 if (e instanceof RangeError) return '...'; | |
207 throw e; | |
208 } | |
209 } | |
210 | |
211 function toJSON(value) { | |
212 return Str('', { '': value }, []); | |
213 } | |
214 | |
215 function Str(key, holder, stack) { | |
216 var value = holder[key], | |
217 type = typeof value; | |
218 | |
219 if (Type(value) === OBJECT_TYPE && typeof value.toJSON === 'function') { | |
220 value = value.toJSON(key); | |
221 } | |
222 | |
223 var _class = _toString.call(value); | |
224 | |
225 switch (_class) { | |
226 case NUMBER_CLASS: | |
227 case BOOLEAN_CLASS: | |
228 case STRING_CLASS: | |
229 value = value.valueOf(); | |
230 } | |
231 | |
232 switch (value) { | |
233 case null: return 'null'; | |
234 case true: return 'true'; | |
235 case false: return 'false'; | |
236 } | |
237 | |
238 type = typeof value; | |
239 switch (type) { | |
240 case 'string': | |
241 return value.inspect(true); | |
242 case 'number': | |
243 return isFinite(value) ? String(value) : 'null'; | |
244 case 'object': | |
245 | |
246 for (var i = 0, length = stack.length; i < length; i++) { | |
247 if (stack[i] === value) { throw new TypeError(); } | |
248 } | |
249 stack.push(value); | |
250 | |
251 var partial = []; | |
252 if (_class === ARRAY_CLASS) { | |
253 for (var i = 0, length = value.length; i < length; i++) { | |
254 var str = Str(i, value, stack); | |
255 partial.push(typeof str === 'undefined' ? 'null' : str); | |
256 } | |
257 partial = '[' + partial.join(',') + ']'; | |
258 } else { | |
259 var keys = Object.keys(value); | |
260 for (var i = 0, length = keys.length; i < length; i++) { | |
261 var key = keys[i], str = Str(key, value, stack); | |
262 if (typeof str !== "undefined") { | |
263 partial.push(key.inspect(true)+ ':' + str); | |
264 } | |
265 } | |
266 partial = '{' + partial.join(',') + '}'; | |
267 } | |
268 stack.pop(); | |
269 return partial; | |
270 } | |
271 } | |
272 | |
273 function stringify(object) { | |
274 return JSON.stringify(object); | |
275 } | |
276 | |
277 function toQueryString(object) { | |
278 return $H(object).toQueryString(); | |
279 } | |
280 | |
281 function toHTML(object) { | |
282 return object && object.toHTML ? object.toHTML() : String.interpret(object); | |
283 } | |
284 | |
285 function keys(object) { | |
286 if (Type(object) !== OBJECT_TYPE) { throw new TypeError(); } | |
287 var results = []; | |
288 for (var property in object) { | |
289 if (object.hasOwnProperty(property)) { | |
290 results.push(property); | |
291 } | |
292 } | |
293 return results; | |
294 } | |
295 | |
296 function values(object) { | |
297 var results = []; | |
298 for (var property in object) | |
299 results.push(object[property]); | |
300 return results; | |
301 } | |
302 | |
303 function clone(object) { | |
304 return extend({ }, object); | |
305 } | |
306 | |
307 function isElement(object) { | |
308 return !!(object && object.nodeType == 1); | |
309 } | |
310 | |
311 function isArray(object) { | |
312 return _toString.call(object) === ARRAY_CLASS; | |
313 } | |
314 | |
315 var hasNativeIsArray = (typeof Array.isArray == 'function') | |
316 && Array.isArray([]) && !Array.isArray({}); | |
317 | |
318 if (hasNativeIsArray) { | |
319 isArray = Array.isArray; | |
320 } | |
321 | |
322 function isHash(object) { | |
323 return object instanceof Hash; | |
324 } | |
325 | |
326 function isFunction(object) { | |
327 return _toString.call(object) === FUNCTION_CLASS; | |
328 } | |
329 | |
330 function isString(object) { | |
331 return _toString.call(object) === STRING_CLASS; | |
332 } | |
333 | |
334 function isNumber(object) { | |
335 return _toString.call(object) === NUMBER_CLASS; | |
336 } | |
337 | |
338 function isDate(object) { | |
339 return _toString.call(object) === DATE_CLASS; | |
340 } | |
341 | |
342 function isUndefined(object) { | |
343 return typeof object === "undefined"; | |
344 } | |
345 | |
346 extend(Object, { | |
347 extend: extend, | |
348 inspect: inspect, | |
349 toJSON: NATIVE_JSON_STRINGIFY_SUPPORT ? stringify : toJSON, | |
350 toQueryString: toQueryString, | |
351 toHTML: toHTML, | |
352 keys: Object.keys || keys, | |
353 values: values, | |
354 clone: clone, | |
355 isElement: isElement, | |
356 isArray: isArray, | |
357 isHash: isHash, | |
358 isFunction: isFunction, | |
359 isString: isString, | |
360 isNumber: isNumber, | |
361 isDate: isDate, | |
362 isUndefined: isUndefined | |
363 }); | |
364 })(); | |
365 Object.extend(Function.prototype, (function() { | |
366 var slice = Array.prototype.slice; | |
367 | |
368 function update(array, args) { | |
369 var arrayLength = array.length, length = args.length; | |
370 while (length--) array[arrayLength + length] = args[length]; | |
371 return array; | |
372 } | |
373 | |
374 function merge(array, args) { | |
375 array = slice.call(array, 0); | |
376 return update(array, args); | |
377 } | |
378 | |
379 function argumentNames() { | |
380 var names = this.toString().match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1] | |
381 .replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, '') | |
382 .replace(/\s+/g, '').split(','); | |
383 return names.length == 1 && !names[0] ? [] : names; | |
384 } | |
385 | |
386 function bind(context) { | |
387 if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this; | |
388 var __method = this, args = slice.call(arguments, 1); | |
389 return function() { | |
390 var a = merge(args, arguments); | |
391 return __method.apply(context, a); | |
392 } | |
393 } | |
394 | |
395 function bindAsEventListener(context) { | |
396 var __method = this, args = slice.call(arguments, 1); | |
397 return function(event) { | |
398 var a = update([event || window.event], args); | |
399 return __method.apply(context, a); | |
400 } | |
401 } | |
402 | |
403 function curry() { | |
404 if (!arguments.length) return this; | |
405 var __method = this, args = slice.call(arguments, 0); | |
406 return function() { | |
407 var a = merge(args, arguments); | |
408 return __method.apply(this, a); | |
409 } | |
410 } | |
411 | |
412 function delay(timeout) { | |
413 var __method = this, args = slice.call(arguments, 1); | |
414 timeout = timeout * 1000; | |
415 return window.setTimeout(function() { | |
416 return __method.apply(__method, args); | |
417 }, timeout); | |
418 } | |
419 | |
420 function defer() { | |
421 var args = update([0.01], arguments); | |
422 return this.delay.apply(this, args); | |
423 } | |
424 | |
425 function wrap(wrapper) { | |
426 var __method = this; | |
427 return function() { | |
428 var a = update([__method.bind(this)], arguments); | |
429 return wrapper.apply(this, a); | |
430 } | |
431 } | |
432 | |
433 function methodize() { | |
434 if (this._methodized) return this._methodized; | |
435 var __method = this; | |
436 return this._methodized = function() { | |
437 var a = update([this], arguments); | |
438 return __method.apply(null, a); | |
439 }; | |
440 } | |
441 | |
442 return { | |
443 argumentNames: argumentNames, | |
444 bind: bind, | |
445 bindAsEventListener: bindAsEventListener, | |
446 curry: curry, | |
447 delay: delay, | |
448 defer: defer, | |
449 wrap: wrap, | |
450 methodize: methodize | |
451 } | |
452 })()); | |
453 | |
454 | |
455 | |
456 (function(proto) { | |
457 | |
458 | |
459 function toISOString() { | |
460 return this.getUTCFullYear() + '-' + | |
461 (this.getUTCMonth() + 1).toPaddedString(2) + '-' + | |
462 this.getUTCDate().toPaddedString(2) + 'T' + | |
463 this.getUTCHours().toPaddedString(2) + ':' + | |
464 this.getUTCMinutes().toPaddedString(2) + ':' + | |
465 this.getUTCSeconds().toPaddedString(2) + 'Z'; | |
466 } | |
467 | |
468 | |
469 function toJSON() { | |
470 return this.toISOString(); | |
471 } | |
472 | |
473 if (!proto.toISOString) proto.toISOString = toISOString; | |
474 if (!proto.toJSON) proto.toJSON = toJSON; | |
475 | |
476 })(Date.prototype); | |
477 | |
478 | |
286 RegExp.prototype.match = RegExp.prototype.test; | 479 RegExp.prototype.match = RegExp.prototype.test; |
287 | 480 |
288 RegExp.escape = function(str) { | 481 RegExp.escape = function(str) { |
289 return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1'); | 482 return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1'); |
290 }; | 483 }; |
291 | |
292 /*--------------------------------------------------------------------------*/ | |
293 | |
294 var PeriodicalExecuter = Class.create({ | 484 var PeriodicalExecuter = Class.create({ |
295 initialize: function(callback, frequency) { | 485 initialize: function(callback, frequency) { |
296 this.callback = callback; | 486 this.callback = callback; |
297 this.frequency = frequency; | 487 this.frequency = frequency; |
298 this.currentlyExecuting = false; | 488 this.currentlyExecuting = false; |
317 onTimerEvent: function() { | 507 onTimerEvent: function() { |
318 if (!this.currentlyExecuting) { | 508 if (!this.currentlyExecuting) { |
319 try { | 509 try { |
320 this.currentlyExecuting = true; | 510 this.currentlyExecuting = true; |
321 this.execute(); | 511 this.execute(); |
322 } finally { | |
323 this.currentlyExecuting = false; | 512 this.currentlyExecuting = false; |
513 } catch(e) { | |
514 this.currentlyExecuting = false; | |
515 throw e; | |
324 } | 516 } |
325 } | 517 } |
326 } | 518 } |
327 }); | 519 }); |
328 Object.extend(String, { | 520 Object.extend(String, { |
337 '\r': '\\r', | 529 '\r': '\\r', |
338 '\\': '\\\\' | 530 '\\': '\\\\' |
339 } | 531 } |
340 }); | 532 }); |
341 | 533 |
342 Object.extend(String.prototype, { | 534 Object.extend(String.prototype, (function() { |
343 gsub: function(pattern, replacement) { | 535 var NATIVE_JSON_PARSE_SUPPORT = window.JSON && |
536 typeof JSON.parse === 'function' && | |
537 JSON.parse('{"test": true}').test; | |
538 | |
539 function prepareReplacement(replacement) { | |
540 if (Object.isFunction(replacement)) return replacement; | |
541 var template = new Template(replacement); | |
542 return function(match) { return template.evaluate(match) }; | |
543 } | |
544 | |
545 function gsub(pattern, replacement) { | |
344 var result = '', source = this, match; | 546 var result = '', source = this, match; |
345 replacement = arguments.callee.prepareReplacement(replacement); | 547 replacement = prepareReplacement(replacement); |
548 | |
549 if (Object.isString(pattern)) | |
550 pattern = RegExp.escape(pattern); | |
551 | |
552 if (!(pattern.length || pattern.source)) { | |
553 replacement = replacement(''); | |
554 return replacement + source.split('').join(replacement) + replacement; | |
555 } | |
346 | 556 |
347 while (source.length > 0) { | 557 while (source.length > 0) { |
348 if (match = source.match(pattern)) { | 558 if (match = source.match(pattern)) { |
349 result += source.slice(0, match.index); | 559 result += source.slice(0, match.index); |
350 result += String.interpret(replacement(match)); | 560 result += String.interpret(replacement(match)); |
352 } else { | 562 } else { |
353 result += source, source = ''; | 563 result += source, source = ''; |
354 } | 564 } |
355 } | 565 } |
356 return result; | 566 return result; |
357 }, | 567 } |
358 | 568 |
359 sub: function(pattern, replacement, count) { | 569 function sub(pattern, replacement, count) { |
360 replacement = this.gsub.prepareReplacement(replacement); | 570 replacement = prepareReplacement(replacement); |
361 count = Object.isUndefined(count) ? 1 : count; | 571 count = Object.isUndefined(count) ? 1 : count; |
362 | 572 |
363 return this.gsub(pattern, function(match) { | 573 return this.gsub(pattern, function(match) { |
364 if (--count < 0) return match[0]; | 574 if (--count < 0) return match[0]; |
365 return replacement(match); | 575 return replacement(match); |
366 }); | 576 }); |
367 }, | 577 } |
368 | 578 |
369 scan: function(pattern, iterator) { | 579 function scan(pattern, iterator) { |
370 this.gsub(pattern, iterator); | 580 this.gsub(pattern, iterator); |
371 return String(this); | 581 return String(this); |
372 }, | 582 } |
373 | 583 |
374 truncate: function(length, truncation) { | 584 function truncate(length, truncation) { |
375 length = length || 30; | 585 length = length || 30; |
376 truncation = Object.isUndefined(truncation) ? '...' : truncation; | 586 truncation = Object.isUndefined(truncation) ? '...' : truncation; |
377 return this.length > length ? | 587 return this.length > length ? |
378 this.slice(0, length - truncation.length) + truncation : String(this); | 588 this.slice(0, length - truncation.length) + truncation : String(this); |
379 }, | 589 } |
380 | 590 |
381 strip: function() { | 591 function strip() { |
382 return this.replace(/^\s+/, '').replace(/\s+$/, ''); | 592 return this.replace(/^\s+/, '').replace(/\s+$/, ''); |
383 }, | 593 } |
384 | 594 |
385 stripTags: function() { | 595 function stripTags() { |
386 return this.replace(/<\/?[^>]+>/gi, ''); | 596 return this.replace(/<\w+(\s+("[^"]*"|'[^']*'|[^>])+)?>|<\/\w+>/gi, ''); |
387 }, | 597 } |
388 | 598 |
389 stripScripts: function() { | 599 function stripScripts() { |
390 return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); | 600 return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); |
391 }, | 601 } |
392 | 602 |
393 extractScripts: function() { | 603 function extractScripts() { |
394 var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); | 604 var matchAll = new RegExp(Prototype.ScriptFragment, 'img'), |
395 var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); | 605 matchOne = new RegExp(Prototype.ScriptFragment, 'im'); |
396 return (this.match(matchAll) || []).map(function(scriptTag) { | 606 return (this.match(matchAll) || []).map(function(scriptTag) { |
397 return (scriptTag.match(matchOne) || ['', ''])[1]; | 607 return (scriptTag.match(matchOne) || ['', ''])[1]; |
398 }); | 608 }); |
399 }, | 609 } |
400 | 610 |
401 evalScripts: function() { | 611 function evalScripts() { |
402 return this.extractScripts().map(function(script) { return eval(script) }); | 612 return this.extractScripts().map(function(script) { return eval(script) }); |
403 }, | 613 } |
404 | 614 |
405 escapeHTML: function() { | 615 function escapeHTML() { |
406 var self = arguments.callee; | 616 return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); |
407 self.text.data = this; | 617 } |
408 return self.div.innerHTML; | 618 |
409 }, | 619 function unescapeHTML() { |
410 | 620 return this.stripTags().replace(/</g,'<').replace(/>/g,'>').replace(/&/g,'&'); |
411 unescapeHTML: function() { | 621 } |
412 var div = new Element('div'); | 622 |
413 div.innerHTML = this.stripTags(); | 623 |
414 return div.childNodes[0] ? (div.childNodes.length > 1 ? | 624 function toQueryParams(separator) { |
415 $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) : | |
416 div.childNodes[0].nodeValue) : ''; | |
417 }, | |
418 | |
419 toQueryParams: function(separator) { | |
420 var match = this.strip().match(/([^?#]*)(#.*)?$/); | 625 var match = this.strip().match(/([^?#]*)(#.*)?$/); |
421 if (!match) return { }; | 626 if (!match) return { }; |
422 | 627 |
423 return match[1].split(separator || '&').inject({ }, function(hash, pair) { | 628 return match[1].split(separator || '&').inject({ }, function(hash, pair) { |
424 if ((pair = pair.split('='))[0]) { | 629 if ((pair = pair.split('='))[0]) { |
425 var key = decodeURIComponent(pair.shift()); | 630 var key = decodeURIComponent(pair.shift()), |
426 var value = pair.length > 1 ? pair.join('=') : pair[0]; | 631 value = pair.length > 1 ? pair.join('=') : pair[0]; |
632 | |
427 if (value != undefined) value = decodeURIComponent(value); | 633 if (value != undefined) value = decodeURIComponent(value); |
428 | 634 |
429 if (key in hash) { | 635 if (key in hash) { |
430 if (!Object.isArray(hash[key])) hash[key] = [hash[key]]; | 636 if (!Object.isArray(hash[key])) hash[key] = [hash[key]]; |
431 hash[key].push(value); | 637 hash[key].push(value); |
432 } | 638 } |
433 else hash[key] = value; | 639 else hash[key] = value; |
434 } | 640 } |
435 return hash; | 641 return hash; |
436 }); | 642 }); |
437 }, | 643 } |
438 | 644 |
439 toArray: function() { | 645 function toArray() { |
440 return this.split(''); | 646 return this.split(''); |
441 }, | 647 } |
442 | 648 |
443 succ: function() { | 649 function succ() { |
444 return this.slice(0, this.length - 1) + | 650 return this.slice(0, this.length - 1) + |
445 String.fromCharCode(this.charCodeAt(this.length - 1) + 1); | 651 String.fromCharCode(this.charCodeAt(this.length - 1) + 1); |
446 }, | 652 } |
447 | 653 |
448 times: function(count) { | 654 function times(count) { |
449 return count < 1 ? '' : new Array(count + 1).join(this); | 655 return count < 1 ? '' : new Array(count + 1).join(this); |
450 }, | 656 } |
451 | 657 |
452 camelize: function() { | 658 function camelize() { |
453 var parts = this.split('-'), len = parts.length; | 659 return this.replace(/-+(.)?/g, function(match, chr) { |
454 if (len == 1) return parts[0]; | 660 return chr ? chr.toUpperCase() : ''; |
455 | 661 }); |
456 var camelized = this.charAt(0) == '-' | 662 } |
457 ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1) | 663 |
458 : parts[0]; | 664 function capitalize() { |
459 | |
460 for (var i = 1; i < len; i++) | |
461 camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1); | |
462 | |
463 return camelized; | |
464 }, | |
465 | |
466 capitalize: function() { | |
467 return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase(); | 665 return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase(); |
468 }, | 666 } |
469 | 667 |
470 underscore: function() { | 668 function underscore() { |
471 return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase(); | 669 return this.replace(/::/g, '/') |
472 }, | 670 .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2') |
473 | 671 .replace(/([a-z\d])([A-Z])/g, '$1_$2') |
474 dasherize: function() { | 672 .replace(/-/g, '_') |
475 return this.gsub(/_/,'-'); | 673 .toLowerCase(); |
476 }, | 674 } |
477 | 675 |
478 inspect: function(useDoubleQuotes) { | 676 function dasherize() { |
479 var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) { | 677 return this.replace(/_/g, '-'); |
480 var character = String.specialChar[match[0]]; | 678 } |
481 return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16); | 679 |
680 function inspect(useDoubleQuotes) { | |
681 var escapedString = this.replace(/[\x00-\x1f\\]/g, function(character) { | |
682 if (character in String.specialChar) { | |
683 return String.specialChar[character]; | |
684 } | |
685 return '\\u00' + character.charCodeAt().toPaddedString(2, 16); | |
482 }); | 686 }); |
483 if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"'; | 687 if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"'; |
484 return "'" + escapedString.replace(/'/g, '\\\'') + "'"; | 688 return "'" + escapedString.replace(/'/g, '\\\'') + "'"; |
485 }, | 689 } |
486 | 690 |
487 toJSON: function() { | 691 function unfilterJSON(filter) { |
488 return this.inspect(true); | 692 return this.replace(filter || Prototype.JSONFilter, '$1'); |
489 }, | 693 } |
490 | 694 |
491 unfilterJSON: function(filter) { | 695 function isJSON() { |
492 return this.sub(filter || Prototype.JSONFilter, '#{1}'); | |
493 }, | |
494 | |
495 isJSON: function() { | |
496 var str = this; | 696 var str = this; |
497 if (str.blank()) return false; | 697 if (str.blank()) return false; |
498 str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, ''); | 698 str = str.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@'); |
499 return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str); | 699 str = str.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']'); |
500 }, | 700 str = str.replace(/(?:^|:|,)(?:\s*\[)+/g, ''); |
501 | 701 return (/^[\],:{}\s]*$/).test(str); |
502 evalJSON: function(sanitize) { | 702 } |
503 var json = this.unfilterJSON(); | 703 |
704 function evalJSON(sanitize) { | |
705 var json = this.unfilterJSON(), | |
706 cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; | |
707 if (cx.test(json)) { | |
708 json = json.replace(cx, function (a) { | |
709 return '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); | |
710 }); | |
711 } | |
504 try { | 712 try { |
505 if (!sanitize || json.isJSON()) return eval('(' + json + ')'); | 713 if (!sanitize || json.isJSON()) return eval('(' + json + ')'); |
506 } catch (e) { } | 714 } catch (e) { } |
507 throw new SyntaxError('Badly formed JSON string: ' + this.inspect()); | 715 throw new SyntaxError('Badly formed JSON string: ' + this.inspect()); |
508 }, | 716 } |
509 | 717 |
510 include: function(pattern) { | 718 function parseJSON() { |
719 var json = this.unfilterJSON(); | |
720 return JSON.parse(json); | |
721 } | |
722 | |
723 function include(pattern) { | |
511 return this.indexOf(pattern) > -1; | 724 return this.indexOf(pattern) > -1; |
512 }, | 725 } |
513 | 726 |
514 startsWith: function(pattern) { | 727 function startsWith(pattern) { |
515 return this.indexOf(pattern) === 0; | 728 return this.lastIndexOf(pattern, 0) === 0; |
516 }, | 729 } |
517 | 730 |
518 endsWith: function(pattern) { | 731 function endsWith(pattern) { |
519 var d = this.length - pattern.length; | 732 var d = this.length - pattern.length; |
520 return d >= 0 && this.lastIndexOf(pattern) === d; | 733 return d >= 0 && this.indexOf(pattern, d) === d; |
521 }, | 734 } |
522 | 735 |
523 empty: function() { | 736 function empty() { |
524 return this == ''; | 737 return this == ''; |
525 }, | 738 } |
526 | 739 |
527 blank: function() { | 740 function blank() { |
528 return /^\s*$/.test(this); | 741 return /^\s*$/.test(this); |
529 }, | 742 } |
530 | 743 |
531 interpolate: function(object, pattern) { | 744 function interpolate(object, pattern) { |
532 return new Template(this, pattern).evaluate(object); | 745 return new Template(this, pattern).evaluate(object); |
533 } | 746 } |
534 }); | 747 |
535 | 748 return { |
536 if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, { | 749 gsub: gsub, |
537 escapeHTML: function() { | 750 sub: sub, |
538 return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); | 751 scan: scan, |
539 }, | 752 truncate: truncate, |
540 unescapeHTML: function() { | 753 strip: String.prototype.trim || strip, |
541 return this.stripTags().replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); | 754 stripTags: stripTags, |
542 } | 755 stripScripts: stripScripts, |
543 }); | 756 extractScripts: extractScripts, |
544 | 757 evalScripts: evalScripts, |
545 String.prototype.gsub.prepareReplacement = function(replacement) { | 758 escapeHTML: escapeHTML, |
546 if (Object.isFunction(replacement)) return replacement; | 759 unescapeHTML: unescapeHTML, |
547 var template = new Template(replacement); | 760 toQueryParams: toQueryParams, |
548 return function(match) { return template.evaluate(match) }; | 761 parseQuery: toQueryParams, |
549 }; | 762 toArray: toArray, |
550 | 763 succ: succ, |
551 String.prototype.parseQuery = String.prototype.toQueryParams; | 764 times: times, |
552 | 765 camelize: camelize, |
553 Object.extend(String.prototype.escapeHTML, { | 766 capitalize: capitalize, |
554 div: document.createElement('div'), | 767 underscore: underscore, |
555 text: document.createTextNode('') | 768 dasherize: dasherize, |
556 }); | 769 inspect: inspect, |
557 | 770 unfilterJSON: unfilterJSON, |
558 String.prototype.escapeHTML.div.appendChild(String.prototype.escapeHTML.text); | 771 isJSON: isJSON, |
772 evalJSON: NATIVE_JSON_PARSE_SUPPORT ? parseJSON : evalJSON, | |
773 include: include, | |
774 startsWith: startsWith, | |
775 endsWith: endsWith, | |
776 empty: empty, | |
777 blank: blank, | |
778 interpolate: interpolate | |
779 }; | |
780 })()); | |
559 | 781 |
560 var Template = Class.create({ | 782 var Template = Class.create({ |
561 initialize: function(template, pattern) { | 783 initialize: function(template, pattern) { |
562 this.template = template.toString(); | 784 this.template = template.toString(); |
563 this.pattern = pattern || Template.Pattern; | 785 this.pattern = pattern || Template.Pattern; |
564 }, | 786 }, |
565 | 787 |
566 evaluate: function(object) { | 788 evaluate: function(object) { |
567 if (Object.isFunction(object.toTemplateReplacements)) | 789 if (object && Object.isFunction(object.toTemplateReplacements)) |
568 object = object.toTemplateReplacements(); | 790 object = object.toTemplateReplacements(); |
569 | 791 |
570 return this.template.gsub(this.pattern, function(match) { | 792 return this.template.gsub(this.pattern, function(match) { |
571 if (object == null) return ''; | 793 if (object == null) return (match[1] + ''); |
572 | 794 |
573 var before = match[1] || ''; | 795 var before = match[1] || ''; |
574 if (before == '\\') return match[2]; | 796 if (before == '\\') return match[2]; |
575 | 797 |
576 var ctx = object, expr = match[3]; | 798 var ctx = object, expr = match[3], |
577 var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/; | 799 pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/; |
800 | |
578 match = pattern.exec(expr); | 801 match = pattern.exec(expr); |
579 if (match == null) return before; | 802 if (match == null) return before; |
580 | 803 |
581 while (match != null) { | 804 while (match != null) { |
582 var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1]; | 805 var comp = match[1].startsWith('[') ? match[2].replace(/\\\\]/g, ']') : match[1]; |
583 ctx = ctx[comp]; | 806 ctx = ctx[comp]; |
584 if (null == ctx || '' == match[3]) break; | 807 if (null == ctx || '' == match[3]) break; |
585 expr = expr.substring('[' == match[3] ? match[1].length : match[0].length); | 808 expr = expr.substring('[' == match[3] ? match[1].length : match[0].length); |
586 match = pattern.exec(expr); | 809 match = pattern.exec(expr); |
587 } | 810 } |
592 }); | 815 }); |
593 Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; | 816 Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; |
594 | 817 |
595 var $break = { }; | 818 var $break = { }; |
596 | 819 |
597 var Enumerable = { | 820 var Enumerable = (function() { |
598 each: function(iterator, context) { | 821 function each(iterator, context) { |
599 var index = 0; | 822 var index = 0; |
600 try { | 823 try { |
601 this._each(function(value) { | 824 this._each(function(value) { |
602 iterator.call(context, value, index++); | 825 iterator.call(context, value, index++); |
603 }); | 826 }); |
604 } catch (e) { | 827 } catch (e) { |
605 if (e != $break) throw e; | 828 if (e != $break) throw e; |
606 } | 829 } |
607 return this; | 830 return this; |
608 }, | 831 } |
609 | 832 |
610 eachSlice: function(number, iterator, context) { | 833 function eachSlice(number, iterator, context) { |
611 var index = -number, slices = [], array = this.toArray(); | 834 var index = -number, slices = [], array = this.toArray(); |
612 if (number < 1) return array; | 835 if (number < 1) return array; |
613 while ((index += number) < array.length) | 836 while ((index += number) < array.length) |
614 slices.push(array.slice(index, index+number)); | 837 slices.push(array.slice(index, index+number)); |
615 return slices.collect(iterator, context); | 838 return slices.collect(iterator, context); |
616 }, | 839 } |
617 | 840 |
618 all: function(iterator, context) { | 841 function all(iterator, context) { |
619 iterator = iterator || Prototype.K; | 842 iterator = iterator || Prototype.K; |
620 var result = true; | 843 var result = true; |
621 this.each(function(value, index) { | 844 this.each(function(value, index) { |
622 result = result && !!iterator.call(context, value, index); | 845 result = result && !!iterator.call(context, value, index); |
623 if (!result) throw $break; | 846 if (!result) throw $break; |
624 }); | 847 }); |
625 return result; | 848 return result; |
626 }, | 849 } |
627 | 850 |
628 any: function(iterator, context) { | 851 function any(iterator, context) { |
629 iterator = iterator || Prototype.K; | 852 iterator = iterator || Prototype.K; |
630 var result = false; | 853 var result = false; |
631 this.each(function(value, index) { | 854 this.each(function(value, index) { |
632 if (result = !!iterator.call(context, value, index)) | 855 if (result = !!iterator.call(context, value, index)) |
633 throw $break; | 856 throw $break; |
634 }); | 857 }); |
635 return result; | 858 return result; |
636 }, | 859 } |
637 | 860 |
638 collect: function(iterator, context) { | 861 function collect(iterator, context) { |
639 iterator = iterator || Prototype.K; | 862 iterator = iterator || Prototype.K; |
640 var results = []; | 863 var results = []; |
641 this.each(function(value, index) { | 864 this.each(function(value, index) { |
642 results.push(iterator.call(context, value, index)); | 865 results.push(iterator.call(context, value, index)); |
643 }); | 866 }); |
644 return results; | 867 return results; |
645 }, | 868 } |
646 | 869 |
647 detect: function(iterator, context) { | 870 function detect(iterator, context) { |
648 var result; | 871 var result; |
649 this.each(function(value, index) { | 872 this.each(function(value, index) { |
650 if (iterator.call(context, value, index)) { | 873 if (iterator.call(context, value, index)) { |
651 result = value; | 874 result = value; |
652 throw $break; | 875 throw $break; |
653 } | 876 } |
654 }); | 877 }); |
655 return result; | 878 return result; |
656 }, | 879 } |
657 | 880 |
658 findAll: function(iterator, context) { | 881 function findAll(iterator, context) { |
659 var results = []; | 882 var results = []; |
660 this.each(function(value, index) { | 883 this.each(function(value, index) { |
661 if (iterator.call(context, value, index)) | 884 if (iterator.call(context, value, index)) |
662 results.push(value); | 885 results.push(value); |
663 }); | 886 }); |
664 return results; | 887 return results; |
665 }, | 888 } |
666 | 889 |
667 grep: function(filter, iterator, context) { | 890 function grep(filter, iterator, context) { |
668 iterator = iterator || Prototype.K; | 891 iterator = iterator || Prototype.K; |
669 var results = []; | 892 var results = []; |
670 | 893 |
671 if (Object.isString(filter)) | 894 if (Object.isString(filter)) |
672 filter = new RegExp(filter); | 895 filter = new RegExp(RegExp.escape(filter)); |
673 | 896 |
674 this.each(function(value, index) { | 897 this.each(function(value, index) { |
675 if (filter.match(value)) | 898 if (filter.match(value)) |
676 results.push(iterator.call(context, value, index)); | 899 results.push(iterator.call(context, value, index)); |
677 }); | 900 }); |
678 return results; | 901 return results; |
679 }, | 902 } |
680 | 903 |
681 include: function(object) { | 904 function include(object) { |
682 if (Object.isFunction(this.indexOf)) | 905 if (Object.isFunction(this.indexOf)) |
683 if (this.indexOf(object) != -1) return true; | 906 if (this.indexOf(object) != -1) return true; |
684 | 907 |
685 var found = false; | 908 var found = false; |
686 this.each(function(value) { | 909 this.each(function(value) { |
688 found = true; | 911 found = true; |
689 throw $break; | 912 throw $break; |
690 } | 913 } |
691 }); | 914 }); |
692 return found; | 915 return found; |
693 }, | 916 } |
694 | 917 |
695 inGroupsOf: function(number, fillWith) { | 918 function inGroupsOf(number, fillWith) { |
696 fillWith = Object.isUndefined(fillWith) ? null : fillWith; | 919 fillWith = Object.isUndefined(fillWith) ? null : fillWith; |
697 return this.eachSlice(number, function(slice) { | 920 return this.eachSlice(number, function(slice) { |
698 while(slice.length < number) slice.push(fillWith); | 921 while(slice.length < number) slice.push(fillWith); |
699 return slice; | 922 return slice; |
700 }); | 923 }); |
701 }, | 924 } |
702 | 925 |
703 inject: function(memo, iterator, context) { | 926 function inject(memo, iterator, context) { |
704 this.each(function(value, index) { | 927 this.each(function(value, index) { |
705 memo = iterator.call(context, memo, value, index); | 928 memo = iterator.call(context, memo, value, index); |
706 }); | 929 }); |
707 return memo; | 930 return memo; |
708 }, | 931 } |
709 | 932 |
710 invoke: function(method) { | 933 function invoke(method) { |
711 var args = $A(arguments).slice(1); | 934 var args = $A(arguments).slice(1); |
712 return this.map(function(value) { | 935 return this.map(function(value) { |
713 return value[method].apply(value, args); | 936 return value[method].apply(value, args); |
714 }); | 937 }); |
715 }, | 938 } |
716 | 939 |
717 max: function(iterator, context) { | 940 function max(iterator, context) { |
718 iterator = iterator || Prototype.K; | 941 iterator = iterator || Prototype.K; |
719 var result; | 942 var result; |
720 this.each(function(value, index) { | 943 this.each(function(value, index) { |
721 value = iterator.call(context, value, index); | 944 value = iterator.call(context, value, index); |
722 if (result == null || value >= result) | 945 if (result == null || value >= result) |
723 result = value; | 946 result = value; |
724 }); | 947 }); |
725 return result; | 948 return result; |
726 }, | 949 } |
727 | 950 |
728 min: function(iterator, context) { | 951 function min(iterator, context) { |
729 iterator = iterator || Prototype.K; | 952 iterator = iterator || Prototype.K; |
730 var result; | 953 var result; |
731 this.each(function(value, index) { | 954 this.each(function(value, index) { |
732 value = iterator.call(context, value, index); | 955 value = iterator.call(context, value, index); |
733 if (result == null || value < result) | 956 if (result == null || value < result) |
734 result = value; | 957 result = value; |
735 }); | 958 }); |
736 return result; | 959 return result; |
737 }, | 960 } |
738 | 961 |
739 partition: function(iterator, context) { | 962 function partition(iterator, context) { |
740 iterator = iterator || Prototype.K; | 963 iterator = iterator || Prototype.K; |
741 var trues = [], falses = []; | 964 var trues = [], falses = []; |
742 this.each(function(value, index) { | 965 this.each(function(value, index) { |
743 (iterator.call(context, value, index) ? | 966 (iterator.call(context, value, index) ? |
744 trues : falses).push(value); | 967 trues : falses).push(value); |
745 }); | 968 }); |
746 return [trues, falses]; | 969 return [trues, falses]; |
747 }, | 970 } |
748 | 971 |
749 pluck: function(property) { | 972 function pluck(property) { |
750 var results = []; | 973 var results = []; |
751 this.each(function(value) { | 974 this.each(function(value) { |
752 results.push(value[property]); | 975 results.push(value[property]); |
753 }); | 976 }); |
754 return results; | 977 return results; |
755 }, | 978 } |
756 | 979 |
757 reject: function(iterator, context) { | 980 function reject(iterator, context) { |
758 var results = []; | 981 var results = []; |
759 this.each(function(value, index) { | 982 this.each(function(value, index) { |
760 if (!iterator.call(context, value, index)) | 983 if (!iterator.call(context, value, index)) |
761 results.push(value); | 984 results.push(value); |
762 }); | 985 }); |
763 return results; | 986 return results; |
764 }, | 987 } |
765 | 988 |
766 sortBy: function(iterator, context) { | 989 function sortBy(iterator, context) { |
767 return this.map(function(value, index) { | 990 return this.map(function(value, index) { |
768 return { | 991 return { |
769 value: value, | 992 value: value, |
770 criteria: iterator.call(context, value, index) | 993 criteria: iterator.call(context, value, index) |
771 }; | 994 }; |
772 }).sort(function(left, right) { | 995 }).sort(function(left, right) { |
773 var a = left.criteria, b = right.criteria; | 996 var a = left.criteria, b = right.criteria; |
774 return a < b ? -1 : a > b ? 1 : 0; | 997 return a < b ? -1 : a > b ? 1 : 0; |
775 }).pluck('value'); | 998 }).pluck('value'); |
776 }, | 999 } |
777 | 1000 |
778 toArray: function() { | 1001 function toArray() { |
779 return this.map(); | 1002 return this.map(); |
780 }, | 1003 } |
781 | 1004 |
782 zip: function() { | 1005 function zip() { |
783 var iterator = Prototype.K, args = $A(arguments); | 1006 var iterator = Prototype.K, args = $A(arguments); |
784 if (Object.isFunction(args.last())) | 1007 if (Object.isFunction(args.last())) |
785 iterator = args.pop(); | 1008 iterator = args.pop(); |
786 | 1009 |
787 var collections = [this].concat(args).map($A); | 1010 var collections = [this].concat(args).map($A); |
788 return this.map(function(value, index) { | 1011 return this.map(function(value, index) { |
789 return iterator(collections.pluck(index)); | 1012 return iterator(collections.pluck(index)); |
790 }); | 1013 }); |
791 }, | 1014 } |
792 | 1015 |
793 size: function() { | 1016 function size() { |
794 return this.toArray().length; | 1017 return this.toArray().length; |
795 }, | 1018 } |
796 | 1019 |
797 inspect: function() { | 1020 function inspect() { |
798 return '#<Enumerable:' + this.toArray().inspect() + '>'; | 1021 return '#<Enumerable:' + this.toArray().inspect() + '>'; |
799 } | 1022 } |
800 }; | 1023 |
801 | 1024 |
802 Object.extend(Enumerable, { | 1025 |
803 map: Enumerable.collect, | 1026 |
804 find: Enumerable.detect, | 1027 |
805 select: Enumerable.findAll, | 1028 |
806 filter: Enumerable.findAll, | 1029 |
807 member: Enumerable.include, | 1030 |
808 entries: Enumerable.toArray, | 1031 |
809 every: Enumerable.all, | 1032 return { |
810 some: Enumerable.any | 1033 each: each, |
811 }); | 1034 eachSlice: eachSlice, |
1035 all: all, | |
1036 every: all, | |
1037 any: any, | |
1038 some: any, | |
1039 collect: collect, | |
1040 map: collect, | |
1041 detect: detect, | |
1042 findAll: findAll, | |
1043 select: findAll, | |
1044 filter: findAll, | |
1045 grep: grep, | |
1046 include: include, | |
1047 member: include, | |
1048 inGroupsOf: inGroupsOf, | |
1049 inject: inject, | |
1050 invoke: invoke, | |
1051 max: max, | |
1052 min: min, | |
1053 partition: partition, | |
1054 pluck: pluck, | |
1055 reject: reject, | |
1056 sortBy: sortBy, | |
1057 toArray: toArray, | |
1058 entries: toArray, | |
1059 zip: zip, | |
1060 size: size, | |
1061 inspect: inspect, | |
1062 find: detect | |
1063 }; | |
1064 })(); | |
1065 | |
812 function $A(iterable) { | 1066 function $A(iterable) { |
813 if (!iterable) return []; | 1067 if (!iterable) return []; |
814 if (iterable.toArray) return iterable.toArray(); | 1068 if ('toArray' in Object(iterable)) return iterable.toArray(); |
815 var length = iterable.length || 0, results = new Array(length); | 1069 var length = iterable.length || 0, results = new Array(length); |
816 while (length--) results[length] = iterable[length]; | 1070 while (length--) results[length] = iterable[length]; |
817 return results; | 1071 return results; |
818 } | 1072 } |
819 | 1073 |
820 if (Prototype.Browser.WebKit) { | 1074 |
821 $A = function(iterable) { | 1075 function $w(string) { |
822 if (!iterable) return []; | 1076 if (!Object.isString(string)) return []; |
823 // In Safari, only use the `toArray` method if it's not a NodeList. | 1077 string = string.strip(); |
824 // A NodeList is a function, has an function `item` property, and a numeric | 1078 return string ? string.split(/\s+/) : []; |
825 // `length` property. Adapted from Google Doctype. | |
826 if (!(typeof iterable === 'function' && typeof iterable.length === | |
827 'number' && typeof iterable.item === 'function') && iterable.toArray) | |
828 return iterable.toArray(); | |
829 var length = iterable.length || 0, results = new Array(length); | |
830 while (length--) results[length] = iterable[length]; | |
831 return results; | |
832 }; | |
833 } | 1079 } |
834 | 1080 |
835 Array.from = $A; | 1081 Array.from = $A; |
836 | 1082 |
837 Object.extend(Array.prototype, Enumerable); | 1083 |
838 | 1084 (function() { |
839 if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse; | 1085 var arrayProto = Array.prototype, |
840 | 1086 slice = arrayProto.slice, |
841 Object.extend(Array.prototype, { | 1087 _each = arrayProto.forEach; // use native browser JS 1.6 implementation if available |
842 _each: function(iterator) { | 1088 |
843 for (var i = 0, length = this.length; i < length; i++) | 1089 function each(iterator, context) { |
844 iterator(this[i]); | 1090 for (var i = 0, length = this.length >>> 0; i < length; i++) { |
845 }, | 1091 if (i in this) iterator.call(context, this[i], i, this); |
846 | 1092 } |
847 clear: function() { | 1093 } |
1094 if (!_each) _each = each; | |
1095 | |
1096 function clear() { | |
848 this.length = 0; | 1097 this.length = 0; |
849 return this; | 1098 return this; |
850 }, | 1099 } |
851 | 1100 |
852 first: function() { | 1101 function first() { |
853 return this[0]; | 1102 return this[0]; |
854 }, | 1103 } |
855 | 1104 |
856 last: function() { | 1105 function last() { |
857 return this[this.length - 1]; | 1106 return this[this.length - 1]; |
858 }, | 1107 } |
859 | 1108 |
860 compact: function() { | 1109 function compact() { |
861 return this.select(function(value) { | 1110 return this.select(function(value) { |
862 return value != null; | 1111 return value != null; |
863 }); | 1112 }); |
864 }, | 1113 } |
865 | 1114 |
866 flatten: function() { | 1115 function flatten() { |
867 return this.inject([], function(array, value) { | 1116 return this.inject([], function(array, value) { |
868 return array.concat(Object.isArray(value) ? | 1117 if (Object.isArray(value)) |
869 value.flatten() : [value]); | 1118 return array.concat(value.flatten()); |
1119 array.push(value); | |
1120 return array; | |
870 }); | 1121 }); |
871 }, | 1122 } |
872 | 1123 |
873 without: function() { | 1124 function without() { |
874 var values = $A(arguments); | 1125 var values = slice.call(arguments, 0); |
875 return this.select(function(value) { | 1126 return this.select(function(value) { |
876 return !values.include(value); | 1127 return !values.include(value); |
877 }); | 1128 }); |
878 }, | 1129 } |
879 | 1130 |
880 reverse: function(inline) { | 1131 function reverse(inline) { |
881 return (inline !== false ? this : this.toArray())._reverse(); | 1132 return (inline === false ? this.toArray() : this)._reverse(); |
882 }, | 1133 } |
883 | 1134 |
884 reduce: function() { | 1135 function uniq(sorted) { |
885 return this.length > 1 ? this : this[0]; | |
886 }, | |
887 | |
888 uniq: function(sorted) { | |
889 return this.inject([], function(array, value, index) { | 1136 return this.inject([], function(array, value, index) { |
890 if (0 == index || (sorted ? array.last() != value : !array.include(value))) | 1137 if (0 == index || (sorted ? array.last() != value : !array.include(value))) |
891 array.push(value); | 1138 array.push(value); |
892 return array; | 1139 return array; |
893 }); | 1140 }); |
894 }, | 1141 } |
895 | 1142 |
896 intersect: function(array) { | 1143 function intersect(array) { |
897 return this.uniq().findAll(function(item) { | 1144 return this.uniq().findAll(function(item) { |
898 return array.detect(function(value) { return item === value }); | 1145 return array.detect(function(value) { return item === value }); |
899 }); | 1146 }); |
900 }, | 1147 } |
901 | 1148 |
902 clone: function() { | 1149 |
903 return [].concat(this); | 1150 function clone() { |
904 }, | 1151 return slice.call(this, 0); |
905 | 1152 } |
906 size: function() { | 1153 |
1154 function size() { | |
907 return this.length; | 1155 return this.length; |
908 }, | 1156 } |
909 | 1157 |
910 inspect: function() { | 1158 function inspect() { |
911 return '[' + this.map(Object.inspect).join(', ') + ']'; | 1159 return '[' + this.map(Object.inspect).join(', ') + ']'; |
912 }, | 1160 } |
913 | 1161 |
914 toJSON: function() { | 1162 function indexOf(item, i) { |
915 var results = []; | 1163 i || (i = 0); |
916 this.each(function(object) { | 1164 var length = this.length; |
917 var value = Object.toJSON(object); | 1165 if (i < 0) i = length + i; |
918 if (!Object.isUndefined(value)) results.push(value); | 1166 for (; i < length; i++) |
919 }); | 1167 if (this[i] === item) return i; |
920 return '[' + results.join(', ') + ']'; | 1168 return -1; |
921 } | 1169 } |
922 }); | 1170 |
923 | 1171 function lastIndexOf(item, i) { |
924 // use native browser JS 1.6 implementation if available | 1172 i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1; |
925 if (Object.isFunction(Array.prototype.forEach)) | 1173 var n = this.slice(0, i).reverse().indexOf(item); |
926 Array.prototype._each = Array.prototype.forEach; | 1174 return (n < 0) ? n : i - n - 1; |
927 | 1175 } |
928 if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) { | 1176 |
929 i || (i = 0); | 1177 function concat() { |
930 var length = this.length; | 1178 var array = slice.call(this, 0), item; |
931 if (i < 0) i = length + i; | |
932 for (; i < length; i++) | |
933 if (this[i] === item) return i; | |
934 return -1; | |
935 }; | |
936 | |
937 if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) { | |
938 i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1; | |
939 var n = this.slice(0, i).reverse().indexOf(item); | |
940 return (n < 0) ? n : i - n - 1; | |
941 }; | |
942 | |
943 Array.prototype.toArray = Array.prototype.clone; | |
944 | |
945 function $w(string) { | |
946 if (!Object.isString(string)) return []; | |
947 string = string.strip(); | |
948 return string ? string.split(/\s+/) : []; | |
949 } | |
950 | |
951 if (Prototype.Browser.Opera){ | |
952 Array.prototype.concat = function() { | |
953 var array = []; | |
954 for (var i = 0, length = this.length; i < length; i++) array.push(this[i]); | |
955 for (var i = 0, length = arguments.length; i < length; i++) { | 1179 for (var i = 0, length = arguments.length; i < length; i++) { |
956 if (Object.isArray(arguments[i])) { | 1180 item = arguments[i]; |
957 for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++) | 1181 if (Object.isArray(item) && !('callee' in item)) { |
958 array.push(arguments[i][j]); | 1182 for (var j = 0, arrayLength = item.length; j < arrayLength; j++) |
1183 array.push(item[j]); | |
959 } else { | 1184 } else { |
960 array.push(arguments[i]); | 1185 array.push(item); |
961 } | 1186 } |
962 } | 1187 } |
963 return array; | 1188 return array; |
964 }; | 1189 } |
965 } | 1190 |
966 Object.extend(Number.prototype, { | 1191 Object.extend(arrayProto, Enumerable); |
967 toColorPart: function() { | 1192 |
968 return this.toPaddedString(2, 16); | 1193 if (!arrayProto._reverse) |
969 }, | 1194 arrayProto._reverse = arrayProto.reverse; |
970 | 1195 |
971 succ: function() { | 1196 Object.extend(arrayProto, { |
972 return this + 1; | 1197 _each: _each, |
973 }, | 1198 clear: clear, |
974 | 1199 first: first, |
975 times: function(iterator, context) { | 1200 last: last, |
976 $R(0, this, true).each(iterator, context); | 1201 compact: compact, |
977 return this; | 1202 flatten: flatten, |
978 }, | 1203 without: without, |
979 | 1204 reverse: reverse, |
980 toPaddedString: function(length, radix) { | 1205 uniq: uniq, |
981 var string = this.toString(radix || 10); | 1206 intersect: intersect, |
982 return '0'.times(length - string.length) + string; | 1207 clone: clone, |
983 }, | 1208 toArray: clone, |
984 | 1209 size: size, |
985 toJSON: function() { | 1210 inspect: inspect |
986 return isFinite(this) ? this.toString() : 'null'; | 1211 }); |
987 } | 1212 |
988 }); | 1213 var CONCAT_ARGUMENTS_BUGGY = (function() { |
989 | 1214 return [].concat(arguments)[0][0] !== 1; |
990 $w('abs round ceil floor').each(function(method){ | 1215 })(1,2) |
991 Number.prototype[method] = Math[method].methodize(); | 1216 |
992 }); | 1217 if (CONCAT_ARGUMENTS_BUGGY) arrayProto.concat = concat; |
1218 | |
1219 if (!arrayProto.indexOf) arrayProto.indexOf = indexOf; | |
1220 if (!arrayProto.lastIndexOf) arrayProto.lastIndexOf = lastIndexOf; | |
1221 })(); | |
993 function $H(object) { | 1222 function $H(object) { |
994 return new Hash(object); | 1223 return new Hash(object); |
995 }; | 1224 }; |
996 | 1225 |
997 var Hash = Class.create(Enumerable, (function() { | 1226 var Hash = Class.create(Enumerable, (function() { |
1227 function initialize(object) { | |
1228 this._object = Object.isHash(object) ? object.toObject() : Object.clone(object); | |
1229 } | |
1230 | |
1231 | |
1232 function _each(iterator) { | |
1233 for (var key in this._object) { | |
1234 var value = this._object[key], pair = [key, value]; | |
1235 pair.key = key; | |
1236 pair.value = value; | |
1237 iterator(pair); | |
1238 } | |
1239 } | |
1240 | |
1241 function set(key, value) { | |
1242 return this._object[key] = value; | |
1243 } | |
1244 | |
1245 function get(key) { | |
1246 if (this._object[key] !== Object.prototype[key]) | |
1247 return this._object[key]; | |
1248 } | |
1249 | |
1250 function unset(key) { | |
1251 var value = this._object[key]; | |
1252 delete this._object[key]; | |
1253 return value; | |
1254 } | |
1255 | |
1256 function toObject() { | |
1257 return Object.clone(this._object); | |
1258 } | |
1259 | |
1260 | |
1261 | |
1262 function keys() { | |
1263 return this.pluck('key'); | |
1264 } | |
1265 | |
1266 function values() { | |
1267 return this.pluck('value'); | |
1268 } | |
1269 | |
1270 function index(value) { | |
1271 var match = this.detect(function(pair) { | |
1272 return pair.value === value; | |
1273 }); | |
1274 return match && match.key; | |
1275 } | |
1276 | |
1277 function merge(object) { | |
1278 return this.clone().update(object); | |
1279 } | |
1280 | |
1281 function update(object) { | |
1282 return new Hash(object).inject(this, function(result, pair) { | |
1283 result.set(pair.key, pair.value); | |
1284 return result; | |
1285 }); | |
1286 } | |
998 | 1287 |
999 function toQueryPair(key, value) { | 1288 function toQueryPair(key, value) { |
1000 if (Object.isUndefined(value)) return key; | 1289 if (Object.isUndefined(value)) return key; |
1001 return key + '=' + encodeURIComponent(String.interpret(value)); | 1290 return key + '=' + encodeURIComponent(String.interpret(value)); |
1002 } | 1291 } |
1003 | 1292 |
1293 function toQueryString() { | |
1294 return this.inject([], function(results, pair) { | |
1295 var key = encodeURIComponent(pair.key), values = pair.value; | |
1296 | |
1297 if (values && typeof values == 'object') { | |
1298 if (Object.isArray(values)) { | |
1299 var queryValues = []; | |
1300 for (var i = 0, len = values.length, value; i < len; i++) { | |
1301 value = values[i]; | |
1302 queryValues.push(toQueryPair(key, value)); | |
1303 } | |
1304 return results.concat(queryValues); | |
1305 } | |
1306 } else results.push(toQueryPair(key, values)); | |
1307 return results; | |
1308 }).join('&'); | |
1309 } | |
1310 | |
1311 function inspect() { | |
1312 return '#<Hash:{' + this.map(function(pair) { | |
1313 return pair.map(Object.inspect).join(': '); | |
1314 }).join(', ') + '}>'; | |
1315 } | |
1316 | |
1317 function clone() { | |
1318 return new Hash(this); | |
1319 } | |
1320 | |
1004 return { | 1321 return { |
1005 initialize: function(object) { | 1322 initialize: initialize, |
1006 this._object = Object.isHash(object) ? object.toObject() : Object.clone(object); | 1323 _each: _each, |
1007 }, | 1324 set: set, |
1008 | 1325 get: get, |
1009 _each: function(iterator) { | 1326 unset: unset, |
1010 for (var key in this._object) { | 1327 toObject: toObject, |
1011 var value = this._object[key], pair = [key, value]; | 1328 toTemplateReplacements: toObject, |
1012 pair.key = key; | 1329 keys: keys, |
1013 pair.value = value; | 1330 values: values, |
1014 iterator(pair); | 1331 index: index, |
1015 } | 1332 merge: merge, |
1016 }, | 1333 update: update, |
1017 | 1334 toQueryString: toQueryString, |
1018 set: function(key, value) { | 1335 inspect: inspect, |
1019 return this._object[key] = value; | 1336 toJSON: toObject, |
1020 }, | 1337 clone: clone |
1021 | 1338 }; |
1022 get: function(key) { | |
1023 // simulating poorly supported hasOwnProperty | |
1024 if (this._object[key] !== Object.prototype[key]) | |
1025 return this._object[key]; | |
1026 }, | |
1027 | |
1028 unset: function(key) { | |
1029 var value = this._object[key]; | |
1030 delete this._object[key]; | |
1031 return value; | |
1032 }, | |
1033 | |
1034 toObject: function() { | |
1035 return Object.clone(this._object); | |
1036 }, | |
1037 | |
1038 keys: function() { | |
1039 return this.pluck('key'); | |
1040 }, | |
1041 | |
1042 values: function() { | |
1043 return this.pluck('value'); | |
1044 }, | |
1045 | |
1046 index: function(value) { | |
1047 var match = this.detect(function(pair) { | |
1048 return pair.value === value; | |
1049 }); | |
1050 return match && match.key; | |
1051 }, | |
1052 | |
1053 merge: function(object) { | |
1054 return this.clone().update(object); | |
1055 }, | |
1056 | |
1057 update: function(object) { | |
1058 return new Hash(object).inject(this, function(result, pair) { | |
1059 result.set(pair.key, pair.value); | |
1060 return result; | |
1061 }); | |
1062 }, | |
1063 | |
1064 toQueryString: function() { | |
1065 return this.inject([], function(results, pair) { | |
1066 var key = encodeURIComponent(pair.key), values = pair.value; | |
1067 | |
1068 if (values && typeof values == 'object') { | |
1069 if (Object.isArray(values)) | |
1070 return results.concat(values.map(toQueryPair.curry(key))); | |
1071 } else results.push(toQueryPair(key, values)); | |
1072 return results; | |
1073 }).join('&'); | |
1074 }, | |
1075 | |
1076 inspect: function() { | |
1077 return '#<Hash:{' + this.map(function(pair) { | |
1078 return pair.map(Object.inspect).join(': '); | |
1079 }).join(', ') + '}>'; | |
1080 }, | |
1081 | |
1082 toJSON: function() { | |
1083 return Object.toJSON(this.toObject()); | |
1084 }, | |
1085 | |
1086 clone: function() { | |
1087 return new Hash(this); | |
1088 } | |
1089 } | |
1090 })()); | 1339 })()); |
1091 | 1340 |
1092 Hash.prototype.toTemplateReplacements = Hash.prototype.toObject; | |
1093 Hash.from = $H; | 1341 Hash.from = $H; |
1094 var ObjectRange = Class.create(Enumerable, { | 1342 Object.extend(Number.prototype, (function() { |
1095 initialize: function(start, end, exclusive) { | 1343 function toColorPart() { |
1344 return this.toPaddedString(2, 16); | |
1345 } | |
1346 | |
1347 function succ() { | |
1348 return this + 1; | |
1349 } | |
1350 | |
1351 function times(iterator, context) { | |
1352 $R(0, this, true).each(iterator, context); | |
1353 return this; | |
1354 } | |
1355 | |
1356 function toPaddedString(length, radix) { | |
1357 var string = this.toString(radix || 10); | |
1358 return '0'.times(length - string.length) + string; | |
1359 } | |
1360 | |
1361 function abs() { | |
1362 return Math.abs(this); | |
1363 } | |
1364 | |
1365 function round() { | |
1366 return Math.round(this); | |
1367 } | |
1368 | |
1369 function ceil() { | |
1370 return Math.ceil(this); | |
1371 } | |
1372 | |
1373 function floor() { | |
1374 return Math.floor(this); | |
1375 } | |
1376 | |
1377 return { | |
1378 toColorPart: toColorPart, | |
1379 succ: succ, | |
1380 times: times, | |
1381 toPaddedString: toPaddedString, | |
1382 abs: abs, | |
1383 round: round, | |
1384 ceil: ceil, | |
1385 floor: floor | |
1386 }; | |
1387 })()); | |
1388 | |
1389 function $R(start, end, exclusive) { | |
1390 return new ObjectRange(start, end, exclusive); | |
1391 } | |
1392 | |
1393 var ObjectRange = Class.create(Enumerable, (function() { | |
1394 function initialize(start, end, exclusive) { | |
1096 this.start = start; | 1395 this.start = start; |
1097 this.end = end; | 1396 this.end = end; |
1098 this.exclusive = exclusive; | 1397 this.exclusive = exclusive; |
1099 }, | 1398 } |
1100 | 1399 |
1101 _each: function(iterator) { | 1400 function _each(iterator) { |
1102 var value = this.start; | 1401 var value = this.start; |
1103 while (this.include(value)) { | 1402 while (this.include(value)) { |
1104 iterator(value); | 1403 iterator(value); |
1105 value = value.succ(); | 1404 value = value.succ(); |
1106 } | 1405 } |
1107 }, | 1406 } |
1108 | 1407 |
1109 include: function(value) { | 1408 function include(value) { |
1110 if (value < this.start) | 1409 if (value < this.start) |
1111 return false; | 1410 return false; |
1112 if (this.exclusive) | 1411 if (this.exclusive) |
1113 return value < this.end; | 1412 return value < this.end; |
1114 return value <= this.end; | 1413 return value <= this.end; |
1115 } | 1414 } |
1116 }); | 1415 |
1117 | 1416 return { |
1118 var $R = function(start, end, exclusive) { | 1417 initialize: initialize, |
1119 return new ObjectRange(start, end, exclusive); | 1418 _each: _each, |
1120 }; | 1419 include: include |
1420 }; | |
1421 })()); | |
1422 | |
1423 | |
1121 | 1424 |
1122 var Ajax = { | 1425 var Ajax = { |
1123 getTransport: function() { | 1426 getTransport: function() { |
1124 return Try.these( | 1427 return Try.these( |
1125 function() {return new XMLHttpRequest()}, | 1428 function() {return new XMLHttpRequest()}, |
1162 | 1465 |
1163 Ajax.Responders.register({ | 1466 Ajax.Responders.register({ |
1164 onCreate: function() { Ajax.activeRequestCount++ }, | 1467 onCreate: function() { Ajax.activeRequestCount++ }, |
1165 onComplete: function() { Ajax.activeRequestCount-- } | 1468 onComplete: function() { Ajax.activeRequestCount-- } |
1166 }); | 1469 }); |
1167 | |
1168 Ajax.Base = Class.create({ | 1470 Ajax.Base = Class.create({ |
1169 initialize: function(options) { | 1471 initialize: function(options) { |
1170 this.options = { | 1472 this.options = { |
1171 method: 'post', | 1473 method: 'post', |
1172 asynchronous: true, | 1474 asynchronous: true, |
1178 }; | 1480 }; |
1179 Object.extend(this.options, options || { }); | 1481 Object.extend(this.options, options || { }); |
1180 | 1482 |
1181 this.options.method = this.options.method.toLowerCase(); | 1483 this.options.method = this.options.method.toLowerCase(); |
1182 | 1484 |
1183 if (Object.isString(this.options.parameters)) | 1485 if (Object.isHash(this.options.parameters)) |
1184 this.options.parameters = this.options.parameters.toQueryParams(); | |
1185 else if (Object.isHash(this.options.parameters)) | |
1186 this.options.parameters = this.options.parameters.toObject(); | 1486 this.options.parameters = this.options.parameters.toObject(); |
1187 } | 1487 } |
1188 }); | 1488 }); |
1189 | |
1190 Ajax.Request = Class.create(Ajax.Base, { | 1489 Ajax.Request = Class.create(Ajax.Base, { |
1191 _complete: false, | 1490 _complete: false, |
1192 | 1491 |
1193 initialize: function($super, url, options) { | 1492 initialize: function($super, url, options) { |
1194 $super(options); | 1493 $super(options); |
1197 }, | 1496 }, |
1198 | 1497 |
1199 request: function(url) { | 1498 request: function(url) { |
1200 this.url = url; | 1499 this.url = url; |
1201 this.method = this.options.method; | 1500 this.method = this.options.method; |
1202 var params = Object.clone(this.options.parameters); | 1501 var params = Object.isString(this.options.parameters) ? |
1502 this.options.parameters : | |
1503 Object.toQueryString(this.options.parameters); | |
1203 | 1504 |
1204 if (!['get', 'post'].include(this.method)) { | 1505 if (!['get', 'post'].include(this.method)) { |
1205 // simulate other verbs over post | 1506 params += (params ? '&' : '') + "_method=" + this.method; |
1206 params['_method'] = this.method; | |
1207 this.method = 'post'; | 1507 this.method = 'post'; |
1208 } | 1508 } |
1209 | 1509 |
1210 this.parameters = params; | 1510 if (params && this.method === 'get') { |
1211 | 1511 this.url += (this.url.include('?') ? '&' : '?') + params; |
1212 if (params = Object.toQueryString(params)) { | 1512 } |
1213 // when GET, append parameters to URL | 1513 |
1214 if (this.method == 'get') | 1514 this.parameters = params.toQueryParams(); |
1215 this.url += (this.url.include('?') ? '&' : '?') + params; | |
1216 else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) | |
1217 params += '&_='; | |
1218 } | |
1219 | 1515 |
1220 try { | 1516 try { |
1221 var response = new Ajax.Response(this); | 1517 var response = new Ajax.Response(this); |
1222 if (this.options.onCreate) this.options.onCreate(response); | 1518 if (this.options.onCreate) this.options.onCreate(response); |
1223 Ajax.Responders.dispatch('onCreate', this, response); | 1519 Ajax.Responders.dispatch('onCreate', this, response); |
1267 if (this.transport.overrideMimeType && | 1563 if (this.transport.overrideMimeType && |
1268 (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005) | 1564 (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005) |
1269 headers['Connection'] = 'close'; | 1565 headers['Connection'] = 'close'; |
1270 } | 1566 } |
1271 | 1567 |
1272 // user-defined headers | |
1273 if (typeof this.options.requestHeaders == 'object') { | 1568 if (typeof this.options.requestHeaders == 'object') { |
1274 var extras = this.options.requestHeaders; | 1569 var extras = this.options.requestHeaders; |
1275 | 1570 |
1276 if (Object.isFunction(extras.push)) | 1571 if (Object.isFunction(extras.push)) |
1277 for (var i = 0, length = extras.length; i < length; i += 2) | 1572 for (var i = 0, length = extras.length; i < length; i += 2) |
1284 this.transport.setRequestHeader(name, headers[name]); | 1579 this.transport.setRequestHeader(name, headers[name]); |
1285 }, | 1580 }, |
1286 | 1581 |
1287 success: function() { | 1582 success: function() { |
1288 var status = this.getStatus(); | 1583 var status = this.getStatus(); |
1289 return !status || (status >= 200 && status < 300); | 1584 return !status || (status >= 200 && status < 300) || status == 304; |
1290 }, | 1585 }, |
1291 | 1586 |
1292 getStatus: function() { | 1587 getStatus: function() { |
1293 try { | 1588 try { |
1589 if (this.transport.status === 1223) return 204; | |
1294 return this.transport.status || 0; | 1590 return this.transport.status || 0; |
1295 } catch (e) { return 0 } | 1591 } catch (e) { return 0 } |
1296 }, | 1592 }, |
1297 | 1593 |
1298 respondToReadyState: function(readyState) { | 1594 respondToReadyState: function(readyState) { |
1321 } catch (e) { | 1617 } catch (e) { |
1322 this.dispatchException(e); | 1618 this.dispatchException(e); |
1323 } | 1619 } |
1324 | 1620 |
1325 if (state == 'Complete') { | 1621 if (state == 'Complete') { |
1326 // avoid memory leak in MSIE: clean up | |
1327 this.transport.onreadystatechange = Prototype.emptyFunction; | 1622 this.transport.onreadystatechange = Prototype.emptyFunction; |
1328 } | 1623 } |
1329 }, | 1624 }, |
1330 | 1625 |
1331 isSameOrigin: function() { | 1626 isSameOrigin: function() { |
1338 }, | 1633 }, |
1339 | 1634 |
1340 getHeader: function(name) { | 1635 getHeader: function(name) { |
1341 try { | 1636 try { |
1342 return this.transport.getResponseHeader(name) || null; | 1637 return this.transport.getResponseHeader(name) || null; |
1343 } catch (e) { return null } | 1638 } catch (e) { return null; } |
1344 }, | 1639 }, |
1345 | 1640 |
1346 evalResponse: function() { | 1641 evalResponse: function() { |
1347 try { | 1642 try { |
1348 return eval((this.transport.responseText || '').unfilterJSON()); | 1643 return eval((this.transport.responseText || '').unfilterJSON()); |
1358 }); | 1653 }); |
1359 | 1654 |
1360 Ajax.Request.Events = | 1655 Ajax.Request.Events = |
1361 ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; | 1656 ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; |
1362 | 1657 |
1658 | |
1659 | |
1660 | |
1661 | |
1662 | |
1663 | |
1664 | |
1363 Ajax.Response = Class.create({ | 1665 Ajax.Response = Class.create({ |
1364 initialize: function(request){ | 1666 initialize: function(request){ |
1365 this.request = request; | 1667 this.request = request; |
1366 var transport = this.transport = request.transport, | 1668 var transport = this.transport = request.transport, |
1367 readyState = this.readyState = transport.readyState; | 1669 readyState = this.readyState = transport.readyState; |
1368 | 1670 |
1369 if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) { | 1671 if ((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) { |
1370 this.status = this.getStatus(); | 1672 this.status = this.getStatus(); |
1371 this.statusText = this.getStatusText(); | 1673 this.statusText = this.getStatusText(); |
1372 this.responseText = String.interpret(transport.responseText); | 1674 this.responseText = String.interpret(transport.responseText); |
1373 this.headerJSON = this._getHeaderJSON(); | 1675 this.headerJSON = this._getHeaderJSON(); |
1374 } | 1676 } |
1375 | 1677 |
1376 if(readyState == 4) { | 1678 if (readyState == 4) { |
1377 var xml = transport.responseXML; | 1679 var xml = transport.responseXML; |
1378 this.responseXML = Object.isUndefined(xml) ? null : xml; | 1680 this.responseXML = Object.isUndefined(xml) ? null : xml; |
1379 this.responseJSON = this._getResponseJSON(); | 1681 this.responseJSON = this._getResponseJSON(); |
1380 } | 1682 } |
1381 }, | 1683 }, |
1382 | 1684 |
1383 status: 0, | 1685 status: 0, |
1686 | |
1384 statusText: '', | 1687 statusText: '', |
1385 | 1688 |
1386 getStatus: Ajax.Request.prototype.getStatus, | 1689 getStatus: Ajax.Request.prototype.getStatus, |
1387 | 1690 |
1388 getStatusText: function() { | 1691 getStatusText: function() { |
1508 | 1811 |
1509 onTimerEvent: function() { | 1812 onTimerEvent: function() { |
1510 this.updater = new Ajax.Updater(this.container, this.url, this.options); | 1813 this.updater = new Ajax.Updater(this.container, this.url, this.options); |
1511 } | 1814 } |
1512 }); | 1815 }); |
1816 | |
1817 | |
1513 function $(element) { | 1818 function $(element) { |
1514 if (arguments.length > 1) { | 1819 if (arguments.length > 1) { |
1515 for (var i = 0, elements = [], length = arguments.length; i < length; i++) | 1820 for (var i = 0, elements = [], length = arguments.length; i < length; i++) |
1516 elements.push($(arguments[i])); | 1821 elements.push($(arguments[i])); |
1517 return elements; | 1822 return elements; |
1532 }; | 1837 }; |
1533 } | 1838 } |
1534 | 1839 |
1535 /*--------------------------------------------------------------------------*/ | 1840 /*--------------------------------------------------------------------------*/ |
1536 | 1841 |
1537 if (!window.Node) var Node = { }; | 1842 if (!Node) var Node = { }; |
1538 | 1843 |
1539 if (!Node.ELEMENT_NODE) { | 1844 if (!Node.ELEMENT_NODE) { |
1540 // DOM level 2 ECMAScript Language Binding | |
1541 Object.extend(Node, { | 1845 Object.extend(Node, { |
1542 ELEMENT_NODE: 1, | 1846 ELEMENT_NODE: 1, |
1543 ATTRIBUTE_NODE: 2, | 1847 ATTRIBUTE_NODE: 2, |
1544 TEXT_NODE: 3, | 1848 TEXT_NODE: 3, |
1545 CDATA_SECTION_NODE: 4, | 1849 CDATA_SECTION_NODE: 4, |
1552 DOCUMENT_FRAGMENT_NODE: 11, | 1856 DOCUMENT_FRAGMENT_NODE: 11, |
1553 NOTATION_NODE: 12 | 1857 NOTATION_NODE: 12 |
1554 }); | 1858 }); |
1555 } | 1859 } |
1556 | 1860 |
1557 (function() { | 1861 |
1558 var element = this.Element; | 1862 |
1559 this.Element = function(tagName, attributes) { | 1863 (function(global) { |
1864 function shouldUseCache(tagName, attributes) { | |
1865 if (tagName === 'select') return false; | |
1866 if ('type' in attributes) return false; | |
1867 return true; | |
1868 } | |
1869 | |
1870 var HAS_EXTENDED_CREATE_ELEMENT_SYNTAX = (function(){ | |
1871 try { | |
1872 var el = document.createElement('<input name="x">'); | |
1873 return el.tagName.toLowerCase() === 'input' && el.name === 'x'; | |
1874 } | |
1875 catch(err) { | |
1876 return false; | |
1877 } | |
1878 })(); | |
1879 | |
1880 var element = global.Element; | |
1881 | |
1882 global.Element = function(tagName, attributes) { | |
1560 attributes = attributes || { }; | 1883 attributes = attributes || { }; |
1561 tagName = tagName.toLowerCase(); | 1884 tagName = tagName.toLowerCase(); |
1562 var cache = Element.cache; | 1885 var cache = Element.cache; |
1563 if (Prototype.Browser.IE && attributes.name) { | 1886 |
1887 if (HAS_EXTENDED_CREATE_ELEMENT_SYNTAX && attributes.name) { | |
1564 tagName = '<' + tagName + ' name="' + attributes.name + '">'; | 1888 tagName = '<' + tagName + ' name="' + attributes.name + '">'; |
1565 delete attributes.name; | 1889 delete attributes.name; |
1566 return Element.writeAttribute(document.createElement(tagName), attributes); | 1890 return Element.writeAttribute(document.createElement(tagName), attributes); |
1567 } | 1891 } |
1892 | |
1568 if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName)); | 1893 if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName)); |
1569 return Element.writeAttribute(cache[tagName].cloneNode(false), attributes); | 1894 |
1895 var node = shouldUseCache(tagName, attributes) ? | |
1896 cache[tagName].cloneNode(false) : document.createElement(tagName); | |
1897 | |
1898 return Element.writeAttribute(node, attributes); | |
1570 }; | 1899 }; |
1571 Object.extend(this.Element, element || { }); | 1900 |
1572 if (element) this.Element.prototype = element.prototype; | 1901 Object.extend(global.Element, element || { }); |
1573 }).call(window); | 1902 if (element) global.Element.prototype = element.prototype; |
1574 | 1903 |
1904 })(this); | |
1905 | |
1906 Element.idCounter = 1; | |
1575 Element.cache = { }; | 1907 Element.cache = { }; |
1908 | |
1909 Element._purgeElement = function(element) { | |
1910 var uid = element._prototypeUID; | |
1911 if (uid) { | |
1912 Element.stopObserving(element); | |
1913 element._prototypeUID = void 0; | |
1914 delete Element.Storage[uid]; | |
1915 } | |
1916 } | |
1576 | 1917 |
1577 Element.Methods = { | 1918 Element.Methods = { |
1578 visible: function(element) { | 1919 visible: function(element) { |
1579 return $(element).style.display != 'none'; | 1920 return $(element).style.display != 'none'; |
1580 }, | 1921 }, |
1601 element = $(element); | 1942 element = $(element); |
1602 element.parentNode.removeChild(element); | 1943 element.parentNode.removeChild(element); |
1603 return element; | 1944 return element; |
1604 }, | 1945 }, |
1605 | 1946 |
1606 update: function(element, content) { | 1947 update: (function(){ |
1607 element = $(element); | 1948 |
1608 if (content && content.toElement) content = content.toElement(); | 1949 var SELECT_ELEMENT_INNERHTML_BUGGY = (function(){ |
1609 if (Object.isElement(content)) return element.update().insert(content); | 1950 var el = document.createElement("select"), |
1610 content = Object.toHTML(content); | 1951 isBuggy = true; |
1611 element.innerHTML = content.stripScripts(); | 1952 el.innerHTML = "<option value=\"test\">test</option>"; |
1612 content.evalScripts.bind(content).defer(); | 1953 if (el.options && el.options[0]) { |
1613 return element; | 1954 isBuggy = el.options[0].nodeName.toUpperCase() !== "OPTION"; |
1614 }, | 1955 } |
1956 el = null; | |
1957 return isBuggy; | |
1958 })(); | |
1959 | |
1960 var TABLE_ELEMENT_INNERHTML_BUGGY = (function(){ | |
1961 try { | |
1962 var el = document.createElement("table"); | |
1963 if (el && el.tBodies) { | |
1964 el.innerHTML = "<tbody><tr><td>test</td></tr></tbody>"; | |
1965 var isBuggy = typeof el.tBodies[0] == "undefined"; | |
1966 el = null; | |
1967 return isBuggy; | |
1968 } | |
1969 } catch (e) { | |
1970 return true; | |
1971 } | |
1972 })(); | |
1973 | |
1974 var LINK_ELEMENT_INNERHTML_BUGGY = (function() { | |
1975 try { | |
1976 var el = document.createElement('div'); | |
1977 el.innerHTML = "<link>"; | |
1978 var isBuggy = (el.childNodes.length === 0); | |
1979 el = null; | |
1980 return isBuggy; | |
1981 } catch(e) { | |
1982 return true; | |
1983 } | |
1984 })(); | |
1985 | |
1986 var ANY_INNERHTML_BUGGY = SELECT_ELEMENT_INNERHTML_BUGGY || | |
1987 TABLE_ELEMENT_INNERHTML_BUGGY || LINK_ELEMENT_INNERHTML_BUGGY; | |
1988 | |
1989 var SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING = (function () { | |
1990 var s = document.createElement("script"), | |
1991 isBuggy = false; | |
1992 try { | |
1993 s.appendChild(document.createTextNode("")); | |
1994 isBuggy = !s.firstChild || | |
1995 s.firstChild && s.firstChild.nodeType !== 3; | |
1996 } catch (e) { | |
1997 isBuggy = true; | |
1998 } | |
1999 s = null; | |
2000 return isBuggy; | |
2001 })(); | |
2002 | |
2003 | |
2004 function update(element, content) { | |
2005 element = $(element); | |
2006 var purgeElement = Element._purgeElement; | |
2007 | |
2008 var descendants = element.getElementsByTagName('*'), | |
2009 i = descendants.length; | |
2010 while (i--) purgeElement(descendants[i]); | |
2011 | |
2012 if (content && content.toElement) | |
2013 content = content.toElement(); | |
2014 | |
2015 if (Object.isElement(content)) | |
2016 return element.update().insert(content); | |
2017 | |
2018 content = Object.toHTML(content); | |
2019 | |
2020 var tagName = element.tagName.toUpperCase(); | |
2021 | |
2022 if (tagName === 'SCRIPT' && SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING) { | |
2023 element.text = content; | |
2024 return element; | |
2025 } | |
2026 | |
2027 if (ANY_INNERHTML_BUGGY) { | |
2028 if (tagName in Element._insertionTranslations.tags) { | |
2029 while (element.firstChild) { | |
2030 element.removeChild(element.firstChild); | |
2031 } | |
2032 Element._getContentFromAnonymousElement(tagName, content.stripScripts()) | |
2033 .each(function(node) { | |
2034 element.appendChild(node) | |
2035 }); | |
2036 } else if (LINK_ELEMENT_INNERHTML_BUGGY && Object.isString(content) && content.indexOf('<link') > -1) { | |
2037 while (element.firstChild) { | |
2038 element.removeChild(element.firstChild); | |
2039 } | |
2040 var nodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts(), true); | |
2041 nodes.each(function(node) { element.appendChild(node) }); | |
2042 } | |
2043 else { | |
2044 element.innerHTML = content.stripScripts(); | |
2045 } | |
2046 } | |
2047 else { | |
2048 element.innerHTML = content.stripScripts(); | |
2049 } | |
2050 | |
2051 content.evalScripts.bind(content).defer(); | |
2052 return element; | |
2053 } | |
2054 | |
2055 return update; | |
2056 })(), | |
1615 | 2057 |
1616 replace: function(element, content) { | 2058 replace: function(element, content) { |
1617 element = $(element); | 2059 element = $(element); |
1618 if (content && content.toElement) content = content.toElement(); | 2060 if (content && content.toElement) content = content.toElement(); |
1619 else if (!Object.isElement(content)) { | 2061 else if (!Object.isElement(content)) { |
1677 | 2119 |
1678 inspect: function(element) { | 2120 inspect: function(element) { |
1679 element = $(element); | 2121 element = $(element); |
1680 var result = '<' + element.tagName.toLowerCase(); | 2122 var result = '<' + element.tagName.toLowerCase(); |
1681 $H({'id': 'id', 'className': 'class'}).each(function(pair) { | 2123 $H({'id': 'id', 'className': 'class'}).each(function(pair) { |
1682 var property = pair.first(), attribute = pair.last(); | 2124 var property = pair.first(), |
1683 var value = (element[property] || '').toString(); | 2125 attribute = pair.last(), |
2126 value = (element[property] || '').toString(); | |
1684 if (value) result += ' ' + attribute + '=' + value.inspect(true); | 2127 if (value) result += ' ' + attribute + '=' + value.inspect(true); |
1685 }); | 2128 }); |
1686 return result + '>'; | 2129 return result + '>'; |
1687 }, | 2130 }, |
1688 | 2131 |
1689 recursivelyCollect: function(element, property) { | 2132 recursivelyCollect: function(element, property, maximumLength) { |
1690 element = $(element); | 2133 element = $(element); |
2134 maximumLength = maximumLength || -1; | |
1691 var elements = []; | 2135 var elements = []; |
1692 while (element = element[property]) | 2136 |
2137 while (element = element[property]) { | |
1693 if (element.nodeType == 1) | 2138 if (element.nodeType == 1) |
1694 elements.push(Element.extend(element)); | 2139 elements.push(Element.extend(element)); |
2140 if (elements.length == maximumLength) | |
2141 break; | |
2142 } | |
2143 | |
1695 return elements; | 2144 return elements; |
1696 }, | 2145 }, |
1697 | 2146 |
1698 ancestors: function(element) { | 2147 ancestors: function(element) { |
1699 return $(element).recursivelyCollect('parentNode'); | 2148 return Element.recursivelyCollect(element, 'parentNode'); |
1700 }, | 2149 }, |
1701 | 2150 |
1702 descendants: function(element) { | 2151 descendants: function(element) { |
1703 return $(element).select("*"); | 2152 return Element.select(element, "*"); |
1704 }, | 2153 }, |
1705 | 2154 |
1706 firstDescendant: function(element) { | 2155 firstDescendant: function(element) { |
1707 element = $(element).firstChild; | 2156 element = $(element).firstChild; |
1708 while (element && element.nodeType != 1) element = element.nextSibling; | 2157 while (element && element.nodeType != 1) element = element.nextSibling; |
1709 return $(element); | 2158 return $(element); |
1710 }, | 2159 }, |
1711 | 2160 |
1712 immediateDescendants: function(element) { | 2161 immediateDescendants: function(element) { |
1713 if (!(element = $(element).firstChild)) return []; | 2162 var results = [], child = $(element).firstChild; |
1714 while (element && element.nodeType != 1) element = element.nextSibling; | 2163 while (child) { |
1715 if (element) return [element].concat($(element).nextSiblings()); | 2164 if (child.nodeType === 1) { |
1716 return []; | 2165 results.push(Element.extend(child)); |
1717 }, | 2166 } |
1718 | 2167 child = child.nextSibling; |
1719 previousSiblings: function(element) { | 2168 } |
1720 return $(element).recursivelyCollect('previousSibling'); | 2169 return results; |
2170 }, | |
2171 | |
2172 previousSiblings: function(element, maximumLength) { | |
2173 return Element.recursivelyCollect(element, 'previousSibling'); | |
1721 }, | 2174 }, |
1722 | 2175 |
1723 nextSiblings: function(element) { | 2176 nextSiblings: function(element) { |
1724 return $(element).recursivelyCollect('nextSibling'); | 2177 return Element.recursivelyCollect(element, 'nextSibling'); |
1725 }, | 2178 }, |
1726 | 2179 |
1727 siblings: function(element) { | 2180 siblings: function(element) { |
1728 element = $(element); | 2181 element = $(element); |
1729 return element.previousSiblings().reverse().concat(element.nextSiblings()); | 2182 return Element.previousSiblings(element).reverse() |
2183 .concat(Element.nextSiblings(element)); | |
1730 }, | 2184 }, |
1731 | 2185 |
1732 match: function(element, selector) { | 2186 match: function(element, selector) { |
2187 element = $(element); | |
1733 if (Object.isString(selector)) | 2188 if (Object.isString(selector)) |
1734 selector = new Selector(selector); | 2189 return Prototype.Selector.match(element, selector); |
1735 return selector.match($(element)); | 2190 return selector.match(element); |
1736 }, | 2191 }, |
1737 | 2192 |
1738 up: function(element, expression, index) { | 2193 up: function(element, expression, index) { |
1739 element = $(element); | 2194 element = $(element); |
1740 if (arguments.length == 1) return $(element.parentNode); | 2195 if (arguments.length == 1) return $(element.parentNode); |
1741 var ancestors = element.ancestors(); | 2196 var ancestors = Element.ancestors(element); |
1742 return Object.isNumber(expression) ? ancestors[expression] : | 2197 return Object.isNumber(expression) ? ancestors[expression] : |
1743 Selector.findElement(ancestors, expression, index); | 2198 Prototype.Selector.find(ancestors, expression, index); |
1744 }, | 2199 }, |
1745 | 2200 |
1746 down: function(element, expression, index) { | 2201 down: function(element, expression, index) { |
1747 element = $(element); | 2202 element = $(element); |
1748 if (arguments.length == 1) return element.firstDescendant(); | 2203 if (arguments.length == 1) return Element.firstDescendant(element); |
1749 return Object.isNumber(expression) ? element.descendants()[expression] : | 2204 return Object.isNumber(expression) ? Element.descendants(element)[expression] : |
1750 Element.select(element, expression)[index || 0]; | 2205 Element.select(element, expression)[index || 0]; |
1751 }, | 2206 }, |
1752 | 2207 |
1753 previous: function(element, expression, index) { | 2208 previous: function(element, expression, index) { |
1754 element = $(element); | 2209 element = $(element); |
1755 if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element)); | 2210 if (Object.isNumber(expression)) index = expression, expression = false; |
1756 var previousSiblings = element.previousSiblings(); | 2211 if (!Object.isNumber(index)) index = 0; |
1757 return Object.isNumber(expression) ? previousSiblings[expression] : | 2212 |
1758 Selector.findElement(previousSiblings, expression, index); | 2213 if (expression) { |
2214 return Prototype.Selector.find(element.previousSiblings(), expression, index); | |
2215 } else { | |
2216 return element.recursivelyCollect("previousSibling", index + 1)[index]; | |
2217 } | |
1759 }, | 2218 }, |
1760 | 2219 |
1761 next: function(element, expression, index) { | 2220 next: function(element, expression, index) { |
1762 element = $(element); | 2221 element = $(element); |
1763 if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element)); | 2222 if (Object.isNumber(expression)) index = expression, expression = false; |
1764 var nextSiblings = element.nextSiblings(); | 2223 if (!Object.isNumber(index)) index = 0; |
1765 return Object.isNumber(expression) ? nextSiblings[expression] : | 2224 |
1766 Selector.findElement(nextSiblings, expression, index); | 2225 if (expression) { |
1767 }, | 2226 return Prototype.Selector.find(element.nextSiblings(), expression, index); |
1768 | 2227 } else { |
1769 select: function() { | 2228 var maximumLength = Object.isNumber(index) ? index + 1 : 1; |
1770 var args = $A(arguments), element = $(args.shift()); | 2229 return element.recursivelyCollect("nextSibling", index + 1)[index]; |
1771 return Selector.findChildElements(element, args); | 2230 } |
1772 }, | 2231 }, |
1773 | 2232 |
1774 adjacent: function() { | 2233 |
1775 var args = $A(arguments), element = $(args.shift()); | 2234 select: function(element) { |
1776 return Selector.findChildElements(element.parentNode, args).without(element); | 2235 element = $(element); |
2236 var expressions = Array.prototype.slice.call(arguments, 1).join(', '); | |
2237 return Prototype.Selector.select(expressions, element); | |
2238 }, | |
2239 | |
2240 adjacent: function(element) { | |
2241 element = $(element); | |
2242 var expressions = Array.prototype.slice.call(arguments, 1).join(', '); | |
2243 return Prototype.Selector.select(expressions, element.parentNode).without(element); | |
1777 }, | 2244 }, |
1778 | 2245 |
1779 identify: function(element) { | 2246 identify: function(element) { |
1780 element = $(element); | 2247 element = $(element); |
1781 var id = element.readAttribute('id'), self = arguments.callee; | 2248 var id = Element.readAttribute(element, 'id'); |
1782 if (id) return id; | 2249 if (id) return id; |
1783 do { id = 'anonymous_element_' + self.counter++ } while ($(id)); | 2250 do { id = 'anonymous_element_' + Element.idCounter++ } while ($(id)); |
1784 element.writeAttribute('id', id); | 2251 Element.writeAttribute(element, 'id', id); |
1785 return id; | 2252 return id; |
1786 }, | 2253 }, |
1787 | 2254 |
1788 readAttribute: function(element, name) { | 2255 readAttribute: function(element, name) { |
1789 element = $(element); | 2256 element = $(element); |
1818 } | 2285 } |
1819 return element; | 2286 return element; |
1820 }, | 2287 }, |
1821 | 2288 |
1822 getHeight: function(element) { | 2289 getHeight: function(element) { |
1823 return $(element).getDimensions().height; | 2290 return Element.getDimensions(element).height; |
1824 }, | 2291 }, |
1825 | 2292 |
1826 getWidth: function(element) { | 2293 getWidth: function(element) { |
1827 return $(element).getDimensions().width; | 2294 return Element.getDimensions(element).width; |
1828 }, | 2295 }, |
1829 | 2296 |
1830 classNames: function(element) { | 2297 classNames: function(element) { |
1831 return new Element.ClassNames(element); | 2298 return new Element.ClassNames(element); |
1832 }, | 2299 }, |
1838 new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName))); | 2305 new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName))); |
1839 }, | 2306 }, |
1840 | 2307 |
1841 addClassName: function(element, className) { | 2308 addClassName: function(element, className) { |
1842 if (!(element = $(element))) return; | 2309 if (!(element = $(element))) return; |
1843 if (!element.hasClassName(className)) | 2310 if (!Element.hasClassName(element, className)) |
1844 element.className += (element.className ? ' ' : '') + className; | 2311 element.className += (element.className ? ' ' : '') + className; |
1845 return element; | 2312 return element; |
1846 }, | 2313 }, |
1847 | 2314 |
1848 removeClassName: function(element, className) { | 2315 removeClassName: function(element, className) { |
1852 return element; | 2319 return element; |
1853 }, | 2320 }, |
1854 | 2321 |
1855 toggleClassName: function(element, className) { | 2322 toggleClassName: function(element, className) { |
1856 if (!(element = $(element))) return; | 2323 if (!(element = $(element))) return; |
1857 return element[element.hasClassName(className) ? | 2324 return Element[Element.hasClassName(element, className) ? |
1858 'removeClassName' : 'addClassName'](className); | 2325 'removeClassName' : 'addClassName'](element, className); |
1859 }, | 2326 }, |
1860 | 2327 |
1861 // removes whitespace-only text node children | |
1862 cleanWhitespace: function(element) { | 2328 cleanWhitespace: function(element) { |
1863 element = $(element); | 2329 element = $(element); |
1864 var node = element.firstChild; | 2330 var node = element.firstChild; |
1865 while (node) { | 2331 while (node) { |
1866 var nextNode = node.nextSibling; | 2332 var nextNode = node.nextSibling; |
1890 return false; | 2356 return false; |
1891 }, | 2357 }, |
1892 | 2358 |
1893 scrollTo: function(element) { | 2359 scrollTo: function(element) { |
1894 element = $(element); | 2360 element = $(element); |
1895 var pos = element.cumulativeOffset(); | 2361 var pos = Element.cumulativeOffset(element); |
1896 window.scrollTo(pos[0], pos[1]); | 2362 window.scrollTo(pos[0], pos[1]); |
1897 return element; | 2363 return element; |
1898 }, | 2364 }, |
1899 | 2365 |
1900 getStyle: function(element, style) { | 2366 getStyle: function(element, style) { |
1936 element.style.opacity = (value == 1 || value === '') ? '' : | 2402 element.style.opacity = (value == 1 || value === '') ? '' : |
1937 (value < 0.00001) ? 0 : value; | 2403 (value < 0.00001) ? 0 : value; |
1938 return element; | 2404 return element; |
1939 }, | 2405 }, |
1940 | 2406 |
1941 getDimensions: function(element) { | |
1942 element = $(element); | |
1943 var display = element.getStyle('display'); | |
1944 if (display != 'none' && display != null) // Safari bug | |
1945 return {width: element.offsetWidth, height: element.offsetHeight}; | |
1946 | |
1947 // All *Width and *Height properties give 0 on elements with display none, | |
1948 // so enable the element temporarily | |
1949 var els = element.style; | |
1950 var originalVisibility = els.visibility; | |
1951 var originalPosition = els.position; | |
1952 var originalDisplay = els.display; | |
1953 els.visibility = 'hidden'; | |
1954 els.position = 'absolute'; | |
1955 els.display = 'block'; | |
1956 var originalWidth = element.clientWidth; | |
1957 var originalHeight = element.clientHeight; | |
1958 els.display = originalDisplay; | |
1959 els.position = originalPosition; | |
1960 els.visibility = originalVisibility; | |
1961 return {width: originalWidth, height: originalHeight}; | |
1962 }, | |
1963 | |
1964 makePositioned: function(element) { | 2407 makePositioned: function(element) { |
1965 element = $(element); | 2408 element = $(element); |
1966 var pos = Element.getStyle(element, 'position'); | 2409 var pos = Element.getStyle(element, 'position'); |
1967 if (pos == 'static' || !pos) { | 2410 if (pos == 'static' || !pos) { |
1968 element._madePositioned = true; | 2411 element._madePositioned = true; |
1969 element.style.position = 'relative'; | 2412 element.style.position = 'relative'; |
1970 // Opera returns the offset relative to the positioning context, when an | |
1971 // element is position relative but top and left have not been defined | |
1972 if (Prototype.Browser.Opera) { | 2413 if (Prototype.Browser.Opera) { |
1973 element.style.top = 0; | 2414 element.style.top = 0; |
1974 element.style.left = 0; | 2415 element.style.left = 0; |
1975 } | 2416 } |
1976 } | 2417 } |
2005 element.style.overflow = element._overflow == 'auto' ? '' : element._overflow; | 2446 element.style.overflow = element._overflow == 'auto' ? '' : element._overflow; |
2006 element._overflow = null; | 2447 element._overflow = null; |
2007 return element; | 2448 return element; |
2008 }, | 2449 }, |
2009 | 2450 |
2010 cumulativeOffset: function(element) { | |
2011 var valueT = 0, valueL = 0; | |
2012 do { | |
2013 valueT += element.offsetTop || 0; | |
2014 valueL += element.offsetLeft || 0; | |
2015 element = element.offsetParent; | |
2016 } while (element); | |
2017 return Element._returnOffset(valueL, valueT); | |
2018 }, | |
2019 | |
2020 positionedOffset: function(element) { | |
2021 var valueT = 0, valueL = 0; | |
2022 do { | |
2023 valueT += element.offsetTop || 0; | |
2024 valueL += element.offsetLeft || 0; | |
2025 element = element.offsetParent; | |
2026 if (element) { | |
2027 if (element.tagName.toUpperCase() == 'BODY') break; | |
2028 var p = Element.getStyle(element, 'position'); | |
2029 if (p !== 'static') break; | |
2030 } | |
2031 } while (element); | |
2032 return Element._returnOffset(valueL, valueT); | |
2033 }, | |
2034 | |
2035 absolutize: function(element) { | |
2036 element = $(element); | |
2037 if (element.getStyle('position') == 'absolute') return element; | |
2038 // Position.prepare(); // To be done manually by Scripty when it needs it. | |
2039 | |
2040 var offsets = element.positionedOffset(); | |
2041 var top = offsets[1]; | |
2042 var left = offsets[0]; | |
2043 var width = element.clientWidth; | |
2044 var height = element.clientHeight; | |
2045 | |
2046 element._originalLeft = left - parseFloat(element.style.left || 0); | |
2047 element._originalTop = top - parseFloat(element.style.top || 0); | |
2048 element._originalWidth = element.style.width; | |
2049 element._originalHeight = element.style.height; | |
2050 | |
2051 element.style.position = 'absolute'; | |
2052 element.style.top = top + 'px'; | |
2053 element.style.left = left + 'px'; | |
2054 element.style.width = width + 'px'; | |
2055 element.style.height = height + 'px'; | |
2056 return element; | |
2057 }, | |
2058 | |
2059 relativize: function(element) { | |
2060 element = $(element); | |
2061 if (element.getStyle('position') == 'relative') return element; | |
2062 // Position.prepare(); // To be done manually by Scripty when it needs it. | |
2063 | |
2064 element.style.position = 'relative'; | |
2065 var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); | |
2066 var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); | |
2067 | |
2068 element.style.top = top + 'px'; | |
2069 element.style.left = left + 'px'; | |
2070 element.style.height = element._originalHeight; | |
2071 element.style.width = element._originalWidth; | |
2072 return element; | |
2073 }, | |
2074 | |
2075 cumulativeScrollOffset: function(element) { | |
2076 var valueT = 0, valueL = 0; | |
2077 do { | |
2078 valueT += element.scrollTop || 0; | |
2079 valueL += element.scrollLeft || 0; | |
2080 element = element.parentNode; | |
2081 } while (element); | |
2082 return Element._returnOffset(valueL, valueT); | |
2083 }, | |
2084 | |
2085 getOffsetParent: function(element) { | |
2086 if (element.offsetParent) return $(element.offsetParent); | |
2087 if (element == document.body) return $(element); | |
2088 | |
2089 while ((element = element.parentNode) && element != document.body) | |
2090 if (Element.getStyle(element, 'position') != 'static') | |
2091 return $(element); | |
2092 | |
2093 return $(document.body); | |
2094 }, | |
2095 | |
2096 viewportOffset: function(forElement) { | |
2097 var valueT = 0, valueL = 0; | |
2098 | |
2099 var element = forElement; | |
2100 do { | |
2101 valueT += element.offsetTop || 0; | |
2102 valueL += element.offsetLeft || 0; | |
2103 | |
2104 // Safari fix | |
2105 if (element.offsetParent == document.body && | |
2106 Element.getStyle(element, 'position') == 'absolute') break; | |
2107 | |
2108 } while (element = element.offsetParent); | |
2109 | |
2110 element = forElement; | |
2111 do { | |
2112 if (!Prototype.Browser.Opera || (element.tagName && (element.tagName.toUpperCase() == 'BODY'))) { | |
2113 valueT -= element.scrollTop || 0; | |
2114 valueL -= element.scrollLeft || 0; | |
2115 } | |
2116 } while (element = element.parentNode); | |
2117 | |
2118 return Element._returnOffset(valueL, valueT); | |
2119 }, | |
2120 | |
2121 clonePosition: function(element, source) { | 2451 clonePosition: function(element, source) { |
2122 var options = Object.extend({ | 2452 var options = Object.extend({ |
2123 setLeft: true, | 2453 setLeft: true, |
2124 setTop: true, | 2454 setTop: true, |
2125 setWidth: true, | 2455 setWidth: true, |
2126 setHeight: true, | 2456 setHeight: true, |
2127 offsetTop: 0, | 2457 offsetTop: 0, |
2128 offsetLeft: 0 | 2458 offsetLeft: 0 |
2129 }, arguments[2] || { }); | 2459 }, arguments[2] || { }); |
2130 | 2460 |
2131 // find page position of source | |
2132 source = $(source); | 2461 source = $(source); |
2133 var p = source.viewportOffset(); | 2462 var p = Element.viewportOffset(source), delta = [0, 0], parent = null; |
2134 | 2463 |
2135 // find coordinate system to use | |
2136 element = $(element); | 2464 element = $(element); |
2137 var delta = [0, 0]; | 2465 |
2138 var parent = null; | |
2139 // delta [0,0] will do fine with position: fixed elements, | |
2140 // position:absolute needs offsetParent deltas | |
2141 if (Element.getStyle(element, 'position') == 'absolute') { | 2466 if (Element.getStyle(element, 'position') == 'absolute') { |
2142 parent = element.getOffsetParent(); | 2467 parent = Element.getOffsetParent(element); |
2143 delta = parent.viewportOffset(); | 2468 delta = Element.viewportOffset(parent); |
2144 } | 2469 } |
2145 | 2470 |
2146 // correct by body offsets (fixes Safari) | |
2147 if (parent == document.body) { | 2471 if (parent == document.body) { |
2148 delta[0] -= document.body.offsetLeft; | 2472 delta[0] -= document.body.offsetLeft; |
2149 delta[1] -= document.body.offsetTop; | 2473 delta[1] -= document.body.offsetTop; |
2150 } | 2474 } |
2151 | 2475 |
2152 // set position | |
2153 if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; | 2476 if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; |
2154 if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; | 2477 if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; |
2155 if (options.setWidth) element.style.width = source.offsetWidth + 'px'; | 2478 if (options.setWidth) element.style.width = source.offsetWidth + 'px'; |
2156 if (options.setHeight) element.style.height = source.offsetHeight + 'px'; | 2479 if (options.setHeight) element.style.height = source.offsetHeight + 'px'; |
2157 return element; | 2480 return element; |
2158 } | 2481 } |
2159 }; | 2482 }; |
2160 | 2483 |
2161 Element.Methods.identify.counter = 1; | |
2162 | |
2163 Object.extend(Element.Methods, { | 2484 Object.extend(Element.Methods, { |
2164 getElementsBySelector: Element.Methods.select, | 2485 getElementsBySelector: Element.Methods.select, |
2486 | |
2165 childElements: Element.Methods.immediateDescendants | 2487 childElements: Element.Methods.immediateDescendants |
2166 }); | 2488 }); |
2167 | 2489 |
2168 Element._attributeTranslations = { | 2490 Element._attributeTranslations = { |
2169 write: { | 2491 write: { |
2177 | 2499 |
2178 if (Prototype.Browser.Opera) { | 2500 if (Prototype.Browser.Opera) { |
2179 Element.Methods.getStyle = Element.Methods.getStyle.wrap( | 2501 Element.Methods.getStyle = Element.Methods.getStyle.wrap( |
2180 function(proceed, element, style) { | 2502 function(proceed, element, style) { |
2181 switch (style) { | 2503 switch (style) { |
2182 case 'left': case 'top': case 'right': case 'bottom': | |
2183 if (proceed(element, 'position') === 'static') return null; | |
2184 case 'height': case 'width': | 2504 case 'height': case 'width': |
2185 // returns '0px' for hidden elements; we want it to return null | |
2186 if (!Element.visible(element)) return null; | 2505 if (!Element.visible(element)) return null; |
2187 | 2506 |
2188 // returns the border-box dimensions rather than the content-box | |
2189 // dimensions, so we subtract padding and borders from the value | |
2190 var dim = parseInt(proceed(element, style), 10); | 2507 var dim = parseInt(proceed(element, style), 10); |
2191 | 2508 |
2192 if (dim !== element['offset' + style.capitalize()]) | 2509 if (dim !== element['offset' + style.capitalize()]) |
2193 return dim + 'px'; | 2510 return dim + 'px'; |
2194 | 2511 |
2217 } | 2534 } |
2218 ); | 2535 ); |
2219 } | 2536 } |
2220 | 2537 |
2221 else if (Prototype.Browser.IE) { | 2538 else if (Prototype.Browser.IE) { |
2222 // IE doesn't report offsets correctly for static elements, so we change them | |
2223 // to "relative" to get the values, then change them back. | |
2224 Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap( | |
2225 function(proceed, element) { | |
2226 element = $(element); | |
2227 // IE throws an error if element is not in document | |
2228 try { element.offsetParent } | |
2229 catch(e) { return $(document.body) } | |
2230 var position = element.getStyle('position'); | |
2231 if (position !== 'static') return proceed(element); | |
2232 element.setStyle({ position: 'relative' }); | |
2233 var value = proceed(element); | |
2234 element.setStyle({ position: position }); | |
2235 return value; | |
2236 } | |
2237 ); | |
2238 | |
2239 $w('positionedOffset viewportOffset').each(function(method) { | |
2240 Element.Methods[method] = Element.Methods[method].wrap( | |
2241 function(proceed, element) { | |
2242 element = $(element); | |
2243 try { element.offsetParent } | |
2244 catch(e) { return Element._returnOffset(0,0) } | |
2245 var position = element.getStyle('position'); | |
2246 if (position !== 'static') return proceed(element); | |
2247 // Trigger hasLayout on the offset parent so that IE6 reports | |
2248 // accurate offsetTop and offsetLeft values for position: fixed. | |
2249 var offsetParent = element.getOffsetParent(); | |
2250 if (offsetParent && offsetParent.getStyle('position') === 'fixed') | |
2251 offsetParent.setStyle({ zoom: 1 }); | |
2252 element.setStyle({ position: 'relative' }); | |
2253 var value = proceed(element); | |
2254 element.setStyle({ position: position }); | |
2255 return value; | |
2256 } | |
2257 ); | |
2258 }); | |
2259 | |
2260 Element.Methods.cumulativeOffset = Element.Methods.cumulativeOffset.wrap( | |
2261 function(proceed, element) { | |
2262 try { element.offsetParent } | |
2263 catch(e) { return Element._returnOffset(0,0) } | |
2264 return proceed(element); | |
2265 } | |
2266 ); | |
2267 | |
2268 Element.Methods.getStyle = function(element, style) { | 2539 Element.Methods.getStyle = function(element, style) { |
2269 element = $(element); | 2540 element = $(element); |
2270 style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize(); | 2541 style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize(); |
2271 var value = element.style[style]; | 2542 var value = element.style[style]; |
2272 if (!value && element.currentStyle) value = element.currentStyle[style]; | 2543 if (!value && element.currentStyle) value = element.currentStyle[style]; |
2304 style.filter = stripAlpha(filter) + | 2575 style.filter = stripAlpha(filter) + |
2305 'alpha(opacity=' + (value * 100) + ')'; | 2576 'alpha(opacity=' + (value * 100) + ')'; |
2306 return element; | 2577 return element; |
2307 }; | 2578 }; |
2308 | 2579 |
2309 Element._attributeTranslations = { | 2580 Element._attributeTranslations = (function(){ |
2310 read: { | 2581 |
2311 names: { | 2582 var classProp = 'className', |
2312 'class': 'className', | 2583 forProp = 'for', |
2313 'for': 'htmlFor' | 2584 el = document.createElement('div'); |
2314 }, | 2585 |
2315 values: { | 2586 el.setAttribute(classProp, 'x'); |
2316 _getAttr: function(element, attribute) { | 2587 |
2317 return element.getAttribute(attribute, 2); | 2588 if (el.className !== 'x') { |
2589 el.setAttribute('class', 'x'); | |
2590 if (el.className === 'x') { | |
2591 classProp = 'class'; | |
2592 } | |
2593 } | |
2594 el = null; | |
2595 | |
2596 el = document.createElement('label'); | |
2597 el.setAttribute(forProp, 'x'); | |
2598 if (el.htmlFor !== 'x') { | |
2599 el.setAttribute('htmlFor', 'x'); | |
2600 if (el.htmlFor === 'x') { | |
2601 forProp = 'htmlFor'; | |
2602 } | |
2603 } | |
2604 el = null; | |
2605 | |
2606 return { | |
2607 read: { | |
2608 names: { | |
2609 'class': classProp, | |
2610 'className': classProp, | |
2611 'for': forProp, | |
2612 'htmlFor': forProp | |
2318 }, | 2613 }, |
2319 _getAttrNode: function(element, attribute) { | 2614 values: { |
2320 var node = element.getAttributeNode(attribute); | 2615 _getAttr: function(element, attribute) { |
2321 return node ? node.value : ""; | 2616 return element.getAttribute(attribute); |
2322 }, | 2617 }, |
2323 _getEv: function(element, attribute) { | 2618 _getAttr2: function(element, attribute) { |
2324 attribute = element.getAttribute(attribute); | 2619 return element.getAttribute(attribute, 2); |
2325 return attribute ? attribute.toString().slice(23, -2) : null; | 2620 }, |
2326 }, | 2621 _getAttrNode: function(element, attribute) { |
2327 _flag: function(element, attribute) { | 2622 var node = element.getAttributeNode(attribute); |
2328 return $(element).hasAttribute(attribute) ? attribute : null; | 2623 return node ? node.value : ""; |
2329 }, | 2624 }, |
2330 style: function(element) { | 2625 _getEv: (function(){ |
2331 return element.style.cssText.toLowerCase(); | 2626 |
2332 }, | 2627 var el = document.createElement('div'), f; |
2333 title: function(element) { | 2628 el.onclick = Prototype.emptyFunction; |
2334 return element.title; | 2629 var value = el.getAttribute('onclick'); |
2630 | |
2631 if (String(value).indexOf('{') > -1) { | |
2632 f = function(element, attribute) { | |
2633 attribute = element.getAttribute(attribute); | |
2634 if (!attribute) return null; | |
2635 attribute = attribute.toString(); | |
2636 attribute = attribute.split('{')[1]; | |
2637 attribute = attribute.split('}')[0]; | |
2638 return attribute.strip(); | |
2639 }; | |
2640 } | |
2641 else if (value === '') { | |
2642 f = function(element, attribute) { | |
2643 attribute = element.getAttribute(attribute); | |
2644 if (!attribute) return null; | |
2645 return attribute.strip(); | |
2646 }; | |
2647 } | |
2648 el = null; | |
2649 return f; | |
2650 })(), | |
2651 _flag: function(element, attribute) { | |
2652 return $(element).hasAttribute(attribute) ? attribute : null; | |
2653 }, | |
2654 style: function(element) { | |
2655 return element.style.cssText.toLowerCase(); | |
2656 }, | |
2657 title: function(element) { | |
2658 return element.title; | |
2659 } | |
2335 } | 2660 } |
2336 } | 2661 } |
2337 } | 2662 } |
2338 }; | 2663 })(); |
2339 | 2664 |
2340 Element._attributeTranslations.write = { | 2665 Element._attributeTranslations.write = { |
2341 names: Object.extend({ | 2666 names: Object.extend({ |
2342 cellpadding: 'cellPadding', | 2667 cellpadding: 'cellPadding', |
2343 cellspacing: 'cellSpacing' | 2668 cellspacing: 'cellSpacing' |
2361 Element._attributeTranslations.has[attr.toLowerCase()] = attr; | 2686 Element._attributeTranslations.has[attr.toLowerCase()] = attr; |
2362 }); | 2687 }); |
2363 | 2688 |
2364 (function(v) { | 2689 (function(v) { |
2365 Object.extend(v, { | 2690 Object.extend(v, { |
2366 href: v._getAttr, | 2691 href: v._getAttr2, |
2367 src: v._getAttr, | 2692 src: v._getAttr2, |
2368 type: v._getAttr, | 2693 type: v._getAttr, |
2369 action: v._getAttrNode, | 2694 action: v._getAttrNode, |
2370 disabled: v._flag, | 2695 disabled: v._flag, |
2371 checked: v._flag, | 2696 checked: v._flag, |
2372 readonly: v._flag, | 2697 readonly: v._flag, |
2389 onreset: v._getEv, | 2714 onreset: v._getEv, |
2390 onselect: v._getEv, | 2715 onselect: v._getEv, |
2391 onchange: v._getEv | 2716 onchange: v._getEv |
2392 }); | 2717 }); |
2393 })(Element._attributeTranslations.read.values); | 2718 })(Element._attributeTranslations.read.values); |
2719 | |
2720 if (Prototype.BrowserFeatures.ElementExtensions) { | |
2721 (function() { | |
2722 function _descendants(element) { | |
2723 var nodes = element.getElementsByTagName('*'), results = []; | |
2724 for (var i = 0, node; node = nodes[i]; i++) | |
2725 if (node.tagName !== "!") // Filter out comment nodes. | |
2726 results.push(node); | |
2727 return results; | |
2728 } | |
2729 | |
2730 Element.Methods.down = function(element, expression, index) { | |
2731 element = $(element); | |
2732 if (arguments.length == 1) return element.firstDescendant(); | |
2733 return Object.isNumber(expression) ? _descendants(element)[expression] : | |
2734 Element.select(element, expression)[index || 0]; | |
2735 } | |
2736 })(); | |
2737 } | |
2738 | |
2394 } | 2739 } |
2395 | 2740 |
2396 else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) { | 2741 else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) { |
2397 Element.Methods.setOpacity = function(element, value) { | 2742 Element.Methods.setOpacity = function(element, value) { |
2398 element = $(element); | 2743 element = $(element); |
2407 element = $(element); | 2752 element = $(element); |
2408 element.style.opacity = (value == 1 || value === '') ? '' : | 2753 element.style.opacity = (value == 1 || value === '') ? '' : |
2409 (value < 0.00001) ? 0 : value; | 2754 (value < 0.00001) ? 0 : value; |
2410 | 2755 |
2411 if (value == 1) | 2756 if (value == 1) |
2412 if(element.tagName.toUpperCase() == 'IMG' && element.width) { | 2757 if (element.tagName.toUpperCase() == 'IMG' && element.width) { |
2413 element.width++; element.width--; | 2758 element.width++; element.width--; |
2414 } else try { | 2759 } else try { |
2415 var n = document.createTextNode(' '); | 2760 var n = document.createTextNode(' '); |
2416 element.appendChild(n); | 2761 element.appendChild(n); |
2417 element.removeChild(n); | 2762 element.removeChild(n); |
2418 } catch (e) { } | 2763 } catch (e) { } |
2419 | 2764 |
2420 return element; | 2765 return element; |
2421 }; | 2766 }; |
2422 | |
2423 // Safari returns margins on body which is incorrect if the child is absolutely | |
2424 // positioned. For performance reasons, redefine Element#cumulativeOffset for | |
2425 // KHTML/WebKit only. | |
2426 Element.Methods.cumulativeOffset = function(element) { | |
2427 var valueT = 0, valueL = 0; | |
2428 do { | |
2429 valueT += element.offsetTop || 0; | |
2430 valueL += element.offsetLeft || 0; | |
2431 if (element.offsetParent == document.body) | |
2432 if (Element.getStyle(element, 'position') == 'absolute') break; | |
2433 | |
2434 element = element.offsetParent; | |
2435 } while (element); | |
2436 | |
2437 return Element._returnOffset(valueL, valueT); | |
2438 }; | |
2439 } | 2767 } |
2440 | 2768 |
2441 if (Prototype.Browser.IE || Prototype.Browser.Opera) { | 2769 if ('outerHTML' in document.documentElement) { |
2442 // IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements | |
2443 Element.Methods.update = function(element, content) { | |
2444 element = $(element); | |
2445 | |
2446 if (content && content.toElement) content = content.toElement(); | |
2447 if (Object.isElement(content)) return element.update().insert(content); | |
2448 | |
2449 content = Object.toHTML(content); | |
2450 var tagName = element.tagName.toUpperCase(); | |
2451 | |
2452 if (tagName in Element._insertionTranslations.tags) { | |
2453 $A(element.childNodes).each(function(node) { element.removeChild(node) }); | |
2454 Element._getContentFromAnonymousElement(tagName, content.stripScripts()) | |
2455 .each(function(node) { element.appendChild(node) }); | |
2456 } | |
2457 else element.innerHTML = content.stripScripts(); | |
2458 | |
2459 content.evalScripts.bind(content).defer(); | |
2460 return element; | |
2461 }; | |
2462 } | |
2463 | |
2464 if ('outerHTML' in document.createElement('div')) { | |
2465 Element.Methods.replace = function(element, content) { | 2770 Element.Methods.replace = function(element, content) { |
2466 element = $(element); | 2771 element = $(element); |
2467 | 2772 |
2468 if (content && content.toElement) content = content.toElement(); | 2773 if (content && content.toElement) content = content.toElement(); |
2469 if (Object.isElement(content)) { | 2774 if (Object.isElement(content)) { |
2473 | 2778 |
2474 content = Object.toHTML(content); | 2779 content = Object.toHTML(content); |
2475 var parent = element.parentNode, tagName = parent.tagName.toUpperCase(); | 2780 var parent = element.parentNode, tagName = parent.tagName.toUpperCase(); |
2476 | 2781 |
2477 if (Element._insertionTranslations.tags[tagName]) { | 2782 if (Element._insertionTranslations.tags[tagName]) { |
2478 var nextSibling = element.next(); | 2783 var nextSibling = element.next(), |
2479 var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); | 2784 fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); |
2480 parent.removeChild(element); | 2785 parent.removeChild(element); |
2481 if (nextSibling) | 2786 if (nextSibling) |
2482 fragments.each(function(node) { parent.insertBefore(node, nextSibling) }); | 2787 fragments.each(function(node) { parent.insertBefore(node, nextSibling) }); |
2483 else | 2788 else |
2484 fragments.each(function(node) { parent.appendChild(node) }); | 2789 fragments.each(function(node) { parent.appendChild(node) }); |
2495 result.left = l; | 2800 result.left = l; |
2496 result.top = t; | 2801 result.top = t; |
2497 return result; | 2802 return result; |
2498 }; | 2803 }; |
2499 | 2804 |
2500 Element._getContentFromAnonymousElement = function(tagName, html) { | 2805 Element._getContentFromAnonymousElement = function(tagName, html, force) { |
2501 var div = new Element('div'), t = Element._insertionTranslations.tags[tagName]; | 2806 var div = new Element('div'), |
2502 if (t) { | 2807 t = Element._insertionTranslations.tags[tagName]; |
2503 div.innerHTML = t[0] + html + t[1]; | 2808 |
2504 t[2].times(function() { div = div.firstChild }); | 2809 var workaround = false; |
2505 } else div.innerHTML = html; | 2810 if (t) workaround = true; |
2811 else if (force) { | |
2812 workaround = true; | |
2813 t = ['', '', 0]; | |
2814 } | |
2815 | |
2816 if (workaround) { | |
2817 div.innerHTML = ' ' + t[0] + html + t[1]; | |
2818 div.removeChild(div.firstChild); | |
2819 for (var i = t[2]; i--; ) { | |
2820 div = div.firstChild; | |
2821 } | |
2822 } | |
2823 else { | |
2824 div.innerHTML = html; | |
2825 } | |
2506 return $A(div.childNodes); | 2826 return $A(div.childNodes); |
2507 }; | 2827 }; |
2508 | 2828 |
2509 Element._insertionTranslations = { | 2829 Element._insertionTranslations = { |
2510 before: function(element, node) { | 2830 before: function(element, node) { |
2527 SELECT: ['<select>', '</select>', 1] | 2847 SELECT: ['<select>', '</select>', 1] |
2528 } | 2848 } |
2529 }; | 2849 }; |
2530 | 2850 |
2531 (function() { | 2851 (function() { |
2532 Object.extend(this.tags, { | 2852 var tags = Element._insertionTranslations.tags; |
2533 THEAD: this.tags.TBODY, | 2853 Object.extend(tags, { |
2534 TFOOT: this.tags.TBODY, | 2854 THEAD: tags.TBODY, |
2535 TH: this.tags.TD | 2855 TFOOT: tags.TBODY, |
2856 TH: tags.TD | |
2536 }); | 2857 }); |
2537 }).call(Element._insertionTranslations); | 2858 })(); |
2538 | 2859 |
2539 Element.Methods.Simulated = { | 2860 Element.Methods.Simulated = { |
2540 hasAttribute: function(element, attribute) { | 2861 hasAttribute: function(element, attribute) { |
2541 attribute = Element._attributeTranslations.has[attribute] || attribute; | 2862 attribute = Element._attributeTranslations.has[attribute] || attribute; |
2542 var node = $(element).getAttributeNode(attribute); | 2863 var node = $(element).getAttributeNode(attribute); |
2546 | 2867 |
2547 Element.Methods.ByTag = { }; | 2868 Element.Methods.ByTag = { }; |
2548 | 2869 |
2549 Object.extend(Element, Element.Methods); | 2870 Object.extend(Element, Element.Methods); |
2550 | 2871 |
2551 if (!Prototype.BrowserFeatures.ElementExtensions && | 2872 (function(div) { |
2552 document.createElement('div')['__proto__']) { | 2873 |
2553 window.HTMLElement = { }; | 2874 if (!Prototype.BrowserFeatures.ElementExtensions && div['__proto__']) { |
2554 window.HTMLElement.prototype = document.createElement('div')['__proto__']; | 2875 window.HTMLElement = { }; |
2555 Prototype.BrowserFeatures.ElementExtensions = true; | 2876 window.HTMLElement.prototype = div['__proto__']; |
2556 } | 2877 Prototype.BrowserFeatures.ElementExtensions = true; |
2878 } | |
2879 | |
2880 div = null; | |
2881 | |
2882 })(document.createElement('div')); | |
2557 | 2883 |
2558 Element.extend = (function() { | 2884 Element.extend = (function() { |
2559 if (Prototype.BrowserFeatures.SpecificElementExtensions) | 2885 |
2560 return Prototype.K; | 2886 function checkDeficiency(tagName) { |
2561 | 2887 if (typeof window.Element != 'undefined') { |
2562 var Methods = { }, ByTag = Element.Methods.ByTag; | 2888 var proto = window.Element.prototype; |
2563 | 2889 if (proto) { |
2564 var extend = Object.extend(function(element) { | 2890 var id = '_' + (Math.random()+'').slice(2), |
2565 if (!element || element._extendedByPrototype || | 2891 el = document.createElement(tagName); |
2566 element.nodeType != 1 || element == window) return element; | 2892 proto[id] = 'x'; |
2567 | 2893 var isBuggy = (el[id] !== 'x'); |
2568 var methods = Object.clone(Methods), | 2894 delete proto[id]; |
2569 tagName = element.tagName.toUpperCase(), property, value; | 2895 el = null; |
2570 | 2896 return isBuggy; |
2571 // extend methods for specific tags | 2897 } |
2572 if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]); | 2898 } |
2573 | 2899 return false; |
2574 for (property in methods) { | 2900 } |
2575 value = methods[property]; | 2901 |
2902 function extendElementWith(element, methods) { | |
2903 for (var property in methods) { | |
2904 var value = methods[property]; | |
2576 if (Object.isFunction(value) && !(property in element)) | 2905 if (Object.isFunction(value) && !(property in element)) |
2577 element[property] = value.methodize(); | 2906 element[property] = value.methodize(); |
2578 } | 2907 } |
2908 } | |
2909 | |
2910 var HTMLOBJECTELEMENT_PROTOTYPE_BUGGY = checkDeficiency('object'); | |
2911 | |
2912 if (Prototype.BrowserFeatures.SpecificElementExtensions) { | |
2913 if (HTMLOBJECTELEMENT_PROTOTYPE_BUGGY) { | |
2914 return function(element) { | |
2915 if (element && typeof element._extendedByPrototype == 'undefined') { | |
2916 var t = element.tagName; | |
2917 if (t && (/^(?:object|applet|embed)$/i.test(t))) { | |
2918 extendElementWith(element, Element.Methods); | |
2919 extendElementWith(element, Element.Methods.Simulated); | |
2920 extendElementWith(element, Element.Methods.ByTag[t.toUpperCase()]); | |
2921 } | |
2922 } | |
2923 return element; | |
2924 } | |
2925 } | |
2926 return Prototype.K; | |
2927 } | |
2928 | |
2929 var Methods = { }, ByTag = Element.Methods.ByTag; | |
2930 | |
2931 var extend = Object.extend(function(element) { | |
2932 if (!element || typeof element._extendedByPrototype != 'undefined' || | |
2933 element.nodeType != 1 || element == window) return element; | |
2934 | |
2935 var methods = Object.clone(Methods), | |
2936 tagName = element.tagName.toUpperCase(); | |
2937 | |
2938 if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]); | |
2939 | |
2940 extendElementWith(element, methods); | |
2579 | 2941 |
2580 element._extendedByPrototype = Prototype.emptyFunction; | 2942 element._extendedByPrototype = Prototype.emptyFunction; |
2581 return element; | 2943 return element; |
2582 | 2944 |
2583 }, { | 2945 }, { |
2584 refresh: function() { | 2946 refresh: function() { |
2585 // extend methods for all tags (Safari doesn't need this) | |
2586 if (!Prototype.BrowserFeatures.ElementExtensions) { | 2947 if (!Prototype.BrowserFeatures.ElementExtensions) { |
2587 Object.extend(Methods, Element.Methods); | 2948 Object.extend(Methods, Element.Methods); |
2588 Object.extend(Methods, Element.Methods.Simulated); | 2949 Object.extend(Methods, Element.Methods.Simulated); |
2589 } | 2950 } |
2590 } | 2951 } |
2592 | 2953 |
2593 extend.refresh(); | 2954 extend.refresh(); |
2594 return extend; | 2955 return extend; |
2595 })(); | 2956 })(); |
2596 | 2957 |
2597 Element.hasAttribute = function(element, attribute) { | 2958 if (document.documentElement.hasAttribute) { |
2598 if (element.hasAttribute) return element.hasAttribute(attribute); | 2959 Element.hasAttribute = function(element, attribute) { |
2599 return Element.Methods.Simulated.hasAttribute(element, attribute); | 2960 return element.hasAttribute(attribute); |
2600 }; | 2961 }; |
2962 } | |
2963 else { | |
2964 Element.hasAttribute = Element.Methods.Simulated.hasAttribute; | |
2965 } | |
2601 | 2966 |
2602 Element.addMethods = function(methods) { | 2967 Element.addMethods = function(methods) { |
2603 var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag; | 2968 var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag; |
2604 | 2969 |
2605 if (!methods) { | 2970 if (!methods) { |
2607 Object.extend(Form.Element, Form.Element.Methods); | 2972 Object.extend(Form.Element, Form.Element.Methods); |
2608 Object.extend(Element.Methods.ByTag, { | 2973 Object.extend(Element.Methods.ByTag, { |
2609 "FORM": Object.clone(Form.Methods), | 2974 "FORM": Object.clone(Form.Methods), |
2610 "INPUT": Object.clone(Form.Element.Methods), | 2975 "INPUT": Object.clone(Form.Element.Methods), |
2611 "SELECT": Object.clone(Form.Element.Methods), | 2976 "SELECT": Object.clone(Form.Element.Methods), |
2612 "TEXTAREA": Object.clone(Form.Element.Methods) | 2977 "TEXTAREA": Object.clone(Form.Element.Methods), |
2978 "BUTTON": Object.clone(Form.Element.Methods) | |
2613 }); | 2979 }); |
2614 } | 2980 } |
2615 | 2981 |
2616 if (arguments.length == 2) { | 2982 if (arguments.length == 2) { |
2617 var tagName = methods; | 2983 var tagName = methods; |
2659 klass = 'HTML' + tagName + 'Element'; | 3025 klass = 'HTML' + tagName + 'Element'; |
2660 if (window[klass]) return window[klass]; | 3026 if (window[klass]) return window[klass]; |
2661 klass = 'HTML' + tagName.capitalize() + 'Element'; | 3027 klass = 'HTML' + tagName.capitalize() + 'Element'; |
2662 if (window[klass]) return window[klass]; | 3028 if (window[klass]) return window[klass]; |
2663 | 3029 |
2664 window[klass] = { }; | 3030 var element = document.createElement(tagName), |
2665 window[klass].prototype = document.createElement(tagName)['__proto__']; | 3031 proto = element['__proto__'] || element.constructor.prototype; |
2666 return window[klass]; | 3032 |
2667 } | 3033 element = null; |
3034 return proto; | |
3035 } | |
3036 | |
3037 var elementPrototype = window.HTMLElement ? HTMLElement.prototype : | |
3038 Element.prototype; | |
2668 | 3039 |
2669 if (F.ElementExtensions) { | 3040 if (F.ElementExtensions) { |
2670 copy(Element.Methods, HTMLElement.prototype); | 3041 copy(Element.Methods, elementPrototype); |
2671 copy(Element.Methods.Simulated, HTMLElement.prototype, true); | 3042 copy(Element.Methods.Simulated, elementPrototype, true); |
2672 } | 3043 } |
2673 | 3044 |
2674 if (F.SpecificElementExtensions) { | 3045 if (F.SpecificElementExtensions) { |
2675 for (var tag in Element.Methods.ByTag) { | 3046 for (var tag in Element.Methods.ByTag) { |
2676 var klass = findDOMClass(tag); | 3047 var klass = findDOMClass(tag); |
2684 | 3055 |
2685 if (Element.extend.refresh) Element.extend.refresh(); | 3056 if (Element.extend.refresh) Element.extend.refresh(); |
2686 Element.cache = { }; | 3057 Element.cache = { }; |
2687 }; | 3058 }; |
2688 | 3059 |
3060 | |
2689 document.viewport = { | 3061 document.viewport = { |
3062 | |
2690 getDimensions: function() { | 3063 getDimensions: function() { |
2691 var dimensions = { }, B = Prototype.Browser; | 3064 return { width: this.getWidth(), height: this.getHeight() }; |
2692 $w('width height').each(function(d) { | |
2693 var D = d.capitalize(); | |
2694 if (B.WebKit && !document.evaluate) { | |
2695 // Safari <3.0 needs self.innerWidth/Height | |
2696 dimensions[d] = self['inner' + D]; | |
2697 } else if (B.Opera && parseFloat(window.opera.version()) < 9.5) { | |
2698 // Opera <9.5 needs document.body.clientWidth/Height | |
2699 dimensions[d] = document.body['client' + D] | |
2700 } else { | |
2701 dimensions[d] = document.documentElement['client' + D]; | |
2702 } | |
2703 }); | |
2704 return dimensions; | |
2705 }, | |
2706 | |
2707 getWidth: function() { | |
2708 return this.getDimensions().width; | |
2709 }, | |
2710 | |
2711 getHeight: function() { | |
2712 return this.getDimensions().height; | |
2713 }, | 3065 }, |
2714 | 3066 |
2715 getScrollOffsets: function() { | 3067 getScrollOffsets: function() { |
2716 return Element._returnOffset( | 3068 return Element._returnOffset( |
2717 window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft, | 3069 window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft, |
2718 window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop); | 3070 window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop); |
2719 } | 3071 } |
2720 }; | 3072 }; |
2721 /* Portions of the Selector class are derived from Jack Slocum's DomQuery, | 3073 |
2722 * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style | 3074 (function(viewport) { |
2723 * license. Please see http://www.yui-ext.com/ for more information. */ | 3075 var B = Prototype.Browser, doc = document, element, property = {}; |
2724 | 3076 |
2725 var Selector = Class.create({ | 3077 function getRootElement() { |
2726 initialize: function(expression) { | 3078 if (B.WebKit && !doc.evaluate) |
2727 this.expression = expression.strip(); | 3079 return document; |
2728 | 3080 |
2729 if (this.shouldUseSelectorsAPI()) { | 3081 if (B.Opera && window.parseFloat(window.opera.version()) < 9.5) |
2730 this.mode = 'selectorsAPI'; | 3082 return document.body; |
2731 } else if (this.shouldUseXPath()) { | 3083 |
2732 this.mode = 'xpath'; | 3084 return document.documentElement; |
2733 this.compileXPathMatcher(); | 3085 } |
3086 | |
3087 function define(D) { | |
3088 if (!element) element = getRootElement(); | |
3089 | |
3090 property[D] = 'client' + D; | |
3091 | |
3092 viewport['get' + D] = function() { return element[property[D]] }; | |
3093 return viewport['get' + D](); | |
3094 } | |
3095 | |
3096 viewport.getWidth = define.curry('Width'); | |
3097 | |
3098 viewport.getHeight = define.curry('Height'); | |
3099 })(document.viewport); | |
3100 | |
3101 | |
3102 Element.Storage = { | |
3103 UID: 1 | |
3104 }; | |
3105 | |
3106 Element.addMethods({ | |
3107 getStorage: function(element) { | |
3108 if (!(element = $(element))) return; | |
3109 | |
3110 var uid; | |
3111 if (element === window) { | |
3112 uid = 0; | |
2734 } else { | 3113 } else { |
2735 this.mode = "normal"; | 3114 if (typeof element._prototypeUID === "undefined") |
2736 this.compileMatcher(); | 3115 element._prototypeUID = Element.Storage.UID++; |
2737 } | 3116 uid = element._prototypeUID; |
2738 | 3117 } |
2739 }, | 3118 |
2740 | 3119 if (!Element.Storage[uid]) |
2741 shouldUseXPath: function() { | 3120 Element.Storage[uid] = $H(); |
2742 if (!Prototype.BrowserFeatures.XPath) return false; | 3121 |
2743 | 3122 return Element.Storage[uid]; |
2744 var e = this.expression; | 3123 }, |
2745 | 3124 |
2746 // Safari 3 chokes on :*-of-type and :empty | 3125 store: function(element, key, value) { |
2747 if (Prototype.Browser.WebKit && | 3126 if (!(element = $(element))) return; |
2748 (e.include("-of-type") || e.include(":empty"))) | 3127 |
2749 return false; | 3128 if (arguments.length === 2) { |
2750 | 3129 Element.getStorage(element).update(key); |
2751 // XPath can't do namespaced attributes, nor can it read | 3130 } else { |
2752 // the "checked" property from DOM nodes | 3131 Element.getStorage(element).set(key, value); |
2753 if ((/(\[[\w-]*?:|:checked)/).test(e)) | 3132 } |
2754 return false; | 3133 |
2755 | 3134 return element; |
3135 }, | |
3136 | |
3137 retrieve: function(element, key, defaultValue) { | |
3138 if (!(element = $(element))) return; | |
3139 var hash = Element.getStorage(element), value = hash.get(key); | |
3140 | |
3141 if (Object.isUndefined(value)) { | |
3142 hash.set(key, defaultValue); | |
3143 value = defaultValue; | |
3144 } | |
3145 | |
3146 return value; | |
3147 }, | |
3148 | |
3149 clone: function(element, deep) { | |
3150 if (!(element = $(element))) return; | |
3151 var clone = element.cloneNode(deep); | |
3152 clone._prototypeUID = void 0; | |
3153 if (deep) { | |
3154 var descendants = Element.select(clone, '*'), | |
3155 i = descendants.length; | |
3156 while (i--) { | |
3157 descendants[i]._prototypeUID = void 0; | |
3158 } | |
3159 } | |
3160 return Element.extend(clone); | |
3161 }, | |
3162 | |
3163 purge: function(element) { | |
3164 if (!(element = $(element))) return; | |
3165 var purgeElement = Element._purgeElement; | |
3166 | |
3167 purgeElement(element); | |
3168 | |
3169 var descendants = element.getElementsByTagName('*'), | |
3170 i = descendants.length; | |
3171 | |
3172 while (i--) purgeElement(descendants[i]); | |
3173 | |
3174 return null; | |
3175 } | |
3176 }); | |
3177 | |
3178 (function() { | |
3179 | |
3180 function toDecimal(pctString) { | |
3181 var match = pctString.match(/^(\d+)%?$/i); | |
3182 if (!match) return null; | |
3183 return (Number(match[1]) / 100); | |
3184 } | |
3185 | |
3186 function getPixelValue(value, property, context) { | |
3187 var element = null; | |
3188 if (Object.isElement(value)) { | |
3189 element = value; | |
3190 value = element.getStyle(property); | |
3191 } | |
3192 | |
3193 if (value === null) { | |
3194 return null; | |
3195 } | |
3196 | |
3197 if ((/^(?:-)?\d+(\.\d+)?(px)?$/i).test(value)) { | |
3198 return window.parseFloat(value); | |
3199 } | |
3200 | |
3201 var isPercentage = value.include('%'), isViewport = (context === document.viewport); | |
3202 | |
3203 if (/\d/.test(value) && element && element.runtimeStyle && !(isPercentage && isViewport)) { | |
3204 var style = element.style.left, rStyle = element.runtimeStyle.left; | |
3205 element.runtimeStyle.left = element.currentStyle.left; | |
3206 element.style.left = value || 0; | |
3207 value = element.style.pixelLeft; | |
3208 element.style.left = style; | |
3209 element.runtimeStyle.left = rStyle; | |
3210 | |
3211 return value; | |
3212 } | |
3213 | |
3214 if (element && isPercentage) { | |
3215 context = context || element.parentNode; | |
3216 var decimal = toDecimal(value); | |
3217 var whole = null; | |
3218 var position = element.getStyle('position'); | |
3219 | |
3220 var isHorizontal = property.include('left') || property.include('right') || | |
3221 property.include('width'); | |
3222 | |
3223 var isVertical = property.include('top') || property.include('bottom') || | |
3224 property.include('height'); | |
3225 | |
3226 if (context === document.viewport) { | |
3227 if (isHorizontal) { | |
3228 whole = document.viewport.getWidth(); | |
3229 } else if (isVertical) { | |
3230 whole = document.viewport.getHeight(); | |
3231 } | |
3232 } else { | |
3233 if (isHorizontal) { | |
3234 whole = $(context).measure('width'); | |
3235 } else if (isVertical) { | |
3236 whole = $(context).measure('height'); | |
3237 } | |
3238 } | |
3239 | |
3240 return (whole === null) ? 0 : whole * decimal; | |
3241 } | |
3242 | |
3243 return 0; | |
3244 } | |
3245 | |
3246 function toCSSPixels(number) { | |
3247 if (Object.isString(number) && number.endsWith('px')) { | |
3248 return number; | |
3249 } | |
3250 return number + 'px'; | |
3251 } | |
3252 | |
3253 function isDisplayed(element) { | |
3254 var originalElement = element; | |
3255 while (element && element.parentNode) { | |
3256 var display = element.getStyle('display'); | |
3257 if (display === 'none') { | |
3258 return false; | |
3259 } | |
3260 element = $(element.parentNode); | |
3261 } | |
2756 return true; | 3262 return true; |
2757 }, | 3263 } |
2758 | 3264 |
2759 shouldUseSelectorsAPI: function() { | 3265 var hasLayout = Prototype.K; |
2760 if (!Prototype.BrowserFeatures.SelectorsAPI) return false; | 3266 if ('currentStyle' in document.documentElement) { |
2761 | 3267 hasLayout = function(element) { |
2762 if (!Selector._div) Selector._div = new Element('div'); | 3268 if (!element.currentStyle.hasLayout) { |
2763 | 3269 element.style.zoom = 1; |
2764 // Make sure the browser treats the selector as valid. Test on an | 3270 } |
2765 // isolated element to minimize cost of this check. | 3271 return element; |
2766 try { | 3272 }; |
2767 Selector._div.querySelector(this.expression); | 3273 } |
2768 } catch(e) { | 3274 |
2769 return false; | 3275 function cssNameFor(key) { |
2770 } | 3276 if (key.include('border')) key = key + '-width'; |
2771 | 3277 return key.camelize(); |
2772 return true; | 3278 } |
2773 }, | 3279 |
2774 | 3280 Element.Layout = Class.create(Hash, { |
2775 compileMatcher: function() { | 3281 initialize: function($super, element, preCompute) { |
2776 var e = this.expression, ps = Selector.patterns, h = Selector.handlers, | 3282 $super(); |
2777 c = Selector.criteria, le, p, m; | 3283 this.element = $(element); |
2778 | 3284 |
2779 if (Selector._cache[e]) { | 3285 Element.Layout.PROPERTIES.each( function(property) { |
2780 this.matcher = Selector._cache[e]; | 3286 this._set(property, null); |
2781 return; | 3287 }, this); |
2782 } | 3288 |
2783 | 3289 if (preCompute) { |
2784 this.matcher = ["this.matcher = function(root) {", | 3290 this._preComputing = true; |
2785 "var r = root, h = Selector.handlers, c = false, n;"]; | 3291 this._begin(); |
2786 | 3292 Element.Layout.PROPERTIES.each( this._compute, this ); |
2787 while (e && le != e && (/\S/).test(e)) { | 3293 this._end(); |
2788 le = e; | 3294 this._preComputing = false; |
2789 for (var i in ps) { | 3295 } |
2790 p = ps[i]; | 3296 }, |
2791 if (m = e.match(p)) { | 3297 |
2792 this.matcher.push(Object.isFunction(c[i]) ? c[i](m) : | 3298 _set: function(property, value) { |
2793 new Template(c[i]).evaluate(m)); | 3299 return Hash.prototype.set.call(this, property, value); |
2794 e = e.replace(m[0], ''); | 3300 }, |
3301 | |
3302 set: function(property, value) { | |
3303 throw "Properties of Element.Layout are read-only."; | |
3304 }, | |
3305 | |
3306 get: function($super, property) { | |
3307 var value = $super(property); | |
3308 return value === null ? this._compute(property) : value; | |
3309 }, | |
3310 | |
3311 _begin: function() { | |
3312 if (this._prepared) return; | |
3313 | |
3314 var element = this.element; | |
3315 if (isDisplayed(element)) { | |
3316 this._prepared = true; | |
3317 return; | |
3318 } | |
3319 | |
3320 var originalStyles = { | |
3321 position: element.style.position || '', | |
3322 width: element.style.width || '', | |
3323 visibility: element.style.visibility || '', | |
3324 display: element.style.display || '' | |
3325 }; | |
3326 | |
3327 element.store('prototype_original_styles', originalStyles); | |
3328 | |
3329 var position = element.getStyle('position'), | |
3330 width = element.getStyle('width'); | |
3331 | |
3332 if (width === "0px" || width === null) { | |
3333 element.style.display = 'block'; | |
3334 width = element.getStyle('width'); | |
3335 } | |
3336 | |
3337 var context = (position === 'fixed') ? document.viewport : | |
3338 element.parentNode; | |
3339 | |
3340 element.setStyle({ | |
3341 position: 'absolute', | |
3342 visibility: 'hidden', | |
3343 display: 'block' | |
3344 }); | |
3345 | |
3346 var positionedWidth = element.getStyle('width'); | |
3347 | |
3348 var newWidth; | |
3349 if (width && (positionedWidth === width)) { | |
3350 newWidth = getPixelValue(element, 'width', context); | |
3351 } else if (position === 'absolute' || position === 'fixed') { | |
3352 newWidth = getPixelValue(element, 'width', context); | |
3353 } else { | |
3354 var parent = element.parentNode, pLayout = $(parent).getLayout(); | |
3355 | |
3356 newWidth = pLayout.get('width') - | |
3357 this.get('margin-left') - | |
3358 this.get('border-left') - | |
3359 this.get('padding-left') - | |
3360 this.get('padding-right') - | |
3361 this.get('border-right') - | |
3362 this.get('margin-right'); | |
3363 } | |
3364 | |
3365 element.setStyle({ width: newWidth + 'px' }); | |
3366 | |
3367 this._prepared = true; | |
3368 }, | |
3369 | |
3370 _end: function() { | |
3371 var element = this.element; | |
3372 var originalStyles = element.retrieve('prototype_original_styles'); | |
3373 element.store('prototype_original_styles', null); | |
3374 element.setStyle(originalStyles); | |
3375 this._prepared = false; | |
3376 }, | |
3377 | |
3378 _compute: function(property) { | |
3379 var COMPUTATIONS = Element.Layout.COMPUTATIONS; | |
3380 if (!(property in COMPUTATIONS)) { | |
3381 throw "Property not found."; | |
3382 } | |
3383 | |
3384 return this._set(property, COMPUTATIONS[property].call(this, this.element)); | |
3385 }, | |
3386 | |
3387 toObject: function() { | |
3388 var args = $A(arguments); | |
3389 var keys = (args.length === 0) ? Element.Layout.PROPERTIES : | |
3390 args.join(' ').split(' '); | |
3391 var obj = {}; | |
3392 keys.each( function(key) { | |
3393 if (!Element.Layout.PROPERTIES.include(key)) return; | |
3394 var value = this.get(key); | |
3395 if (value != null) obj[key] = value; | |
3396 }, this); | |
3397 return obj; | |
3398 }, | |
3399 | |
3400 toHash: function() { | |
3401 var obj = this.toObject.apply(this, arguments); | |
3402 return new Hash(obj); | |
3403 }, | |
3404 | |
3405 toCSS: function() { | |
3406 var args = $A(arguments); | |
3407 var keys = (args.length === 0) ? Element.Layout.PROPERTIES : | |
3408 args.join(' ').split(' '); | |
3409 var css = {}; | |
3410 | |
3411 keys.each( function(key) { | |
3412 if (!Element.Layout.PROPERTIES.include(key)) return; | |
3413 if (Element.Layout.COMPOSITE_PROPERTIES.include(key)) return; | |
3414 | |
3415 var value = this.get(key); | |
3416 if (value != null) css[cssNameFor(key)] = value + 'px'; | |
3417 }, this); | |
3418 return css; | |
3419 }, | |
3420 | |
3421 inspect: function() { | |
3422 return "#<Element.Layout>"; | |
3423 } | |
3424 }); | |
3425 | |
3426 Object.extend(Element.Layout, { | |
3427 PROPERTIES: $w('height width top left right bottom border-left border-right border-top border-bottom padding-left padding-right padding-top padding-bottom margin-top margin-bottom margin-left margin-right padding-box-width padding-box-height border-box-width border-box-height margin-box-width margin-box-height'), | |
3428 | |
3429 COMPOSITE_PROPERTIES: $w('padding-box-width padding-box-height margin-box-width margin-box-height border-box-width border-box-height'), | |
3430 | |
3431 COMPUTATIONS: { | |
3432 'height': function(element) { | |
3433 if (!this._preComputing) this._begin(); | |
3434 | |
3435 var bHeight = this.get('border-box-height'); | |
3436 if (bHeight <= 0) { | |
3437 if (!this._preComputing) this._end(); | |
3438 return 0; | |
3439 } | |
3440 | |
3441 var bTop = this.get('border-top'), | |
3442 bBottom = this.get('border-bottom'); | |
3443 | |
3444 var pTop = this.get('padding-top'), | |
3445 pBottom = this.get('padding-bottom'); | |
3446 | |
3447 if (!this._preComputing) this._end(); | |
3448 | |
3449 return bHeight - bTop - bBottom - pTop - pBottom; | |
3450 }, | |
3451 | |
3452 'width': function(element) { | |
3453 if (!this._preComputing) this._begin(); | |
3454 | |
3455 var bWidth = this.get('border-box-width'); | |
3456 if (bWidth <= 0) { | |
3457 if (!this._preComputing) this._end(); | |
3458 return 0; | |
3459 } | |
3460 | |
3461 var bLeft = this.get('border-left'), | |
3462 bRight = this.get('border-right'); | |
3463 | |
3464 var pLeft = this.get('padding-left'), | |
3465 pRight = this.get('padding-right'); | |
3466 | |
3467 if (!this._preComputing) this._end(); | |
3468 | |
3469 return bWidth - bLeft - bRight - pLeft - pRight; | |
3470 }, | |
3471 | |
3472 'padding-box-height': function(element) { | |
3473 var height = this.get('height'), | |
3474 pTop = this.get('padding-top'), | |
3475 pBottom = this.get('padding-bottom'); | |
3476 | |
3477 return height + pTop + pBottom; | |
3478 }, | |
3479 | |
3480 'padding-box-width': function(element) { | |
3481 var width = this.get('width'), | |
3482 pLeft = this.get('padding-left'), | |
3483 pRight = this.get('padding-right'); | |
3484 | |
3485 return width + pLeft + pRight; | |
3486 }, | |
3487 | |
3488 'border-box-height': function(element) { | |
3489 if (!this._preComputing) this._begin(); | |
3490 var height = element.offsetHeight; | |
3491 if (!this._preComputing) this._end(); | |
3492 return height; | |
3493 }, | |
3494 | |
3495 'border-box-width': function(element) { | |
3496 if (!this._preComputing) this._begin(); | |
3497 var width = element.offsetWidth; | |
3498 if (!this._preComputing) this._end(); | |
3499 return width; | |
3500 }, | |
3501 | |
3502 'margin-box-height': function(element) { | |
3503 var bHeight = this.get('border-box-height'), | |
3504 mTop = this.get('margin-top'), | |
3505 mBottom = this.get('margin-bottom'); | |
3506 | |
3507 if (bHeight <= 0) return 0; | |
3508 | |
3509 return bHeight + mTop + mBottom; | |
3510 }, | |
3511 | |
3512 'margin-box-width': function(element) { | |
3513 var bWidth = this.get('border-box-width'), | |
3514 mLeft = this.get('margin-left'), | |
3515 mRight = this.get('margin-right'); | |
3516 | |
3517 if (bWidth <= 0) return 0; | |
3518 | |
3519 return bWidth + mLeft + mRight; | |
3520 }, | |
3521 | |
3522 'top': function(element) { | |
3523 var offset = element.positionedOffset(); | |
3524 return offset.top; | |
3525 }, | |
3526 | |
3527 'bottom': function(element) { | |
3528 var offset = element.positionedOffset(), | |
3529 parent = element.getOffsetParent(), | |
3530 pHeight = parent.measure('height'); | |
3531 | |
3532 var mHeight = this.get('border-box-height'); | |
3533 | |
3534 return pHeight - mHeight - offset.top; | |
3535 }, | |
3536 | |
3537 'left': function(element) { | |
3538 var offset = element.positionedOffset(); | |
3539 return offset.left; | |
3540 }, | |
3541 | |
3542 'right': function(element) { | |
3543 var offset = element.positionedOffset(), | |
3544 parent = element.getOffsetParent(), | |
3545 pWidth = parent.measure('width'); | |
3546 | |
3547 var mWidth = this.get('border-box-width'); | |
3548 | |
3549 return pWidth - mWidth - offset.left; | |
3550 }, | |
3551 | |
3552 'padding-top': function(element) { | |
3553 return getPixelValue(element, 'paddingTop'); | |
3554 }, | |
3555 | |
3556 'padding-bottom': function(element) { | |
3557 return getPixelValue(element, 'paddingBottom'); | |
3558 }, | |
3559 | |
3560 'padding-left': function(element) { | |
3561 return getPixelValue(element, 'paddingLeft'); | |
3562 }, | |
3563 | |
3564 'padding-right': function(element) { | |
3565 return getPixelValue(element, 'paddingRight'); | |
3566 }, | |
3567 | |
3568 'border-top': function(element) { | |
3569 return getPixelValue(element, 'borderTopWidth'); | |
3570 }, | |
3571 | |
3572 'border-bottom': function(element) { | |
3573 return getPixelValue(element, 'borderBottomWidth'); | |
3574 }, | |
3575 | |
3576 'border-left': function(element) { | |
3577 return getPixelValue(element, 'borderLeftWidth'); | |
3578 }, | |
3579 | |
3580 'border-right': function(element) { | |
3581 return getPixelValue(element, 'borderRightWidth'); | |
3582 }, | |
3583 | |
3584 'margin-top': function(element) { | |
3585 return getPixelValue(element, 'marginTop'); | |
3586 }, | |
3587 | |
3588 'margin-bottom': function(element) { | |
3589 return getPixelValue(element, 'marginBottom'); | |
3590 }, | |
3591 | |
3592 'margin-left': function(element) { | |
3593 return getPixelValue(element, 'marginLeft'); | |
3594 }, | |
3595 | |
3596 'margin-right': function(element) { | |
3597 return getPixelValue(element, 'marginRight'); | |
3598 } | |
3599 } | |
3600 }); | |
3601 | |
3602 if ('getBoundingClientRect' in document.documentElement) { | |
3603 Object.extend(Element.Layout.COMPUTATIONS, { | |
3604 'right': function(element) { | |
3605 var parent = hasLayout(element.getOffsetParent()); | |
3606 var rect = element.getBoundingClientRect(), | |
3607 pRect = parent.getBoundingClientRect(); | |
3608 | |
3609 return (pRect.right - rect.right).round(); | |
3610 }, | |
3611 | |
3612 'bottom': function(element) { | |
3613 var parent = hasLayout(element.getOffsetParent()); | |
3614 var rect = element.getBoundingClientRect(), | |
3615 pRect = parent.getBoundingClientRect(); | |
3616 | |
3617 return (pRect.bottom - rect.bottom).round(); | |
3618 } | |
3619 }); | |
3620 } | |
3621 | |
3622 Element.Offset = Class.create({ | |
3623 initialize: function(left, top) { | |
3624 this.left = left.round(); | |
3625 this.top = top.round(); | |
3626 | |
3627 this[0] = this.left; | |
3628 this[1] = this.top; | |
3629 }, | |
3630 | |
3631 relativeTo: function(offset) { | |
3632 return new Element.Offset( | |
3633 this.left - offset.left, | |
3634 this.top - offset.top | |
3635 ); | |
3636 }, | |
3637 | |
3638 inspect: function() { | |
3639 return "#<Element.Offset left: #{left} top: #{top}>".interpolate(this); | |
3640 }, | |
3641 | |
3642 toString: function() { | |
3643 return "[#{left}, #{top}]".interpolate(this); | |
3644 }, | |
3645 | |
3646 toArray: function() { | |
3647 return [this.left, this.top]; | |
3648 } | |
3649 }); | |
3650 | |
3651 function getLayout(element, preCompute) { | |
3652 return new Element.Layout(element, preCompute); | |
3653 } | |
3654 | |
3655 function measure(element, property) { | |
3656 return $(element).getLayout().get(property); | |
3657 } | |
3658 | |
3659 function getDimensions(element) { | |
3660 element = $(element); | |
3661 var display = Element.getStyle(element, 'display'); | |
3662 | |
3663 if (display && display !== 'none') { | |
3664 return { width: element.offsetWidth, height: element.offsetHeight }; | |
3665 } | |
3666 | |
3667 var style = element.style; | |
3668 var originalStyles = { | |
3669 visibility: style.visibility, | |
3670 position: style.position, | |
3671 display: style.display | |
3672 }; | |
3673 | |
3674 var newStyles = { | |
3675 visibility: 'hidden', | |
3676 display: 'block' | |
3677 }; | |
3678 | |
3679 if (originalStyles.position !== 'fixed') | |
3680 newStyles.position = 'absolute'; | |
3681 | |
3682 Element.setStyle(element, newStyles); | |
3683 | |
3684 var dimensions = { | |
3685 width: element.offsetWidth, | |
3686 height: element.offsetHeight | |
3687 }; | |
3688 | |
3689 Element.setStyle(element, originalStyles); | |
3690 | |
3691 return dimensions; | |
3692 } | |
3693 | |
3694 function getOffsetParent(element) { | |
3695 element = $(element); | |
3696 | |
3697 if (isDocument(element) || isDetached(element) || isBody(element) || isHtml(element)) | |
3698 return $(document.body); | |
3699 | |
3700 var isInline = (Element.getStyle(element, 'display') === 'inline'); | |
3701 if (!isInline && element.offsetParent) return $(element.offsetParent); | |
3702 | |
3703 while ((element = element.parentNode) && element !== document.body) { | |
3704 if (Element.getStyle(element, 'position') !== 'static') { | |
3705 return isHtml(element) ? $(document.body) : $(element); | |
3706 } | |
3707 } | |
3708 | |
3709 return $(document.body); | |
3710 } | |
3711 | |
3712 | |
3713 function cumulativeOffset(element) { | |
3714 element = $(element); | |
3715 var valueT = 0, valueL = 0; | |
3716 if (element.parentNode) { | |
3717 do { | |
3718 valueT += element.offsetTop || 0; | |
3719 valueL += element.offsetLeft || 0; | |
3720 element = element.offsetParent; | |
3721 } while (element); | |
3722 } | |
3723 return new Element.Offset(valueL, valueT); | |
3724 } | |
3725 | |
3726 function positionedOffset(element) { | |
3727 element = $(element); | |
3728 | |
3729 var layout = element.getLayout(); | |
3730 | |
3731 var valueT = 0, valueL = 0; | |
3732 do { | |
3733 valueT += element.offsetTop || 0; | |
3734 valueL += element.offsetLeft || 0; | |
3735 element = element.offsetParent; | |
3736 if (element) { | |
3737 if (isBody(element)) break; | |
3738 var p = Element.getStyle(element, 'position'); | |
3739 if (p !== 'static') break; | |
3740 } | |
3741 } while (element); | |
3742 | |
3743 valueL -= layout.get('margin-top'); | |
3744 valueT -= layout.get('margin-left'); | |
3745 | |
3746 return new Element.Offset(valueL, valueT); | |
3747 } | |
3748 | |
3749 function cumulativeScrollOffset(element) { | |
3750 var valueT = 0, valueL = 0; | |
3751 do { | |
3752 valueT += element.scrollTop || 0; | |
3753 valueL += element.scrollLeft || 0; | |
3754 element = element.parentNode; | |
3755 } while (element); | |
3756 return new Element.Offset(valueL, valueT); | |
3757 } | |
3758 | |
3759 function viewportOffset(forElement) { | |
3760 element = $(element); | |
3761 var valueT = 0, valueL = 0, docBody = document.body; | |
3762 | |
3763 var element = forElement; | |
3764 do { | |
3765 valueT += element.offsetTop || 0; | |
3766 valueL += element.offsetLeft || 0; | |
3767 if (element.offsetParent == docBody && | |
3768 Element.getStyle(element, 'position') == 'absolute') break; | |
3769 } while (element = element.offsetParent); | |
3770 | |
3771 element = forElement; | |
3772 do { | |
3773 if (element != docBody) { | |
3774 valueT -= element.scrollTop || 0; | |
3775 valueL -= element.scrollLeft || 0; | |
3776 } | |
3777 } while (element = element.parentNode); | |
3778 return new Element.Offset(valueL, valueT); | |
3779 } | |
3780 | |
3781 function absolutize(element) { | |
3782 element = $(element); | |
3783 | |
3784 if (Element.getStyle(element, 'position') === 'absolute') { | |
3785 return element; | |
3786 } | |
3787 | |
3788 var offsetParent = getOffsetParent(element); | |
3789 var eOffset = element.viewportOffset(), | |
3790 pOffset = offsetParent.viewportOffset(); | |
3791 | |
3792 var offset = eOffset.relativeTo(pOffset); | |
3793 var layout = element.getLayout(); | |
3794 | |
3795 element.store('prototype_absolutize_original_styles', { | |
3796 left: element.getStyle('left'), | |
3797 top: element.getStyle('top'), | |
3798 width: element.getStyle('width'), | |
3799 height: element.getStyle('height') | |
3800 }); | |
3801 | |
3802 element.setStyle({ | |
3803 position: 'absolute', | |
3804 top: offset.top + 'px', | |
3805 left: offset.left + 'px', | |
3806 width: layout.get('width') + 'px', | |
3807 height: layout.get('height') + 'px' | |
3808 }); | |
3809 | |
3810 return element; | |
3811 } | |
3812 | |
3813 function relativize(element) { | |
3814 element = $(element); | |
3815 if (Element.getStyle(element, 'position') === 'relative') { | |
3816 return element; | |
3817 } | |
3818 | |
3819 var originalStyles = | |
3820 element.retrieve('prototype_absolutize_original_styles'); | |
3821 | |
3822 if (originalStyles) element.setStyle(originalStyles); | |
3823 return element; | |
3824 } | |
3825 | |
3826 if (Prototype.Browser.IE) { | |
3827 getOffsetParent = getOffsetParent.wrap( | |
3828 function(proceed, element) { | |
3829 element = $(element); | |
3830 | |
3831 if (isDocument(element) || isDetached(element) || isBody(element) || isHtml(element)) | |
3832 return $(document.body); | |
3833 | |
3834 var position = element.getStyle('position'); | |
3835 if (position !== 'static') return proceed(element); | |
3836 | |
3837 element.setStyle({ position: 'relative' }); | |
3838 var value = proceed(element); | |
3839 element.setStyle({ position: position }); | |
3840 return value; | |
3841 } | |
3842 ); | |
3843 | |
3844 positionedOffset = positionedOffset.wrap(function(proceed, element) { | |
3845 element = $(element); | |
3846 if (!element.parentNode) return new Element.Offset(0, 0); | |
3847 var position = element.getStyle('position'); | |
3848 if (position !== 'static') return proceed(element); | |
3849 | |
3850 var offsetParent = element.getOffsetParent(); | |
3851 if (offsetParent && offsetParent.getStyle('position') === 'fixed') | |
3852 hasLayout(offsetParent); | |
3853 | |
3854 element.setStyle({ position: 'relative' }); | |
3855 var value = proceed(element); | |
3856 element.setStyle({ position: position }); | |
3857 return value; | |
3858 }); | |
3859 } else if (Prototype.Browser.Webkit) { | |
3860 cumulativeOffset = function(element) { | |
3861 element = $(element); | |
3862 var valueT = 0, valueL = 0; | |
3863 do { | |
3864 valueT += element.offsetTop || 0; | |
3865 valueL += element.offsetLeft || 0; | |
3866 if (element.offsetParent == document.body) | |
3867 if (Element.getStyle(element, 'position') == 'absolute') break; | |
3868 | |
3869 element = element.offsetParent; | |
3870 } while (element); | |
3871 | |
3872 return new Element.Offset(valueL, valueT); | |
3873 }; | |
3874 } | |
3875 | |
3876 | |
3877 Element.addMethods({ | |
3878 getLayout: getLayout, | |
3879 measure: measure, | |
3880 getDimensions: getDimensions, | |
3881 getOffsetParent: getOffsetParent, | |
3882 cumulativeOffset: cumulativeOffset, | |
3883 positionedOffset: positionedOffset, | |
3884 cumulativeScrollOffset: cumulativeScrollOffset, | |
3885 viewportOffset: viewportOffset, | |
3886 absolutize: absolutize, | |
3887 relativize: relativize | |
3888 }); | |
3889 | |
3890 function isBody(element) { | |
3891 return element.nodeName.toUpperCase() === 'BODY'; | |
3892 } | |
3893 | |
3894 function isHtml(element) { | |
3895 return element.nodeName.toUpperCase() === 'HTML'; | |
3896 } | |
3897 | |
3898 function isDocument(element) { | |
3899 return element.nodeType === Node.DOCUMENT_NODE; | |
3900 } | |
3901 | |
3902 function isDetached(element) { | |
3903 return element !== document.body && | |
3904 !Element.descendantOf(element, document.body); | |
3905 } | |
3906 | |
3907 if ('getBoundingClientRect' in document.documentElement) { | |
3908 Element.addMethods({ | |
3909 viewportOffset: function(element) { | |
3910 element = $(element); | |
3911 if (isDetached(element)) return new Element.Offset(0, 0); | |
3912 | |
3913 var rect = element.getBoundingClientRect(), | |
3914 docEl = document.documentElement; | |
3915 return new Element.Offset(rect.left - docEl.clientLeft, | |
3916 rect.top - docEl.clientTop); | |
3917 } | |
3918 }); | |
3919 } | |
3920 })(); | |
3921 window.$$ = function() { | |
3922 var expression = $A(arguments).join(', '); | |
3923 return Prototype.Selector.select(expression, document); | |
3924 }; | |
3925 | |
3926 Prototype.Selector = (function() { | |
3927 | |
3928 function select() { | |
3929 throw new Error('Method "Prototype.Selector.select" must be defined.'); | |
3930 } | |
3931 | |
3932 function match() { | |
3933 throw new Error('Method "Prototype.Selector.match" must be defined.'); | |
3934 } | |
3935 | |
3936 function find(elements, expression, index) { | |
3937 index = index || 0; | |
3938 var match = Prototype.Selector.match, length = elements.length, matchIndex = 0, i; | |
3939 | |
3940 for (i = 0; i < length; i++) { | |
3941 if (match(elements[i], expression) && index == matchIndex++) { | |
3942 return Element.extend(elements[i]); | |
3943 } | |
3944 } | |
3945 } | |
3946 | |
3947 function extendElements(elements) { | |
3948 for (var i = 0, length = elements.length; i < length; i++) { | |
3949 Element.extend(elements[i]); | |
3950 } | |
3951 return elements; | |
3952 } | |
3953 | |
3954 | |
3955 var K = Prototype.K; | |
3956 | |
3957 return { | |
3958 select: select, | |
3959 match: match, | |
3960 find: find, | |
3961 extendElements: (Element.extend === K) ? K : extendElements, | |
3962 extendElement: Element.extend | |
3963 }; | |
3964 })(); | |
3965 Prototype._original_property = window.Sizzle; | |
3966 /*! | |
3967 * Sizzle CSS Selector Engine - v1.0 | |
3968 * Copyright 2009, The Dojo Foundation | |
3969 * Released under the MIT, BSD, and GPL Licenses. | |
3970 * More information: http://sizzlejs.com/ | |
3971 */ | |
3972 (function(){ | |
3973 | |
3974 var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, | |
3975 done = 0, | |
3976 toString = Object.prototype.toString, | |
3977 hasDuplicate = false, | |
3978 baseHasDuplicate = true; | |
3979 | |
3980 [0, 0].sort(function(){ | |
3981 baseHasDuplicate = false; | |
3982 return 0; | |
3983 }); | |
3984 | |
3985 var Sizzle = function(selector, context, results, seed) { | |
3986 results = results || []; | |
3987 var origContext = context = context || document; | |
3988 | |
3989 if ( context.nodeType !== 1 && context.nodeType !== 9 ) { | |
3990 return []; | |
3991 } | |
3992 | |
3993 if ( !selector || typeof selector !== "string" ) { | |
3994 return results; | |
3995 } | |
3996 | |
3997 var parts = [], m, set, checkSet, check, mode, extra, prune = true, contextXML = isXML(context), | |
3998 soFar = selector; | |
3999 | |
4000 while ( (chunker.exec(""), m = chunker.exec(soFar)) !== null ) { | |
4001 soFar = m[3]; | |
4002 | |
4003 parts.push( m[1] ); | |
4004 | |
4005 if ( m[2] ) { | |
4006 extra = m[3]; | |
4007 break; | |
4008 } | |
4009 } | |
4010 | |
4011 if ( parts.length > 1 && origPOS.exec( selector ) ) { | |
4012 if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { | |
4013 set = posProcess( parts[0] + parts[1], context ); | |
4014 } else { | |
4015 set = Expr.relative[ parts[0] ] ? | |
4016 [ context ] : | |
4017 Sizzle( parts.shift(), context ); | |
4018 | |
4019 while ( parts.length ) { | |
4020 selector = parts.shift(); | |
4021 | |
4022 if ( Expr.relative[ selector ] ) | |
4023 selector += parts.shift(); | |
4024 | |
4025 set = posProcess( selector, set ); | |
4026 } | |
4027 } | |
4028 } else { | |
4029 if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && | |
4030 Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { | |
4031 var ret = Sizzle.find( parts.shift(), context, contextXML ); | |
4032 context = ret.expr ? Sizzle.filter( ret.expr, ret.set )[0] : ret.set[0]; | |
4033 } | |
4034 | |
4035 if ( context ) { | |
4036 var ret = seed ? | |
4037 { expr: parts.pop(), set: makeArray(seed) } : | |
4038 Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); | |
4039 set = ret.expr ? Sizzle.filter( ret.expr, ret.set ) : ret.set; | |
4040 | |
4041 if ( parts.length > 0 ) { | |
4042 checkSet = makeArray(set); | |
4043 } else { | |
4044 prune = false; | |
4045 } | |
4046 | |
4047 while ( parts.length ) { | |
4048 var cur = parts.pop(), pop = cur; | |
4049 | |
4050 if ( !Expr.relative[ cur ] ) { | |
4051 cur = ""; | |
4052 } else { | |
4053 pop = parts.pop(); | |
4054 } | |
4055 | |
4056 if ( pop == null ) { | |
4057 pop = context; | |
4058 } | |
4059 | |
4060 Expr.relative[ cur ]( checkSet, pop, contextXML ); | |
4061 } | |
4062 } else { | |
4063 checkSet = parts = []; | |
4064 } | |
4065 } | |
4066 | |
4067 if ( !checkSet ) { | |
4068 checkSet = set; | |
4069 } | |
4070 | |
4071 if ( !checkSet ) { | |
4072 throw "Syntax error, unrecognized expression: " + (cur || selector); | |
4073 } | |
4074 | |
4075 if ( toString.call(checkSet) === "[object Array]" ) { | |
4076 if ( !prune ) { | |
4077 results.push.apply( results, checkSet ); | |
4078 } else if ( context && context.nodeType === 1 ) { | |
4079 for ( var i = 0; checkSet[i] != null; i++ ) { | |
4080 if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) { | |
4081 results.push( set[i] ); | |
4082 } | |
4083 } | |
4084 } else { | |
4085 for ( var i = 0; checkSet[i] != null; i++ ) { | |
4086 if ( checkSet[i] && checkSet[i].nodeType === 1 ) { | |
4087 results.push( set[i] ); | |
4088 } | |
4089 } | |
4090 } | |
4091 } else { | |
4092 makeArray( checkSet, results ); | |
4093 } | |
4094 | |
4095 if ( extra ) { | |
4096 Sizzle( extra, origContext, results, seed ); | |
4097 Sizzle.uniqueSort( results ); | |
4098 } | |
4099 | |
4100 return results; | |
4101 }; | |
4102 | |
4103 Sizzle.uniqueSort = function(results){ | |
4104 if ( sortOrder ) { | |
4105 hasDuplicate = baseHasDuplicate; | |
4106 results.sort(sortOrder); | |
4107 | |
4108 if ( hasDuplicate ) { | |
4109 for ( var i = 1; i < results.length; i++ ) { | |
4110 if ( results[i] === results[i-1] ) { | |
4111 results.splice(i--, 1); | |
4112 } | |
4113 } | |
4114 } | |
4115 } | |
4116 | |
4117 return results; | |
4118 }; | |
4119 | |
4120 Sizzle.matches = function(expr, set){ | |
4121 return Sizzle(expr, null, null, set); | |
4122 }; | |
4123 | |
4124 Sizzle.find = function(expr, context, isXML){ | |
4125 var set, match; | |
4126 | |
4127 if ( !expr ) { | |
4128 return []; | |
4129 } | |
4130 | |
4131 for ( var i = 0, l = Expr.order.length; i < l; i++ ) { | |
4132 var type = Expr.order[i], match; | |
4133 | |
4134 if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { | |
4135 var left = match[1]; | |
4136 match.splice(1,1); | |
4137 | |
4138 if ( left.substr( left.length - 1 ) !== "\\" ) { | |
4139 match[1] = (match[1] || "").replace(/\\/g, ""); | |
4140 set = Expr.find[ type ]( match, context, isXML ); | |
4141 if ( set != null ) { | |
4142 expr = expr.replace( Expr.match[ type ], "" ); | |
2795 break; | 4143 break; |
2796 } | 4144 } |
2797 } | 4145 } |
2798 } | 4146 } |
2799 | 4147 } |
2800 this.matcher.push("return h.unique(n);\n}"); | 4148 |
2801 eval(this.matcher.join('\n')); | 4149 if ( !set ) { |
2802 Selector._cache[this.expression] = this.matcher; | 4150 set = context.getElementsByTagName("*"); |
2803 }, | 4151 } |
2804 | 4152 |
2805 compileXPathMatcher: function() { | 4153 return {set: set, expr: expr}; |
2806 var e = this.expression, ps = Selector.patterns, | 4154 }; |
2807 x = Selector.xpath, le, m; | 4155 |
2808 | 4156 Sizzle.filter = function(expr, set, inplace, not){ |
2809 if (Selector._cache[e]) { | 4157 var old = expr, result = [], curLoop = set, match, anyFound, |
2810 this.xpath = Selector._cache[e]; return; | 4158 isXMLFilter = set && set[0] && isXML(set[0]); |
2811 } | 4159 |
2812 | 4160 while ( expr && set.length ) { |
2813 this.matcher = ['.//*']; | 4161 for ( var type in Expr.filter ) { |
2814 while (e && le != e && (/\S/).test(e)) { | 4162 if ( (match = Expr.match[ type ].exec( expr )) != null ) { |
2815 le = e; | 4163 var filter = Expr.filter[ type ], found, item; |
2816 for (var i in ps) { | 4164 anyFound = false; |
2817 if (m = e.match(ps[i])) { | 4165 |
2818 this.matcher.push(Object.isFunction(x[i]) ? x[i](m) : | 4166 if ( curLoop == result ) { |
2819 new Template(x[i]).evaluate(m)); | 4167 result = []; |
2820 e = e.replace(m[0], ''); | |
2821 break; | |
2822 } | 4168 } |
2823 } | 4169 |
2824 } | 4170 if ( Expr.preFilter[ type ] ) { |
2825 | 4171 match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); |
2826 this.xpath = this.matcher.join(''); | 4172 |
2827 Selector._cache[this.expression] = this.xpath; | 4173 if ( !match ) { |
2828 }, | 4174 anyFound = found = true; |
2829 | 4175 } else if ( match === true ) { |
2830 findElements: function(root) { | 4176 continue; |
2831 root = root || document; | |
2832 var e = this.expression, results; | |
2833 | |
2834 switch (this.mode) { | |
2835 case 'selectorsAPI': | |
2836 // querySelectorAll queries document-wide, then filters to descendants | |
2837 // of the context element. That's not what we want. | |
2838 // Add an explicit context to the selector if necessary. | |
2839 if (root !== document) { | |
2840 var oldId = root.id, id = $(root).identify(); | |
2841 e = "#" + id + " " + e; | |
2842 } | |
2843 | |
2844 results = $A(root.querySelectorAll(e)).map(Element.extend); | |
2845 root.id = oldId; | |
2846 | |
2847 return results; | |
2848 case 'xpath': | |
2849 return document._getElementsByXPath(this.xpath, root); | |
2850 default: | |
2851 return this.matcher(root); | |
2852 } | |
2853 }, | |
2854 | |
2855 match: function(element) { | |
2856 this.tokens = []; | |
2857 | |
2858 var e = this.expression, ps = Selector.patterns, as = Selector.assertions; | |
2859 var le, p, m; | |
2860 | |
2861 while (e && le !== e && (/\S/).test(e)) { | |
2862 le = e; | |
2863 for (var i in ps) { | |
2864 p = ps[i]; | |
2865 if (m = e.match(p)) { | |
2866 // use the Selector.assertions methods unless the selector | |
2867 // is too complex. | |
2868 if (as[i]) { | |
2869 this.tokens.push([i, Object.clone(m)]); | |
2870 e = e.replace(m[0], ''); | |
2871 } else { | |
2872 // reluctantly do a document-wide search | |
2873 // and look for a match in the array | |
2874 return this.findElements(document).include(element); | |
2875 } | 4177 } |
2876 } | 4178 } |
2877 } | 4179 |
2878 } | 4180 if ( match ) { |
2879 | 4181 for ( var i = 0; (item = curLoop[i]) != null; i++ ) { |
2880 var match = true, name, matches; | 4182 if ( item ) { |
2881 for (var i = 0, token; token = this.tokens[i]; i++) { | 4183 found = filter( item, match, i, curLoop ); |
2882 name = token[0], matches = token[1]; | 4184 var pass = not ^ !!found; |
2883 if (!Selector.assertions[name](element, matches)) { | 4185 |
2884 match = false; break; | 4186 if ( inplace && found != null ) { |
2885 } | 4187 if ( pass ) { |
2886 } | 4188 anyFound = true; |
2887 | 4189 } else { |
2888 return match; | 4190 curLoop[i] = false; |
2889 }, | 4191 } |
2890 | 4192 } else if ( pass ) { |
2891 toString: function() { | 4193 result.push( item ); |
2892 return this.expression; | 4194 anyFound = true; |
2893 }, | 4195 } |
2894 | |
2895 inspect: function() { | |
2896 return "#<Selector:" + this.expression.inspect() + ">"; | |
2897 } | |
2898 }); | |
2899 | |
2900 Object.extend(Selector, { | |
2901 _cache: { }, | |
2902 | |
2903 xpath: { | |
2904 descendant: "//*", | |
2905 child: "/*", | |
2906 adjacent: "/following-sibling::*[1]", | |
2907 laterSibling: '/following-sibling::*', | |
2908 tagName: function(m) { | |
2909 if (m[1] == '*') return ''; | |
2910 return "[local-name()='" + m[1].toLowerCase() + | |
2911 "' or local-name()='" + m[1].toUpperCase() + "']"; | |
2912 }, | |
2913 className: "[contains(concat(' ', @class, ' '), ' #{1} ')]", | |
2914 id: "[@id='#{1}']", | |
2915 attrPresence: function(m) { | |
2916 m[1] = m[1].toLowerCase(); | |
2917 return new Template("[@#{1}]").evaluate(m); | |
2918 }, | |
2919 attr: function(m) { | |
2920 m[1] = m[1].toLowerCase(); | |
2921 m[3] = m[5] || m[6]; | |
2922 return new Template(Selector.xpath.operators[m[2]]).evaluate(m); | |
2923 }, | |
2924 pseudo: function(m) { | |
2925 var h = Selector.xpath.pseudos[m[1]]; | |
2926 if (!h) return ''; | |
2927 if (Object.isFunction(h)) return h(m); | |
2928 return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m); | |
2929 }, | |
2930 operators: { | |
2931 '=': "[@#{1}='#{3}']", | |
2932 '!=': "[@#{1}!='#{3}']", | |
2933 '^=': "[starts-with(@#{1}, '#{3}')]", | |
2934 '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']", | |
2935 '*=': "[contains(@#{1}, '#{3}')]", | |
2936 '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]", | |
2937 '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]" | |
2938 }, | |
2939 pseudos: { | |
2940 'first-child': '[not(preceding-sibling::*)]', | |
2941 'last-child': '[not(following-sibling::*)]', | |
2942 'only-child': '[not(preceding-sibling::* or following-sibling::*)]', | |
2943 'empty': "[count(*) = 0 and (count(text()) = 0)]", | |
2944 'checked': "[@checked]", | |
2945 'disabled': "[(@disabled) and (@type!='hidden')]", | |
2946 'enabled': "[not(@disabled) and (@type!='hidden')]", | |
2947 'not': function(m) { | |
2948 var e = m[6], p = Selector.patterns, | |
2949 x = Selector.xpath, le, v; | |
2950 | |
2951 var exclusion = []; | |
2952 while (e && le != e && (/\S/).test(e)) { | |
2953 le = e; | |
2954 for (var i in p) { | |
2955 if (m = e.match(p[i])) { | |
2956 v = Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m); | |
2957 exclusion.push("(" + v.substring(1, v.length - 1) + ")"); | |
2958 e = e.replace(m[0], ''); | |
2959 break; | |
2960 } | 4196 } |
2961 } | 4197 } |
2962 } | 4198 } |
2963 return "[not(" + exclusion.join(" and ") + ")]"; | 4199 |
2964 }, | 4200 if ( found !== undefined ) { |
2965 'nth-child': function(m) { | 4201 if ( !inplace ) { |
2966 return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m); | 4202 curLoop = result; |
2967 }, | 4203 } |
2968 'nth-last-child': function(m) { | 4204 |
2969 return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m); | 4205 expr = expr.replace( Expr.match[ type ], "" ); |
2970 }, | 4206 |
2971 'nth-of-type': function(m) { | 4207 if ( !anyFound ) { |
2972 return Selector.xpath.pseudos.nth("position() ", m); | 4208 return []; |
2973 }, | 4209 } |
2974 'nth-last-of-type': function(m) { | 4210 |
2975 return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m); | 4211 break; |
2976 }, | |
2977 'first-of-type': function(m) { | |
2978 m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m); | |
2979 }, | |
2980 'last-of-type': function(m) { | |
2981 m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m); | |
2982 }, | |
2983 'only-of-type': function(m) { | |
2984 var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m); | |
2985 }, | |
2986 nth: function(fragment, m) { | |
2987 var mm, formula = m[6], predicate; | |
2988 if (formula == 'even') formula = '2n+0'; | |
2989 if (formula == 'odd') formula = '2n+1'; | |
2990 if (mm = formula.match(/^(\d+)$/)) // digit only | |
2991 return '[' + fragment + "= " + mm[1] + ']'; | |
2992 if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b | |
2993 if (mm[1] == "-") mm[1] = -1; | |
2994 var a = mm[1] ? Number(mm[1]) : 1; | |
2995 var b = mm[2] ? Number(mm[2]) : 0; | |
2996 predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " + | |
2997 "((#{fragment} - #{b}) div #{a} >= 0)]"; | |
2998 return new Template(predicate).evaluate({ | |
2999 fragment: fragment, a: a, b: b }); | |
3000 } | 4212 } |
3001 } | 4213 } |
3002 } | 4214 } |
3003 }, | 4215 |
3004 | 4216 if ( expr == old ) { |
3005 criteria: { | 4217 if ( anyFound == null ) { |
3006 tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;', | 4218 throw "Syntax error, unrecognized expression: " + expr; |
3007 className: 'n = h.className(n, r, "#{1}", c); c = false;', | 4219 } else { |
3008 id: 'n = h.id(n, r, "#{1}", c); c = false;', | 4220 break; |
3009 attrPresence: 'n = h.attrPresence(n, r, "#{1}", c); c = false;', | 4221 } |
3010 attr: function(m) { | 4222 } |
3011 m[3] = (m[5] || m[6]); | 4223 |
3012 return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); c = false;').evaluate(m); | 4224 old = expr; |
3013 }, | 4225 } |
3014 pseudo: function(m) { | 4226 |
3015 if (m[6]) m[6] = m[6].replace(/"/g, '\\"'); | 4227 return curLoop; |
3016 return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m); | 4228 }; |
3017 }, | 4229 |
3018 descendant: 'c = "descendant";', | 4230 var Expr = Sizzle.selectors = { |
3019 child: 'c = "child";', | 4231 order: [ "ID", "NAME", "TAG" ], |
3020 adjacent: 'c = "adjacent";', | 4232 match: { |
3021 laterSibling: 'c = "laterSibling";' | 4233 ID: /#((?:[\w\u00c0-\uFFFF-]|\\.)+)/, |
3022 }, | 4234 CLASS: /\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/, |
3023 | 4235 NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/, |
3024 patterns: { | 4236 ATTR: /\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/, |
3025 // combinators must be listed first | 4237 TAG: /^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/, |
3026 // (and descendant needs to be last combinator) | 4238 CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/, |
3027 laterSibling: /^\s*~\s*/, | 4239 POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/, |
3028 child: /^\s*>\s*/, | 4240 PSEUDO: /:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/ |
3029 adjacent: /^\s*\+\s*/, | 4241 }, |
3030 descendant: /^\s/, | 4242 leftMatch: {}, |
3031 | 4243 attrMap: { |
3032 // selectors follow | 4244 "class": "className", |
3033 tagName: /^\s*(\*|[\w\-]+)(\b|$)?/, | 4245 "for": "htmlFor" |
3034 id: /^#([\w\-\*]+)(\b|$)/, | 4246 }, |
3035 className: /^\.([\w\-\*]+)(\b|$)/, | 4247 attrHandle: { |
3036 pseudo: | 4248 href: function(elem){ |
3037 /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/, | 4249 return elem.getAttribute("href"); |
3038 attrPresence: /^\[((?:[\w]+:)?[\w]+)\]/, | 4250 } |
3039 attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/ | 4251 }, |
3040 }, | 4252 relative: { |
3041 | 4253 "+": function(checkSet, part, isXML){ |
3042 // for Selector.match and Element#match | 4254 var isPartStr = typeof part === "string", |
3043 assertions: { | 4255 isTag = isPartStr && !/\W/.test(part), |
3044 tagName: function(element, matches) { | 4256 isPartStrNotTag = isPartStr && !isTag; |
3045 return matches[1].toUpperCase() == element.tagName.toUpperCase(); | 4257 |
3046 }, | 4258 if ( isTag && !isXML ) { |
3047 | 4259 part = part.toUpperCase(); |
3048 className: function(element, matches) { | 4260 } |
3049 return Element.hasClassName(element, matches[1]); | 4261 |
3050 }, | 4262 for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { |
3051 | 4263 if ( (elem = checkSet[i]) ) { |
3052 id: function(element, matches) { | 4264 while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} |
3053 return element.id === matches[1]; | 4265 |
3054 }, | 4266 checkSet[i] = isPartStrNotTag || elem && elem.nodeName === part ? |
3055 | 4267 elem || false : |
3056 attrPresence: function(element, matches) { | 4268 elem === part; |
3057 return Element.hasAttribute(element, matches[1]); | 4269 } |
3058 }, | 4270 } |
3059 | 4271 |
3060 attr: function(element, matches) { | 4272 if ( isPartStrNotTag ) { |
3061 var nodeValue = Element.readAttribute(element, matches[1]); | 4273 Sizzle.filter( part, checkSet, true ); |
3062 return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]); | 4274 } |
3063 } | 4275 }, |
3064 }, | 4276 ">": function(checkSet, part, isXML){ |
3065 | 4277 var isPartStr = typeof part === "string"; |
3066 handlers: { | 4278 |
3067 // UTILITY FUNCTIONS | 4279 if ( isPartStr && !/\W/.test(part) ) { |
3068 // joins two collections | 4280 part = isXML ? part : part.toUpperCase(); |
3069 concat: function(a, b) { | 4281 |
3070 for (var i = 0, node; node = b[i]; i++) | 4282 for ( var i = 0, l = checkSet.length; i < l; i++ ) { |
3071 a.push(node); | 4283 var elem = checkSet[i]; |
3072 return a; | 4284 if ( elem ) { |
3073 }, | 4285 var parent = elem.parentNode; |
3074 | 4286 checkSet[i] = parent.nodeName === part ? parent : false; |
3075 // marks an array of nodes for counting | 4287 } |
3076 mark: function(nodes) { | |
3077 var _true = Prototype.emptyFunction; | |
3078 for (var i = 0, node; node = nodes[i]; i++) | |
3079 node._countedByPrototype = _true; | |
3080 return nodes; | |
3081 }, | |
3082 | |
3083 unmark: function(nodes) { | |
3084 for (var i = 0, node; node = nodes[i]; i++) | |
3085 node._countedByPrototype = undefined; | |
3086 return nodes; | |
3087 }, | |
3088 | |
3089 // mark each child node with its position (for nth calls) | |
3090 // "ofType" flag indicates whether we're indexing for nth-of-type | |
3091 // rather than nth-child | |
3092 index: function(parentNode, reverse, ofType) { | |
3093 parentNode._countedByPrototype = Prototype.emptyFunction; | |
3094 if (reverse) { | |
3095 for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) { | |
3096 var node = nodes[i]; | |
3097 if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++; | |
3098 } | 4288 } |
3099 } else { | 4289 } else { |
3100 for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++) | 4290 for ( var i = 0, l = checkSet.length; i < l; i++ ) { |
3101 if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++; | 4291 var elem = checkSet[i]; |
3102 } | 4292 if ( elem ) { |
3103 }, | 4293 checkSet[i] = isPartStr ? |
3104 | 4294 elem.parentNode : |
3105 // filters out duplicates and extends all nodes | 4295 elem.parentNode === part; |
3106 unique: function(nodes) { | 4296 } |
3107 if (nodes.length == 0) return nodes; | |
3108 var results = [], n; | |
3109 for (var i = 0, l = nodes.length; i < l; i++) | |
3110 if (!(n = nodes[i])._countedByPrototype) { | |
3111 n._countedByPrototype = Prototype.emptyFunction; | |
3112 results.push(Element.extend(n)); | |
3113 } | 4297 } |
3114 return Selector.handlers.unmark(results); | 4298 |
3115 }, | 4299 if ( isPartStr ) { |
3116 | 4300 Sizzle.filter( part, checkSet, true ); |
3117 // COMBINATOR FUNCTIONS | 4301 } |
3118 descendant: function(nodes) { | 4302 } |
3119 var h = Selector.handlers; | 4303 }, |
3120 for (var i = 0, results = [], node; node = nodes[i]; i++) | 4304 "": function(checkSet, part, isXML){ |
3121 h.concat(results, node.getElementsByTagName('*')); | 4305 var doneName = done++, checkFn = dirCheck; |
4306 | |
4307 if ( !/\W/.test(part) ) { | |
4308 var nodeCheck = part = isXML ? part : part.toUpperCase(); | |
4309 checkFn = dirNodeCheck; | |
4310 } | |
4311 | |
4312 checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML); | |
4313 }, | |
4314 "~": function(checkSet, part, isXML){ | |
4315 var doneName = done++, checkFn = dirCheck; | |
4316 | |
4317 if ( typeof part === "string" && !/\W/.test(part) ) { | |
4318 var nodeCheck = part = isXML ? part : part.toUpperCase(); | |
4319 checkFn = dirNodeCheck; | |
4320 } | |
4321 | |
4322 checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML); | |
4323 } | |
4324 }, | |
4325 find: { | |
4326 ID: function(match, context, isXML){ | |
4327 if ( typeof context.getElementById !== "undefined" && !isXML ) { | |
4328 var m = context.getElementById(match[1]); | |
4329 return m ? [m] : []; | |
4330 } | |
4331 }, | |
4332 NAME: function(match, context, isXML){ | |
4333 if ( typeof context.getElementsByName !== "undefined" ) { | |
4334 var ret = [], results = context.getElementsByName(match[1]); | |
4335 | |
4336 for ( var i = 0, l = results.length; i < l; i++ ) { | |
4337 if ( results[i].getAttribute("name") === match[1] ) { | |
4338 ret.push( results[i] ); | |
4339 } | |
4340 } | |
4341 | |
4342 return ret.length === 0 ? null : ret; | |
4343 } | |
4344 }, | |
4345 TAG: function(match, context){ | |
4346 return context.getElementsByTagName(match[1]); | |
4347 } | |
4348 }, | |
4349 preFilter: { | |
4350 CLASS: function(match, curLoop, inplace, result, not, isXML){ | |
4351 match = " " + match[1].replace(/\\/g, "") + " "; | |
4352 | |
4353 if ( isXML ) { | |
4354 return match; | |
4355 } | |
4356 | |
4357 for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { | |
4358 if ( elem ) { | |
4359 if ( not ^ (elem.className && (" " + elem.className + " ").indexOf(match) >= 0) ) { | |
4360 if ( !inplace ) | |
4361 result.push( elem ); | |
4362 } else if ( inplace ) { | |
4363 curLoop[i] = false; | |
4364 } | |
4365 } | |
4366 } | |
4367 | |
4368 return false; | |
4369 }, | |
4370 ID: function(match){ | |
4371 return match[1].replace(/\\/g, ""); | |
4372 }, | |
4373 TAG: function(match, curLoop){ | |
4374 for ( var i = 0; curLoop[i] === false; i++ ){} | |
4375 return curLoop[i] && isXML(curLoop[i]) ? match[1] : match[1].toUpperCase(); | |
4376 }, | |
4377 CHILD: function(match){ | |
4378 if ( match[1] == "nth" ) { | |
4379 var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec( | |
4380 match[2] == "even" && "2n" || match[2] == "odd" && "2n+1" || | |
4381 !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); | |
4382 | |
4383 match[2] = (test[1] + (test[2] || 1)) - 0; | |
4384 match[3] = test[3] - 0; | |
4385 } | |
4386 | |
4387 match[0] = done++; | |
4388 | |
4389 return match; | |
4390 }, | |
4391 ATTR: function(match, curLoop, inplace, result, not, isXML){ | |
4392 var name = match[1].replace(/\\/g, ""); | |
4393 | |
4394 if ( !isXML && Expr.attrMap[name] ) { | |
4395 match[1] = Expr.attrMap[name]; | |
4396 } | |
4397 | |
4398 if ( match[2] === "~=" ) { | |
4399 match[4] = " " + match[4] + " "; | |
4400 } | |
4401 | |
4402 return match; | |
4403 }, | |
4404 PSEUDO: function(match, curLoop, inplace, result, not){ | |
4405 if ( match[1] === "not" ) { | |
4406 if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { | |
4407 match[3] = Sizzle(match[3], null, null, curLoop); | |
4408 } else { | |
4409 var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); | |
4410 if ( !inplace ) { | |
4411 result.push.apply( result, ret ); | |
4412 } | |
4413 return false; | |
4414 } | |
4415 } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { | |
4416 return true; | |
4417 } | |
4418 | |
4419 return match; | |
4420 }, | |
4421 POS: function(match){ | |
4422 match.unshift( true ); | |
4423 return match; | |
4424 } | |
4425 }, | |
4426 filters: { | |
4427 enabled: function(elem){ | |
4428 return elem.disabled === false && elem.type !== "hidden"; | |
4429 }, | |
4430 disabled: function(elem){ | |
4431 return elem.disabled === true; | |
4432 }, | |
4433 checked: function(elem){ | |
4434 return elem.checked === true; | |
4435 }, | |
4436 selected: function(elem){ | |
4437 elem.parentNode.selectedIndex; | |
4438 return elem.selected === true; | |
4439 }, | |
4440 parent: function(elem){ | |
4441 return !!elem.firstChild; | |
4442 }, | |
4443 empty: function(elem){ | |
4444 return !elem.firstChild; | |
4445 }, | |
4446 has: function(elem, i, match){ | |
4447 return !!Sizzle( match[3], elem ).length; | |
4448 }, | |
4449 header: function(elem){ | |
4450 return /h\d/i.test( elem.nodeName ); | |
4451 }, | |
4452 text: function(elem){ | |
4453 return "text" === elem.type; | |
4454 }, | |
4455 radio: function(elem){ | |
4456 return "radio" === elem.type; | |
4457 }, | |
4458 checkbox: function(elem){ | |
4459 return "checkbox" === elem.type; | |
4460 }, | |
4461 file: function(elem){ | |
4462 return "file" === elem.type; | |
4463 }, | |
4464 password: function(elem){ | |
4465 return "password" === elem.type; | |
4466 }, | |
4467 submit: function(elem){ | |
4468 return "submit" === elem.type; | |
4469 }, | |
4470 image: function(elem){ | |
4471 return "image" === elem.type; | |
4472 }, | |
4473 reset: function(elem){ | |
4474 return "reset" === elem.type; | |
4475 }, | |
4476 button: function(elem){ | |
4477 return "button" === elem.type || elem.nodeName.toUpperCase() === "BUTTON"; | |
4478 }, | |
4479 input: function(elem){ | |
4480 return /input|select|textarea|button/i.test(elem.nodeName); | |
4481 } | |
4482 }, | |
4483 setFilters: { | |
4484 first: function(elem, i){ | |
4485 return i === 0; | |
4486 }, | |
4487 last: function(elem, i, match, array){ | |
4488 return i === array.length - 1; | |
4489 }, | |
4490 even: function(elem, i){ | |
4491 return i % 2 === 0; | |
4492 }, | |
4493 odd: function(elem, i){ | |
4494 return i % 2 === 1; | |
4495 }, | |
4496 lt: function(elem, i, match){ | |
4497 return i < match[3] - 0; | |
4498 }, | |
4499 gt: function(elem, i, match){ | |
4500 return i > match[3] - 0; | |
4501 }, | |
4502 nth: function(elem, i, match){ | |
4503 return match[3] - 0 == i; | |
4504 }, | |
4505 eq: function(elem, i, match){ | |
4506 return match[3] - 0 == i; | |
4507 } | |
4508 }, | |
4509 filter: { | |
4510 PSEUDO: function(elem, match, i, array){ | |
4511 var name = match[1], filter = Expr.filters[ name ]; | |
4512 | |
4513 if ( filter ) { | |
4514 return filter( elem, i, match, array ); | |
4515 } else if ( name === "contains" ) { | |
4516 return (elem.textContent || elem.innerText || "").indexOf(match[3]) >= 0; | |
4517 } else if ( name === "not" ) { | |
4518 var not = match[3]; | |
4519 | |
4520 for ( var i = 0, l = not.length; i < l; i++ ) { | |
4521 if ( not[i] === elem ) { | |
4522 return false; | |
4523 } | |
4524 } | |
4525 | |
4526 return true; | |
4527 } | |
4528 }, | |
4529 CHILD: function(elem, match){ | |
4530 var type = match[1], node = elem; | |
4531 switch (type) { | |
4532 case 'only': | |
4533 case 'first': | |
4534 while ( (node = node.previousSibling) ) { | |
4535 if ( node.nodeType === 1 ) return false; | |
4536 } | |
4537 if ( type == 'first') return true; | |
4538 node = elem; | |
4539 case 'last': | |
4540 while ( (node = node.nextSibling) ) { | |
4541 if ( node.nodeType === 1 ) return false; | |
4542 } | |
4543 return true; | |
4544 case 'nth': | |
4545 var first = match[2], last = match[3]; | |
4546 | |
4547 if ( first == 1 && last == 0 ) { | |
4548 return true; | |
4549 } | |
4550 | |
4551 var doneName = match[0], | |
4552 parent = elem.parentNode; | |
4553 | |
4554 if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) { | |
4555 var count = 0; | |
4556 for ( node = parent.firstChild; node; node = node.nextSibling ) { | |
4557 if ( node.nodeType === 1 ) { | |
4558 node.nodeIndex = ++count; | |
4559 } | |
4560 } | |
4561 parent.sizcache = doneName; | |
4562 } | |
4563 | |
4564 var diff = elem.nodeIndex - last; | |
4565 if ( first == 0 ) { | |
4566 return diff == 0; | |
4567 } else { | |
4568 return ( diff % first == 0 && diff / first >= 0 ); | |
4569 } | |
4570 } | |
4571 }, | |
4572 ID: function(elem, match){ | |
4573 return elem.nodeType === 1 && elem.getAttribute("id") === match; | |
4574 }, | |
4575 TAG: function(elem, match){ | |
4576 return (match === "*" && elem.nodeType === 1) || elem.nodeName === match; | |
4577 }, | |
4578 CLASS: function(elem, match){ | |
4579 return (" " + (elem.className || elem.getAttribute("class")) + " ") | |
4580 .indexOf( match ) > -1; | |
4581 }, | |
4582 ATTR: function(elem, match){ | |
4583 var name = match[1], | |
4584 result = Expr.attrHandle[ name ] ? | |
4585 Expr.attrHandle[ name ]( elem ) : | |
4586 elem[ name ] != null ? | |
4587 elem[ name ] : | |
4588 elem.getAttribute( name ), | |
4589 value = result + "", | |
4590 type = match[2], | |
4591 check = match[4]; | |
4592 | |
4593 return result == null ? | |
4594 type === "!=" : | |
4595 type === "=" ? | |
4596 value === check : | |
4597 type === "*=" ? | |
4598 value.indexOf(check) >= 0 : | |
4599 type === "~=" ? | |
4600 (" " + value + " ").indexOf(check) >= 0 : | |
4601 !check ? | |
4602 value && result !== false : | |
4603 type === "!=" ? | |
4604 value != check : | |
4605 type === "^=" ? | |
4606 value.indexOf(check) === 0 : | |
4607 type === "$=" ? | |
4608 value.substr(value.length - check.length) === check : | |
4609 type === "|=" ? | |
4610 value === check || value.substr(0, check.length + 1) === check + "-" : | |
4611 false; | |
4612 }, | |
4613 POS: function(elem, match, i, array){ | |
4614 var name = match[2], filter = Expr.setFilters[ name ]; | |
4615 | |
4616 if ( filter ) { | |
4617 return filter( elem, i, match, array ); | |
4618 } | |
4619 } | |
4620 } | |
4621 }; | |
4622 | |
4623 var origPOS = Expr.match.POS; | |
4624 | |
4625 for ( var type in Expr.match ) { | |
4626 Expr.match[ type ] = new RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source ); | |
4627 Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source ); | |
4628 } | |
4629 | |
4630 var makeArray = function(array, results) { | |
4631 array = Array.prototype.slice.call( array, 0 ); | |
4632 | |
4633 if ( results ) { | |
4634 results.push.apply( results, array ); | |
4635 return results; | |
4636 } | |
4637 | |
4638 return array; | |
4639 }; | |
4640 | |
4641 try { | |
4642 Array.prototype.slice.call( document.documentElement.childNodes, 0 ); | |
4643 | |
4644 } catch(e){ | |
4645 makeArray = function(array, results) { | |
4646 var ret = results || []; | |
4647 | |
4648 if ( toString.call(array) === "[object Array]" ) { | |
4649 Array.prototype.push.apply( ret, array ); | |
4650 } else { | |
4651 if ( typeof array.length === "number" ) { | |
4652 for ( var i = 0, l = array.length; i < l; i++ ) { | |
4653 ret.push( array[i] ); | |
4654 } | |
4655 } else { | |
4656 for ( var i = 0; array[i]; i++ ) { | |
4657 ret.push( array[i] ); | |
4658 } | |
4659 } | |
4660 } | |
4661 | |
4662 return ret; | |
4663 }; | |
4664 } | |
4665 | |
4666 var sortOrder; | |
4667 | |
4668 if ( document.documentElement.compareDocumentPosition ) { | |
4669 sortOrder = function( a, b ) { | |
4670 if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { | |
4671 if ( a == b ) { | |
4672 hasDuplicate = true; | |
4673 } | |
4674 return 0; | |
4675 } | |
4676 | |
4677 var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1; | |
4678 if ( ret === 0 ) { | |
4679 hasDuplicate = true; | |
4680 } | |
4681 return ret; | |
4682 }; | |
4683 } else if ( "sourceIndex" in document.documentElement ) { | |
4684 sortOrder = function( a, b ) { | |
4685 if ( !a.sourceIndex || !b.sourceIndex ) { | |
4686 if ( a == b ) { | |
4687 hasDuplicate = true; | |
4688 } | |
4689 return 0; | |
4690 } | |
4691 | |
4692 var ret = a.sourceIndex - b.sourceIndex; | |
4693 if ( ret === 0 ) { | |
4694 hasDuplicate = true; | |
4695 } | |
4696 return ret; | |
4697 }; | |
4698 } else if ( document.createRange ) { | |
4699 sortOrder = function( a, b ) { | |
4700 if ( !a.ownerDocument || !b.ownerDocument ) { | |
4701 if ( a == b ) { | |
4702 hasDuplicate = true; | |
4703 } | |
4704 return 0; | |
4705 } | |
4706 | |
4707 var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange(); | |
4708 aRange.setStart(a, 0); | |
4709 aRange.setEnd(a, 0); | |
4710 bRange.setStart(b, 0); | |
4711 bRange.setEnd(b, 0); | |
4712 var ret = aRange.compareBoundaryPoints(Range.START_TO_END, bRange); | |
4713 if ( ret === 0 ) { | |
4714 hasDuplicate = true; | |
4715 } | |
4716 return ret; | |
4717 }; | |
4718 } | |
4719 | |
4720 (function(){ | |
4721 var form = document.createElement("div"), | |
4722 id = "script" + (new Date).getTime(); | |
4723 form.innerHTML = "<a name='" + id + "'/>"; | |
4724 | |
4725 var root = document.documentElement; | |
4726 root.insertBefore( form, root.firstChild ); | |
4727 | |
4728 if ( !!document.getElementById( id ) ) { | |
4729 Expr.find.ID = function(match, context, isXML){ | |
4730 if ( typeof context.getElementById !== "undefined" && !isXML ) { | |
4731 var m = context.getElementById(match[1]); | |
4732 return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : []; | |
4733 } | |
4734 }; | |
4735 | |
4736 Expr.filter.ID = function(elem, match){ | |
4737 var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); | |
4738 return elem.nodeType === 1 && node && node.nodeValue === match; | |
4739 }; | |
4740 } | |
4741 | |
4742 root.removeChild( form ); | |
4743 root = form = null; // release memory in IE | |
4744 })(); | |
4745 | |
4746 (function(){ | |
4747 | |
4748 var div = document.createElement("div"); | |
4749 div.appendChild( document.createComment("") ); | |
4750 | |
4751 if ( div.getElementsByTagName("*").length > 0 ) { | |
4752 Expr.find.TAG = function(match, context){ | |
4753 var results = context.getElementsByTagName(match[1]); | |
4754 | |
4755 if ( match[1] === "*" ) { | |
4756 var tmp = []; | |
4757 | |
4758 for ( var i = 0; results[i]; i++ ) { | |
4759 if ( results[i].nodeType === 1 ) { | |
4760 tmp.push( results[i] ); | |
4761 } | |
4762 } | |
4763 | |
4764 results = tmp; | |
4765 } | |
4766 | |
3122 return results; | 4767 return results; |
3123 }, | 4768 }; |
3124 | 4769 } |
3125 child: function(nodes) { | 4770 |
3126 var h = Selector.handlers; | 4771 div.innerHTML = "<a href='#'></a>"; |
3127 for (var i = 0, results = [], node; node = nodes[i]; i++) { | 4772 if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && |
3128 for (var j = 0, child; child = node.childNodes[j]; j++) | 4773 div.firstChild.getAttribute("href") !== "#" ) { |
3129 if (child.nodeType == 1 && child.tagName != '!') results.push(child); | 4774 Expr.attrHandle.href = function(elem){ |
3130 } | 4775 return elem.getAttribute("href", 2); |
3131 return results; | 4776 }; |
3132 }, | 4777 } |
3133 | 4778 |
3134 adjacent: function(nodes) { | 4779 div = null; // release memory in IE |
3135 for (var i = 0, results = [], node; node = nodes[i]; i++) { | 4780 })(); |
3136 var next = this.nextElementSibling(node); | 4781 |
3137 if (next) results.push(next); | 4782 if ( document.querySelectorAll ) (function(){ |
3138 } | 4783 var oldSizzle = Sizzle, div = document.createElement("div"); |
3139 return results; | 4784 div.innerHTML = "<p class='TEST'></p>"; |
3140 }, | 4785 |
3141 | 4786 if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { |
3142 laterSibling: function(nodes) { | 4787 return; |
3143 var h = Selector.handlers; | 4788 } |
3144 for (var i = 0, results = [], node; node = nodes[i]; i++) | 4789 |
3145 h.concat(results, Element.nextSiblings(node)); | 4790 Sizzle = function(query, context, extra, seed){ |
3146 return results; | 4791 context = context || document; |
3147 }, | 4792 |
3148 | 4793 if ( !seed && context.nodeType === 9 && !isXML(context) ) { |
3149 nextElementSibling: function(node) { | 4794 try { |
3150 while (node = node.nextSibling) | 4795 return makeArray( context.querySelectorAll(query), extra ); |
3151 if (node.nodeType == 1) return node; | 4796 } catch(e){} |
3152 return null; | 4797 } |
3153 }, | 4798 |
3154 | 4799 return oldSizzle(query, context, extra, seed); |
3155 previousElementSibling: function(node) { | 4800 }; |
3156 while (node = node.previousSibling) | 4801 |
3157 if (node.nodeType == 1) return node; | 4802 for ( var prop in oldSizzle ) { |
3158 return null; | 4803 Sizzle[ prop ] = oldSizzle[ prop ]; |
3159 }, | 4804 } |
3160 | 4805 |
3161 // TOKEN FUNCTIONS | 4806 div = null; // release memory in IE |
3162 tagName: function(nodes, root, tagName, combinator) { | 4807 })(); |
3163 var uTagName = tagName.toUpperCase(); | 4808 |
3164 var results = [], h = Selector.handlers; | 4809 if ( document.getElementsByClassName && document.documentElement.getElementsByClassName ) (function(){ |
3165 if (nodes) { | 4810 var div = document.createElement("div"); |
3166 if (combinator) { | 4811 div.innerHTML = "<div class='test e'></div><div class='test'></div>"; |
3167 // fastlane for ordinary descendant combinators | 4812 |
3168 if (combinator == "descendant") { | 4813 if ( div.getElementsByClassName("e").length === 0 ) |
3169 for (var i = 0, node; node = nodes[i]; i++) | 4814 return; |
3170 h.concat(results, node.getElementsByTagName(tagName)); | 4815 |
3171 return results; | 4816 div.lastChild.className = "e"; |
3172 } else nodes = this[combinator](nodes); | 4817 |
3173 if (tagName == "*") return nodes; | 4818 if ( div.getElementsByClassName("e").length === 1 ) |
4819 return; | |
4820 | |
4821 Expr.order.splice(1, 0, "CLASS"); | |
4822 Expr.find.CLASS = function(match, context, isXML) { | |
4823 if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { | |
4824 return context.getElementsByClassName(match[1]); | |
4825 } | |
4826 }; | |
4827 | |
4828 div = null; // release memory in IE | |
4829 })(); | |
4830 | |
4831 function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { | |
4832 var sibDir = dir == "previousSibling" && !isXML; | |
4833 for ( var i = 0, l = checkSet.length; i < l; i++ ) { | |
4834 var elem = checkSet[i]; | |
4835 if ( elem ) { | |
4836 if ( sibDir && elem.nodeType === 1 ){ | |
4837 elem.sizcache = doneName; | |
4838 elem.sizset = i; | |
4839 } | |
4840 elem = elem[dir]; | |
4841 var match = false; | |
4842 | |
4843 while ( elem ) { | |
4844 if ( elem.sizcache === doneName ) { | |
4845 match = checkSet[elem.sizset]; | |
4846 break; | |
3174 } | 4847 } |
3175 for (var i = 0, node; node = nodes[i]; i++) | 4848 |
3176 if (node.tagName.toUpperCase() === uTagName) results.push(node); | 4849 if ( elem.nodeType === 1 && !isXML ){ |
3177 return results; | 4850 elem.sizcache = doneName; |
3178 } else return root.getElementsByTagName(tagName); | 4851 elem.sizset = i; |
3179 }, | |
3180 | |
3181 id: function(nodes, root, id, combinator) { | |
3182 var targetNode = $(id), h = Selector.handlers; | |
3183 if (!targetNode) return []; | |
3184 if (!nodes && root == document) return [targetNode]; | |
3185 if (nodes) { | |
3186 if (combinator) { | |
3187 if (combinator == 'child') { | |
3188 for (var i = 0, node; node = nodes[i]; i++) | |
3189 if (targetNode.parentNode == node) return [targetNode]; | |
3190 } else if (combinator == 'descendant') { | |
3191 for (var i = 0, node; node = nodes[i]; i++) | |
3192 if (Element.descendantOf(targetNode, node)) return [targetNode]; | |
3193 } else if (combinator == 'adjacent') { | |
3194 for (var i = 0, node; node = nodes[i]; i++) | |
3195 if (Selector.handlers.previousElementSibling(targetNode) == node) | |
3196 return [targetNode]; | |
3197 } else nodes = h[combinator](nodes); | |
3198 } | 4852 } |
3199 for (var i = 0, node; node = nodes[i]; i++) | 4853 |
3200 if (node == targetNode) return [targetNode]; | 4854 if ( elem.nodeName === cur ) { |
3201 return []; | 4855 match = elem; |
3202 } | 4856 break; |
3203 return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : []; | |
3204 }, | |
3205 | |
3206 className: function(nodes, root, className, combinator) { | |
3207 if (nodes && combinator) nodes = this[combinator](nodes); | |
3208 return Selector.handlers.byClassName(nodes, root, className); | |
3209 }, | |
3210 | |
3211 byClassName: function(nodes, root, className) { | |
3212 if (!nodes) nodes = Selector.handlers.descendant([root]); | |
3213 var needle = ' ' + className + ' '; | |
3214 for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) { | |
3215 nodeClassName = node.className; | |
3216 if (nodeClassName.length == 0) continue; | |
3217 if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle)) | |
3218 results.push(node); | |
3219 } | |
3220 return results; | |
3221 }, | |
3222 | |
3223 attrPresence: function(nodes, root, attr, combinator) { | |
3224 if (!nodes) nodes = root.getElementsByTagName("*"); | |
3225 if (nodes && combinator) nodes = this[combinator](nodes); | |
3226 var results = []; | |
3227 for (var i = 0, node; node = nodes[i]; i++) | |
3228 if (Element.hasAttribute(node, attr)) results.push(node); | |
3229 return results; | |
3230 }, | |
3231 | |
3232 attr: function(nodes, root, attr, value, operator, combinator) { | |
3233 if (!nodes) nodes = root.getElementsByTagName("*"); | |
3234 if (nodes && combinator) nodes = this[combinator](nodes); | |
3235 var handler = Selector.operators[operator], results = []; | |
3236 for (var i = 0, node; node = nodes[i]; i++) { | |
3237 var nodeValue = Element.readAttribute(node, attr); | |
3238 if (nodeValue === null) continue; | |
3239 if (handler(nodeValue, value)) results.push(node); | |
3240 } | |
3241 return results; | |
3242 }, | |
3243 | |
3244 pseudo: function(nodes, name, value, root, combinator) { | |
3245 if (nodes && combinator) nodes = this[combinator](nodes); | |
3246 if (!nodes) nodes = root.getElementsByTagName("*"); | |
3247 return Selector.pseudos[name](nodes, value, root); | |
3248 } | |
3249 }, | |
3250 | |
3251 pseudos: { | |
3252 'first-child': function(nodes, value, root) { | |
3253 for (var i = 0, results = [], node; node = nodes[i]; i++) { | |
3254 if (Selector.handlers.previousElementSibling(node)) continue; | |
3255 results.push(node); | |
3256 } | |
3257 return results; | |
3258 }, | |
3259 'last-child': function(nodes, value, root) { | |
3260 for (var i = 0, results = [], node; node = nodes[i]; i++) { | |
3261 if (Selector.handlers.nextElementSibling(node)) continue; | |
3262 results.push(node); | |
3263 } | |
3264 return results; | |
3265 }, | |
3266 'only-child': function(nodes, value, root) { | |
3267 var h = Selector.handlers; | |
3268 for (var i = 0, results = [], node; node = nodes[i]; i++) | |
3269 if (!h.previousElementSibling(node) && !h.nextElementSibling(node)) | |
3270 results.push(node); | |
3271 return results; | |
3272 }, | |
3273 'nth-child': function(nodes, formula, root) { | |
3274 return Selector.pseudos.nth(nodes, formula, root); | |
3275 }, | |
3276 'nth-last-child': function(nodes, formula, root) { | |
3277 return Selector.pseudos.nth(nodes, formula, root, true); | |
3278 }, | |
3279 'nth-of-type': function(nodes, formula, root) { | |
3280 return Selector.pseudos.nth(nodes, formula, root, false, true); | |
3281 }, | |
3282 'nth-last-of-type': function(nodes, formula, root) { | |
3283 return Selector.pseudos.nth(nodes, formula, root, true, true); | |
3284 }, | |
3285 'first-of-type': function(nodes, formula, root) { | |
3286 return Selector.pseudos.nth(nodes, "1", root, false, true); | |
3287 }, | |
3288 'last-of-type': function(nodes, formula, root) { | |
3289 return Selector.pseudos.nth(nodes, "1", root, true, true); | |
3290 }, | |
3291 'only-of-type': function(nodes, formula, root) { | |
3292 var p = Selector.pseudos; | |
3293 return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root); | |
3294 }, | |
3295 | |
3296 // handles the an+b logic | |
3297 getIndices: function(a, b, total) { | |
3298 if (a == 0) return b > 0 ? [b] : []; | |
3299 return $R(1, total).inject([], function(memo, i) { | |
3300 if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i); | |
3301 return memo; | |
3302 }); | |
3303 }, | |
3304 | |
3305 // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type | |
3306 nth: function(nodes, formula, root, reverse, ofType) { | |
3307 if (nodes.length == 0) return []; | |
3308 if (formula == 'even') formula = '2n+0'; | |
3309 if (formula == 'odd') formula = '2n+1'; | |
3310 var h = Selector.handlers, results = [], indexed = [], m; | |
3311 h.mark(nodes); | |
3312 for (var i = 0, node; node = nodes[i]; i++) { | |
3313 if (!node.parentNode._countedByPrototype) { | |
3314 h.index(node.parentNode, reverse, ofType); | |
3315 indexed.push(node.parentNode); | |
3316 } | 4857 } |
3317 } | 4858 |
3318 if (formula.match(/^\d+$/)) { // just a number | 4859 elem = elem[dir]; |
3319 formula = Number(formula); | 4860 } |
3320 for (var i = 0, node; node = nodes[i]; i++) | 4861 |
3321 if (node.nodeIndex == formula) results.push(node); | 4862 checkSet[i] = match; |
3322 } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b | 4863 } |
3323 if (m[1] == "-") m[1] = -1; | 4864 } |
3324 var a = m[1] ? Number(m[1]) : 1; | 4865 } |
3325 var b = m[2] ? Number(m[2]) : 0; | 4866 |
3326 var indices = Selector.pseudos.getIndices(a, b, nodes.length); | 4867 function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { |
3327 for (var i = 0, node, l = indices.length; node = nodes[i]; i++) { | 4868 var sibDir = dir == "previousSibling" && !isXML; |
3328 for (var j = 0; j < l; j++) | 4869 for ( var i = 0, l = checkSet.length; i < l; i++ ) { |
3329 if (node.nodeIndex == indices[j]) results.push(node); | 4870 var elem = checkSet[i]; |
4871 if ( elem ) { | |
4872 if ( sibDir && elem.nodeType === 1 ) { | |
4873 elem.sizcache = doneName; | |
4874 elem.sizset = i; | |
4875 } | |
4876 elem = elem[dir]; | |
4877 var match = false; | |
4878 | |
4879 while ( elem ) { | |
4880 if ( elem.sizcache === doneName ) { | |
4881 match = checkSet[elem.sizset]; | |
4882 break; | |
3330 } | 4883 } |
3331 } | 4884 |
3332 h.unmark(nodes); | 4885 if ( elem.nodeType === 1 ) { |
3333 h.unmark(indexed); | 4886 if ( !isXML ) { |
3334 return results; | 4887 elem.sizcache = doneName; |
3335 }, | 4888 elem.sizset = i; |
3336 | 4889 } |
3337 'empty': function(nodes, value, root) { | 4890 if ( typeof cur !== "string" ) { |
3338 for (var i = 0, results = [], node; node = nodes[i]; i++) { | 4891 if ( elem === cur ) { |
3339 // IE treats comments as element nodes | 4892 match = true; |
3340 if (node.tagName == '!' || node.firstChild) continue; | 4893 break; |
3341 results.push(node); | 4894 } |
3342 } | 4895 |
3343 return results; | 4896 } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { |
3344 }, | 4897 match = elem; |
3345 | 4898 break; |
3346 'not': function(nodes, selector, root) { | 4899 } |
3347 var h = Selector.handlers, selectorType, m; | 4900 } |
3348 var exclusions = new Selector(selector).findElements(root); | 4901 |
3349 h.mark(exclusions); | 4902 elem = elem[dir]; |
3350 for (var i = 0, results = [], node; node = nodes[i]; i++) | 4903 } |
3351 if (!node._countedByPrototype) results.push(node); | 4904 |
3352 h.unmark(exclusions); | 4905 checkSet[i] = match; |
3353 return results; | 4906 } |
3354 }, | 4907 } |
3355 | |
3356 'enabled': function(nodes, value, root) { | |
3357 for (var i = 0, results = [], node; node = nodes[i]; i++) | |
3358 if (!node.disabled && (!node.type || node.type !== 'hidden')) | |
3359 results.push(node); | |
3360 return results; | |
3361 }, | |
3362 | |
3363 'disabled': function(nodes, value, root) { | |
3364 for (var i = 0, results = [], node; node = nodes[i]; i++) | |
3365 if (node.disabled) results.push(node); | |
3366 return results; | |
3367 }, | |
3368 | |
3369 'checked': function(nodes, value, root) { | |
3370 for (var i = 0, results = [], node; node = nodes[i]; i++) | |
3371 if (node.checked) results.push(node); | |
3372 return results; | |
3373 } | |
3374 }, | |
3375 | |
3376 operators: { | |
3377 '=': function(nv, v) { return nv == v; }, | |
3378 '!=': function(nv, v) { return nv != v; }, | |
3379 '^=': function(nv, v) { return nv == v || nv && nv.startsWith(v); }, | |
3380 '$=': function(nv, v) { return nv == v || nv && nv.endsWith(v); }, | |
3381 '*=': function(nv, v) { return nv == v || nv && nv.include(v); }, | |
3382 '$=': function(nv, v) { return nv.endsWith(v); }, | |
3383 '*=': function(nv, v) { return nv.include(v); }, | |
3384 '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); }, | |
3385 '|=': function(nv, v) { return ('-' + (nv || "").toUpperCase() + | |
3386 '-').include('-' + (v || "").toUpperCase() + '-'); } | |
3387 }, | |
3388 | |
3389 split: function(expression) { | |
3390 var expressions = []; | |
3391 expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) { | |
3392 expressions.push(m[1].strip()); | |
3393 }); | |
3394 return expressions; | |
3395 }, | |
3396 | |
3397 matchElements: function(elements, expression) { | |
3398 var matches = $$(expression), h = Selector.handlers; | |
3399 h.mark(matches); | |
3400 for (var i = 0, results = [], element; element = elements[i]; i++) | |
3401 if (element._countedByPrototype) results.push(element); | |
3402 h.unmark(matches); | |
3403 return results; | |
3404 }, | |
3405 | |
3406 findElement: function(elements, expression, index) { | |
3407 if (Object.isNumber(expression)) { | |
3408 index = expression; expression = false; | |
3409 } | |
3410 return Selector.matchElements(elements, expression || '*')[index || 0]; | |
3411 }, | |
3412 | |
3413 findChildElements: function(element, expressions) { | |
3414 expressions = Selector.split(expressions.join(',')); | |
3415 var results = [], h = Selector.handlers; | |
3416 for (var i = 0, l = expressions.length, selector; i < l; i++) { | |
3417 selector = new Selector(expressions[i].strip()); | |
3418 h.concat(results, selector.findElements(element)); | |
3419 } | |
3420 return (l > 1) ? h.unique(results) : results; | |
3421 } | |
3422 }); | |
3423 | |
3424 if (Prototype.Browser.IE) { | |
3425 Object.extend(Selector.handlers, { | |
3426 // IE returns comment nodes on getElementsByTagName("*"). | |
3427 // Filter them out. | |
3428 concat: function(a, b) { | |
3429 for (var i = 0, node; node = b[i]; i++) | |
3430 if (node.tagName !== "!") a.push(node); | |
3431 return a; | |
3432 }, | |
3433 | |
3434 // IE improperly serializes _countedByPrototype in (inner|outer)HTML. | |
3435 unmark: function(nodes) { | |
3436 for (var i = 0, node; node = nodes[i]; i++) | |
3437 node.removeAttribute('_countedByPrototype'); | |
3438 return nodes; | |
3439 } | |
3440 }); | |
3441 } | 4908 } |
3442 | 4909 |
3443 function $$() { | 4910 var contains = document.compareDocumentPosition ? function(a, b){ |
3444 return Selector.findChildElements(document, $A(arguments)); | 4911 return a.compareDocumentPosition(b) & 16; |
3445 } | 4912 } : function(a, b){ |
4913 return a !== b && (a.contains ? a.contains(b) : true); | |
4914 }; | |
4915 | |
4916 var isXML = function(elem){ | |
4917 return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" || | |
4918 !!elem.ownerDocument && elem.ownerDocument.documentElement.nodeName !== "HTML"; | |
4919 }; | |
4920 | |
4921 var posProcess = function(selector, context){ | |
4922 var tmpSet = [], later = "", match, | |
4923 root = context.nodeType ? [context] : context; | |
4924 | |
4925 while ( (match = Expr.match.PSEUDO.exec( selector )) ) { | |
4926 later += match[0]; | |
4927 selector = selector.replace( Expr.match.PSEUDO, "" ); | |
4928 } | |
4929 | |
4930 selector = Expr.relative[selector] ? selector + "*" : selector; | |
4931 | |
4932 for ( var i = 0, l = root.length; i < l; i++ ) { | |
4933 Sizzle( selector, root[i], tmpSet ); | |
4934 } | |
4935 | |
4936 return Sizzle.filter( later, tmpSet ); | |
4937 }; | |
4938 | |
4939 | |
4940 window.Sizzle = Sizzle; | |
4941 | |
4942 })(); | |
4943 | |
4944 ;(function(engine) { | |
4945 var extendElements = Prototype.Selector.extendElements; | |
4946 | |
4947 function select(selector, scope) { | |
4948 return extendElements(engine(selector, scope || document)); | |
4949 } | |
4950 | |
4951 function match(element, selector) { | |
4952 return engine.matches(selector, [element]).length == 1; | |
4953 } | |
4954 | |
4955 Prototype.Selector.engine = engine; | |
4956 Prototype.Selector.select = select; | |
4957 Prototype.Selector.match = match; | |
4958 })(Sizzle); | |
4959 | |
4960 window.Sizzle = Prototype._original_property; | |
4961 delete Prototype._original_property; | |
4962 | |
3446 var Form = { | 4963 var Form = { |
3447 reset: function(form) { | 4964 reset: function(form) { |
3448 $(form).reset(); | 4965 form = $(form); |
4966 form.reset(); | |
3449 return form; | 4967 return form; |
3450 }, | 4968 }, |
3451 | 4969 |
3452 serializeElements: function(elements, options) { | 4970 serializeElements: function(elements, options) { |
3453 if (typeof options != 'object') options = { hash: !!options }; | 4971 if (typeof options != 'object') options = { hash: !!options }; |
3454 else if (Object.isUndefined(options.hash)) options.hash = true; | 4972 else if (Object.isUndefined(options.hash)) options.hash = true; |
3455 var key, value, submitted = false, submit = options.submit; | 4973 var key, value, submitted = false, submit = options.submit, accumulator, initial; |
3456 | 4974 |
3457 var data = elements.inject({ }, function(result, element) { | 4975 if (options.hash) { |
4976 initial = {}; | |
4977 accumulator = function(result, key, value) { | |
4978 if (key in result) { | |
4979 if (!Object.isArray(result[key])) result[key] = [result[key]]; | |
4980 result[key].push(value); | |
4981 } else result[key] = value; | |
4982 return result; | |
4983 }; | |
4984 } else { | |
4985 initial = ''; | |
4986 accumulator = function(result, key, value) { | |
4987 return result + (result ? '&' : '') + encodeURIComponent(key) + '=' + encodeURIComponent(value); | |
4988 } | |
4989 } | |
4990 | |
4991 return elements.inject(initial, function(result, element) { | |
3458 if (!element.disabled && element.name) { | 4992 if (!element.disabled && element.name) { |
3459 key = element.name; value = $(element).getValue(); | 4993 key = element.name; value = $(element).getValue(); |
3460 if (value != null && element.type != 'file' && (element.type != 'submit' || (!submitted && | 4994 if (value != null && element.type != 'file' && (element.type != 'submit' || (!submitted && |
3461 submit !== false && (!submit || key == submit) && (submitted = true)))) { | 4995 submit !== false && (!submit || key == submit) && (submitted = true)))) { |
3462 if (key in result) { | 4996 result = accumulator(result, key, value); |
3463 // a key is already present; construct an array of values | |
3464 if (!Object.isArray(result[key])) result[key] = [result[key]]; | |
3465 result[key].push(value); | |
3466 } | |
3467 else result[key] = value; | |
3468 } | 4997 } |
3469 } | 4998 } |
3470 return result; | 4999 return result; |
3471 }); | 5000 }); |
3472 | |
3473 return options.hash ? data : Object.toQueryString(data); | |
3474 } | 5001 } |
3475 }; | 5002 }; |
3476 | 5003 |
3477 Form.Methods = { | 5004 Form.Methods = { |
3478 serialize: function(form, options) { | 5005 serialize: function(form, options) { |
3479 return Form.serializeElements(Form.getElements(form), options); | 5006 return Form.serializeElements(Form.getElements(form), options); |
3480 }, | 5007 }, |
3481 | 5008 |
3482 getElements: function(form) { | 5009 getElements: function(form) { |
3483 return $A($(form).getElementsByTagName('*')).inject([], | 5010 var elements = $(form).getElementsByTagName('*'), |
3484 function(elements, child) { | 5011 element, |
3485 if (Form.Element.Serializers[child.tagName.toLowerCase()]) | 5012 arr = [ ], |
3486 elements.push(Element.extend(child)); | 5013 serializers = Form.Element.Serializers; |
3487 return elements; | 5014 for (var i = 0; element = elements[i]; i++) { |
3488 } | 5015 arr.push(element); |
3489 ); | 5016 } |
5017 return arr.inject([], function(elements, child) { | |
5018 if (serializers[child.tagName.toLowerCase()]) | |
5019 elements.push(Element.extend(child)); | |
5020 return elements; | |
5021 }) | |
3490 }, | 5022 }, |
3491 | 5023 |
3492 getInputs: function(form, typeName, name) { | 5024 getInputs: function(form, typeName, name) { |
3493 form = $(form); | 5025 form = $(form); |
3494 var inputs = form.getElementsByTagName('input'); | 5026 var inputs = form.getElementsByTagName('input'); |
3524 var firstByIndex = elements.findAll(function(element) { | 5056 var firstByIndex = elements.findAll(function(element) { |
3525 return element.hasAttribute('tabIndex') && element.tabIndex >= 0; | 5057 return element.hasAttribute('tabIndex') && element.tabIndex >= 0; |
3526 }).sortBy(function(element) { return element.tabIndex }).first(); | 5058 }).sortBy(function(element) { return element.tabIndex }).first(); |
3527 | 5059 |
3528 return firstByIndex ? firstByIndex : elements.find(function(element) { | 5060 return firstByIndex ? firstByIndex : elements.find(function(element) { |
3529 return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); | 5061 return /^(?:input|select|textarea)$/i.test(element.tagName); |
3530 }); | 5062 }); |
3531 }, | 5063 }, |
3532 | 5064 |
3533 focusFirstElement: function(form) { | 5065 focusFirstElement: function(form) { |
3534 form = $(form); | 5066 form = $(form); |
3535 form.findFirstElement().activate(); | 5067 var element = form.findFirstElement(); |
5068 if (element) element.activate(); | |
3536 return form; | 5069 return form; |
3537 }, | 5070 }, |
3538 | 5071 |
3539 request: function(form, options) { | 5072 request: function(form, options) { |
3540 form = $(form), options = Object.clone(options || { }); | 5073 form = $(form), options = Object.clone(options || { }); |
3554 return new Ajax.Request(action, options); | 5087 return new Ajax.Request(action, options); |
3555 } | 5088 } |
3556 }; | 5089 }; |
3557 | 5090 |
3558 /*--------------------------------------------------------------------------*/ | 5091 /*--------------------------------------------------------------------------*/ |
5092 | |
3559 | 5093 |
3560 Form.Element = { | 5094 Form.Element = { |
3561 focus: function(element) { | 5095 focus: function(element) { |
3562 $(element).focus(); | 5096 $(element).focus(); |
3563 return element; | 5097 return element; |
3568 return element; | 5102 return element; |
3569 } | 5103 } |
3570 }; | 5104 }; |
3571 | 5105 |
3572 Form.Element.Methods = { | 5106 Form.Element.Methods = { |
5107 | |
3573 serialize: function(element) { | 5108 serialize: function(element) { |
3574 element = $(element); | 5109 element = $(element); |
3575 if (!element.disabled && element.name) { | 5110 if (!element.disabled && element.name) { |
3576 var value = element.getValue(); | 5111 var value = element.getValue(); |
3577 if (value != undefined) { | 5112 if (value != undefined) { |
3608 activate: function(element) { | 5143 activate: function(element) { |
3609 element = $(element); | 5144 element = $(element); |
3610 try { | 5145 try { |
3611 element.focus(); | 5146 element.focus(); |
3612 if (element.select && (element.tagName.toLowerCase() != 'input' || | 5147 if (element.select && (element.tagName.toLowerCase() != 'input' || |
3613 !['button', 'reset', 'submit'].include(element.type))) | 5148 !(/^(?:button|reset|submit)$/i.test(element.type)))) |
3614 element.select(); | 5149 element.select(); |
3615 } catch (e) { } | 5150 } catch (e) { } |
3616 return element; | 5151 return element; |
3617 }, | 5152 }, |
3618 | 5153 |
3630 }; | 5165 }; |
3631 | 5166 |
3632 /*--------------------------------------------------------------------------*/ | 5167 /*--------------------------------------------------------------------------*/ |
3633 | 5168 |
3634 var Field = Form.Element; | 5169 var Field = Form.Element; |
5170 | |
3635 var $F = Form.Element.Methods.getValue; | 5171 var $F = Form.Element.Methods.getValue; |
3636 | 5172 |
3637 /*--------------------------------------------------------------------------*/ | 5173 /*--------------------------------------------------------------------------*/ |
3638 | 5174 |
3639 Form.Element.Serializers = { | 5175 Form.Element.Serializers = (function() { |
3640 input: function(element, value) { | 5176 function input(element, value) { |
3641 switch (element.type.toLowerCase()) { | 5177 switch (element.type.toLowerCase()) { |
3642 case 'checkbox': | 5178 case 'checkbox': |
3643 case 'radio': | 5179 case 'radio': |
3644 return Form.Element.Serializers.inputSelector(element, value); | 5180 return inputSelector(element, value); |
3645 default: | 5181 default: |
3646 return Form.Element.Serializers.textarea(element, value); | 5182 return valueSelector(element, value); |
3647 } | 5183 } |
3648 }, | 5184 } |
3649 | 5185 |
3650 inputSelector: function(element, value) { | 5186 function inputSelector(element, value) { |
3651 if (Object.isUndefined(value)) return element.checked ? element.value : null; | 5187 if (Object.isUndefined(value)) |
5188 return element.checked ? element.value : null; | |
3652 else element.checked = !!value; | 5189 else element.checked = !!value; |
3653 }, | 5190 } |
3654 | 5191 |
3655 textarea: function(element, value) { | 5192 function valueSelector(element, value) { |
3656 if (Object.isUndefined(value)) return element.value; | 5193 if (Object.isUndefined(value)) return element.value; |
3657 else element.value = value; | 5194 else element.value = value; |
3658 }, | 5195 } |
3659 | 5196 |
3660 select: function(element, value) { | 5197 function select(element, value) { |
3661 if (Object.isUndefined(value)) | 5198 if (Object.isUndefined(value)) |
3662 return this[element.type == 'select-one' ? | 5199 return (element.type === 'select-one' ? selectOne : selectMany)(element); |
3663 'selectOne' : 'selectMany'](element); | 5200 |
3664 else { | 5201 var opt, currentValue, single = !Object.isArray(value); |
3665 var opt, currentValue, single = !Object.isArray(value); | 5202 for (var i = 0, length = element.length; i < length; i++) { |
3666 for (var i = 0, length = element.length; i < length; i++) { | 5203 opt = element.options[i]; |
3667 opt = element.options[i]; | 5204 currentValue = this.optionValue(opt); |
3668 currentValue = this.optionValue(opt); | 5205 if (single) { |
3669 if (single) { | 5206 if (currentValue == value) { |
3670 if (currentValue == value) { | 5207 opt.selected = true; |
3671 opt.selected = true; | 5208 return; |
3672 return; | |
3673 } | |
3674 } | 5209 } |
3675 else opt.selected = value.include(currentValue); | 5210 } |
3676 } | 5211 else opt.selected = value.include(currentValue); |
3677 } | 5212 } |
3678 }, | 5213 } |
3679 | 5214 |
3680 selectOne: function(element) { | 5215 function selectOne(element) { |
3681 var index = element.selectedIndex; | 5216 var index = element.selectedIndex; |
3682 return index >= 0 ? this.optionValue(element.options[index]) : null; | 5217 return index >= 0 ? optionValue(element.options[index]) : null; |
3683 }, | 5218 } |
3684 | 5219 |
3685 selectMany: function(element) { | 5220 function selectMany(element) { |
3686 var values, length = element.length; | 5221 var values, length = element.length; |
3687 if (!length) return null; | 5222 if (!length) return null; |
3688 | 5223 |
3689 for (var i = 0, values = []; i < length; i++) { | 5224 for (var i = 0, values = []; i < length; i++) { |
3690 var opt = element.options[i]; | 5225 var opt = element.options[i]; |
3691 if (opt.selected) values.push(this.optionValue(opt)); | 5226 if (opt.selected) values.push(optionValue(opt)); |
3692 } | 5227 } |
3693 return values; | 5228 return values; |
3694 }, | 5229 } |
3695 | 5230 |
3696 optionValue: function(opt) { | 5231 function optionValue(opt) { |
3697 // extend element because hasAttribute may not be native | 5232 return Element.hasAttribute(opt, 'value') ? opt.value : opt.text; |
3698 return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text; | 5233 } |
3699 } | 5234 |
3700 }; | 5235 return { |
5236 input: input, | |
5237 inputSelector: inputSelector, | |
5238 textarea: valueSelector, | |
5239 select: select, | |
5240 selectOne: selectOne, | |
5241 selectMany: selectMany, | |
5242 optionValue: optionValue, | |
5243 button: valueSelector | |
5244 }; | |
5245 })(); | |
3701 | 5246 |
3702 /*--------------------------------------------------------------------------*/ | 5247 /*--------------------------------------------------------------------------*/ |
5248 | |
3703 | 5249 |
3704 Abstract.TimedObserver = Class.create(PeriodicalExecuter, { | 5250 Abstract.TimedObserver = Class.create(PeriodicalExecuter, { |
3705 initialize: function($super, element, frequency, callback) { | 5251 initialize: function($super, element, frequency, callback) { |
3706 $super(callback, frequency); | 5252 $super(callback, frequency); |
3707 this.element = $(element); | 5253 this.element = $(element); |
3780 Form.EventObserver = Class.create(Abstract.EventObserver, { | 5326 Form.EventObserver = Class.create(Abstract.EventObserver, { |
3781 getValue: function() { | 5327 getValue: function() { |
3782 return Form.serialize(this.element); | 5328 return Form.serialize(this.element); |
3783 } | 5329 } |
3784 }); | 5330 }); |
3785 if (!window.Event) var Event = { }; | 5331 (function() { |
3786 | 5332 |
3787 Object.extend(Event, { | 5333 var Event = { |
3788 KEY_BACKSPACE: 8, | 5334 KEY_BACKSPACE: 8, |
3789 KEY_TAB: 9, | 5335 KEY_TAB: 9, |
3790 KEY_RETURN: 13, | 5336 KEY_RETURN: 13, |
3791 KEY_ESC: 27, | 5337 KEY_ESC: 27, |
3792 KEY_LEFT: 37, | 5338 KEY_LEFT: 37, |
3793 KEY_UP: 38, | 5339 KEY_UP: 38, |
3794 KEY_RIGHT: 39, | 5340 KEY_RIGHT: 39, |
3795 KEY_DOWN: 40, | 5341 KEY_DOWN: 40, |
3796 KEY_DELETE: 46, | 5342 KEY_DELETE: 46, |
3797 KEY_HOME: 36, | 5343 KEY_HOME: 36, |
3798 KEY_END: 35, | 5344 KEY_END: 35, |
3799 KEY_PAGEUP: 33, | 5345 KEY_PAGEUP: 33, |
3800 KEY_PAGEDOWN: 34, | 5346 KEY_PAGEDOWN: 34, |
3801 KEY_INSERT: 45, | 5347 KEY_INSERT: 45, |
3802 | 5348 |
3803 cache: { }, | 5349 cache: {} |
3804 | 5350 }; |
3805 relatedTarget: function(event) { | 5351 |
3806 var element; | 5352 var docEl = document.documentElement; |
3807 switch(event.type) { | 5353 var MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED = 'onmouseenter' in docEl |
3808 case 'mouseover': element = event.fromElement; break; | 5354 && 'onmouseleave' in docEl; |
3809 case 'mouseout': element = event.toElement; break; | 5355 |
3810 default: return null; | 5356 |
3811 } | 5357 |
3812 return Element.extend(element); | 5358 var isIELegacyEvent = function(event) { return false; }; |
3813 } | 5359 |
3814 }); | 5360 if (window.attachEvent) { |
3815 | 5361 if (window.addEventListener) { |
3816 Event.Methods = (function() { | 5362 isIELegacyEvent = function(event) { |
3817 var isButton; | 5363 return !(event instanceof window.Event); |
3818 | 5364 }; |
3819 if (Prototype.Browser.IE) { | 5365 } else { |
3820 var buttonMap = { 0: 1, 1: 4, 2: 2 }; | 5366 isIELegacyEvent = function(event) { return true; }; |
3821 isButton = function(event, code) { | 5367 } |
3822 return event.button == buttonMap[code]; | 5368 } |
3823 }; | 5369 |
3824 | 5370 var _isButton; |
5371 | |
5372 function _isButtonForDOMEvents(event, code) { | |
5373 return event.which ? (event.which === code + 1) : (event.button === code); | |
5374 } | |
5375 | |
5376 var legacyButtonMap = { 0: 1, 1: 4, 2: 2 }; | |
5377 function _isButtonForLegacyEvents(event, code) { | |
5378 return event.button === legacyButtonMap[code]; | |
5379 } | |
5380 | |
5381 function _isButtonForWebKit(event, code) { | |
5382 switch (code) { | |
5383 case 0: return event.which == 1 && !event.metaKey; | |
5384 case 1: return event.which == 2 || (event.which == 1 && event.metaKey); | |
5385 case 2: return event.which == 3; | |
5386 default: return false; | |
5387 } | |
5388 } | |
5389 | |
5390 if (window.attachEvent) { | |
5391 if (!window.addEventListener) { | |
5392 _isButton = _isButtonForLegacyEvents; | |
5393 } else { | |
5394 _isButton = function(event, code) { | |
5395 return isIELegacyEvent(event) ? _isButtonForLegacyEvents(event, code) : | |
5396 _isButtonForDOMEvents(event, code); | |
5397 } | |
5398 } | |
3825 } else if (Prototype.Browser.WebKit) { | 5399 } else if (Prototype.Browser.WebKit) { |
3826 isButton = function(event, code) { | 5400 _isButton = _isButtonForWebKit; |
3827 switch (code) { | |
3828 case 0: return event.which == 1 && !event.metaKey; | |
3829 case 1: return event.which == 1 && event.metaKey; | |
3830 default: return false; | |
3831 } | |
3832 }; | |
3833 | |
3834 } else { | 5401 } else { |
3835 isButton = function(event, code) { | 5402 _isButton = _isButtonForDOMEvents; |
3836 return event.which ? (event.which === code + 1) : (event.button === code); | 5403 } |
3837 }; | 5404 |
3838 } | 5405 function isLeftClick(event) { return _isButton(event, 0) } |
3839 | 5406 |
3840 return { | 5407 function isMiddleClick(event) { return _isButton(event, 1) } |
3841 isLeftClick: function(event) { return isButton(event, 0) }, | 5408 |
3842 isMiddleClick: function(event) { return isButton(event, 1) }, | 5409 function isRightClick(event) { return _isButton(event, 2) } |
3843 isRightClick: function(event) { return isButton(event, 2) }, | 5410 |
3844 | 5411 function element(event) { |
3845 element: function(event) { | 5412 event = Event.extend(event); |
3846 event = Event.extend(event); | 5413 |
3847 | 5414 var node = event.target, type = event.type, |
3848 var node = event.target, | 5415 currentTarget = event.currentTarget; |
3849 type = event.type, | 5416 |
3850 currentTarget = event.currentTarget; | 5417 if (currentTarget && currentTarget.tagName) { |
3851 | 5418 if (type === 'load' || type === 'error' || |
3852 if (currentTarget && currentTarget.tagName) { | 5419 (type === 'click' && currentTarget.tagName.toLowerCase() === 'input' |
3853 // Firefox screws up the "click" event when moving between radio buttons | 5420 && currentTarget.type === 'radio')) |
3854 // via arrow keys. It also screws up the "load" and "error" events on images, | 5421 node = currentTarget; |
3855 // reporting the document as the target instead of the original image. | 5422 } |
3856 if (type === 'load' || type === 'error' || | 5423 |
3857 (type === 'click' && currentTarget.tagName.toLowerCase() === 'input' | 5424 if (node.nodeType == Node.TEXT_NODE) |
3858 && currentTarget.type === 'radio')) | 5425 node = node.parentNode; |
3859 node = currentTarget; | 5426 |
3860 } | 5427 return Element.extend(node); |
3861 if (node.nodeType == Node.TEXT_NODE) node = node.parentNode; | 5428 } |
3862 return Element.extend(node); | 5429 |
3863 }, | 5430 function findElement(event, expression) { |
3864 | 5431 var element = Event.element(event); |
3865 findElement: function(event, expression) { | 5432 |
3866 var element = Event.element(event); | 5433 if (!expression) return element; |
3867 if (!expression) return element; | 5434 while (element) { |
3868 var elements = [element].concat(element.ancestors()); | 5435 if (Object.isElement(element) && Prototype.Selector.match(element, expression)) { |
3869 return Selector.findElement(elements, expression, 0); | 5436 return Element.extend(element); |
3870 }, | 5437 } |
3871 | 5438 element = element.parentNode; |
3872 pointer: function(event) { | 5439 } |
3873 var docElement = document.documentElement, | 5440 } |
3874 body = document.body || { scrollLeft: 0, scrollTop: 0 }; | 5441 |
3875 return { | 5442 function pointer(event) { |
3876 x: event.pageX || (event.clientX + | 5443 return { x: pointerX(event), y: pointerY(event) }; |
3877 (docElement.scrollLeft || body.scrollLeft) - | 5444 } |
3878 (docElement.clientLeft || 0)), | 5445 |
3879 y: event.pageY || (event.clientY + | 5446 function pointerX(event) { |
3880 (docElement.scrollTop || body.scrollTop) - | 5447 var docElement = document.documentElement, |
3881 (docElement.clientTop || 0)) | 5448 body = document.body || { scrollLeft: 0 }; |
3882 }; | 5449 |
3883 }, | 5450 return event.pageX || (event.clientX + |
3884 | 5451 (docElement.scrollLeft || body.scrollLeft) - |
3885 pointerX: function(event) { return Event.pointer(event).x }, | 5452 (docElement.clientLeft || 0)); |
3886 pointerY: function(event) { return Event.pointer(event).y }, | 5453 } |
3887 | 5454 |
3888 stop: function(event) { | 5455 function pointerY(event) { |
3889 Event.extend(event); | 5456 var docElement = document.documentElement, |
3890 event.preventDefault(); | 5457 body = document.body || { scrollTop: 0 }; |
3891 event.stopPropagation(); | 5458 |
3892 event.stopped = true; | 5459 return event.pageY || (event.clientY + |
3893 } | 5460 (docElement.scrollTop || body.scrollTop) - |
5461 (docElement.clientTop || 0)); | |
5462 } | |
5463 | |
5464 | |
5465 function stop(event) { | |
5466 Event.extend(event); | |
5467 event.preventDefault(); | |
5468 event.stopPropagation(); | |
5469 | |
5470 event.stopped = true; | |
5471 } | |
5472 | |
5473 | |
5474 Event.Methods = { | |
5475 isLeftClick: isLeftClick, | |
5476 isMiddleClick: isMiddleClick, | |
5477 isRightClick: isRightClick, | |
5478 | |
5479 element: element, | |
5480 findElement: findElement, | |
5481 | |
5482 pointer: pointer, | |
5483 pointerX: pointerX, | |
5484 pointerY: pointerY, | |
5485 | |
5486 stop: stop | |
3894 }; | 5487 }; |
3895 })(); | 5488 |
3896 | |
3897 Event.extend = (function() { | |
3898 var methods = Object.keys(Event.Methods).inject({ }, function(m, name) { | 5489 var methods = Object.keys(Event.Methods).inject({ }, function(m, name) { |
3899 m[name] = Event.Methods[name].methodize(); | 5490 m[name] = Event.Methods[name].methodize(); |
3900 return m; | 5491 return m; |
3901 }); | 5492 }); |
3902 | 5493 |
3903 if (Prototype.Browser.IE) { | 5494 if (window.attachEvent) { |
3904 Object.extend(methods, { | 5495 function _relatedTarget(event) { |
5496 var element; | |
5497 switch (event.type) { | |
5498 case 'mouseover': | |
5499 case 'mouseenter': | |
5500 element = event.fromElement; | |
5501 break; | |
5502 case 'mouseout': | |
5503 case 'mouseleave': | |
5504 element = event.toElement; | |
5505 break; | |
5506 default: | |
5507 return null; | |
5508 } | |
5509 return Element.extend(element); | |
5510 } | |
5511 | |
5512 var additionalMethods = { | |
3905 stopPropagation: function() { this.cancelBubble = true }, | 5513 stopPropagation: function() { this.cancelBubble = true }, |
3906 preventDefault: function() { this.returnValue = false }, | 5514 preventDefault: function() { this.returnValue = false }, |
3907 inspect: function() { return "[object Event]" } | 5515 inspect: function() { return '[object Event]' } |
3908 }); | 5516 }; |
3909 | 5517 |
3910 return function(event) { | 5518 Event.extend = function(event, element) { |
3911 if (!event) return false; | 5519 if (!event) return false; |
5520 | |
5521 if (!isIELegacyEvent(event)) return event; | |
5522 | |
3912 if (event._extendedByPrototype) return event; | 5523 if (event._extendedByPrototype) return event; |
3913 | |
3914 event._extendedByPrototype = Prototype.emptyFunction; | 5524 event._extendedByPrototype = Prototype.emptyFunction; |
5525 | |
3915 var pointer = Event.pointer(event); | 5526 var pointer = Event.pointer(event); |
5527 | |
3916 Object.extend(event, { | 5528 Object.extend(event, { |
3917 target: event.srcElement, | 5529 target: event.srcElement || element, |
3918 relatedTarget: Event.relatedTarget(event), | 5530 relatedTarget: _relatedTarget(event), |
3919 pageX: pointer.x, | 5531 pageX: pointer.x, |
3920 pageY: pointer.y | 5532 pageY: pointer.y |
3921 }); | 5533 }); |
3922 return Object.extend(event, methods); | 5534 |
5535 Object.extend(event, methods); | |
5536 Object.extend(event, additionalMethods); | |
5537 | |
5538 return event; | |
3923 }; | 5539 }; |
3924 | |
3925 } else { | 5540 } else { |
3926 Event.prototype = Event.prototype || document.createEvent("HTMLEvents")['__proto__']; | 5541 Event.extend = Prototype.K; |
5542 } | |
5543 | |
5544 if (window.addEventListener) { | |
5545 Event.prototype = window.Event.prototype || document.createEvent('HTMLEvents').__proto__; | |
3927 Object.extend(Event.prototype, methods); | 5546 Object.extend(Event.prototype, methods); |
3928 return Prototype.K; | 5547 } |
3929 } | 5548 |
5549 function _createResponder(element, eventName, handler) { | |
5550 var registry = Element.retrieve(element, 'prototype_event_registry'); | |
5551 | |
5552 if (Object.isUndefined(registry)) { | |
5553 CACHE.push(element); | |
5554 registry = Element.retrieve(element, 'prototype_event_registry', $H()); | |
5555 } | |
5556 | |
5557 var respondersForEvent = registry.get(eventName); | |
5558 if (Object.isUndefined(respondersForEvent)) { | |
5559 respondersForEvent = []; | |
5560 registry.set(eventName, respondersForEvent); | |
5561 } | |
5562 | |
5563 if (respondersForEvent.pluck('handler').include(handler)) return false; | |
5564 | |
5565 var responder; | |
5566 if (eventName.include(":")) { | |
5567 responder = function(event) { | |
5568 if (Object.isUndefined(event.eventName)) | |
5569 return false; | |
5570 | |
5571 if (event.eventName !== eventName) | |
5572 return false; | |
5573 | |
5574 Event.extend(event, element); | |
5575 handler.call(element, event); | |
5576 }; | |
5577 } else { | |
5578 if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED && | |
5579 (eventName === "mouseenter" || eventName === "mouseleave")) { | |
5580 if (eventName === "mouseenter" || eventName === "mouseleave") { | |
5581 responder = function(event) { | |
5582 Event.extend(event, element); | |
5583 | |
5584 var parent = event.relatedTarget; | |
5585 while (parent && parent !== element) { | |
5586 try { parent = parent.parentNode; } | |
5587 catch(e) { parent = element; } | |
5588 } | |
5589 | |
5590 if (parent === element) return; | |
5591 | |
5592 handler.call(element, event); | |
5593 }; | |
5594 } | |
5595 } else { | |
5596 responder = function(event) { | |
5597 Event.extend(event, element); | |
5598 handler.call(element, event); | |
5599 }; | |
5600 } | |
5601 } | |
5602 | |
5603 responder.handler = handler; | |
5604 respondersForEvent.push(responder); | |
5605 return responder; | |
5606 } | |
5607 | |
5608 function _destroyCache() { | |
5609 for (var i = 0, length = CACHE.length; i < length; i++) { | |
5610 Event.stopObserving(CACHE[i]); | |
5611 CACHE[i] = null; | |
5612 } | |
5613 } | |
5614 | |
5615 var CACHE = []; | |
5616 | |
5617 if (Prototype.Browser.IE) | |
5618 window.attachEvent('onunload', _destroyCache); | |
5619 | |
5620 if (Prototype.Browser.WebKit) | |
5621 window.addEventListener('unload', Prototype.emptyFunction, false); | |
5622 | |
5623 | |
5624 var _getDOMEventName = Prototype.K, | |
5625 translations = { mouseenter: "mouseover", mouseleave: "mouseout" }; | |
5626 | |
5627 if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED) { | |
5628 _getDOMEventName = function(eventName) { | |
5629 return (translations[eventName] || eventName); | |
5630 }; | |
5631 } | |
5632 | |
5633 function observe(element, eventName, handler) { | |
5634 element = $(element); | |
5635 | |
5636 var responder = _createResponder(element, eventName, handler); | |
5637 | |
5638 if (!responder) return element; | |
5639 | |
5640 if (eventName.include(':')) { | |
5641 if (element.addEventListener) | |
5642 element.addEventListener("dataavailable", responder, false); | |
5643 else { | |
5644 element.attachEvent("ondataavailable", responder); | |
5645 element.attachEvent("onlosecapture", responder); | |
5646 } | |
5647 } else { | |
5648 var actualEventName = _getDOMEventName(eventName); | |
5649 | |
5650 if (element.addEventListener) | |
5651 element.addEventListener(actualEventName, responder, false); | |
5652 else | |
5653 element.attachEvent("on" + actualEventName, responder); | |
5654 } | |
5655 | |
5656 return element; | |
5657 } | |
5658 | |
5659 function stopObserving(element, eventName, handler) { | |
5660 element = $(element); | |
5661 | |
5662 var registry = Element.retrieve(element, 'prototype_event_registry'); | |
5663 if (!registry) return element; | |
5664 | |
5665 if (!eventName) { | |
5666 registry.each( function(pair) { | |
5667 var eventName = pair.key; | |
5668 stopObserving(element, eventName); | |
5669 }); | |
5670 return element; | |
5671 } | |
5672 | |
5673 var responders = registry.get(eventName); | |
5674 if (!responders) return element; | |
5675 | |
5676 if (!handler) { | |
5677 responders.each(function(r) { | |
5678 stopObserving(element, eventName, r.handler); | |
5679 }); | |
5680 return element; | |
5681 } | |
5682 | |
5683 var i = responders.length, responder; | |
5684 while (i--) { | |
5685 if (responders[i].handler === handler) { | |
5686 responder = responders[i]; | |
5687 break; | |
5688 } | |
5689 } | |
5690 if (!responder) return element; | |
5691 | |
5692 if (eventName.include(':')) { | |
5693 if (element.removeEventListener) | |
5694 element.removeEventListener("dataavailable", responder, false); | |
5695 else { | |
5696 element.detachEvent("ondataavailable", responder); | |
5697 element.detachEvent("onlosecapture", responder); | |
5698 } | |
5699 } else { | |
5700 var actualEventName = _getDOMEventName(eventName); | |
5701 if (element.removeEventListener) | |
5702 element.removeEventListener(actualEventName, responder, false); | |
5703 else | |
5704 element.detachEvent('on' + actualEventName, responder); | |
5705 } | |
5706 | |
5707 registry.set(eventName, responders.without(responder)); | |
5708 | |
5709 return element; | |
5710 } | |
5711 | |
5712 function fire(element, eventName, memo, bubble) { | |
5713 element = $(element); | |
5714 | |
5715 if (Object.isUndefined(bubble)) | |
5716 bubble = true; | |
5717 | |
5718 if (element == document && document.createEvent && !element.dispatchEvent) | |
5719 element = document.documentElement; | |
5720 | |
5721 var event; | |
5722 if (document.createEvent) { | |
5723 event = document.createEvent('HTMLEvents'); | |
5724 event.initEvent('dataavailable', bubble, true); | |
5725 } else { | |
5726 event = document.createEventObject(); | |
5727 event.eventType = bubble ? 'ondataavailable' : 'onlosecapture'; | |
5728 } | |
5729 | |
5730 event.eventName = eventName; | |
5731 event.memo = memo || { }; | |
5732 | |
5733 if (document.createEvent) | |
5734 element.dispatchEvent(event); | |
5735 else | |
5736 element.fireEvent(event.eventType, event); | |
5737 | |
5738 return Event.extend(event); | |
5739 } | |
5740 | |
5741 Event.Handler = Class.create({ | |
5742 initialize: function(element, eventName, selector, callback) { | |
5743 this.element = $(element); | |
5744 this.eventName = eventName; | |
5745 this.selector = selector; | |
5746 this.callback = callback; | |
5747 this.handler = this.handleEvent.bind(this); | |
5748 }, | |
5749 | |
5750 start: function() { | |
5751 Event.observe(this.element, this.eventName, this.handler); | |
5752 return this; | |
5753 }, | |
5754 | |
5755 stop: function() { | |
5756 Event.stopObserving(this.element, this.eventName, this.handler); | |
5757 return this; | |
5758 }, | |
5759 | |
5760 handleEvent: function(event) { | |
5761 var element = Event.findElement(event, this.selector); | |
5762 if (element) this.callback.call(this.element, event, element); | |
5763 } | |
5764 }); | |
5765 | |
5766 function on(element, eventName, selector, callback) { | |
5767 element = $(element); | |
5768 if (Object.isFunction(selector) && Object.isUndefined(callback)) { | |
5769 callback = selector, selector = null; | |
5770 } | |
5771 | |
5772 return new Event.Handler(element, eventName, selector, callback).start(); | |
5773 } | |
5774 | |
5775 Object.extend(Event, Event.Methods); | |
5776 | |
5777 Object.extend(Event, { | |
5778 fire: fire, | |
5779 observe: observe, | |
5780 stopObserving: stopObserving, | |
5781 on: on | |
5782 }); | |
5783 | |
5784 Element.addMethods({ | |
5785 fire: fire, | |
5786 | |
5787 observe: observe, | |
5788 | |
5789 stopObserving: stopObserving, | |
5790 | |
5791 on: on | |
5792 }); | |
5793 | |
5794 Object.extend(document, { | |
5795 fire: fire.methodize(), | |
5796 | |
5797 observe: observe.methodize(), | |
5798 | |
5799 stopObserving: stopObserving.methodize(), | |
5800 | |
5801 on: on.methodize(), | |
5802 | |
5803 loaded: false | |
5804 }); | |
5805 | |
5806 if (window.Event) Object.extend(window.Event, Event); | |
5807 else window.Event = Event; | |
3930 })(); | 5808 })(); |
3931 | |
3932 Object.extend(Event, (function() { | |
3933 var cache = Event.cache; | |
3934 | |
3935 function getEventID(element) { | |
3936 if (element._prototypeEventID) return element._prototypeEventID[0]; | |
3937 arguments.callee.id = arguments.callee.id || 1; | |
3938 return element._prototypeEventID = [++arguments.callee.id]; | |
3939 } | |
3940 | |
3941 function getDOMEventName(eventName) { | |
3942 if (eventName && eventName.include(':')) return "dataavailable"; | |
3943 return eventName; | |
3944 } | |
3945 | |
3946 function getCacheForID(id) { | |
3947 return cache[id] = cache[id] || { }; | |
3948 } | |
3949 | |
3950 function getWrappersForEventName(id, eventName) { | |
3951 var c = getCacheForID(id); | |
3952 return c[eventName] = c[eventName] || []; | |
3953 } | |
3954 | |
3955 function createWrapper(element, eventName, handler) { | |
3956 var id = getEventID(element); | |
3957 var c = getWrappersForEventName(id, eventName); | |
3958 if (c.pluck("handler").include(handler)) return false; | |
3959 | |
3960 var wrapper = function(event) { | |
3961 if (!Event || !Event.extend || | |
3962 (event.eventName && event.eventName != eventName)) | |
3963 return false; | |
3964 | |
3965 Event.extend(event); | |
3966 handler.call(element, event); | |
3967 }; | |
3968 | |
3969 wrapper.handler = handler; | |
3970 c.push(wrapper); | |
3971 return wrapper; | |
3972 } | |
3973 | |
3974 function findWrapper(id, eventName, handler) { | |
3975 var c = getWrappersForEventName(id, eventName); | |
3976 return c.find(function(wrapper) { return wrapper.handler == handler }); | |
3977 } | |
3978 | |
3979 function destroyWrapper(id, eventName, handler) { | |
3980 var c = getCacheForID(id); | |
3981 if (!c[eventName]) return false; | |
3982 c[eventName] = c[eventName].without(findWrapper(id, eventName, handler)); | |
3983 } | |
3984 | |
3985 function destroyCache() { | |
3986 for (var id in cache) | |
3987 for (var eventName in cache[id]) | |
3988 cache[id][eventName] = null; | |
3989 } | |
3990 | |
3991 | |
3992 // Internet Explorer needs to remove event handlers on page unload | |
3993 // in order to avoid memory leaks. | |
3994 if (window.attachEvent) { | |
3995 window.attachEvent("onunload", destroyCache); | |
3996 } | |
3997 | |
3998 // Safari has a dummy event handler on page unload so that it won't | |
3999 // use its bfcache. Safari <= 3.1 has an issue with restoring the "document" | |
4000 // object when page is returned to via the back button using its bfcache. | |
4001 if (Prototype.Browser.WebKit) { | |
4002 window.addEventListener('unload', Prototype.emptyFunction, false); | |
4003 } | |
4004 | |
4005 return { | |
4006 observe: function(element, eventName, handler) { | |
4007 element = $(element); | |
4008 var name = getDOMEventName(eventName); | |
4009 | |
4010 var wrapper = createWrapper(element, eventName, handler); | |
4011 if (!wrapper) return element; | |
4012 | |
4013 if (element.addEventListener) { | |
4014 element.addEventListener(name, wrapper, false); | |
4015 } else { | |
4016 element.attachEvent("on" + name, wrapper); | |
4017 } | |
4018 | |
4019 return element; | |
4020 }, | |
4021 | |
4022 stopObserving: function(element, eventName, handler) { | |
4023 element = $(element); | |
4024 var id = getEventID(element), name = getDOMEventName(eventName); | |
4025 | |
4026 if (!handler && eventName) { | |
4027 getWrappersForEventName(id, eventName).each(function(wrapper) { | |
4028 element.stopObserving(eventName, wrapper.handler); | |
4029 }); | |
4030 return element; | |
4031 | |
4032 } else if (!eventName) { | |
4033 Object.keys(getCacheForID(id)).each(function(eventName) { | |
4034 element.stopObserving(eventName); | |
4035 }); | |
4036 return element; | |
4037 } | |
4038 | |
4039 var wrapper = findWrapper(id, eventName, handler); | |
4040 if (!wrapper) return element; | |
4041 | |
4042 if (element.removeEventListener) { | |
4043 element.removeEventListener(name, wrapper, false); | |
4044 } else { | |
4045 element.detachEvent("on" + name, wrapper); | |
4046 } | |
4047 | |
4048 destroyWrapper(id, eventName, handler); | |
4049 | |
4050 return element; | |
4051 }, | |
4052 | |
4053 fire: function(element, eventName, memo) { | |
4054 element = $(element); | |
4055 if (element == document && document.createEvent && !element.dispatchEvent) | |
4056 element = document.documentElement; | |
4057 | |
4058 var event; | |
4059 if (document.createEvent) { | |
4060 event = document.createEvent("HTMLEvents"); | |
4061 event.initEvent("dataavailable", true, true); | |
4062 } else { | |
4063 event = document.createEventObject(); | |
4064 event.eventType = "ondataavailable"; | |
4065 } | |
4066 | |
4067 event.eventName = eventName; | |
4068 event.memo = memo || { }; | |
4069 | |
4070 if (document.createEvent) { | |
4071 element.dispatchEvent(event); | |
4072 } else { | |
4073 element.fireEvent(event.eventType, event); | |
4074 } | |
4075 | |
4076 return Event.extend(event); | |
4077 } | |
4078 }; | |
4079 })()); | |
4080 | |
4081 Object.extend(Event, Event.Methods); | |
4082 | |
4083 Element.addMethods({ | |
4084 fire: Event.fire, | |
4085 observe: Event.observe, | |
4086 stopObserving: Event.stopObserving | |
4087 }); | |
4088 | |
4089 Object.extend(document, { | |
4090 fire: Element.Methods.fire.methodize(), | |
4091 observe: Element.Methods.observe.methodize(), | |
4092 stopObserving: Element.Methods.stopObserving.methodize(), | |
4093 loaded: false | |
4094 }); | |
4095 | 5809 |
4096 (function() { | 5810 (function() { |
4097 /* Support for the DOMContentLoaded event is based on work by Dan Webb, | 5811 /* Support for the DOMContentLoaded event is based on work by Dan Webb, |
4098 Matthias Miller, Dean Edwards and John Resig. */ | 5812 Matthias Miller, Dean Edwards, John Resig, and Diego Perini. */ |
4099 | 5813 |
4100 var timer; | 5814 var timer; |
4101 | 5815 |
4102 function fireContentLoadedEvent() { | 5816 function fireContentLoadedEvent() { |
4103 if (document.loaded) return; | 5817 if (document.loaded) return; |
4104 if (timer) window.clearInterval(timer); | 5818 if (timer) window.clearTimeout(timer); |
4105 document.fire("dom:loaded"); | |
4106 document.loaded = true; | 5819 document.loaded = true; |
5820 document.fire('dom:loaded'); | |
5821 } | |
5822 | |
5823 function checkReadyState() { | |
5824 if (document.readyState === 'complete') { | |
5825 document.stopObserving('readystatechange', checkReadyState); | |
5826 fireContentLoadedEvent(); | |
5827 } | |
5828 } | |
5829 | |
5830 function pollDoScroll() { | |
5831 try { document.documentElement.doScroll('left'); } | |
5832 catch(e) { | |
5833 timer = pollDoScroll.defer(); | |
5834 return; | |
5835 } | |
5836 fireContentLoadedEvent(); | |
4107 } | 5837 } |
4108 | 5838 |
4109 if (document.addEventListener) { | 5839 if (document.addEventListener) { |
4110 if (Prototype.Browser.WebKit) { | 5840 document.addEventListener('DOMContentLoaded', fireContentLoadedEvent, false); |
4111 timer = window.setInterval(function() { | |
4112 if (/loaded|complete/.test(document.readyState)) | |
4113 fireContentLoadedEvent(); | |
4114 }, 0); | |
4115 | |
4116 Event.observe(window, "load", fireContentLoadedEvent); | |
4117 | |
4118 } else { | |
4119 document.addEventListener("DOMContentLoaded", | |
4120 fireContentLoadedEvent, false); | |
4121 } | |
4122 | |
4123 } else { | 5841 } else { |
4124 document.write("<script id=__onDOMContentLoaded defer src=//:><\/script>"); | 5842 document.observe('readystatechange', checkReadyState); |
4125 $("__onDOMContentLoaded").onreadystatechange = function() { | 5843 if (window == top) |
4126 if (this.readyState == "complete") { | 5844 timer = pollDoScroll.defer(); |
4127 this.onreadystatechange = null; | 5845 } |
4128 fireContentLoadedEvent(); | 5846 |
4129 } | 5847 Event.observe(window, 'load', fireContentLoadedEvent); |
4130 }; | |
4131 } | |
4132 })(); | 5848 })(); |
5849 | |
5850 Element.addMethods(); | |
5851 | |
4133 /*------------------------------- DEPRECATED -------------------------------*/ | 5852 /*------------------------------- DEPRECATED -------------------------------*/ |
4134 | 5853 |
4135 Hash.toQueryString = Object.toQueryString; | 5854 Hash.toQueryString = Object.toQueryString; |
4136 | 5855 |
4137 var Toggle = { display: Element.toggle }; | 5856 var Toggle = { display: Element.toggle }; |
4156 } | 5875 } |
4157 }; | 5876 }; |
4158 | 5877 |
4159 var $continue = new Error('"throw $continue" is deprecated, use "return" instead'); | 5878 var $continue = new Error('"throw $continue" is deprecated, use "return" instead'); |
4160 | 5879 |
4161 // This should be moved to script.aculo.us; notice the deprecated methods | |
4162 // further below, that map to the newer Element methods. | |
4163 var Position = { | 5880 var Position = { |
4164 // set to true if needed, warning: firefox performance problems | |
4165 // NOT neeeded for page scrolling, only if draggable contained in | |
4166 // scrollable elements | |
4167 includeScrollOffsets: false, | 5881 includeScrollOffsets: false, |
4168 | 5882 |
4169 // must be called before calling withinIncludingScrolloffset, every time the | |
4170 // page is scrolled | |
4171 prepare: function() { | 5883 prepare: function() { |
4172 this.deltaX = window.pageXOffset | 5884 this.deltaX = window.pageXOffset |
4173 || document.documentElement.scrollLeft | 5885 || document.documentElement.scrollLeft |
4174 || document.body.scrollLeft | 5886 || document.body.scrollLeft |
4175 || 0; | 5887 || 0; |
4177 || document.documentElement.scrollTop | 5889 || document.documentElement.scrollTop |
4178 || document.body.scrollTop | 5890 || document.body.scrollTop |
4179 || 0; | 5891 || 0; |
4180 }, | 5892 }, |
4181 | 5893 |
4182 // caches x/y coordinate pair to use with overlap | |
4183 within: function(element, x, y) { | 5894 within: function(element, x, y) { |
4184 if (this.includeScrollOffsets) | 5895 if (this.includeScrollOffsets) |
4185 return this.withinIncludingScrolloffsets(element, x, y); | 5896 return this.withinIncludingScrolloffsets(element, x, y); |
4186 this.xcomp = x; | 5897 this.xcomp = x; |
4187 this.ycomp = y; | 5898 this.ycomp = y; |
4204 this.ycomp < this.offset[1] + element.offsetHeight && | 5915 this.ycomp < this.offset[1] + element.offsetHeight && |
4205 this.xcomp >= this.offset[0] && | 5916 this.xcomp >= this.offset[0] && |
4206 this.xcomp < this.offset[0] + element.offsetWidth); | 5917 this.xcomp < this.offset[0] + element.offsetWidth); |
4207 }, | 5918 }, |
4208 | 5919 |
4209 // within must be called directly before | |
4210 overlap: function(mode, element) { | 5920 overlap: function(mode, element) { |
4211 if (!mode) return 0; | 5921 if (!mode) return 0; |
4212 if (mode == 'vertical') | 5922 if (mode == 'vertical') |
4213 return ((this.offset[1] + element.offsetHeight) - this.ycomp) / | 5923 return ((this.offset[1] + element.offsetHeight) - this.ycomp) / |
4214 element.offsetHeight; | 5924 element.offsetHeight; |
4215 if (mode == 'horizontal') | 5925 if (mode == 'horizontal') |
4216 return ((this.offset[0] + element.offsetWidth) - this.xcomp) / | 5926 return ((this.offset[0] + element.offsetWidth) - this.xcomp) / |
4217 element.offsetWidth; | 5927 element.offsetWidth; |
4218 }, | 5928 }, |
4219 | 5929 |
4220 // Deprecation layer -- use newer Element methods now (1.5.2). | |
4221 | 5930 |
4222 cumulativeOffset: Element.Methods.cumulativeOffset, | 5931 cumulativeOffset: Element.Methods.cumulativeOffset, |
4223 | 5932 |
4224 positionedOffset: Element.Methods.positionedOffset, | 5933 positionedOffset: Element.Methods.positionedOffset, |
4225 | 5934 |
4315 | 6024 |
4316 Object.extend(Element.ClassNames.prototype, Enumerable); | 6025 Object.extend(Element.ClassNames.prototype, Enumerable); |
4317 | 6026 |
4318 /*--------------------------------------------------------------------------*/ | 6027 /*--------------------------------------------------------------------------*/ |
4319 | 6028 |
4320 Element.addMethods(); | 6029 (function() { |
6030 window.Selector = Class.create({ | |
6031 initialize: function(expression) { | |
6032 this.expression = expression.strip(); | |
6033 }, | |
6034 | |
6035 findElements: function(rootElement) { | |
6036 return Prototype.Selector.select(this.expression, rootElement); | |
6037 }, | |
6038 | |
6039 match: function(element) { | |
6040 return Prototype.Selector.match(element, this.expression); | |
6041 }, | |
6042 | |
6043 toString: function() { | |
6044 return this.expression; | |
6045 }, | |
6046 | |
6047 inspect: function() { | |
6048 return "#<Selector: " + this.expression + ">"; | |
6049 } | |
6050 }); | |
6051 | |
6052 Object.extend(Selector, { | |
6053 matchElements: function(elements, expression) { | |
6054 var match = Prototype.Selector.match, | |
6055 results = []; | |
6056 | |
6057 for (var i = 0, length = elements.length; i < length; i++) { | |
6058 var element = elements[i]; | |
6059 if (match(element, expression)) { | |
6060 results.push(Element.extend(element)); | |
6061 } | |
6062 } | |
6063 return results; | |
6064 }, | |
6065 | |
6066 findElement: function(elements, expression, index) { | |
6067 index = index || 0; | |
6068 var matchIndex = 0, element; | |
6069 for (var i = 0, length = elements.length; i < length; i++) { | |
6070 element = elements[i]; | |
6071 if (Prototype.Selector.match(element, expression) && index === matchIndex++) { | |
6072 return Element.extend(element); | |
6073 } | |
6074 } | |
6075 }, | |
6076 | |
6077 findChildElements: function(element, expressions) { | |
6078 var selector = expressions.toArray().join(', '); | |
6079 return Prototype.Selector.select(selector, element || document); | |
6080 } | |
6081 }); | |
6082 })(); |