aight-rails 0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 6896d05c1298cc9e6340f5cbb4fcb759ff7e16e0
4
+ data.tar.gz: 2b15719777bcfb15824ab27125994d36e491dcc0
5
+ SHA512:
6
+ metadata.gz: 52844cd40542bfb884bb944c92038c6a1af367185fdc4bb5460756b817dd13504621e768ee743a0262c0b52394bb8437746a161e6d2fb233d90bad725fab9e79
7
+ data.tar.gz: 0d4afcd12372dd059a95f28b7719855244faad1c0a8dae3a865b4f76ddf88a7d7852cdbaf22d46dd7504d1f54ea1fb1954b0c462c1f2a7971c14ea8281f5f203
@@ -0,0 +1,39 @@
1
+ # Aight::Rails
2
+
3
+ Adds the excellent [Aight shim/polyfill](https://github.com/shawnbot/aight) into your rails application.
4
+
5
+ ## Usage
6
+
7
+ Add the following to your Gemfile:
8
+
9
+ ```ruby
10
+ gem 'aight-rails'
11
+ ```
12
+
13
+ then run:
14
+
15
+ ```
16
+ bundle install
17
+ ```
18
+
19
+ Now you only need to add the following to your layout:
20
+
21
+ ```erb
22
+ <!--[if lt IE 9]>
23
+ <%= javascript_include_tag 'aight' %>
24
+ <![endif]-->
25
+ ```
26
+
27
+ Also includes the d3 extension to aight. To include it just:
28
+
29
+ ```erb
30
+ <!--[if lt IE 9]>
31
+ <%= javascript_include_tag 'aight.d3' %>
32
+ <![endif]-->
33
+ ```
34
+
35
+ ## License
36
+
37
+ Same as Aight itself this is public domain.
38
+ See https://github.com/shawnbot/aight/blob/master/LICENSE
39
+ for further details.
@@ -0,0 +1,5 @@
1
+ require "aight-rails/engine"
2
+
3
+ module AightRails
4
+ # intentionally blank
5
+ end
@@ -0,0 +1,7 @@
1
+ module AightRails
2
+ class Engine < ::Rails::Engine
3
+ initializer "aight-rails.assets.precompile" do |app|
4
+ app.config.assets.precompile << %w(aight.js aight.d3.js)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,57 @@
1
+ (function(exports) {
2
+
3
+ aight.d3 = {};
4
+
5
+ if (aight.browser.ie8) {
6
+ function mapped(property, format, parse) {
7
+ var read = function(p) {
8
+ var value = this.node().style[property];
9
+ return parse
10
+ ? parse.call(this, value, p)
11
+ : value;
12
+ },
13
+ write = function(p, value) {
14
+ return this.each(function() {
15
+ var v = (typeof value === "function")
16
+ ? value.apply(this, arguments)
17
+ : value;
18
+ this.style[property] = format
19
+ ? format.call(this, v, p)
20
+ : v;
21
+ });
22
+ };
23
+ return function() {
24
+ return arguments.length > 1
25
+ ? write.apply(this, arguments)
26
+ : read.call(this);
27
+ };
28
+ }
29
+
30
+ var aight_d3_style = {
31
+ "background-image": mapped("backgroundImage"),
32
+ "background-repeat": mapped("backgroundRepeat"),
33
+ "background-position": mapped("backgroundPosition"),
34
+ "background-color": mapped("backgroundColor"),
35
+
36
+ "opacity": mapped("filter",
37
+ function opacity_to_filter(opacity) {
38
+ return ["alpha(opacity=", Math.round(opacity * 100), ")"].join("");
39
+ },
40
+ function filter_to_opacity(filter) {
41
+ var opacity = (filter || "").match(/opacity=(\d+)/)[1] || 100;
42
+ return opacity / 100;
43
+ })
44
+ };
45
+
46
+ aight.d3.style = aight_d3_style;
47
+
48
+ var d3_style = d3.selection.prototype.style;
49
+ d3.selection.prototype.style = function(prop) {
50
+ var style = aight_d3_style.hasOwnProperty(prop)
51
+ ? aight_d3_style[prop]
52
+ : d3_style;
53
+ return style.apply(this, arguments);
54
+ };
55
+ }
56
+
57
+ })(this);
@@ -0,0 +1,1820 @@
1
+ /*
2
+ * aight <http://github.com/shawnbot/aight/>
3
+ * Aight is a collection of JavaScript shims that make IE8 behave like a modern
4
+ * browser (sans SVG).
5
+ */
6
+ (function(exports) {
7
+
8
+ var aight = exports.aight = (function() {
9
+ var nav = navigator.appName,
10
+ version = navigator.appVersion,
11
+ ie = (nav == 'Microsoft Internet Explorer');
12
+ if (ie) {
13
+ var match = navigator.userAgent.match(/MSIE ([0-9]{1,}[\.0-9]{0,})/);
14
+ version = match ? parseFloat(match[1]) : 0;
15
+ }
16
+ return {
17
+ version: "1.2.5",
18
+ browser: {
19
+ name: nav,
20
+ version: version,
21
+ ie: ie,
22
+ ie10: (ie && version >= 10),
23
+ ie9: (ie && version >= 9 && version < 10),
24
+ ie8: (ie && version >= 8 && version < 9),
25
+ ie7: (ie && version >= 7 && version < 8),
26
+ ie6: (ie && version >= 6 && version < 7)
27
+ }
28
+ };
29
+ })();
30
+
31
+ })(this);
32
+ /*
33
+ * classList.js: Cross-browser full element.classList implementation.
34
+ * 2012-11-15
35
+ *
36
+ * By Eli Grey, http://eligrey.com
37
+ * Public Domain.
38
+ * NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
39
+ */
40
+
41
+ /*global self, document, DOMException */
42
+
43
+ /*! @source http://purl.eligrey.com/github/classList.js/blob/master/classList.js*/
44
+
45
+ if (typeof document !== "undefined" && !("classList" in document.createElement("a"))) {
46
+
47
+ (function (view) {
48
+
49
+ "use strict";
50
+
51
+ if (!('HTMLElement' in view) && !('Element' in view)) return;
52
+
53
+ var
54
+ classListProp = "classList"
55
+ , protoProp = "prototype"
56
+ , elemCtrProto = (view.HTMLElement || view.Element)[protoProp]
57
+ , objCtr = Object
58
+ , strTrim = String[protoProp].trim || function () {
59
+ return this.replace(/^\s+|\s+$/g, "");
60
+ }
61
+ , arrIndexOf = Array[protoProp].indexOf || function (item) {
62
+ var
63
+ i = 0
64
+ , len = this.length
65
+ ;
66
+ for (; i < len; i++) {
67
+ if (i in this && this[i] === item) {
68
+ return i;
69
+ }
70
+ }
71
+ return -1;
72
+ }
73
+ // Vendors: please allow content code to instantiate DOMExceptions
74
+ , DOMEx = function (type, message) {
75
+ this.name = type;
76
+ this.code = DOMException[type];
77
+ this.message = message;
78
+ }
79
+ , checkTokenAndGetIndex = function (classList, token) {
80
+ if (token === "") {
81
+ throw new DOMEx(
82
+ "SYNTAX_ERR"
83
+ , "An invalid or illegal string was specified"
84
+ );
85
+ }
86
+ if (/\s/.test(token)) {
87
+ throw new DOMEx(
88
+ "INVALID_CHARACTER_ERR"
89
+ , "String contains an invalid character"
90
+ );
91
+ }
92
+ return arrIndexOf.call(classList, token);
93
+ }
94
+ , ClassList = function (elem) {
95
+ var
96
+ trimmedClasses = strTrim.call(elem.className)
97
+ , classes = trimmedClasses ? trimmedClasses.split(/\s+/) : []
98
+ , i = 0
99
+ , len = classes.length
100
+ ;
101
+ for (; i < len; i++) {
102
+ this.push(classes[i]);
103
+ }
104
+ this._updateClassName = function () {
105
+ elem.className = this.toString();
106
+ };
107
+ }
108
+ , classListProto = ClassList[protoProp] = []
109
+ , classListGetter = function () {
110
+ return new ClassList(this);
111
+ }
112
+ ;
113
+ // Most DOMException implementations don't allow calling DOMException's toString()
114
+ // on non-DOMExceptions. Error's toString() is sufficient here.
115
+ DOMEx[protoProp] = Error[protoProp];
116
+ classListProto.item = function (i) {
117
+ return this[i] || null;
118
+ };
119
+ classListProto.contains = function (token) {
120
+ token += "";
121
+ return checkTokenAndGetIndex(this, token) !== -1;
122
+ };
123
+ classListProto.add = function () {
124
+ var
125
+ tokens = arguments
126
+ , i = 0
127
+ , l = tokens.length
128
+ , token
129
+ , updated = false
130
+ ;
131
+ do {
132
+ token = tokens[i] + "";
133
+ if (checkTokenAndGetIndex(this, token) === -1) {
134
+ this.push(token);
135
+ updated = true;
136
+ }
137
+ }
138
+ while (++i < l);
139
+
140
+ if (updated) {
141
+ this._updateClassName();
142
+ }
143
+ };
144
+ classListProto.remove = function () {
145
+ var
146
+ tokens = arguments
147
+ , i = 0
148
+ , l = tokens.length
149
+ , token
150
+ , updated = false
151
+ ;
152
+ do {
153
+ token = tokens[i] + "";
154
+ var index = checkTokenAndGetIndex(this, token);
155
+ if (index !== -1) {
156
+ this.splice(index, 1);
157
+ updated = true;
158
+ }
159
+ }
160
+ while (++i < l);
161
+
162
+ if (updated) {
163
+ this._updateClassName();
164
+ }
165
+ };
166
+ classListProto.toggle = function (token, forse) {
167
+ token += "";
168
+
169
+ var
170
+ result = this.contains(token)
171
+ , method = result ?
172
+ forse !== true && "remove"
173
+ :
174
+ forse !== false && "add"
175
+ ;
176
+
177
+ if (method) {
178
+ this[method](token);
179
+ }
180
+
181
+ return !result;
182
+ };
183
+ classListProto.toString = function () {
184
+ return this.join(" ");
185
+ };
186
+
187
+ if (objCtr.defineProperty) {
188
+ var classListPropDesc = {
189
+ get: classListGetter
190
+ , enumerable: true
191
+ , configurable: true
192
+ };
193
+ try {
194
+ objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);
195
+ } catch (ex) { // IE 8 doesn't support enumerable:true
196
+ if (ex.number === -0x7FF5EC54) {
197
+ classListPropDesc.enumerable = false;
198
+ objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);
199
+ }
200
+ }
201
+ } else if (objCtr[protoProp].__defineGetter__) {
202
+ elemCtrProto.__defineGetter__(classListProp, classListGetter);
203
+ }
204
+
205
+ }(self));
206
+
207
+ }
208
+ // Copyright 2009-2012 by contributors, MIT License
209
+ // vim: ts=4 sts=4 sw=4 expandtab
210
+
211
+ // Module systems magic dance
212
+ (function (definition) {
213
+ // RequireJS
214
+ if (typeof define == "function") {
215
+ define(definition);
216
+ // YUI3
217
+ } else if (typeof YUI == "function") {
218
+ YUI.add("es5", definition);
219
+ // CommonJS and <script>
220
+ } else {
221
+ definition();
222
+ }
223
+ })(function () {
224
+
225
+ /**
226
+ * Brings an environment as close to ECMAScript 5 compliance
227
+ * as is possible with the facilities of erstwhile engines.
228
+ *
229
+ * Annotated ES5: http://es5.github.com/ (specific links below)
230
+ * ES5 Spec: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf
231
+ * Required reading: http://javascriptweblog.wordpress.com/2011/12/05/extending-javascript-natives/
232
+ */
233
+
234
+ //
235
+ // Function
236
+ // ========
237
+ //
238
+
239
+ // ES-5 15.3.4.5
240
+ // http://es5.github.com/#x15.3.4.5
241
+
242
+ function Empty() {}
243
+
244
+ if (!Function.prototype.bind) {
245
+ Function.prototype.bind = function bind(that) { // .length is 1
246
+ // 1. Let Target be the this value.
247
+ var target = this;
248
+ // 2. If IsCallable(Target) is false, throw a TypeError exception.
249
+ if (typeof target != "function") {
250
+ throw new TypeError("Function.prototype.bind called on incompatible " + target);
251
+ }
252
+ // 3. Let A be a new (possibly empty) internal list of all of the
253
+ // argument values provided after thisArg (arg1, arg2 etc), in order.
254
+ // XXX slicedArgs will stand in for "A" if used
255
+ var args = _Array_slice_.call(arguments, 1); // for normal call
256
+ // 4. Let F be a new native ECMAScript object.
257
+ // 11. Set the [[Prototype]] internal property of F to the standard
258
+ // built-in Function prototype object as specified in 15.3.3.1.
259
+ // 12. Set the [[Call]] internal property of F as described in
260
+ // 15.3.4.5.1.
261
+ // 13. Set the [[Construct]] internal property of F as described in
262
+ // 15.3.4.5.2.
263
+ // 14. Set the [[HasInstance]] internal property of F as described in
264
+ // 15.3.4.5.3.
265
+ var bound = function () {
266
+
267
+ if (this instanceof bound) {
268
+ // 15.3.4.5.2 [[Construct]]
269
+ // When the [[Construct]] internal method of a function object,
270
+ // F that was created using the bind function is called with a
271
+ // list of arguments ExtraArgs, the following steps are taken:
272
+ // 1. Let target be the value of F's [[TargetFunction]]
273
+ // internal property.
274
+ // 2. If target has no [[Construct]] internal method, a
275
+ // TypeError exception is thrown.
276
+ // 3. Let boundArgs be the value of F's [[BoundArgs]] internal
277
+ // property.
278
+ // 4. Let args be a new list containing the same values as the
279
+ // list boundArgs in the same order followed by the same
280
+ // values as the list ExtraArgs in the same order.
281
+ // 5. Return the result of calling the [[Construct]] internal
282
+ // method of target providing args as the arguments.
283
+
284
+ var result = target.apply(
285
+ this,
286
+ args.concat(_Array_slice_.call(arguments))
287
+ );
288
+ if (Object(result) === result) {
289
+ return result;
290
+ }
291
+ return this;
292
+
293
+ } else {
294
+ // 15.3.4.5.1 [[Call]]
295
+ // When the [[Call]] internal method of a function object, F,
296
+ // which was created using the bind function is called with a
297
+ // this value and a list of arguments ExtraArgs, the following
298
+ // steps are taken:
299
+ // 1. Let boundArgs be the value of F's [[BoundArgs]] internal
300
+ // property.
301
+ // 2. Let boundThis be the value of F's [[BoundThis]] internal
302
+ // property.
303
+ // 3. Let target be the value of F's [[TargetFunction]] internal
304
+ // property.
305
+ // 4. Let args be a new list containing the same values as the
306
+ // list boundArgs in the same order followed by the same
307
+ // values as the list ExtraArgs in the same order.
308
+ // 5. Return the result of calling the [[Call]] internal method
309
+ // of target providing boundThis as the this value and
310
+ // providing args as the arguments.
311
+
312
+ // equiv: target.call(this, ...boundArgs, ...args)
313
+ return target.apply(
314
+ that,
315
+ args.concat(_Array_slice_.call(arguments))
316
+ );
317
+
318
+ }
319
+
320
+ };
321
+ if(target.prototype) {
322
+ Empty.prototype = target.prototype;
323
+ bound.prototype = new Empty();
324
+ // Clean up dangling references.
325
+ Empty.prototype = null;
326
+ }
327
+ // XXX bound.length is never writable, so don't even try
328
+ //
329
+ // 15. If the [[Class]] internal property of Target is "Function", then
330
+ // a. Let L be the length property of Target minus the length of A.
331
+ // b. Set the length own property of F to either 0 or L, whichever is
332
+ // larger.
333
+ // 16. Else set the length own property of F to 0.
334
+ // 17. Set the attributes of the length own property of F to the values
335
+ // specified in 15.3.5.1.
336
+
337
+ // TODO
338
+ // 18. Set the [[Extensible]] internal property of F to true.
339
+
340
+ // TODO
341
+ // 19. Let thrower be the [[ThrowTypeError]] function Object (13.2.3).
342
+ // 20. Call the [[DefineOwnProperty]] internal method of F with
343
+ // arguments "caller", PropertyDescriptor {[[Get]]: thrower, [[Set]]:
344
+ // thrower, [[Enumerable]]: false, [[Configurable]]: false}, and
345
+ // false.
346
+ // 21. Call the [[DefineOwnProperty]] internal method of F with
347
+ // arguments "arguments", PropertyDescriptor {[[Get]]: thrower,
348
+ // [[Set]]: thrower, [[Enumerable]]: false, [[Configurable]]: false},
349
+ // and false.
350
+
351
+ // TODO
352
+ // NOTE Function objects created using Function.prototype.bind do not
353
+ // have a prototype property or the [[Code]], [[FormalParameters]], and
354
+ // [[Scope]] internal properties.
355
+ // XXX can't delete prototype in pure-js.
356
+
357
+ // 22. Return F.
358
+ return bound;
359
+ };
360
+ }
361
+
362
+ // Shortcut to an often accessed properties, in order to avoid multiple
363
+ // dereference that costs universally.
364
+ // _Please note: Shortcuts are defined after `Function.prototype.bind` as we
365
+ // us it in defining shortcuts.
366
+ var call = Function.prototype.call;
367
+ var prototypeOfArray = Array.prototype;
368
+ var prototypeOfObject = Object.prototype;
369
+ var _Array_slice_ = prototypeOfArray.slice;
370
+ // Having a toString local variable name breaks in Opera so use _toString.
371
+ var _toString = call.bind(prototypeOfObject.toString);
372
+ var owns = call.bind(prototypeOfObject.hasOwnProperty);
373
+
374
+ // If JS engine supports accessors creating shortcuts.
375
+ var defineGetter;
376
+ var defineSetter;
377
+ var lookupGetter;
378
+ var lookupSetter;
379
+ var supportsAccessors;
380
+ if ((supportsAccessors = owns(prototypeOfObject, "__defineGetter__"))) {
381
+ defineGetter = call.bind(prototypeOfObject.__defineGetter__);
382
+ defineSetter = call.bind(prototypeOfObject.__defineSetter__);
383
+ lookupGetter = call.bind(prototypeOfObject.__lookupGetter__);
384
+ lookupSetter = call.bind(prototypeOfObject.__lookupSetter__);
385
+ }
386
+
387
+ //
388
+ // Array
389
+ // =====
390
+ //
391
+
392
+ // ES5 15.4.4.12
393
+ // http://es5.github.com/#x15.4.4.12
394
+ // Default value for second param
395
+ // [bugfix, ielt9, old browsers]
396
+ // IE < 9 bug: [1,2].splice(0).join("") == "" but should be "12"
397
+ if ([1,2].splice(0).length != 2) {
398
+ var array_splice = Array.prototype.splice;
399
+
400
+ if(function() { // test IE < 9 to splice bug - see issue #138
401
+ function makeArray(l) {
402
+ var a = [];
403
+ while (l--) {
404
+ a.unshift(l)
405
+ }
406
+ return a
407
+ }
408
+
409
+ var array = []
410
+ , lengthBefore
411
+ ;
412
+
413
+ array.splice.bind(array, 0, 0).apply(null, makeArray(20));
414
+ array.splice.bind(array, 0, 0).apply(null, makeArray(26));
415
+
416
+ lengthBefore = array.length; //20
417
+ array.splice(5, 0, "XXX"); // add one element
418
+
419
+ if(lengthBefore + 1 == array.length) {
420
+ return true;// has right splice implementation without bugs
421
+ }
422
+ // else {
423
+ // IE8 bug
424
+ // }
425
+ }()) {//IE 6/7
426
+ Array.prototype.splice = function(start, deleteCount) {
427
+ if (!arguments.length) {
428
+ return [];
429
+ } else {
430
+ return array_splice.apply(this, [
431
+ start === void 0 ? 0 : start,
432
+ deleteCount === void 0 ? (this.length - start) : deleteCount
433
+ ].concat(_Array_slice_.call(arguments, 2)))
434
+ }
435
+ };
436
+ }
437
+ else {//IE8
438
+ Array.prototype.splice = function(start, deleteCount) {
439
+ var result
440
+ , args = _Array_slice_.call(arguments, 2)
441
+ , addElementsCount = args.length
442
+ ;
443
+
444
+ if(!arguments.length) {
445
+ return [];
446
+ }
447
+
448
+ if(start === void 0) { // default
449
+ start = 0;
450
+ }
451
+ if(deleteCount === void 0) { // default
452
+ deleteCount = this.length - start;
453
+ }
454
+
455
+ if(addElementsCount > 0) {
456
+ if(deleteCount <= 0) {
457
+ if(start == this.length) { // tiny optimisation #1
458
+ this.push.apply(this, args);
459
+ return [];
460
+ }
461
+
462
+ if(start == 0) { // tiny optimisation #2
463
+ this.unshift.apply(this, args);
464
+ return [];
465
+ }
466
+ }
467
+
468
+ // Array.prototype.splice implementation
469
+ result = _Array_slice_.call(this, start, start + deleteCount);// delete part
470
+ args.push.apply(args, _Array_slice_.call(this, start + deleteCount, this.length));// right part
471
+ args.unshift.apply(args, _Array_slice_.call(this, 0, start));// left part
472
+
473
+ // delete all items from this array and replace it to 'left part' + _Array_slice_.call(arguments, 2) + 'right part'
474
+ args.unshift(0, this.length);
475
+
476
+ array_splice.apply(this, args);
477
+
478
+ return result;
479
+ }
480
+
481
+ return array_splice.call(this, start, deleteCount);
482
+ }
483
+
484
+ }
485
+ }
486
+
487
+ // ES5 15.4.4.12
488
+ // http://es5.github.com/#x15.4.4.13
489
+ // Return len+argCount.
490
+ // [bugfix, ielt8]
491
+ // IE < 8 bug: [].unshift(0) == undefined but should be "1"
492
+ if ([].unshift(0) != 1) {
493
+ var array_unshift = Array.prototype.unshift;
494
+ Array.prototype.unshift = function() {
495
+ array_unshift.apply(this, arguments);
496
+ return this.length;
497
+ };
498
+ }
499
+
500
+ // ES5 15.4.3.2
501
+ // http://es5.github.com/#x15.4.3.2
502
+ // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/isArray
503
+ if (!Array.isArray) {
504
+ Array.isArray = function isArray(obj) {
505
+ return _toString(obj) == "[object Array]";
506
+ };
507
+ }
508
+
509
+ // The IsCallable() check in the Array functions
510
+ // has been replaced with a strict check on the
511
+ // internal class of the object to trap cases where
512
+ // the provided function was actually a regular
513
+ // expression literal, which in V8 and
514
+ // JavaScriptCore is a typeof "function". Only in
515
+ // V8 are regular expression literals permitted as
516
+ // reduce parameters, so it is desirable in the
517
+ // general case for the shim to match the more
518
+ // strict and common behavior of rejecting regular
519
+ // expressions.
520
+
521
+ // ES5 15.4.4.18
522
+ // http://es5.github.com/#x15.4.4.18
523
+ // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/array/forEach
524
+
525
+ // Check failure of by-index access of string characters (IE < 9)
526
+ // and failure of `0 in boxedString` (Rhino)
527
+ var boxedString = Object("a"),
528
+ splitString = boxedString[0] != "a" || !(0 in boxedString);
529
+
530
+ if (!Array.prototype.forEach) {
531
+ Array.prototype.forEach = function forEach(fun /*, thisp*/) {
532
+ var object = toObject(this),
533
+ self = splitString && _toString(this) == "[object String]" ?
534
+ this.split("") :
535
+ object,
536
+ thisp = arguments[1],
537
+ i = -1,
538
+ length = self.length >>> 0;
539
+
540
+ // If no callback function or if callback is not a callable function
541
+ if (_toString(fun) != "[object Function]") {
542
+ throw new TypeError(); // TODO message
543
+ }
544
+
545
+ while (++i < length) {
546
+ if (i in self) {
547
+ // Invoke the callback function with call, passing arguments:
548
+ // context, property value, property key, thisArg object
549
+ // context
550
+ fun.call(thisp, self[i], i, object);
551
+ }
552
+ }
553
+ };
554
+ }
555
+
556
+ // ES5 15.4.4.19
557
+ // http://es5.github.com/#x15.4.4.19
558
+ // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/map
559
+ if (!Array.prototype.map) {
560
+ Array.prototype.map = function map(fun /*, thisp*/) {
561
+ var object = toObject(this),
562
+ self = splitString && _toString(this) == "[object String]" ?
563
+ this.split("") :
564
+ object,
565
+ length = self.length >>> 0,
566
+ result = Array(length),
567
+ thisp = arguments[1];
568
+
569
+ // If no callback function or if callback is not a callable function
570
+ if (_toString(fun) != "[object Function]") {
571
+ throw new TypeError(fun + " is not a function");
572
+ }
573
+
574
+ for (var i = 0; i < length; i++) {
575
+ if (i in self)
576
+ result[i] = fun.call(thisp, self[i], i, object);
577
+ }
578
+ return result;
579
+ };
580
+ }
581
+
582
+ // ES5 15.4.4.20
583
+ // http://es5.github.com/#x15.4.4.20
584
+ // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/filter
585
+ if (!Array.prototype.filter) {
586
+ Array.prototype.filter = function filter(fun /*, thisp */) {
587
+ var object = toObject(this),
588
+ self = splitString && _toString(this) == "[object String]" ?
589
+ this.split("") :
590
+ object,
591
+ length = self.length >>> 0,
592
+ result = [],
593
+ value,
594
+ thisp = arguments[1];
595
+
596
+ // If no callback function or if callback is not a callable function
597
+ if (_toString(fun) != "[object Function]") {
598
+ throw new TypeError(fun + " is not a function");
599
+ }
600
+
601
+ for (var i = 0; i < length; i++) {
602
+ if (i in self) {
603
+ value = self[i];
604
+ if (fun.call(thisp, value, i, object)) {
605
+ result.push(value);
606
+ }
607
+ }
608
+ }
609
+ return result;
610
+ };
611
+ }
612
+
613
+ // ES5 15.4.4.16
614
+ // http://es5.github.com/#x15.4.4.16
615
+ // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/every
616
+ if (!Array.prototype.every) {
617
+ Array.prototype.every = function every(fun /*, thisp */) {
618
+ var object = toObject(this),
619
+ self = splitString && _toString(this) == "[object String]" ?
620
+ this.split("") :
621
+ object,
622
+ length = self.length >>> 0,
623
+ thisp = arguments[1];
624
+
625
+ // If no callback function or if callback is not a callable function
626
+ if (_toString(fun) != "[object Function]") {
627
+ throw new TypeError(fun + " is not a function");
628
+ }
629
+
630
+ for (var i = 0; i < length; i++) {
631
+ if (i in self && !fun.call(thisp, self[i], i, object)) {
632
+ return false;
633
+ }
634
+ }
635
+ return true;
636
+ };
637
+ }
638
+
639
+ // ES5 15.4.4.17
640
+ // http://es5.github.com/#x15.4.4.17
641
+ // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/some
642
+ if (!Array.prototype.some) {
643
+ Array.prototype.some = function some(fun /*, thisp */) {
644
+ var object = toObject(this),
645
+ self = splitString && _toString(this) == "[object String]" ?
646
+ this.split("") :
647
+ object,
648
+ length = self.length >>> 0,
649
+ thisp = arguments[1];
650
+
651
+ // If no callback function or if callback is not a callable function
652
+ if (_toString(fun) != "[object Function]") {
653
+ throw new TypeError(fun + " is not a function");
654
+ }
655
+
656
+ for (var i = 0; i < length; i++) {
657
+ if (i in self && fun.call(thisp, self[i], i, object)) {
658
+ return true;
659
+ }
660
+ }
661
+ return false;
662
+ };
663
+ }
664
+
665
+ // ES5 15.4.4.21
666
+ // http://es5.github.com/#x15.4.4.21
667
+ // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduce
668
+ if (!Array.prototype.reduce) {
669
+ Array.prototype.reduce = function reduce(fun /*, initial*/) {
670
+ var object = toObject(this),
671
+ self = splitString && _toString(this) == "[object String]" ?
672
+ this.split("") :
673
+ object,
674
+ length = self.length >>> 0;
675
+
676
+ // If no callback function or if callback is not a callable function
677
+ if (_toString(fun) != "[object Function]") {
678
+ throw new TypeError(fun + " is not a function");
679
+ }
680
+
681
+ // no value to return if no initial value and an empty array
682
+ if (!length && arguments.length == 1) {
683
+ throw new TypeError("reduce of empty array with no initial value");
684
+ }
685
+
686
+ var i = 0;
687
+ var result;
688
+ if (arguments.length >= 2) {
689
+ result = arguments[1];
690
+ } else {
691
+ do {
692
+ if (i in self) {
693
+ result = self[i++];
694
+ break;
695
+ }
696
+
697
+ // if array contains no values, no initial value to return
698
+ if (++i >= length) {
699
+ throw new TypeError("reduce of empty array with no initial value");
700
+ }
701
+ } while (true);
702
+ }
703
+
704
+ for (; i < length; i++) {
705
+ if (i in self) {
706
+ result = fun.call(void 0, result, self[i], i, object);
707
+ }
708
+ }
709
+
710
+ return result;
711
+ };
712
+ }
713
+
714
+ // ES5 15.4.4.22
715
+ // http://es5.github.com/#x15.4.4.22
716
+ // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduceRight
717
+ if (!Array.prototype.reduceRight) {
718
+ Array.prototype.reduceRight = function reduceRight(fun /*, initial*/) {
719
+ var object = toObject(this),
720
+ self = splitString && _toString(this) == "[object String]" ?
721
+ this.split("") :
722
+ object,
723
+ length = self.length >>> 0;
724
+
725
+ // If no callback function or if callback is not a callable function
726
+ if (_toString(fun) != "[object Function]") {
727
+ throw new TypeError(fun + " is not a function");
728
+ }
729
+
730
+ // no value to return if no initial value, empty array
731
+ if (!length && arguments.length == 1) {
732
+ throw new TypeError("reduceRight of empty array with no initial value");
733
+ }
734
+
735
+ var result, i = length - 1;
736
+ if (arguments.length >= 2) {
737
+ result = arguments[1];
738
+ } else {
739
+ do {
740
+ if (i in self) {
741
+ result = self[i--];
742
+ break;
743
+ }
744
+
745
+ // if array contains no values, no initial value to return
746
+ if (--i < 0) {
747
+ throw new TypeError("reduceRight of empty array with no initial value");
748
+ }
749
+ } while (true);
750
+ }
751
+
752
+ if (i < 0) {
753
+ return result;
754
+ }
755
+
756
+ do {
757
+ if (i in this) {
758
+ result = fun.call(void 0, result, self[i], i, object);
759
+ }
760
+ } while (i--);
761
+
762
+ return result;
763
+ };
764
+ }
765
+
766
+ // ES5 15.4.4.14
767
+ // http://es5.github.com/#x15.4.4.14
768
+ // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf
769
+ if (!Array.prototype.indexOf || ([0, 1].indexOf(1, 2) != -1)) {
770
+ Array.prototype.indexOf = function indexOf(sought /*, fromIndex */ ) {
771
+ var self = splitString && _toString(this) == "[object String]" ?
772
+ this.split("") :
773
+ toObject(this),
774
+ length = self.length >>> 0;
775
+
776
+ if (!length) {
777
+ return -1;
778
+ }
779
+
780
+ var i = 0;
781
+ if (arguments.length > 1) {
782
+ i = toInteger(arguments[1]);
783
+ }
784
+
785
+ // handle negative indices
786
+ i = i >= 0 ? i : Math.max(0, length + i);
787
+ for (; i < length; i++) {
788
+ if (i in self && self[i] === sought) {
789
+ return i;
790
+ }
791
+ }
792
+ return -1;
793
+ };
794
+ }
795
+
796
+ // ES5 15.4.4.15
797
+ // http://es5.github.com/#x15.4.4.15
798
+ // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/lastIndexOf
799
+ if (!Array.prototype.lastIndexOf || ([0, 1].lastIndexOf(0, -3) != -1)) {
800
+ Array.prototype.lastIndexOf = function lastIndexOf(sought /*, fromIndex */) {
801
+ var self = splitString && _toString(this) == "[object String]" ?
802
+ this.split("") :
803
+ toObject(this),
804
+ length = self.length >>> 0;
805
+
806
+ if (!length) {
807
+ return -1;
808
+ }
809
+ var i = length - 1;
810
+ if (arguments.length > 1) {
811
+ i = Math.min(i, toInteger(arguments[1]));
812
+ }
813
+ // handle negative indices
814
+ i = i >= 0 ? i : length - Math.abs(i);
815
+ for (; i >= 0; i--) {
816
+ if (i in self && sought === self[i]) {
817
+ return i;
818
+ }
819
+ }
820
+ return -1;
821
+ };
822
+ }
823
+
824
+ //
825
+ // Object
826
+ // ======
827
+ //
828
+
829
+ // ES5 15.2.3.14
830
+ // http://es5.github.com/#x15.2.3.14
831
+ if (!Object.keys) {
832
+ // http://whattheheadsaid.com/2010/10/a-safer-object-keys-compatibility-implementation
833
+ var hasDontEnumBug = true,
834
+ dontEnums = [
835
+ "toString",
836
+ "toLocaleString",
837
+ "valueOf",
838
+ "hasOwnProperty",
839
+ "isPrototypeOf",
840
+ "propertyIsEnumerable",
841
+ "constructor"
842
+ ],
843
+ dontEnumsLength = dontEnums.length;
844
+
845
+ for (var key in {"toString": null}) {
846
+ hasDontEnumBug = false;
847
+ }
848
+
849
+ Object.keys = function keys(object) {
850
+
851
+ if (
852
+ (typeof object != "object" && typeof object != "function") ||
853
+ object === null
854
+ ) {
855
+ throw new TypeError("Object.keys called on a non-object");
856
+ }
857
+
858
+ var keys = [];
859
+ for (var name in object) {
860
+ if (owns(object, name)) {
861
+ keys.push(name);
862
+ }
863
+ }
864
+
865
+ if (hasDontEnumBug) {
866
+ for (var i = 0, ii = dontEnumsLength; i < ii; i++) {
867
+ var dontEnum = dontEnums[i];
868
+ if (owns(object, dontEnum)) {
869
+ keys.push(dontEnum);
870
+ }
871
+ }
872
+ }
873
+ return keys;
874
+ };
875
+
876
+ }
877
+
878
+ //
879
+ // Date
880
+ // ====
881
+ //
882
+
883
+ // ES5 15.9.5.43
884
+ // http://es5.github.com/#x15.9.5.43
885
+ // This function returns a String value represent the instance in time
886
+ // represented by this Date object. The format of the String is the Date Time
887
+ // string format defined in 15.9.1.15. All fields are present in the String.
888
+ // The time zone is always UTC, denoted by the suffix Z. If the time value of
889
+ // this object is not a finite Number a RangeError exception is thrown.
890
+ var negativeDate = -62198755200000,
891
+ negativeYearString = "-000001";
892
+ if (
893
+ !Date.prototype.toISOString ||
894
+ (new Date(negativeDate).toISOString().indexOf(negativeYearString) === -1)
895
+ ) {
896
+ Date.prototype.toISOString = function toISOString() {
897
+ var result, length, value, year, month;
898
+ if (!isFinite(this)) {
899
+ throw new RangeError("Date.prototype.toISOString called on non-finite value.");
900
+ }
901
+
902
+ year = this.getUTCFullYear();
903
+
904
+ month = this.getUTCMonth();
905
+ // see https://github.com/kriskowal/es5-shim/issues/111
906
+ year += Math.floor(month / 12);
907
+ month = (month % 12 + 12) % 12;
908
+
909
+ // the date time string format is specified in 15.9.1.15.
910
+ result = [month + 1, this.getUTCDate(),
911
+ this.getUTCHours(), this.getUTCMinutes(), this.getUTCSeconds()];
912
+ year = (
913
+ (year < 0 ? "-" : (year > 9999 ? "+" : "")) +
914
+ ("00000" + Math.abs(year))
915
+ .slice(0 <= year && year <= 9999 ? -4 : -6)
916
+ );
917
+
918
+ length = result.length;
919
+ while (length--) {
920
+ value = result[length];
921
+ // pad months, days, hours, minutes, and seconds to have two
922
+ // digits.
923
+ if (value < 10) {
924
+ result[length] = "0" + value;
925
+ }
926
+ }
927
+ // pad milliseconds to have three digits.
928
+ return (
929
+ year + "-" + result.slice(0, 2).join("-") +
930
+ "T" + result.slice(2).join(":") + "." +
931
+ ("000" + this.getUTCMilliseconds()).slice(-3) + "Z"
932
+ );
933
+ };
934
+ }
935
+
936
+
937
+ // ES5 15.9.5.44
938
+ // http://es5.github.com/#x15.9.5.44
939
+ // This function provides a String representation of a Date object for use by
940
+ // JSON.stringify (15.12.3).
941
+ var dateToJSONIsSupported = false;
942
+ try {
943
+ dateToJSONIsSupported = (
944
+ Date.prototype.toJSON &&
945
+ new Date(NaN).toJSON() === null &&
946
+ new Date(negativeDate).toJSON().indexOf(negativeYearString) !== -1 &&
947
+ Date.prototype.toJSON.call({ // generic
948
+ toISOString: function () {
949
+ return true;
950
+ }
951
+ })
952
+ );
953
+ } catch (e) {
954
+ }
955
+ if (!dateToJSONIsSupported) {
956
+ Date.prototype.toJSON = function toJSON(key) {
957
+ // When the toJSON method is called with argument key, the following
958
+ // steps are taken:
959
+
960
+ // 1. Let O be the result of calling ToObject, giving it the this
961
+ // value as its argument.
962
+ // 2. Let tv be toPrimitive(O, hint Number).
963
+ var o = Object(this),
964
+ tv = toPrimitive(o),
965
+ toISO;
966
+ // 3. If tv is a Number and is not finite, return null.
967
+ if (typeof tv === "number" && !isFinite(tv)) {
968
+ return null;
969
+ }
970
+ // 4. Let toISO be the result of calling the [[Get]] internal method of
971
+ // O with argument "toISOString".
972
+ toISO = o.toISOString;
973
+ // 5. If IsCallable(toISO) is false, throw a TypeError exception.
974
+ if (typeof toISO != "function") {
975
+ throw new TypeError("toISOString property is not callable");
976
+ }
977
+ // 6. Return the result of calling the [[Call]] internal method of
978
+ // toISO with O as the this value and an empty argument list.
979
+ return toISO.call(o);
980
+
981
+ // NOTE 1 The argument is ignored.
982
+
983
+ // NOTE 2 The toJSON function is intentionally generic; it does not
984
+ // require that its this value be a Date object. Therefore, it can be
985
+ // transferred to other kinds of objects for use as a method. However,
986
+ // it does require that any such object have a toISOString method. An
987
+ // object is free to use the argument key to filter its
988
+ // stringification.
989
+ };
990
+ }
991
+
992
+ // ES5 15.9.4.2
993
+ // http://es5.github.com/#x15.9.4.2
994
+ // based on work shared by Daniel Friesen (dantman)
995
+ // http://gist.github.com/303249
996
+ if (!Date.parse || "Date.parse is buggy") {
997
+ // XXX global assignment won't work in embeddings that use
998
+ // an alternate object for the context.
999
+ Date = (function(NativeDate) {
1000
+
1001
+ // Date.length === 7
1002
+ function Date(Y, M, D, h, m, s, ms) {
1003
+ var length = arguments.length;
1004
+ if (this instanceof NativeDate) {
1005
+ var date = length == 1 && String(Y) === Y ? // isString(Y)
1006
+ // We explicitly pass it through parse:
1007
+ new NativeDate(Date.parse(Y)) :
1008
+ // We have to manually make calls depending on argument
1009
+ // length here
1010
+ length >= 7 ? new NativeDate(Y, M, D, h, m, s, ms) :
1011
+ length >= 6 ? new NativeDate(Y, M, D, h, m, s) :
1012
+ length >= 5 ? new NativeDate(Y, M, D, h, m) :
1013
+ length >= 4 ? new NativeDate(Y, M, D, h) :
1014
+ length >= 3 ? new NativeDate(Y, M, D) :
1015
+ length >= 2 ? new NativeDate(Y, M) :
1016
+ length >= 1 ? new NativeDate(Y) :
1017
+ new NativeDate();
1018
+ // Prevent mixups with unfixed Date object
1019
+ date.constructor = Date;
1020
+ return date;
1021
+ }
1022
+ return NativeDate.apply(this, arguments);
1023
+ };
1024
+
1025
+ // 15.9.1.15 Date Time String Format.
1026
+ var isoDateExpression = new RegExp("^" +
1027
+ "(\\d{4}|[\+\-]\\d{6})" + // four-digit year capture or sign +
1028
+ // 6-digit extended year
1029
+ "(?:-(\\d{2})" + // optional month capture
1030
+ "(?:-(\\d{2})" + // optional day capture
1031
+ "(?:" + // capture hours:minutes:seconds.milliseconds
1032
+ "T(\\d{2})" + // hours capture
1033
+ ":(\\d{2})" + // minutes capture
1034
+ "(?:" + // optional :seconds.milliseconds
1035
+ ":(\\d{2})" + // seconds capture
1036
+ "(?:(\\.\\d{1,}))?" + // milliseconds capture
1037
+ ")?" +
1038
+ "(" + // capture UTC offset component
1039
+ "Z|" + // UTC capture
1040
+ "(?:" + // offset specifier +/-hours:minutes
1041
+ "([-+])" + // sign capture
1042
+ "(\\d{2})" + // hours offset capture
1043
+ ":(\\d{2})" + // minutes offset capture
1044
+ ")" +
1045
+ ")?)?)?)?" +
1046
+ "$");
1047
+
1048
+ var months = [
1049
+ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
1050
+ ];
1051
+
1052
+ function dayFromMonth(year, month) {
1053
+ var t = month > 1 ? 1 : 0;
1054
+ return (
1055
+ months[month] +
1056
+ Math.floor((year - 1969 + t) / 4) -
1057
+ Math.floor((year - 1901 + t) / 100) +
1058
+ Math.floor((year - 1601 + t) / 400) +
1059
+ 365 * (year - 1970)
1060
+ );
1061
+ }
1062
+
1063
+ function toUTC(t) {
1064
+ return Number(new NativeDate(1970, 0, 1, 0, 0, 0, t));
1065
+ }
1066
+
1067
+ // Copy any custom methods a 3rd party library may have added
1068
+ for (var key in NativeDate) {
1069
+ Date[key] = NativeDate[key];
1070
+ }
1071
+
1072
+ // Copy "native" methods explicitly; they may be non-enumerable
1073
+ Date.now = NativeDate.now;
1074
+ Date.UTC = NativeDate.UTC;
1075
+ Date.prototype = NativeDate.prototype;
1076
+ Date.prototype.constructor = Date;
1077
+
1078
+ // Upgrade Date.parse to handle simplified ISO 8601 strings
1079
+ Date.parse = function parse(string) {
1080
+ var match = isoDateExpression.exec(string);
1081
+ if (match) {
1082
+ // parse months, days, hours, minutes, seconds, and milliseconds
1083
+ // provide default values if necessary
1084
+ // parse the UTC offset component
1085
+ var year = Number(match[1]),
1086
+ month = Number(match[2] || 1) - 1,
1087
+ day = Number(match[3] || 1) - 1,
1088
+ hour = Number(match[4] || 0),
1089
+ minute = Number(match[5] || 0),
1090
+ second = Number(match[6] || 0),
1091
+ millisecond = Math.floor(Number(match[7] || 0) * 1000),
1092
+ // When time zone is missed, local offset should be used
1093
+ // (ES 5.1 bug)
1094
+ // see https://bugs.ecmascript.org/show_bug.cgi?id=112
1095
+ isLocalTime = Boolean(match[4] && !match[8]),
1096
+ signOffset = match[9] === "-" ? 1 : -1,
1097
+ hourOffset = Number(match[10] || 0),
1098
+ minuteOffset = Number(match[11] || 0),
1099
+ result;
1100
+ if (
1101
+ hour < (
1102
+ minute > 0 || second > 0 || millisecond > 0 ?
1103
+ 24 : 25
1104
+ ) &&
1105
+ minute < 60 && second < 60 && millisecond < 1000 &&
1106
+ month > -1 && month < 12 && hourOffset < 24 &&
1107
+ minuteOffset < 60 && // detect invalid offsets
1108
+ day > -1 &&
1109
+ day < (
1110
+ dayFromMonth(year, month + 1) -
1111
+ dayFromMonth(year, month)
1112
+ )
1113
+ ) {
1114
+ result = (
1115
+ (dayFromMonth(year, month) + day) * 24 +
1116
+ hour +
1117
+ hourOffset * signOffset
1118
+ ) * 60;
1119
+ result = (
1120
+ (result + minute + minuteOffset * signOffset) * 60 +
1121
+ second
1122
+ ) * 1000 + millisecond;
1123
+ if (isLocalTime) {
1124
+ result = toUTC(result);
1125
+ }
1126
+ if (-8.64e15 <= result && result <= 8.64e15) {
1127
+ return result;
1128
+ }
1129
+ }
1130
+ return NaN;
1131
+ }
1132
+ return NativeDate.parse.apply(this, arguments);
1133
+ };
1134
+
1135
+ return Date;
1136
+ })(Date);
1137
+ }
1138
+
1139
+ // ES5 15.9.4.4
1140
+ // http://es5.github.com/#x15.9.4.4
1141
+ if (!Date.now) {
1142
+ Date.now = function now() {
1143
+ return new Date().getTime();
1144
+ };
1145
+ }
1146
+
1147
+
1148
+ //
1149
+ // Number
1150
+ // ======
1151
+ //
1152
+
1153
+ // ES5.1 15.7.4.5
1154
+ // http://es5.github.com/#x15.7.4.5
1155
+ if (!Number.prototype.toFixed || (0.00008).toFixed(3) !== '0.000' || (0.9).toFixed(0) === '0' || (1.255).toFixed(2) !== '1.25' || (1000000000000000128).toFixed(0) !== "1000000000000000128") {
1156
+ // Hide these variables and functions
1157
+ (function () {
1158
+ var base, size, data, i;
1159
+
1160
+ base = 1e7;
1161
+ size = 6;
1162
+ data = [0, 0, 0, 0, 0, 0];
1163
+
1164
+ function multiply(n, c) {
1165
+ var i = -1;
1166
+ while (++i < size) {
1167
+ c += n * data[i];
1168
+ data[i] = c % base;
1169
+ c = Math.floor(c / base);
1170
+ }
1171
+ }
1172
+
1173
+ function divide(n) {
1174
+ var i = size, c = 0;
1175
+ while (--i >= 0) {
1176
+ c += data[i];
1177
+ data[i] = Math.floor(c / n);
1178
+ c = (c % n) * base;
1179
+ }
1180
+ }
1181
+
1182
+ function toString() {
1183
+ var i = size;
1184
+ var s = '';
1185
+ while (--i >= 0) {
1186
+ if (s !== '' || i === 0 || data[i] !== 0) {
1187
+ var t = String(data[i]);
1188
+ if (s === '') {
1189
+ s = t;
1190
+ } else {
1191
+ s += '0000000'.slice(0, 7 - t.length) + t;
1192
+ }
1193
+ }
1194
+ }
1195
+ return s;
1196
+ }
1197
+
1198
+ function pow(x, n, acc) {
1199
+ return (n === 0 ? acc : (n % 2 === 1 ? pow(x, n - 1, acc * x) : pow(x * x, n / 2, acc)));
1200
+ }
1201
+
1202
+ function log(x) {
1203
+ var n = 0;
1204
+ while (x >= 4096) {
1205
+ n += 12;
1206
+ x /= 4096;
1207
+ }
1208
+ while (x >= 2) {
1209
+ n += 1;
1210
+ x /= 2;
1211
+ }
1212
+ return n;
1213
+ }
1214
+
1215
+ Number.prototype.toFixed = function (fractionDigits) {
1216
+ var f, x, s, m, e, z, j, k;
1217
+
1218
+ // Test for NaN and round fractionDigits down
1219
+ f = Number(fractionDigits);
1220
+ f = f !== f ? 0 : Math.floor(f);
1221
+
1222
+ if (f < 0 || f > 20) {
1223
+ throw new RangeError("Number.toFixed called with invalid number of decimals");
1224
+ }
1225
+
1226
+ x = Number(this);
1227
+
1228
+ // Test for NaN
1229
+ if (x !== x) {
1230
+ return "NaN";
1231
+ }
1232
+
1233
+ // If it is too big or small, return the string value of the number
1234
+ if (x <= -1e21 || x >= 1e21) {
1235
+ return String(x);
1236
+ }
1237
+
1238
+ s = "";
1239
+
1240
+ if (x < 0) {
1241
+ s = "-";
1242
+ x = -x;
1243
+ }
1244
+
1245
+ m = "0";
1246
+
1247
+ if (x > 1e-21) {
1248
+ // 1e-21 < x < 1e21
1249
+ // -70 < log2(x) < 70
1250
+ e = log(x * pow(2, 69, 1)) - 69;
1251
+ z = (e < 0 ? x * pow(2, -e, 1) : x / pow(2, e, 1));
1252
+ z *= 0x10000000000000; // Math.pow(2, 52);
1253
+ e = 52 - e;
1254
+
1255
+ // -18 < e < 122
1256
+ // x = z / 2 ^ e
1257
+ if (e > 0) {
1258
+ multiply(0, z);
1259
+ j = f;
1260
+
1261
+ while (j >= 7) {
1262
+ multiply(1e7, 0);
1263
+ j -= 7;
1264
+ }
1265
+
1266
+ multiply(pow(10, j, 1), 0);
1267
+ j = e - 1;
1268
+
1269
+ while (j >= 23) {
1270
+ divide(1 << 23);
1271
+ j -= 23;
1272
+ }
1273
+
1274
+ divide(1 << j);
1275
+ multiply(1, 1);
1276
+ divide(2);
1277
+ m = toString();
1278
+ } else {
1279
+ multiply(0, z);
1280
+ multiply(1 << (-e), 0);
1281
+ m = toString() + '0.00000000000000000000'.slice(2, 2 + f);
1282
+ }
1283
+ }
1284
+
1285
+ if (f > 0) {
1286
+ k = m.length;
1287
+
1288
+ if (k <= f) {
1289
+ m = s + '0.0000000000000000000'.slice(0, f - k + 2) + m;
1290
+ } else {
1291
+ m = s + m.slice(0, k - f) + '.' + m.slice(k - f);
1292
+ }
1293
+ } else {
1294
+ m = s + m;
1295
+ }
1296
+
1297
+ return m;
1298
+ }
1299
+ }());
1300
+ }
1301
+
1302
+
1303
+ //
1304
+ // String
1305
+ // ======
1306
+ //
1307
+
1308
+
1309
+ // ES5 15.5.4.14
1310
+ // http://es5.github.com/#x15.5.4.14
1311
+
1312
+ // [bugfix, IE lt 9, firefox 4, Konqueror, Opera, obscure browsers]
1313
+ // Many browsers do not split properly with regular expressions or they
1314
+ // do not perform the split correctly under obscure conditions.
1315
+ // See http://blog.stevenlevithan.com/archives/cross-browser-split
1316
+ // I've tested in many browsers and this seems to cover the deviant ones:
1317
+ // 'ab'.split(/(?:ab)*/) should be ["", ""], not [""]
1318
+ // '.'.split(/(.?)(.?)/) should be ["", ".", "", ""], not ["", ""]
1319
+ // 'tesst'.split(/(s)*/) should be ["t", undefined, "e", "s", "t"], not
1320
+ // [undefined, "t", undefined, "e", ...]
1321
+ // ''.split(/.?/) should be [], not [""]
1322
+ // '.'.split(/()()/) should be ["."], not ["", "", "."]
1323
+
1324
+ var string_split = String.prototype.split;
1325
+ if (
1326
+ 'ab'.split(/(?:ab)*/).length !== 2 ||
1327
+ '.'.split(/(.?)(.?)/).length !== 4 ||
1328
+ 'tesst'.split(/(s)*/)[1] === "t" ||
1329
+ ''.split(/.?/).length === 0 ||
1330
+ '.'.split(/()()/).length > 1
1331
+ ) {
1332
+ (function () {
1333
+ var compliantExecNpcg = /()??/.exec("")[1] === void 0; // NPCG: nonparticipating capturing group
1334
+
1335
+ String.prototype.split = function (separator, limit) {
1336
+ var string = this;
1337
+ if (separator === void 0 && limit === 0)
1338
+ return [];
1339
+
1340
+ // If `separator` is not a regex, use native split
1341
+ if (Object.prototype.toString.call(separator) !== "[object RegExp]") {
1342
+ return string_split.apply(this, arguments);
1343
+ }
1344
+
1345
+ var output = [],
1346
+ flags = (separator.ignoreCase ? "i" : "") +
1347
+ (separator.multiline ? "m" : "") +
1348
+ (separator.extended ? "x" : "") + // Proposed for ES6
1349
+ (separator.sticky ? "y" : ""), // Firefox 3+
1350
+ lastLastIndex = 0,
1351
+ // Make `global` and avoid `lastIndex` issues by working with a copy
1352
+ separator = new RegExp(separator.source, flags + "g"),
1353
+ separator2, match, lastIndex, lastLength;
1354
+ string += ""; // Type-convert
1355
+ if (!compliantExecNpcg) {
1356
+ // Doesn't need flags gy, but they don't hurt
1357
+ separator2 = new RegExp("^" + separator.source + "$(?!\\s)", flags);
1358
+ }
1359
+ /* Values for `limit`, per the spec:
1360
+ * If undefined: 4294967295 // Math.pow(2, 32) - 1
1361
+ * If 0, Infinity, or NaN: 0
1362
+ * If positive number: limit = Math.floor(limit); if (limit > 4294967295) limit -= 4294967296;
1363
+ * If negative number: 4294967296 - Math.floor(Math.abs(limit))
1364
+ * If other: Type-convert, then use the above rules
1365
+ */
1366
+ limit = limit === void 0 ?
1367
+ -1 >>> 0 : // Math.pow(2, 32) - 1
1368
+ limit >>> 0; // ToUint32(limit)
1369
+ while (match = separator.exec(string)) {
1370
+ // `separator.lastIndex` is not reliable cross-browser
1371
+ lastIndex = match.index + match[0].length;
1372
+ if (lastIndex > lastLastIndex) {
1373
+ output.push(string.slice(lastLastIndex, match.index));
1374
+ // Fix browsers whose `exec` methods don't consistently return `undefined` for
1375
+ // nonparticipating capturing groups
1376
+ if (!compliantExecNpcg && match.length > 1) {
1377
+ match[0].replace(separator2, function () {
1378
+ for (var i = 1; i < arguments.length - 2; i++) {
1379
+ if (arguments[i] === void 0) {
1380
+ match[i] = void 0;
1381
+ }
1382
+ }
1383
+ });
1384
+ }
1385
+ if (match.length > 1 && match.index < string.length) {
1386
+ Array.prototype.push.apply(output, match.slice(1));
1387
+ }
1388
+ lastLength = match[0].length;
1389
+ lastLastIndex = lastIndex;
1390
+ if (output.length >= limit) {
1391
+ break;
1392
+ }
1393
+ }
1394
+ if (separator.lastIndex === match.index) {
1395
+ separator.lastIndex++; // Avoid an infinite loop
1396
+ }
1397
+ }
1398
+ if (lastLastIndex === string.length) {
1399
+ if (lastLength || !separator.test("")) {
1400
+ output.push("");
1401
+ }
1402
+ } else {
1403
+ output.push(string.slice(lastLastIndex));
1404
+ }
1405
+ return output.length > limit ? output.slice(0, limit) : output;
1406
+ };
1407
+ }());
1408
+
1409
+ // [bugfix, chrome]
1410
+ // If separator is undefined, then the result array contains just one String,
1411
+ // which is the this value (converted to a String). If limit is not undefined,
1412
+ // then the output array is truncated so that it contains no more than limit
1413
+ // elements.
1414
+ // "0".split(undefined, 0) -> []
1415
+ } else if ("0".split(void 0, 0).length) {
1416
+ String.prototype.split = function(separator, limit) {
1417
+ if (separator === void 0 && limit === 0) return [];
1418
+ return string_split.apply(this, arguments);
1419
+ }
1420
+ }
1421
+
1422
+
1423
+ // ECMA-262, 3rd B.2.3
1424
+ // Note an ECMAScript standart, although ECMAScript 3rd Edition has a
1425
+ // non-normative section suggesting uniform semantics and it should be
1426
+ // normalized across all browsers
1427
+ // [bugfix, IE lt 9] IE < 9 substr() with negative value not working in IE
1428
+ if("".substr && "0b".substr(-1) !== "b") {
1429
+ var string_substr = String.prototype.substr;
1430
+ /**
1431
+ * Get the substring of a string
1432
+ * @param {integer} start where to start the substring
1433
+ * @param {integer} length how many characters to return
1434
+ * @return {string}
1435
+ */
1436
+ String.prototype.substr = function(start, length) {
1437
+ return string_substr.call(
1438
+ this,
1439
+ start < 0 ? ((start = this.length + start) < 0 ? 0 : start) : start,
1440
+ length
1441
+ );
1442
+ }
1443
+ }
1444
+
1445
+ // ES5 15.5.4.20
1446
+ // http://es5.github.com/#x15.5.4.20
1447
+ var ws = "\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003" +
1448
+ "\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028" +
1449
+ "\u2029\uFEFF";
1450
+ if (!String.prototype.trim || ws.trim()) {
1451
+ // http://blog.stevenlevithan.com/archives/faster-trim-javascript
1452
+ // http://perfectionkills.com/whitespace-deviations/
1453
+ ws = "[" + ws + "]";
1454
+ var trimBeginRegexp = new RegExp("^" + ws + ws + "*"),
1455
+ trimEndRegexp = new RegExp(ws + ws + "*$");
1456
+ String.prototype.trim = function trim() {
1457
+ if (this === void 0 || this === null) {
1458
+ throw new TypeError("can't convert "+this+" to object");
1459
+ }
1460
+ return String(this)
1461
+ .replace(trimBeginRegexp, "")
1462
+ .replace(trimEndRegexp, "");
1463
+ };
1464
+ }
1465
+
1466
+ //
1467
+ // Util
1468
+ // ======
1469
+ //
1470
+
1471
+ // ES5 9.4
1472
+ // http://es5.github.com/#x9.4
1473
+ // http://jsperf.com/to-integer
1474
+
1475
+ function toInteger(n) {
1476
+ n = +n;
1477
+ if (n !== n) { // isNaN
1478
+ n = 0;
1479
+ } else if (n !== 0 && n !== (1/0) && n !== -(1/0)) {
1480
+ n = (n > 0 || -1) * Math.floor(Math.abs(n));
1481
+ }
1482
+ return n;
1483
+ }
1484
+
1485
+ function isPrimitive(input) {
1486
+ var type = typeof input;
1487
+ return (
1488
+ input === null ||
1489
+ type === "undefined" ||
1490
+ type === "boolean" ||
1491
+ type === "number" ||
1492
+ type === "string"
1493
+ );
1494
+ }
1495
+
1496
+ function toPrimitive(input) {
1497
+ var val, valueOf, toString;
1498
+ if (isPrimitive(input)) {
1499
+ return input;
1500
+ }
1501
+ valueOf = input.valueOf;
1502
+ if (typeof valueOf === "function") {
1503
+ val = valueOf.call(input);
1504
+ if (isPrimitive(val)) {
1505
+ return val;
1506
+ }
1507
+ }
1508
+ toString = input.toString;
1509
+ if (typeof toString === "function") {
1510
+ val = toString.call(input);
1511
+ if (isPrimitive(val)) {
1512
+ return val;
1513
+ }
1514
+ }
1515
+ throw new TypeError();
1516
+ }
1517
+
1518
+ // ES5 9.9
1519
+ // http://es5.github.com/#x9.9
1520
+ var toObject = function (o) {
1521
+ if (o == null) { // this matches both null and undefined
1522
+ throw new TypeError("can't convert "+o+" to object");
1523
+ }
1524
+ return Object(o);
1525
+ };
1526
+
1527
+ });
1528
+ // see https://github.com/jonathantneal/polyfill
1529
+ // Window.prototype.getComputedStyle
1530
+ !('getComputedStyle' in Window.prototype) && (function () {
1531
+ function getComputedStylePixel(element, property, fontSize) {
1532
+ element.document; // Internet Explorer sometimes struggles to read currentStyle until the element's document is accessed.
1533
+
1534
+ var
1535
+ value = element.currentStyle[property].match(/([\d\.]+)(%|cm|em|in|mm|pc|pt|)/) || [0, 0, ''],
1536
+ size = value[1],
1537
+ suffix = value[2],
1538
+ rootSize;
1539
+
1540
+ fontSize = !fontSize ? fontSize : /%|em/.test(suffix) && element.parentElement ? getComputedStylePixel(element.parentElement, 'fontSize', null) : 16;
1541
+ rootSize = property == 'fontSize' ? fontSize : /width/i.test(property) ? element.clientWidth : element.clientHeight;
1542
+
1543
+ return suffix == '%' ? size / 100 * rootSize :
1544
+ suffix == 'cm' ? size * 0.3937 * 96 :
1545
+ suffix == 'em' ? size * fontSize :
1546
+ suffix == 'in' ? size * 96 :
1547
+ suffix == 'mm' ? size * 0.3937 * 96 / 10 :
1548
+ suffix == 'pc' ? size * 12 * 96 / 72 :
1549
+ suffix == 'pt' ? size * 96 / 72 :
1550
+ size;
1551
+ }
1552
+
1553
+ function setShortStyleProperty(style, property) {
1554
+ var
1555
+ borderSuffix = property == 'border' ? 'Width' : '',
1556
+ t = property + 'Top' + borderSuffix,
1557
+ r = property + 'Right' + borderSuffix,
1558
+ b = property + 'Bottom' + borderSuffix,
1559
+ l = property + 'Left' + borderSuffix;
1560
+
1561
+ style[property] = (style[t] == style[r] && style[t] == style[b] && style[t] == style[l] ? [ style[t] ] :
1562
+ style[t] == style[b] && style[l] == style[r] ? [ style[t], style[r] ] :
1563
+ style[l] == style[r] ? [ style[t], style[r], style[b] ] :
1564
+ [ style[t], style[r], style[b], style[l] ]).join(' ');
1565
+ }
1566
+
1567
+ // <CSSStyleDeclaration>
1568
+ function CSSStyleDeclaration(element) {
1569
+ var
1570
+ style = this,
1571
+ currentStyle = element.currentStyle,
1572
+ fontSize = getComputedStylePixel(element, 'fontSize'),
1573
+ unCamelCase = function (match) {
1574
+ return '-' + match.toLowerCase();
1575
+ },
1576
+ property;
1577
+
1578
+ for (property in currentStyle) {
1579
+ Array.prototype.push.call(style, property == 'styleFloat' ? 'float' : property.replace(/[A-Z]/, unCamelCase));
1580
+
1581
+ if (property == 'width') {
1582
+ style[property] = element.offsetWidth + 'px';
1583
+ } else if (property == 'height') {
1584
+ style[property] = element.offsetHeight + 'px';
1585
+ } else if (property == 'styleFloat') {
1586
+ style.float = currentStyle[property];
1587
+ } else if (/margin.|padding.|border.+W/.test(property) && style[property] != 'auto') {
1588
+ style[property] = Math.round(getComputedStylePixel(element, property, fontSize)) + 'px';
1589
+ } else if (/^outline/.test(property)) {
1590
+ // errors on checking outline
1591
+ try {
1592
+ style[property] = currentStyle[property];
1593
+ } catch (error) {
1594
+ style.outlineColor = currentStyle.color;
1595
+ style.outlineStyle = style.outlineStyle || 'none';
1596
+ style.outlineWidth = style.outlineWidth || '0px';
1597
+ style.outline = [style.outlineColor, style.outlineWidth, style.outlineStyle].join(' ');
1598
+ }
1599
+ } else {
1600
+ style[property] = currentStyle[property];
1601
+ }
1602
+ }
1603
+
1604
+ setShortStyleProperty(style, 'margin');
1605
+ setShortStyleProperty(style, 'padding');
1606
+ setShortStyleProperty(style, 'border');
1607
+
1608
+ style.fontSize = Math.round(fontSize) + 'px';
1609
+ }
1610
+
1611
+ CSSStyleDeclaration.prototype = {
1612
+ constructor: CSSStyleDeclaration,
1613
+ // <CSSStyleDeclaration>.getPropertyPriority
1614
+ getPropertyPriority: function () {
1615
+ throw new Error('NotSupportedError: DOM Exception 9');
1616
+ },
1617
+ // <CSSStyleDeclaration>.getPropertyValue
1618
+ getPropertyValue: function (property) {
1619
+ return this[property.replace(/-\w/g, function (match) {
1620
+ return match[1].toUpperCase();
1621
+ })];
1622
+ },
1623
+ // <CSSStyleDeclaration>.item
1624
+ item: function (index) {
1625
+ return this[index];
1626
+ },
1627
+ // <CSSStyleDeclaration>.removeProperty
1628
+ removeProperty: function () {
1629
+ throw new Error('NoModificationAllowedError: DOM Exception 7');
1630
+ },
1631
+ // <CSSStyleDeclaration>.setProperty
1632
+ setProperty: function () {
1633
+ throw new Error('NoModificationAllowedError: DOM Exception 7');
1634
+ },
1635
+ // <CSSStyleDeclaration>.getPropertyCSSValue
1636
+ getPropertyCSSValue: function () {
1637
+ throw new Error('NotSupportedError: DOM Exception 9');
1638
+ }
1639
+ };
1640
+
1641
+ // <window>.getComputedStyle
1642
+ window.getComputedStyle = Window.prototype.getComputedStyle = function (element) {
1643
+ return new CSSStyleDeclaration(element);
1644
+ };
1645
+ })();
1646
+ if (!CSSStyleDeclaration.prototype.getPropertyValue) {
1647
+ CSSStyleDeclaration.prototype.getPropertyValue = function(a) {
1648
+ return this.getAttribute(a);
1649
+ };
1650
+ CSSStyleDeclaration.prototype.setProperty = function(a, b) {
1651
+ return this.setAttribute(String(a), b);
1652
+ };
1653
+ CSSStyleDeclaration.prototype.removeProperty = function(a) {
1654
+ return this.removeAttribute(a);
1655
+ };
1656
+ }
1657
+ if (!('createElementNS' in HTMLDocument.prototype)) {
1658
+ HTMLDocument.prototype.createElementNS = function(ns, name) {
1659
+ if (ns) throw "sorry, this browser does not support namespaces";
1660
+ return HTMLDocument.prototype.createElement.call(this, name);
1661
+ };
1662
+ }
1663
+ !window.addEventListener && (function (WindowPrototype, DocumentPrototype, ElementPrototype, addEventListener, removeEventListener, dispatchEvent, registry) {
1664
+ WindowPrototype[addEventListener] = DocumentPrototype[addEventListener] = ElementPrototype[addEventListener] = function (type, listener) {
1665
+ var target = this;
1666
+
1667
+ registry.unshift([target, type, listener, function (event) {
1668
+ event.currentTarget = target;
1669
+ event.preventDefault = function () { event.returnValue = false; };
1670
+ event.stopPropagation = function () { event.cancelBubble = true; };
1671
+ event.target = event.srcElement || target;
1672
+
1673
+ listener.call(target, event);
1674
+ }]);
1675
+
1676
+ this.attachEvent("on" + type, registry[0][3]);
1677
+ };
1678
+
1679
+ WindowPrototype[removeEventListener] = DocumentPrototype[removeEventListener] = ElementPrototype[removeEventListener] = function (type, listener) {
1680
+ for (var index = 0, register; (register = registry[index]); ++index) {
1681
+ if (register[0] == this && register[1] == type && register[2] == listener) {
1682
+ return this.detachEvent("on" + type, registry.splice(index, 1)[0][3]);
1683
+ }
1684
+ }
1685
+ };
1686
+
1687
+ WindowPrototype[dispatchEvent] = DocumentPrototype[dispatchEvent] = ElementPrototype[dispatchEvent] = function (eventObject) {
1688
+ return this.fireEvent("on" + eventObject.type, eventObject);
1689
+ };
1690
+ })(Window.prototype, HTMLDocument.prototype, Element.prototype, "addEventListener", "removeEventListener", "dispatchEvent", []);
1691
+ (function() {
1692
+ try {
1693
+ // inspired by Eli Grey's shim @ http://eligrey.com/blog/post/textcontent-in-ie8
1694
+ // heavily modified to better match the spec:
1695
+ // http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#Node3-textContent
1696
+ if (Object.defineProperty && Object.getOwnPropertyDescriptor &&
1697
+ Object.getOwnPropertyDescriptor(Element.prototype, "textContent") &&
1698
+ !Object.getOwnPropertyDescriptor(Element.prototype, "textContent").get) {
1699
+
1700
+ // NOTE: Neither of these "drop-in" patterns would work:
1701
+ // Object.defineProperty(..., ..., descriptor); // nope!
1702
+ // Object.defineProperty(..., ..., { get: descriptor.get, set: descriptor.set }); // nope!
1703
+ // So must use function-wrapped descriptor.fn.call pattern.
1704
+
1705
+ // "Normal" Elements
1706
+ // NOTE: textContent is different from innerText, so its use would be incorrect:
1707
+ //var innerText = Object.getOwnPropertyDescriptor(Element.prototype, "innerText"); // nope!
1708
+ var getTextContent = function(x) {
1709
+ var c = this.firstChild;
1710
+ var tc=[];
1711
+ // append the textContent of its children
1712
+ while(!!c) {
1713
+ if (c.nodeType !== 8 && c.nodeType !== 7) { // skip comments
1714
+ tc.push(c.textContent);
1715
+ }
1716
+ c = c.nextSibling;
1717
+ }
1718
+ // a <br> Element should show as a newline
1719
+ if (this.tagName === 'BR') { tc.push('\n'); }
1720
+ c = null;
1721
+ tc = tc.join('');
1722
+ return tc;
1723
+ };
1724
+ var setTextContent = function(x) {
1725
+ var c;
1726
+ while(!!(c=this.lastChild)) {
1727
+ this.removeChild(c);
1728
+ }
1729
+ if (x!==null) {
1730
+ c=document.createTextNode(x);
1731
+ this.appendChild(c);
1732
+ }
1733
+ return x;
1734
+ };
1735
+ Object.defineProperty(Element.prototype, "textContent", {
1736
+ get: function() {
1737
+ // return innerText.get.call(this); // not good enough!
1738
+ return getTextContent.call(this);
1739
+ },
1740
+ set: function(x) {
1741
+ // return innerText.set.call(this, x); // not good enough!
1742
+ return setTextContent.call(this, x);
1743
+ }
1744
+ });
1745
+ // <script> Elements
1746
+ var scriptText = Object.getOwnPropertyDescriptor(HTMLScriptElement.prototype, "text");
1747
+ Object.defineProperty(HTMLScriptElement.prototype, "textContent", {
1748
+ get: function() {
1749
+ return scriptText.get.call(this);
1750
+ },
1751
+ set: function(x) {
1752
+ return scriptText.set.call(this, x);
1753
+ }
1754
+ });
1755
+ // <style> Elements
1756
+ var cssText = Object.getOwnPropertyDescriptor(CSSStyleSheet.prototype, "cssText");
1757
+ Object.defineProperty(HTMLStyleElement.prototype, "textContent", {
1758
+ get: function() {
1759
+ return cssText.get.call(this.styleSheet);
1760
+ },
1761
+ set: function(x) {
1762
+ return cssText.set.call(this.styleSheet, x);
1763
+ }
1764
+ });
1765
+ // <title> Elements
1766
+ var titleText = Object.getOwnPropertyDescriptor(HTMLTitleElement.prototype, "text");
1767
+ Object.defineProperty(HTMLTitleElement.prototype, "textContent", {
1768
+ get: function() {
1769
+ return titleText.get.call(this);
1770
+ },
1771
+ set: function(x) {
1772
+ return titleText.set.call(this, x);
1773
+ }
1774
+ });
1775
+ // Text nodes
1776
+ var textNodeValue = Object.getOwnPropertyDescriptor(Text.prototype, "nodeValue");
1777
+ Object.defineProperty(Text.prototype, "textContent", {
1778
+ get: function() {
1779
+ return textNodeValue.get.call(this);
1780
+ },
1781
+ set: function(x) {
1782
+ return textNodeValue.set.call(this, x);
1783
+ }
1784
+ });
1785
+ // Comments (and possibly other weird Node types that are treated as comments in IE)
1786
+ var elementNodeValue = Object.getOwnPropertyDescriptor(Element.prototype, "nodeValue");
1787
+ Object.defineProperty(HTMLCommentElement.prototype, "textContent", {
1788
+ get: function() {
1789
+ return elementNodeValue.get.call(this);
1790
+ },
1791
+ set: function(x) {
1792
+ return elementNodeValue.set.call(this, x);
1793
+ }
1794
+ });
1795
+ // Document and DocumentFragment Nodes
1796
+ // NOTE: IE8 seems to reuse HTMLDocument for both, so have to check nodeType explicitly
1797
+ var documentNodeValue = Object.getOwnPropertyDescriptor(HTMLDocument.prototype, "nodeValue");
1798
+ Object.defineProperty(HTMLDocument.prototype, "textContent", {
1799
+ get: function() {
1800
+ // document fragments have textContent
1801
+ if (this.nodeType === 11) {
1802
+ return getTextContent.call(this);
1803
+ }
1804
+ // a true Document's textContent is always null
1805
+ return null; // === documentNodeValue.get.call(this);
1806
+ },
1807
+ set: function(x) {
1808
+ if (this.nodeType === 11) {
1809
+ return setTextContent.call(this, x);
1810
+ }
1811
+ // setting a Document's textContent has no side effects
1812
+ return x; // === documentNodeValue.set.call(this, x);
1813
+ }
1814
+ });
1815
+ // other Node types are either deprecated or don't matter in HTML5/IE standards mode
1816
+ }
1817
+ } catch (e) {
1818
+ // bad Firefox
1819
+ }
1820
+ })();