PluginProbe
HTML Forms – Simple WordPress Forms Plugin / 1.0
HTML Forms – Simple WordPress Forms Plugin v1.0
1.7.0 trunk 1.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.1 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.2.0 1.3.0 1.3.1 1.3.10 1.3.11 1.3.12 1.3.13 1.3.14 1.3.15 1.3.16 All 67 releases
html-forms / assets / js / public.js

public.js in HTML Forms – Simple WordPress Forms Plugin 1.0, at assets/js/public.js

2,992 lines 115.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 (function () { var require = undefined; var module = undefined; var exports = undefined; var define = undefined;(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
2 'use strict';
3
4 function getButtonText(button) {
5 return button.innerHTML ? button.innerHTML : button.value;
6 }
7
8 function setButtonText(button, text) {
9 button.innerHTML ? button.innerHTML = text : button.value = text;
10 }
11
12 function Loader(formElement) {
13 this.form = formElement;
14 this.button = formElement.querySelector('input[type="submit"], button[type="submit"]');
15 this.loadingInterval = 0;
16 this.character = '\xB7';
17
18 if (this.button) {
19 this.originalButton = this.button.cloneNode(true);
20 }
21 }
22
23 Loader.prototype.setCharacter = function (c) {
24 this.character = c;
25 };
26
27 Loader.prototype.start = function () {
28 if (this.button) {
29 // loading text
30 var loadingText = this.button.getAttribute('data-loading-text');
31 if (loadingText) {
32 setButtonText(this.button, loadingText);
33 return;
34 }
35
36 // Show AJAX loader
37 var styles = window.getComputedStyle(this.button);
38 this.button.style.width = styles.width;
39 setButtonText(this.button, this.character);
40 this.loadingInterval = window.setInterval(this.tick.bind(this), 500);
41 } else {
42 this.form.style.opacity = '0.5';
43 }
44 };
45
46 Loader.prototype.tick = function () {
47 // count chars, start over at 5
48 var text = getButtonText(this.button);
49 var loadingChar = this.character;
50 setButtonText(this.button, text.length >= 5 ? loadingChar : text + " " + loadingChar);
51 };
52
53 Loader.prototype.stop = function () {
54 if (this.button) {
55 this.button.style.width = this.originalButton.style.width;
56 var text = getButtonText(this.originalButton);
57 setButtonText(this.button, text);
58 window.clearInterval(this.loadingInterval);
59 } else {
60 this.form.style.opacity = '';
61 }
62 };
63
64 module.exports = Loader;
65
66 },{}],2:[function(require,module,exports){
67 "use strict";
68
69 var shim = require('es5-shim');
70 var serialize = require('form-serialize');
71 var Loader = require('./form-loading-indicator.js');
72 var vars = window.hf_js_vars || { ajax_url: window.location.href };
73 var EventEmitter = require('wolfy87-eventemitter');
74 var events = new EventEmitter();
75
76 function cleanFormMessages(formEl) {
77 var messageElements = formEl.querySelectorAll('.hf-message');
78 messageElements.forEach(function (el) {
79 el.parentNode.removeChild(el);
80 });
81 }
82
83 function addFormMessage(formEl, message) {
84 var txtElement = document.createElement('p');
85 txtElement.className = 'hf-message hf-message-' + message.type;
86 txtElement.innerHTML = message.text;
87 formEl.insertBefore(txtElement, formEl.lastElementChild.nextElementSibling);
88 }
89
90 function handleSubmitEvents(e) {
91 var formEl = e.target;
92
93 // only act on html-forms
94 if (formEl.className.indexOf('hf-form') < 0) {
95 return;
96 }
97
98 e.preventDefault();
99 submitForm(formEl);
100 }
101
102 function submitForm(formEl) {
103 events.emit('submit', [formEl]);
104
105 var data = serialize(formEl, { "hash": false, "empty": true });
106 var request = new XMLHttpRequest();
107
108 cleanFormMessages(formEl);
109 request.onreadystatechange = createRequestHandler(formEl);
110 request.open('POST', vars.ajax_url, true);
111 request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
112 request.setRequestHeader("X-Requested-With", "XMLHttpRequest");
113 request.send(data);
114 request = null;
115 }
116
117 function createRequestHandler(formEl) {
118 var loader = new Loader(formEl);
119 loader.start();
120
121 return function () {
122 // are we done?
123 if (this.readyState === 4) {
124 var response = void 0;
125 loader.stop();
126
127 if (this.status >= 200 && this.status < 400) {
128 try {
129 response = JSON.parse(this.responseText);
130 } catch (error) {
131 console.log('HTML Forms: failed to parse AJAX response.\n\nError: "' + error + '"');
132 return;
133 }
134
135 events.emit('submitted', [formEl]);
136
137 if (response.error) {
138 events.emit('error', [formEl]);
139 } else {
140 events.emit('success', [formEl]);
141 }
142
143 // Show form message
144 if (response.message) {
145 addFormMessage(formEl, response.message);
146 }
147
148 // Should we hide form?
149 if (response.hide_form) {
150 formEl.querySelector('.hf-fields-wrap').style.display = 'none';
151 }
152
153 // Should we redirect?
154 if (response.redirect_url) {
155 window.location = response.redirect_url;
156 }
157
158 // clear form
159 formEl.reset();
160 } else {
161 // Server error :(
162 console.log(this.responseText);
163 }
164 }
165 };
166 }
167
168 document.addEventListener('submit', handleSubmitEvents, true);
169
170 window.html_forms = {
171 'on': events.on.bind(events)
172 };
173
174 },{"./form-loading-indicator.js":1,"es5-shim":3,"form-serialize":4,"wolfy87-eventemitter":5}],3:[function(require,module,exports){
175 /*!
176 * https://github.com/es-shims/es5-shim
177 * @license es5-shim Copyright 2009-2015 by contributors, MIT License
178 * see https://github.com/es-shims/es5-shim/blob/master/LICENSE
179 */
180
181 // vim: ts=4 sts=4 sw=4 expandtab
182
183 // Add semicolon to prevent IIFE from being passed as argument to concatenated code.
184 ;
185
186 // UMD (Universal Module Definition)
187 // see https://github.com/umdjs/umd/blob/master/templates/returnExports.js
188 (function (root, factory) {
189 'use strict';
190
191 /* global define, exports, module */
192 if (typeof define === 'function' && define.amd) {
193 // AMD. Register as an anonymous module.
194 define(factory);
195 } else if (typeof exports === 'object') {
196 // Node. Does not work with strict CommonJS, but
197 // only CommonJS-like enviroments that support module.exports,
198 // like Node.
199 module.exports = factory();
200 } else {
201 // Browser globals (root is window)
202 root.returnExports = factory();
203 }
204 }(this, function () {
205 /**
206 * Brings an environment as close to ECMAScript 5 compliance
207 * as is possible with the facilities of erstwhile engines.
208 *
209 * Annotated ES5: http://es5.github.com/ (specific links below)
210 * ES5 Spec: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf
211 * Required reading: http://javascriptweblog.wordpress.com/2011/12/05/extending-javascript-natives/
212 */
213
214 // Shortcut to an often accessed properties, in order to avoid multiple
215 // dereference that costs universally. This also holds a reference to known-good
216 // functions.
217 var $Array = Array;
218 var ArrayPrototype = $Array.prototype;
219 var $Object = Object;
220 var ObjectPrototype = $Object.prototype;
221 var $Function = Function;
222 var FunctionPrototype = $Function.prototype;
223 var $String = String;
224 var StringPrototype = $String.prototype;
225 var $Number = Number;
226 var NumberPrototype = $Number.prototype;
227 var array_slice = ArrayPrototype.slice;
228 var array_splice = ArrayPrototype.splice;
229 var array_push = ArrayPrototype.push;
230 var array_unshift = ArrayPrototype.unshift;
231 var array_concat = ArrayPrototype.concat;
232 var array_join = ArrayPrototype.join;
233 var call = FunctionPrototype.call;
234 var apply = FunctionPrototype.apply;
235 var max = Math.max;
236 var min = Math.min;
237
238 // Having a toString local variable name breaks in Opera so use to_string.
239 var to_string = ObjectPrototype.toString;
240
241 /* global Symbol */
242 /* eslint-disable one-var-declaration-per-line, no-redeclare, max-statements-per-line */
243 var hasToStringTag = typeof Symbol === 'function' && typeof Symbol.toStringTag === 'symbol';
244 var isCallable; /* inlined from https://npmjs.com/is-callable */ var fnToStr = Function.prototype.toString, constructorRegex = /^\s*class /, isES6ClassFn = function isES6ClassFn(value) { try { var fnStr = fnToStr.call(value); var singleStripped = fnStr.replace(/\/\/.*\n/g, ''); var multiStripped = singleStripped.replace(/\/\*[.\s\S]*\*\//g, ''); var spaceStripped = multiStripped.replace(/\n/mg, ' ').replace(/ {2}/g, ' '); return constructorRegex.test(spaceStripped); } catch (e) { return false; /* not a function */ } }, tryFunctionObject = function tryFunctionObject(value) { try { if (isES6ClassFn(value)) { return false; } fnToStr.call(value); return true; } catch (e) { return false; } }, fnClass = '[object Function]', genClass = '[object GeneratorFunction]', isCallable = function isCallable(value) { if (!value) { return false; } if (typeof value !== 'function' && typeof value !== 'object') { return false; } if (hasToStringTag) { return tryFunctionObject(value); } if (isES6ClassFn(value)) { return false; } var strClass = to_string.call(value); return strClass === fnClass || strClass === genClass; };
245
246 var isRegex; /* inlined from https://npmjs.com/is-regex */ var regexExec = RegExp.prototype.exec, tryRegexExec = function tryRegexExec(value) { try { regexExec.call(value); return true; } catch (e) { return false; } }, regexClass = '[object RegExp]'; isRegex = function isRegex(value) { if (typeof value !== 'object') { return false; } return hasToStringTag ? tryRegexExec(value) : to_string.call(value) === regexClass; };
247 var isString; /* inlined from https://npmjs.com/is-string */ var strValue = String.prototype.valueOf, tryStringObject = function tryStringObject(value) { try { strValue.call(value); return true; } catch (e) { return false; } }, stringClass = '[object String]'; isString = function isString(value) { if (typeof value === 'string') { return true; } if (typeof value !== 'object') { return false; } return hasToStringTag ? tryStringObject(value) : to_string.call(value) === stringClass; };
248 /* eslint-enable one-var-declaration-per-line, no-redeclare, max-statements-per-line */
249
250 /* inlined from http://npmjs.com/define-properties */
251 var supportsDescriptors = $Object.defineProperty && (function () {
252 try {
253 var obj = {};
254 $Object.defineProperty(obj, 'x', { enumerable: false, value: obj });
255 for (var _ in obj) { // jscs:ignore disallowUnusedVariables
256 return false;
257 }
258 return obj.x === obj;
259 } catch (e) { /* this is ES3 */
260 return false;
261 }
262 }());
263 var defineProperties = (function (has) {
264 // Define configurable, writable, and non-enumerable props
265 // if they don't exist.
266 var defineProperty;
267 if (supportsDescriptors) {
268 defineProperty = function (object, name, method, forceAssign) {
269 if (!forceAssign && (name in object)) {
270 return;
271 }
272 $Object.defineProperty(object, name, {
273 configurable: true,
274 enumerable: false,
275 writable: true,
276 value: method
277 });
278 };
279 } else {
280 defineProperty = function (object, name, method, forceAssign) {
281 if (!forceAssign && (name in object)) {
282 return;
283 }
284 object[name] = method;
285 };
286 }
287 return function defineProperties(object, map, forceAssign) {
288 for (var name in map) {
289 if (has.call(map, name)) {
290 defineProperty(object, name, map[name], forceAssign);
291 }
292 }
293 };
294 }(ObjectPrototype.hasOwnProperty));
295
296 //
297 // Util
298 // ======
299 //
300
301 /* replaceable with https://npmjs.com/package/es-abstract /helpers/isPrimitive */
302 var isPrimitive = function isPrimitive(input) {
303 var type = typeof input;
304 return input === null || (type !== 'object' && type !== 'function');
305 };
306
307 var isActualNaN = $Number.isNaN || function isActualNaN(x) {
308 return x !== x;
309 };
310
311 var ES = {
312 // ES5 9.4
313 // http://es5.github.com/#x9.4
314 // http://jsperf.com/to-integer
315 /* replaceable with https://npmjs.com/package/es-abstract ES5.ToInteger */
316 ToInteger: function ToInteger(num) {
317 var n = +num;
318 if (isActualNaN(n)) {
319 n = 0;
320 } else if (n !== 0 && n !== (1 / 0) && n !== -(1 / 0)) {
321 n = (n > 0 || -1) * Math.floor(Math.abs(n));
322 }
323 return n;
324 },
325
326 /* replaceable with https://npmjs.com/package/es-abstract ES5.ToPrimitive */
327 ToPrimitive: function ToPrimitive(input) {
328 var val, valueOf, toStr;
329 if (isPrimitive(input)) {
330 return input;
331 }
332 valueOf = input.valueOf;
333 if (isCallable(valueOf)) {
334 val = valueOf.call(input);
335 if (isPrimitive(val)) {
336 return val;
337 }
338 }
339 toStr = input.toString;
340 if (isCallable(toStr)) {
341 val = toStr.call(input);
342 if (isPrimitive(val)) {
343 return val;
344 }
345 }
346 throw new TypeError();
347 },
348
349 // ES5 9.9
350 // http://es5.github.com/#x9.9
351 /* replaceable with https://npmjs.com/package/es-abstract ES5.ToObject */
352 ToObject: function (o) {
353 if (o == null) { // this matches both null and undefined
354 throw new TypeError("can't convert " + o + ' to object');
355 }
356 return $Object(o);
357 },
358
359 /* replaceable with https://npmjs.com/package/es-abstract ES5.ToUint32 */
360 ToUint32: function ToUint32(x) {
361 return x >>> 0;
362 }
363 };
364
365 //
366 // Function
367 // ========
368 //
369
370 // ES-5 15.3.4.5
371 // http://es5.github.com/#x15.3.4.5
372
373 var Empty = function Empty() {};
374
375 defineProperties(FunctionPrototype, {
376 bind: function bind(that) { // .length is 1
377 // 1. Let Target be the this value.
378 var target = this;
379 // 2. If IsCallable(Target) is false, throw a TypeError exception.
380 if (!isCallable(target)) {
381 throw new TypeError('Function.prototype.bind called on incompatible ' + target);
382 }
383 // 3. Let A be a new (possibly empty) internal list of all of the
384 // argument values provided after thisArg (arg1, arg2 etc), in order.
385 // XXX slicedArgs will stand in for "A" if used
386 var args = array_slice.call(arguments, 1); // for normal call
387 // 4. Let F be a new native ECMAScript object.
388 // 11. Set the [[Prototype]] internal property of F to the standard
389 // built-in Function prototype object as specified in 15.3.3.1.
390 // 12. Set the [[Call]] internal property of F as described in
391 // 15.3.4.5.1.
392 // 13. Set the [[Construct]] internal property of F as described in
393 // 15.3.4.5.2.
394 // 14. Set the [[HasInstance]] internal property of F as described in
395 // 15.3.4.5.3.
396 var bound;
397 var binder = function () {
398
399 if (this instanceof bound) {
400 // 15.3.4.5.2 [[Construct]]
401 // When the [[Construct]] internal method of a function object,
402 // F that was created using the bind function is called with a
403 // list of arguments ExtraArgs, the following steps are taken:
404 // 1. Let target be the value of F's [[TargetFunction]]
405 // internal property.
406 // 2. If target has no [[Construct]] internal method, a
407 // TypeError exception is thrown.
408 // 3. Let boundArgs be the value of F's [[BoundArgs]] internal
409 // property.
410 // 4. Let args be a new list containing the same values as the
411 // list boundArgs in the same order followed by the same
412 // values as the list ExtraArgs in the same order.
413 // 5. Return the result of calling the [[Construct]] internal
414 // method of target providing args as the arguments.
415
416 var result = apply.call(
417 target,
418 this,
419 array_concat.call(args, array_slice.call(arguments))
420 );
421 if ($Object(result) === result) {
422 return result;
423 }
424 return this;
425
426 } else {
427 // 15.3.4.5.1 [[Call]]
428 // When the [[Call]] internal method of a function object, F,
429 // which was created using the bind function is called with a
430 // this value and a list of arguments ExtraArgs, the following
431 // steps are taken:
432 // 1. Let boundArgs be the value of F's [[BoundArgs]] internal
433 // property.
434 // 2. Let boundThis be the value of F's [[BoundThis]] internal
435 // property.
436 // 3. Let target be the value of F's [[TargetFunction]] internal
437 // property.
438 // 4. Let args be a new list containing the same values as the
439 // list boundArgs in the same order followed by the same
440 // values as the list ExtraArgs in the same order.
441 // 5. Return the result of calling the [[Call]] internal method
442 // of target providing boundThis as the this value and
443 // providing args as the arguments.
444
445 // equiv: target.call(this, ...boundArgs, ...args)
446 return apply.call(
447 target,
448 that,
449 array_concat.call(args, array_slice.call(arguments))
450 );
451
452 }
453
454 };
455
456 // 15. If the [[Class]] internal property of Target is "Function", then
457 // a. Let L be the length property of Target minus the length of A.
458 // b. Set the length own property of F to either 0 or L, whichever is
459 // larger.
460 // 16. Else set the length own property of F to 0.
461
462 var boundLength = max(0, target.length - args.length);
463
464 // 17. Set the attributes of the length own property of F to the values
465 // specified in 15.3.5.1.
466 var boundArgs = [];
467 for (var i = 0; i < boundLength; i++) {
468 array_push.call(boundArgs, '$' + i);
469 }
470
471 // XXX Build a dynamic function with desired amount of arguments is the only
472 // way to set the length property of a function.
473 // In environments where Content Security Policies enabled (Chrome extensions,
474 // for ex.) all use of eval or Function costructor throws an exception.
475 // However in all of these environments Function.prototype.bind exists
476 // and so this code will never be executed.
477 bound = $Function('binder', 'return function (' + array_join.call(boundArgs, ',') + '){ return binder.apply(this, arguments); }')(binder);
478
479 if (target.prototype) {
480 Empty.prototype = target.prototype;
481 bound.prototype = new Empty();
482 // Clean up dangling references.
483 Empty.prototype = null;
484 }
485
486 // TODO
487 // 18. Set the [[Extensible]] internal property of F to true.
488
489 // TODO
490 // 19. Let thrower be the [[ThrowTypeError]] function Object (13.2.3).
491 // 20. Call the [[DefineOwnProperty]] internal method of F with
492 // arguments "caller", PropertyDescriptor {[[Get]]: thrower, [[Set]]:
493 // thrower, [[Enumerable]]: false, [[Configurable]]: false}, and
494 // false.
495 // 21. Call the [[DefineOwnProperty]] internal method of F with
496 // arguments "arguments", PropertyDescriptor {[[Get]]: thrower,
497 // [[Set]]: thrower, [[Enumerable]]: false, [[Configurable]]: false},
498 // and false.
499
500 // TODO
501 // NOTE Function objects created using Function.prototype.bind do not
502 // have a prototype property or the [[Code]], [[FormalParameters]], and
503 // [[Scope]] internal properties.
504 // XXX can't delete prototype in pure-js.
505
506 // 22. Return F.
507 return bound;
508 }
509 });
510
511 // _Please note: Shortcuts are defined after `Function.prototype.bind` as we
512 // use it in defining shortcuts.
513 var owns = call.bind(ObjectPrototype.hasOwnProperty);
514 var toStr = call.bind(ObjectPrototype.toString);
515 var arraySlice = call.bind(array_slice);
516 var arraySliceApply = apply.bind(array_slice);
517 var strSlice = call.bind(StringPrototype.slice);
518 var strSplit = call.bind(StringPrototype.split);
519 var strIndexOf = call.bind(StringPrototype.indexOf);
520 var pushCall = call.bind(array_push);
521 var isEnum = call.bind(ObjectPrototype.propertyIsEnumerable);
522 var arraySort = call.bind(ArrayPrototype.sort);
523
524 //
525 // Array
526 // =====
527 //
528
529 var isArray = $Array.isArray || function isArray(obj) {
530 return toStr(obj) === '[object Array]';
531 };
532
533 // ES5 15.4.4.12
534 // http://es5.github.com/#x15.4.4.13
535 // Return len+argCount.
536 // [bugfix, ielt8]
537 // IE < 8 bug: [].unshift(0) === undefined but should be "1"
538 var hasUnshiftReturnValueBug = [].unshift(0) !== 1;
539 defineProperties(ArrayPrototype, {
540 unshift: function () {
541 array_unshift.apply(this, arguments);
542 return this.length;
543 }
544 }, hasUnshiftReturnValueBug);
545
546 // ES5 15.4.3.2
547 // http://es5.github.com/#x15.4.3.2
548 // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/isArray
549 defineProperties($Array, { isArray: isArray });
550
551 // The IsCallable() check in the Array functions
552 // has been replaced with a strict check on the
553 // internal class of the object to trap cases where
554 // the provided function was actually a regular
555 // expression literal, which in V8 and
556 // JavaScriptCore is a typeof "function". Only in
557 // V8 are regular expression literals permitted as
558 // reduce parameters, so it is desirable in the
559 // general case for the shim to match the more
560 // strict and common behavior of rejecting regular
561 // expressions.
562
563 // ES5 15.4.4.18
564 // http://es5.github.com/#x15.4.4.18
565 // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/array/forEach
566
567 // Check failure of by-index access of string characters (IE < 9)
568 // and failure of `0 in boxedString` (Rhino)
569 var boxedString = $Object('a');
570 var splitString = boxedString[0] !== 'a' || !(0 in boxedString);
571
572 var properlyBoxesContext = function properlyBoxed(method) {
573 // Check node 0.6.21 bug where third parameter is not boxed
574 var properlyBoxesNonStrict = true;
575 var properlyBoxesStrict = true;
576 var threwException = false;
577 if (method) {
578 try {
579 method.call('foo', function (_, __, context) {
580 if (typeof context !== 'object') {
581 properlyBoxesNonStrict = false;
582 }
583 });
584
585 method.call([1], function () {
586 'use strict';
587
588 properlyBoxesStrict = typeof this === 'string';
589 }, 'x');
590 } catch (e) {
591 threwException = true;
592 }
593 }
594 return !!method && !threwException && properlyBoxesNonStrict && properlyBoxesStrict;
595 };
596
597 defineProperties(ArrayPrototype, {
598 forEach: function forEach(callbackfn/*, thisArg*/) {
599 var object = ES.ToObject(this);
600 var self = splitString && isString(this) ? strSplit(this, '') : object;
601 var i = -1;
602 var length = ES.ToUint32(self.length);
603 var T;
604 if (arguments.length > 1) {
605 T = arguments[1];
606 }
607
608 // If no callback function or if callback is not a callable function
609 if (!isCallable(callbackfn)) {
610 throw new TypeError('Array.prototype.forEach callback must be a function');
611 }
612
613 while (++i < length) {
614 if (i in self) {
615 // Invoke the callback function with call, passing arguments:
616 // context, property value, property key, thisArg object
617 if (typeof T === 'undefined') {
618 callbackfn(self[i], i, object);
619 } else {
620 callbackfn.call(T, self[i], i, object);
621 }
622 }
623 }
624 }
625 }, !properlyBoxesContext(ArrayPrototype.forEach));
626
627 // ES5 15.4.4.19
628 // http://es5.github.com/#x15.4.4.19
629 // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/map
630 defineProperties(ArrayPrototype, {
631 map: function map(callbackfn/*, thisArg*/) {
632 var object = ES.ToObject(this);
633 var self = splitString && isString(this) ? strSplit(this, '') : object;
634 var length = ES.ToUint32(self.length);
635 var result = $Array(length);
636 var T;
637 if (arguments.length > 1) {
638 T = arguments[1];
639 }
640
641 // If no callback function or if callback is not a callable function
642 if (!isCallable(callbackfn)) {
643 throw new TypeError('Array.prototype.map callback must be a function');
644 }
645
646 for (var i = 0; i < length; i++) {
647 if (i in self) {
648 if (typeof T === 'undefined') {
649 result[i] = callbackfn(self[i], i, object);
650 } else {
651 result[i] = callbackfn.call(T, self[i], i, object);
652 }
653 }
654 }
655 return result;
656 }
657 }, !properlyBoxesContext(ArrayPrototype.map));
658
659 // ES5 15.4.4.20
660 // http://es5.github.com/#x15.4.4.20
661 // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/filter
662 defineProperties(ArrayPrototype, {
663 filter: function filter(callbackfn/*, thisArg*/) {
664 var object = ES.ToObject(this);
665 var self = splitString && isString(this) ? strSplit(this, '') : object;
666 var length = ES.ToUint32(self.length);
667 var result = [];
668 var value;
669 var T;
670 if (arguments.length > 1) {
671 T = arguments[1];
672 }
673
674 // If no callback function or if callback is not a callable function
675 if (!isCallable(callbackfn)) {
676 throw new TypeError('Array.prototype.filter callback must be a function');
677 }
678
679 for (var i = 0; i < length; i++) {
680 if (i in self) {
681 value = self[i];
682 if (typeof T === 'undefined' ? callbackfn(value, i, object) : callbackfn.call(T, value, i, object)) {
683 pushCall(result, value);
684 }
685 }
686 }
687 return result;
688 }
689 }, !properlyBoxesContext(ArrayPrototype.filter));
690
691 // ES5 15.4.4.16
692 // http://es5.github.com/#x15.4.4.16
693 // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/every
694 defineProperties(ArrayPrototype, {
695 every: function every(callbackfn/*, thisArg*/) {
696 var object = ES.ToObject(this);
697 var self = splitString && isString(this) ? strSplit(this, '') : object;
698 var length = ES.ToUint32(self.length);
699 var T;
700 if (arguments.length > 1) {
701 T = arguments[1];
702 }
703
704 // If no callback function or if callback is not a callable function
705 if (!isCallable(callbackfn)) {
706 throw new TypeError('Array.prototype.every callback must be a function');
707 }
708
709 for (var i = 0; i < length; i++) {
710 if (i in self && !(typeof T === 'undefined' ? callbackfn(self[i], i, object) : callbackfn.call(T, self[i], i, object))) {
711 return false;
712 }
713 }
714 return true;
715 }
716 }, !properlyBoxesContext(ArrayPrototype.every));
717
718 // ES5 15.4.4.17
719 // http://es5.github.com/#x15.4.4.17
720 // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/some
721 defineProperties(ArrayPrototype, {
722 some: function some(callbackfn/*, thisArg */) {
723 var object = ES.ToObject(this);
724 var self = splitString && isString(this) ? strSplit(this, '') : object;
725 var length = ES.ToUint32(self.length);
726 var T;
727 if (arguments.length > 1) {
728 T = arguments[1];
729 }
730
731 // If no callback function or if callback is not a callable function
732 if (!isCallable(callbackfn)) {
733 throw new TypeError('Array.prototype.some callback must be a function');
734 }
735
736 for (var i = 0; i < length; i++) {
737 if (i in self && (typeof T === 'undefined' ? callbackfn(self[i], i, object) : callbackfn.call(T, self[i], i, object))) {
738 return true;
739 }
740 }
741 return false;
742 }
743 }, !properlyBoxesContext(ArrayPrototype.some));
744
745 // ES5 15.4.4.21
746 // http://es5.github.com/#x15.4.4.21
747 // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduce
748 var reduceCoercesToObject = false;
749 if (ArrayPrototype.reduce) {
750 reduceCoercesToObject = typeof ArrayPrototype.reduce.call('es5', function (_, __, ___, list) {
751 return list;
752 }) === 'object';
753 }
754 defineProperties(ArrayPrototype, {
755 reduce: function reduce(callbackfn/*, initialValue*/) {
756 var object = ES.ToObject(this);
757 var self = splitString && isString(this) ? strSplit(this, '') : object;
758 var length = ES.ToUint32(self.length);
759
760 // If no callback function or if callback is not a callable function
761 if (!isCallable(callbackfn)) {
762 throw new TypeError('Array.prototype.reduce callback must be a function');
763 }
764
765 // no value to return if no initial value and an empty array
766 if (length === 0 && arguments.length === 1) {
767 throw new TypeError('reduce of empty array with no initial value');
768 }
769
770 var i = 0;
771 var result;
772 if (arguments.length >= 2) {
773 result = arguments[1];
774 } else {
775 do {
776 if (i in self) {
777 result = self[i++];
778 break;
779 }
780
781 // if array contains no values, no initial value to return
782 if (++i >= length) {
783 throw new TypeError('reduce of empty array with no initial value');
784 }
785 } while (true);
786 }
787
788 for (; i < length; i++) {
789 if (i in self) {
790 result = callbackfn(result, self[i], i, object);
791 }
792 }
793
794 return result;
795 }
796 }, !reduceCoercesToObject);
797
798 // ES5 15.4.4.22
799 // http://es5.github.com/#x15.4.4.22
800 // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduceRight
801 var reduceRightCoercesToObject = false;
802 if (ArrayPrototype.reduceRight) {
803 reduceRightCoercesToObject = typeof ArrayPrototype.reduceRight.call('es5', function (_, __, ___, list) {
804 return list;
805 }) === 'object';
806 }
807 defineProperties(ArrayPrototype, {
808 reduceRight: function reduceRight(callbackfn/*, initial*/) {
809 var object = ES.ToObject(this);
810 var self = splitString && isString(this) ? strSplit(this, '') : object;
811 var length = ES.ToUint32(self.length);
812
813 // If no callback function or if callback is not a callable function
814 if (!isCallable(callbackfn)) {
815 throw new TypeError('Array.prototype.reduceRight callback must be a function');
816 }
817
818 // no value to return if no initial value, empty array
819 if (length === 0 && arguments.length === 1) {
820 throw new TypeError('reduceRight of empty array with no initial value');
821 }
822
823 var result;
824 var i = length - 1;
825 if (arguments.length >= 2) {
826 result = arguments[1];
827 } else {
828 do {
829 if (i in self) {
830 result = self[i--];
831 break;
832 }
833
834 // if array contains no values, no initial value to return
835 if (--i < 0) {
836 throw new TypeError('reduceRight of empty array with no initial value');
837 }
838 } while (true);
839 }
840
841 if (i < 0) {
842 return result;
843 }
844
845 do {
846 if (i in self) {
847 result = callbackfn(result, self[i], i, object);
848 }
849 } while (i--);
850
851 return result;
852 }
853 }, !reduceRightCoercesToObject);
854
855 // ES5 15.4.4.14
856 // http://es5.github.com/#x15.4.4.14
857 // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf
858 var hasFirefox2IndexOfBug = ArrayPrototype.indexOf && [0, 1].indexOf(1, 2) !== -1;
859 defineProperties(ArrayPrototype, {
860 indexOf: function indexOf(searchElement/*, fromIndex */) {
861 var self = splitString && isString(this) ? strSplit(this, '') : ES.ToObject(this);
862 var length = ES.ToUint32(self.length);
863
864 if (length === 0) {
865 return -1;
866 }
867
868 var i = 0;
869 if (arguments.length > 1) {
870 i = ES.ToInteger(arguments[1]);
871 }
872
873 // handle negative indices
874 i = i >= 0 ? i : max(0, length + i);
875 for (; i < length; i++) {
876 if (i in self && self[i] === searchElement) {
877 return i;
878 }
879 }
880 return -1;
881 }
882 }, hasFirefox2IndexOfBug);
883
884 // ES5 15.4.4.15
885 // http://es5.github.com/#x15.4.4.15
886 // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/lastIndexOf
887 var hasFirefox2LastIndexOfBug = ArrayPrototype.lastIndexOf && [0, 1].lastIndexOf(0, -3) !== -1;
888 defineProperties(ArrayPrototype, {
889 lastIndexOf: function lastIndexOf(searchElement/*, fromIndex */) {
890 var self = splitString && isString(this) ? strSplit(this, '') : ES.ToObject(this);
891 var length = ES.ToUint32(self.length);
892
893 if (length === 0) {
894 return -1;
895 }
896 var i = length - 1;
897 if (arguments.length > 1) {
898 i = min(i, ES.ToInteger(arguments[1]));
899 }
900 // handle negative indices
901 i = i >= 0 ? i : length - Math.abs(i);
902 for (; i >= 0; i--) {
903 if (i in self && searchElement === self[i]) {
904 return i;
905 }
906 }
907 return -1;
908 }
909 }, hasFirefox2LastIndexOfBug);
910
911 // ES5 15.4.4.12
912 // http://es5.github.com/#x15.4.4.12
913 var spliceNoopReturnsEmptyArray = (function () {
914 var a = [1, 2];
915 var result = a.splice();
916 return a.length === 2 && isArray(result) && result.length === 0;
917 }());
918 defineProperties(ArrayPrototype, {
919 // Safari 5.0 bug where .splice() returns undefined
920 splice: function splice(start, deleteCount) {
921 if (arguments.length === 0) {
922 return [];
923 } else {
924 return array_splice.apply(this, arguments);
925 }
926 }
927 }, !spliceNoopReturnsEmptyArray);
928
929 var spliceWorksWithEmptyObject = (function () {
930 var obj = {};
931 ArrayPrototype.splice.call(obj, 0, 0, 1);
932 return obj.length === 1;
933 }());
934 defineProperties(ArrayPrototype, {
935 splice: function splice(start, deleteCount) {
936 if (arguments.length === 0) {
937 return [];
938 }
939 var args = arguments;
940 this.length = max(ES.ToInteger(this.length), 0);
941 if (arguments.length > 0 && typeof deleteCount !== 'number') {
942 args = arraySlice(arguments);
943 if (args.length < 2) {
944 pushCall(args, this.length - start);
945 } else {
946 args[1] = ES.ToInteger(deleteCount);
947 }
948 }
949 return array_splice.apply(this, args);
950 }
951 }, !spliceWorksWithEmptyObject);
952 var spliceWorksWithLargeSparseArrays = (function () {
953 // Per https://github.com/es-shims/es5-shim/issues/295
954 // Safari 7/8 breaks with sparse arrays of size 1e5 or greater
955 var arr = new $Array(1e5);
956 // note: the index MUST be 8 or larger or the test will false pass
957 arr[8] = 'x';
958 arr.splice(1, 1);
959 // note: this test must be defined *after* the indexOf shim
960 // per https://github.com/es-shims/es5-shim/issues/313
961 return arr.indexOf('x') === 7;
962 }());
963 var spliceWorksWithSmallSparseArrays = (function () {
964 // Per https://github.com/es-shims/es5-shim/issues/295
965 // Opera 12.15 breaks on this, no idea why.
966 var n = 256;
967 var arr = [];
968 arr[n] = 'a';
969 arr.splice(n + 1, 0, 'b');
970 return arr[n] === 'a';
971 }());
972 defineProperties(ArrayPrototype, {
973 splice: function splice(start, deleteCount) {
974 var O = ES.ToObject(this);
975 var A = [];
976 var len = ES.ToUint32(O.length);
977 var relativeStart = ES.ToInteger(start);
978 var actualStart = relativeStart < 0 ? max((len + relativeStart), 0) : min(relativeStart, len);
979 var actualDeleteCount = min(max(ES.ToInteger(deleteCount), 0), len - actualStart);
980
981 var k = 0;
982 var from;
983 while (k < actualDeleteCount) {
984 from = $String(actualStart + k);
985 if (owns(O, from)) {
986 A[k] = O[from];
987 }
988 k += 1;
989 }
990
991 var items = arraySlice(arguments, 2);
992 var itemCount = items.length;
993 var to;
994 if (itemCount < actualDeleteCount) {
995 k = actualStart;
996 var maxK = len - actualDeleteCount;
997 while (k < maxK) {
998 from = $String(k + actualDeleteCount);
999 to = $String(k + itemCount);
1000 if (owns(O, from)) {
1001 O[to] = O[from];
1002 } else {
1003 delete O[to];
1004 }
1005 k += 1;
1006 }
1007 k = len;
1008 var minK = len - actualDeleteCount + itemCount;
1009 while (k > minK) {
1010 delete O[k - 1];
1011 k -= 1;
1012 }
1013 } else if (itemCount > actualDeleteCount) {
1014 k = len - actualDeleteCount;
1015 while (k > actualStart) {
1016 from = $String(k + actualDeleteCount - 1);
1017 to = $String(k + itemCount - 1);
1018 if (owns(O, from)) {
1019 O[to] = O[from];
1020 } else {
1021 delete O[to];
1022 }
1023 k -= 1;
1024 }
1025 }
1026 k = actualStart;
1027 for (var i = 0; i < items.length; ++i) {
1028 O[k] = items[i];
1029 k += 1;
1030 }
1031 O.length = len - actualDeleteCount + itemCount;
1032
1033 return A;
1034 }
1035 }, !spliceWorksWithLargeSparseArrays || !spliceWorksWithSmallSparseArrays);
1036
1037 var originalJoin = ArrayPrototype.join;
1038 var hasStringJoinBug;
1039 try {
1040 hasStringJoinBug = Array.prototype.join.call('123', ',') !== '1,2,3';
1041 } catch (e) {
1042 hasStringJoinBug = true;
1043 }
1044 if (hasStringJoinBug) {
1045 defineProperties(ArrayPrototype, {
1046 join: function join(separator) {
1047 var sep = typeof separator === 'undefined' ? ',' : separator;
1048 return originalJoin.call(isString(this) ? strSplit(this, '') : this, sep);
1049 }
1050 }, hasStringJoinBug);
1051 }
1052
1053 var hasJoinUndefinedBug = [1, 2].join(undefined) !== '1,2';
1054 if (hasJoinUndefinedBug) {
1055 defineProperties(ArrayPrototype, {
1056 join: function join(separator) {
1057 var sep = typeof separator === 'undefined' ? ',' : separator;
1058 return originalJoin.call(this, sep);
1059 }
1060 }, hasJoinUndefinedBug);
1061 }
1062
1063 var pushShim = function push(item) {
1064 var O = ES.ToObject(this);
1065 var n = ES.ToUint32(O.length);
1066 var i = 0;
1067 while (i < arguments.length) {
1068 O[n + i] = arguments[i];
1069 i += 1;
1070 }
1071 O.length = n + i;
1072 return n + i;
1073 };
1074
1075 var pushIsNotGeneric = (function () {
1076 var obj = {};
1077 var result = Array.prototype.push.call(obj, undefined);
1078 return result !== 1 || obj.length !== 1 || typeof obj[0] !== 'undefined' || !owns(obj, 0);
1079 }());
1080 defineProperties(ArrayPrototype, {
1081 push: function push(item) {
1082 if (isArray(this)) {
1083 return array_push.apply(this, arguments);
1084 }
1085 return pushShim.apply(this, arguments);
1086 }
1087 }, pushIsNotGeneric);
1088
1089 // This fixes a very weird bug in Opera 10.6 when pushing `undefined
1090 var pushUndefinedIsWeird = (function () {
1091 var arr = [];
1092 var result = arr.push(undefined);
1093 return result !== 1 || arr.length !== 1 || typeof arr[0] !== 'undefined' || !owns(arr, 0);
1094 }());
1095 defineProperties(ArrayPrototype, { push: pushShim }, pushUndefinedIsWeird);
1096
1097 // ES5 15.2.3.14
1098 // http://es5.github.io/#x15.4.4.10
1099 // Fix boxed string bug
1100 defineProperties(ArrayPrototype, {
1101 slice: function (start, end) {
1102 var arr = isString(this) ? strSplit(this, '') : this;
1103 return arraySliceApply(arr, arguments);
1104 }
1105 }, splitString);
1106
1107 var sortIgnoresNonFunctions = (function () {
1108 try {
1109 [1, 2].sort(null);
1110 [1, 2].sort({});
1111 return true;
1112 } catch (e) {}
1113 return false;
1114 }());
1115 var sortThrowsOnRegex = (function () {
1116 // this is a problem in Firefox 4, in which `typeof /a/ === 'function'`
1117 try {
1118 [1, 2].sort(/a/);
1119 return false;
1120 } catch (e) {}
1121 return true;
1122 }());
1123 var sortIgnoresUndefined = (function () {
1124 // applies in IE 8, for one.
1125 try {
1126 [1, 2].sort(undefined);
1127 return true;
1128 } catch (e) {}
1129 return false;
1130 }());
1131 defineProperties(ArrayPrototype, {
1132 sort: function sort(compareFn) {
1133 if (typeof compareFn === 'undefined') {
1134 return arraySort(this);
1135 }
1136 if (!isCallable(compareFn)) {
1137 throw new TypeError('Array.prototype.sort callback must be a function');
1138 }
1139 return arraySort(this, compareFn);
1140 }
1141 }, sortIgnoresNonFunctions || !sortIgnoresUndefined || !sortThrowsOnRegex);
1142
1143 //
1144 // Object
1145 // ======
1146 //
1147
1148 // ES5 15.2.3.14
1149 // http://es5.github.com/#x15.2.3.14
1150
1151 // http://whattheheadsaid.com/2010/10/a-safer-object-keys-compatibility-implementation
1152 var hasDontEnumBug = !isEnum({ 'toString': null }, 'toString');
1153 var hasProtoEnumBug = isEnum(function () {}, 'prototype');
1154 var hasStringEnumBug = !owns('x', '0');
1155 var equalsConstructorPrototype = function (o) {
1156 var ctor = o.constructor;
1157 return ctor && ctor.prototype === o;
1158 };
1159 var blacklistedKeys = {
1160 $window: true,
1161 $console: true,
1162 $parent: true,
1163 $self: true,
1164 $frame: true,
1165 $frames: true,
1166 $frameElement: true,
1167 $webkitIndexedDB: true,
1168 $webkitStorageInfo: true,
1169 $external: true
1170 };
1171 var hasAutomationEqualityBug = (function () {
1172 /* globals window */
1173 if (typeof window === 'undefined') {
1174 return false;
1175 }
1176 for (var k in window) {
1177 try {
1178 if (!blacklistedKeys['$' + k] && owns(window, k) && window[k] !== null && typeof window[k] === 'object') {
1179 equalsConstructorPrototype(window[k]);
1180 }
1181 } catch (e) {
1182 return true;
1183 }
1184 }
1185 return false;
1186 }());
1187 var equalsConstructorPrototypeIfNotBuggy = function (object) {
1188 if (typeof window === 'undefined' || !hasAutomationEqualityBug) {
1189 return equalsConstructorPrototype(object);
1190 }
1191 try {
1192 return equalsConstructorPrototype(object);
1193 } catch (e) {
1194 return false;
1195 }
1196 };
1197 var dontEnums = [
1198 'toString',
1199 'toLocaleString',
1200 'valueOf',
1201 'hasOwnProperty',
1202 'isPrototypeOf',
1203 'propertyIsEnumerable',
1204 'constructor'
1205 ];
1206 var dontEnumsLength = dontEnums.length;
1207
1208 // taken directly from https://github.com/ljharb/is-arguments/blob/master/index.js
1209 // can be replaced with require('is-arguments') if we ever use a build process instead
1210 var isStandardArguments = function isArguments(value) {
1211 return toStr(value) === '[object Arguments]';
1212 };
1213 var isLegacyArguments = function isArguments(value) {
1214 return value !== null &&
1215 typeof value === 'object' &&
1216 typeof value.length === 'number' &&
1217 value.length >= 0 &&
1218 !isArray(value) &&
1219 isCallable(value.callee);
1220 };
1221 var isArguments = isStandardArguments(arguments) ? isStandardArguments : isLegacyArguments;
1222
1223 defineProperties($Object, {
1224 keys: function keys(object) {
1225 var isFn = isCallable(object);
1226 var isArgs = isArguments(object);
1227 var isObject = object !== null && typeof object === 'object';
1228 var isStr = isObject && isString(object);
1229
1230 if (!isObject && !isFn && !isArgs) {
1231 throw new TypeError('Object.keys called on a non-object');
1232 }
1233
1234 var theKeys = [];
1235 var skipProto = hasProtoEnumBug && isFn;
1236 if ((isStr && hasStringEnumBug) || isArgs) {
1237 for (var i = 0; i < object.length; ++i) {
1238 pushCall(theKeys, $String(i));
1239 }
1240 }
1241
1242 if (!isArgs) {
1243 for (var name in object) {
1244 if (!(skipProto && name === 'prototype') && owns(object, name)) {
1245 pushCall(theKeys, $String(name));
1246 }
1247 }
1248 }
1249
1250 if (hasDontEnumBug) {
1251 var skipConstructor = equalsConstructorPrototypeIfNotBuggy(object);
1252 for (var j = 0; j < dontEnumsLength; j++) {
1253 var dontEnum = dontEnums[j];
1254 if (!(skipConstructor && dontEnum === 'constructor') && owns(object, dontEnum)) {
1255 pushCall(theKeys, dontEnum);
1256 }
1257 }
1258 }
1259 return theKeys;
1260 }
1261 });
1262
1263 var keysWorksWithArguments = $Object.keys && (function () {
1264 // Safari 5.0 bug
1265 return $Object.keys(arguments).length === 2;
1266 }(1, 2));
1267 var keysHasArgumentsLengthBug = $Object.keys && (function () {
1268 var argKeys = $Object.keys(arguments);
1269 return arguments.length !== 1 || argKeys.length !== 1 || argKeys[0] !== 1;
1270 }(1));
1271 var originalKeys = $Object.keys;
1272 defineProperties($Object, {
1273 keys: function keys(object) {
1274 if (isArguments(object)) {
1275 return originalKeys(arraySlice(object));
1276 } else {
1277 return originalKeys(object);
1278 }
1279 }
1280 }, !keysWorksWithArguments || keysHasArgumentsLengthBug);
1281
1282 //
1283 // Date
1284 // ====
1285 //
1286
1287 var hasNegativeMonthYearBug = new Date(-3509827329600292).getUTCMonth() !== 0;
1288 var aNegativeTestDate = new Date(-1509842289600292);
1289 var aPositiveTestDate = new Date(1449662400000);
1290 var hasToUTCStringFormatBug = aNegativeTestDate.toUTCString() !== 'Mon, 01 Jan -45875 11:59:59 GMT';
1291 var hasToDateStringFormatBug;
1292 var hasToStringFormatBug;
1293 var timeZoneOffset = aNegativeTestDate.getTimezoneOffset();
1294 if (timeZoneOffset < -720) {
1295 hasToDateStringFormatBug = aNegativeTestDate.toDateString() !== 'Tue Jan 02 -45875';
1296 hasToStringFormatBug = !(/^Thu Dec 10 2015 \d\d:\d\d:\d\d GMT[-\+]\d\d\d\d(?: |$)/).test(aPositiveTestDate.toString());
1297 } else {
1298 hasToDateStringFormatBug = aNegativeTestDate.toDateString() !== 'Mon Jan 01 -45875';
1299 hasToStringFormatBug = !(/^Wed Dec 09 2015 \d\d:\d\d:\d\d GMT[-\+]\d\d\d\d(?: |$)/).test(aPositiveTestDate.toString());
1300 }
1301
1302 var originalGetFullYear = call.bind(Date.prototype.getFullYear);
1303 var originalGetMonth = call.bind(Date.prototype.getMonth);
1304 var originalGetDate = call.bind(Date.prototype.getDate);
1305 var originalGetUTCFullYear = call.bind(Date.prototype.getUTCFullYear);
1306 var originalGetUTCMonth = call.bind(Date.prototype.getUTCMonth);
1307 var originalGetUTCDate = call.bind(Date.prototype.getUTCDate);
1308 var originalGetUTCDay = call.bind(Date.prototype.getUTCDay);
1309 var originalGetUTCHours = call.bind(Date.prototype.getUTCHours);
1310 var originalGetUTCMinutes = call.bind(Date.prototype.getUTCMinutes);
1311 var originalGetUTCSeconds = call.bind(Date.prototype.getUTCSeconds);
1312 var originalGetUTCMilliseconds = call.bind(Date.prototype.getUTCMilliseconds);
1313 var dayName = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
1314 var monthName = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
1315 var daysInMonth = function daysInMonth(month, year) {
1316 return originalGetDate(new Date(year, month, 0));
1317 };
1318
1319 defineProperties(Date.prototype, {
1320 getFullYear: function getFullYear() {
1321 if (!this || !(this instanceof Date)) {
1322 throw new TypeError('this is not a Date object.');
1323 }
1324 var year = originalGetFullYear(this);
1325 if (year < 0 && originalGetMonth(this) > 11) {
1326 return year + 1;
1327 }
1328 return year;
1329 },
1330 getMonth: function getMonth() {
1331 if (!this || !(this instanceof Date)) {
1332 throw new TypeError('this is not a Date object.');
1333 }
1334 var year = originalGetFullYear(this);
1335 var month = originalGetMonth(this);
1336 if (year < 0 && month > 11) {
1337 return 0;
1338 }
1339 return month;
1340 },
1341 getDate: function getDate() {
1342 if (!this || !(this instanceof Date)) {
1343 throw new TypeError('this is not a Date object.');
1344 }
1345 var year = originalGetFullYear(this);
1346 var month = originalGetMonth(this);
1347 var date = originalGetDate(this);
1348 if (year < 0 && month > 11) {
1349 if (month === 12) {
1350 return date;
1351 }
1352 var days = daysInMonth(0, year + 1);
1353 return (days - date) + 1;
1354 }
1355 return date;
1356 },
1357 getUTCFullYear: function getUTCFullYear() {
1358 if (!this || !(this instanceof Date)) {
1359 throw new TypeError('this is not a Date object.');
1360 }
1361 var year = originalGetUTCFullYear(this);
1362 if (year < 0 && originalGetUTCMonth(this) > 11) {
1363 return year + 1;
1364 }
1365 return year;
1366 },
1367 getUTCMonth: function getUTCMonth() {
1368 if (!this || !(this instanceof Date)) {
1369 throw new TypeError('this is not a Date object.');
1370 }
1371 var year = originalGetUTCFullYear(this);
1372 var month = originalGetUTCMonth(this);
1373 if (year < 0 && month > 11) {
1374 return 0;
1375 }
1376 return month;
1377 },
1378 getUTCDate: function getUTCDate() {
1379 if (!this || !(this instanceof Date)) {
1380 throw new TypeError('this is not a Date object.');
1381 }
1382 var year = originalGetUTCFullYear(this);
1383 var month = originalGetUTCMonth(this);
1384 var date = originalGetUTCDate(this);
1385 if (year < 0 && month > 11) {
1386 if (month === 12) {
1387 return date;
1388 }
1389 var days = daysInMonth(0, year + 1);
1390 return (days - date) + 1;
1391 }
1392 return date;
1393 }
1394 }, hasNegativeMonthYearBug);
1395
1396 defineProperties(Date.prototype, {
1397 toUTCString: function toUTCString() {
1398 if (!this || !(this instanceof Date)) {
1399 throw new TypeError('this is not a Date object.');
1400 }
1401 var day = originalGetUTCDay(this);
1402 var date = originalGetUTCDate(this);
1403 var month = originalGetUTCMonth(this);
1404 var year = originalGetUTCFullYear(this);
1405 var hour = originalGetUTCHours(this);
1406 var minute = originalGetUTCMinutes(this);
1407 var second = originalGetUTCSeconds(this);
1408 return dayName[day] + ', ' +
1409 (date < 10 ? '0' + date : date) + ' ' +
1410 monthName[month] + ' ' +
1411 year + ' ' +
1412 (hour < 10 ? '0' + hour : hour) + ':' +
1413 (minute < 10 ? '0' + minute : minute) + ':' +
1414 (second < 10 ? '0' + second : second) + ' GMT';
1415 }
1416 }, hasNegativeMonthYearBug || hasToUTCStringFormatBug);
1417
1418 // Opera 12 has `,`
1419 defineProperties(Date.prototype, {
1420 toDateString: function toDateString() {
1421 if (!this || !(this instanceof Date)) {
1422 throw new TypeError('this is not a Date object.');
1423 }
1424 var day = this.getDay();
1425 var date = this.getDate();
1426 var month = this.getMonth();
1427 var year = this.getFullYear();
1428 return dayName[day] + ' ' +
1429 monthName[month] + ' ' +
1430 (date < 10 ? '0' + date : date) + ' ' +
1431 year;
1432 }
1433 }, hasNegativeMonthYearBug || hasToDateStringFormatBug);
1434
1435 // can't use defineProperties here because of toString enumeration issue in IE <= 8
1436 if (hasNegativeMonthYearBug || hasToStringFormatBug) {
1437 Date.prototype.toString = function toString() {
1438 if (!this || !(this instanceof Date)) {
1439 throw new TypeError('this is not a Date object.');
1440 }
1441 var day = this.getDay();
1442 var date = this.getDate();
1443 var month = this.getMonth();
1444 var year = this.getFullYear();
1445 var hour = this.getHours();
1446 var minute = this.getMinutes();
1447 var second = this.getSeconds();
1448 var timezoneOffset = this.getTimezoneOffset();
1449 var hoursOffset = Math.floor(Math.abs(timezoneOffset) / 60);
1450 var minutesOffset = Math.floor(Math.abs(timezoneOffset) % 60);
1451 return dayName[day] + ' ' +
1452 monthName[month] + ' ' +
1453 (date < 10 ? '0' + date : date) + ' ' +
1454 year + ' ' +
1455 (hour < 10 ? '0' + hour : hour) + ':' +
1456 (minute < 10 ? '0' + minute : minute) + ':' +
1457 (second < 10 ? '0' + second : second) + ' GMT' +
1458 (timezoneOffset > 0 ? '-' : '+') +
1459 (hoursOffset < 10 ? '0' + hoursOffset : hoursOffset) +
1460 (minutesOffset < 10 ? '0' + minutesOffset : minutesOffset);
1461 };
1462 if (supportsDescriptors) {
1463 $Object.defineProperty(Date.prototype, 'toString', {
1464 configurable: true,
1465 enumerable: false,
1466 writable: true
1467 });
1468 }
1469 }
1470
1471 // ES5 15.9.5.43
1472 // http://es5.github.com/#x15.9.5.43
1473 // This function returns a String value represent the instance in time
1474 // represented by this Date object. The format of the String is the Date Time
1475 // string format defined in 15.9.1.15. All fields are present in the String.
1476 // The time zone is always UTC, denoted by the suffix Z. If the time value of
1477 // this object is not a finite Number a RangeError exception is thrown.
1478 var negativeDate = -62198755200000;
1479 var negativeYearString = '-000001';
1480 var hasNegativeDateBug = Date.prototype.toISOString && new Date(negativeDate).toISOString().indexOf(negativeYearString) === -1;
1481 var hasSafari51DateBug = Date.prototype.toISOString && new Date(-1).toISOString() !== '1969-12-31T23:59:59.999Z';
1482
1483 var getTime = call.bind(Date.prototype.getTime);
1484
1485 defineProperties(Date.prototype, {
1486 toISOString: function toISOString() {
1487 if (!isFinite(this) || !isFinite(getTime(this))) {
1488 // Adope Photoshop requires the second check.
1489 throw new RangeError('Date.prototype.toISOString called on non-finite value.');
1490 }
1491
1492 var year = originalGetUTCFullYear(this);
1493
1494 var month = originalGetUTCMonth(this);
1495 // see https://github.com/es-shims/es5-shim/issues/111
1496 year += Math.floor(month / 12);
1497 month = (month % 12 + 12) % 12;
1498
1499 // the date time string format is specified in 15.9.1.15.
1500 var result = [month + 1, originalGetUTCDate(this), originalGetUTCHours(this), originalGetUTCMinutes(this), originalGetUTCSeconds(this)];
1501 year = (
1502 (year < 0 ? '-' : (year > 9999 ? '+' : '')) +
1503 strSlice('00000' + Math.abs(year), (0 <= year && year <= 9999) ? -4 : -6)
1504 );
1505
1506 for (var i = 0; i < result.length; ++i) {
1507 // pad months, days, hours, minutes, and seconds to have two digits.
1508 result[i] = strSlice('00' + result[i], -2);
1509 }
1510 // pad milliseconds to have three digits.
1511 return (
1512 year + '-' + arraySlice(result, 0, 2).join('-') +
1513 'T' + arraySlice(result, 2).join(':') + '.' +
1514 strSlice('000' + originalGetUTCMilliseconds(this), -3) + 'Z'
1515 );
1516 }
1517 }, hasNegativeDateBug || hasSafari51DateBug);
1518
1519 // ES5 15.9.5.44
1520 // http://es5.github.com/#x15.9.5.44
1521 // This function provides a String representation of a Date object for use by
1522 // JSON.stringify (15.12.3).
1523 var dateToJSONIsSupported = (function () {
1524 try {
1525 return Date.prototype.toJSON &&
1526 new Date(NaN).toJSON() === null &&
1527 new Date(negativeDate).toJSON().indexOf(negativeYearString) !== -1 &&
1528 Date.prototype.toJSON.call({ // generic
1529 toISOString: function () { return true; }
1530 });
1531 } catch (e) {
1532 return false;
1533 }
1534 }());
1535 if (!dateToJSONIsSupported) {
1536 Date.prototype.toJSON = function toJSON(key) {
1537 // When the toJSON method is called with argument key, the following
1538 // steps are taken:
1539
1540 // 1. Let O be the result of calling ToObject, giving it the this
1541 // value as its argument.
1542 // 2. Let tv be ES.ToPrimitive(O, hint Number).
1543 var O = $Object(this);
1544 var tv = ES.ToPrimitive(O);
1545 // 3. If tv is a Number and is not finite, return null.
1546 if (typeof tv === 'number' && !isFinite(tv)) {
1547 return null;
1548 }
1549 // 4. Let toISO be the result of calling the [[Get]] internal method of
1550 // O with argument "toISOString".
1551 var toISO = O.toISOString;
1552 // 5. If IsCallable(toISO) is false, throw a TypeError exception.
1553 if (!isCallable(toISO)) {
1554 throw new TypeError('toISOString property is not callable');
1555 }
1556 // 6. Return the result of calling the [[Call]] internal method of
1557 // toISO with O as the this value and an empty argument list.
1558 return toISO.call(O);
1559
1560 // NOTE 1 The argument is ignored.
1561
1562 // NOTE 2 The toJSON function is intentionally generic; it does not
1563 // require that its this value be a Date object. Therefore, it can be
1564 // transferred to other kinds of objects for use as a method. However,
1565 // it does require that any such object have a toISOString method. An
1566 // object is free to use the argument key to filter its
1567 // stringification.
1568 };
1569 }
1570
1571 // ES5 15.9.4.2
1572 // http://es5.github.com/#x15.9.4.2
1573 // based on work shared by Daniel Friesen (dantman)
1574 // http://gist.github.com/303249
1575 var supportsExtendedYears = Date.parse('+033658-09-27T01:46:40.000Z') === 1e15;
1576 var acceptsInvalidDates = !isNaN(Date.parse('2012-04-04T24:00:00.500Z')) || !isNaN(Date.parse('2012-11-31T23:59:59.000Z')) || !isNaN(Date.parse('2012-12-31T23:59:60.000Z'));
1577 var doesNotParseY2KNewYear = isNaN(Date.parse('2000-01-01T00:00:00.000Z'));
1578 if (doesNotParseY2KNewYear || acceptsInvalidDates || !supportsExtendedYears) {
1579 // XXX global assignment won't work in embeddings that use
1580 // an alternate object for the context.
1581 /* global Date: true */
1582 /* eslint-disable no-undef */
1583 var maxSafeUnsigned32Bit = Math.pow(2, 31) - 1;
1584 var hasSafariSignedIntBug = isActualNaN(new Date(1970, 0, 1, 0, 0, 0, maxSafeUnsigned32Bit + 1).getTime());
1585 /* eslint-disable no-implicit-globals */
1586 Date = (function (NativeDate) {
1587 /* eslint-enable no-implicit-globals */
1588 /* eslint-enable no-undef */
1589 // Date.length === 7
1590 var DateShim = function Date(Y, M, D, h, m, s, ms) {
1591 var length = arguments.length;
1592 var date;
1593 if (this instanceof NativeDate) {
1594 var seconds = s;
1595 var millis = ms;
1596 if (hasSafariSignedIntBug && length >= 7 && ms > maxSafeUnsigned32Bit) {
1597 // work around a Safari 8/9 bug where it treats the seconds as signed
1598 var msToShift = Math.floor(ms / maxSafeUnsigned32Bit) * maxSafeUnsigned32Bit;
1599 var sToShift = Math.floor(msToShift / 1e3);
1600 seconds += sToShift;
1601 millis -= sToShift * 1e3;
1602 }
1603 date = length === 1 && $String(Y) === Y ? // isString(Y)
1604 // We explicitly pass it through parse:
1605 new NativeDate(DateShim.parse(Y)) :
1606 // We have to manually make calls depending on argument
1607 // length here
1608 length >= 7 ? new NativeDate(Y, M, D, h, m, seconds, millis) :
1609 length >= 6 ? new NativeDate(Y, M, D, h, m, seconds) :
1610 length >= 5 ? new NativeDate(Y, M, D, h, m) :
1611 length >= 4 ? new NativeDate(Y, M, D, h) :
1612 length >= 3 ? new NativeDate(Y, M, D) :
1613 length >= 2 ? new NativeDate(Y, M) :
1614 length >= 1 ? new NativeDate(Y instanceof NativeDate ? +Y : Y) :
1615 new NativeDate();
1616 } else {
1617 date = NativeDate.apply(this, arguments);
1618 }
1619 if (!isPrimitive(date)) {
1620 // Prevent mixups with unfixed Date object
1621 defineProperties(date, { constructor: DateShim }, true);
1622 }
1623 return date;
1624 };
1625
1626 // 15.9.1.15 Date Time String Format.
1627 var isoDateExpression = new RegExp('^' +
1628 '(\\d{4}|[+-]\\d{6})' + // four-digit year capture or sign +
1629 // 6-digit extended year
1630 '(?:-(\\d{2})' + // optional month capture
1631 '(?:-(\\d{2})' + // optional day capture
1632 '(?:' + // capture hours:minutes:seconds.milliseconds
1633 'T(\\d{2})' + // hours capture
1634 ':(\\d{2})' + // minutes capture
1635 '(?:' + // optional :seconds.milliseconds
1636 ':(\\d{2})' + // seconds capture
1637 '(?:(\\.\\d{1,}))?' + // milliseconds capture
1638 ')?' +
1639 '(' + // capture UTC offset component
1640 'Z|' + // UTC capture
1641 '(?:' + // offset specifier +/-hours:minutes
1642 '([-+])' + // sign capture
1643 '(\\d{2})' + // hours offset capture
1644 ':(\\d{2})' + // minutes offset capture
1645 ')' +
1646 ')?)?)?)?' +
1647 '$');
1648
1649 var months = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365];
1650
1651 var dayFromMonth = function dayFromMonth(year, month) {
1652 var t = month > 1 ? 1 : 0;
1653 return (
1654 months[month] +
1655 Math.floor((year - 1969 + t) / 4) -
1656 Math.floor((year - 1901 + t) / 100) +
1657 Math.floor((year - 1601 + t) / 400) +
1658 365 * (year - 1970)
1659 );
1660 };
1661
1662 var toUTC = function toUTC(t) {
1663 var s = 0;
1664 var ms = t;
1665 if (hasSafariSignedIntBug && ms > maxSafeUnsigned32Bit) {
1666 // work around a Safari 8/9 bug where it treats the seconds as signed
1667 var msToShift = Math.floor(ms / maxSafeUnsigned32Bit) * maxSafeUnsigned32Bit;
1668 var sToShift = Math.floor(msToShift / 1e3);
1669 s += sToShift;
1670 ms -= sToShift * 1e3;
1671 }
1672 return $Number(new NativeDate(1970, 0, 1, 0, 0, s, ms));
1673 };
1674
1675 // Copy any custom methods a 3rd party library may have added
1676 for (var key in NativeDate) {
1677 if (owns(NativeDate, key)) {
1678 DateShim[key] = NativeDate[key];
1679 }
1680 }
1681
1682 // Copy "native" methods explicitly; they may be non-enumerable
1683 defineProperties(DateShim, {
1684 now: NativeDate.now,
1685 UTC: NativeDate.UTC
1686 }, true);
1687 DateShim.prototype = NativeDate.prototype;
1688 defineProperties(DateShim.prototype, {
1689 constructor: DateShim
1690 }, true);
1691
1692 // Upgrade Date.parse to handle simplified ISO 8601 strings
1693 var parseShim = function parse(string) {
1694 var match = isoDateExpression.exec(string);
1695 if (match) {
1696 // parse months, days, hours, minutes, seconds, and milliseconds
1697 // provide default values if necessary
1698 // parse the UTC offset component
1699 var year = $Number(match[1]),
1700 month = $Number(match[2] || 1) - 1,
1701 day = $Number(match[3] || 1) - 1,
1702 hour = $Number(match[4] || 0),
1703 minute = $Number(match[5] || 0),
1704 second = $Number(match[6] || 0),
1705 millisecond = Math.floor($Number(match[7] || 0) * 1000),
1706 // When time zone is missed, local offset should be used
1707 // (ES 5.1 bug)
1708 // see https://bugs.ecmascript.org/show_bug.cgi?id=112
1709 isLocalTime = Boolean(match[4] && !match[8]),
1710 signOffset = match[9] === '-' ? 1 : -1,
1711 hourOffset = $Number(match[10] || 0),
1712 minuteOffset = $Number(match[11] || 0),
1713 result;
1714 var hasMinutesOrSecondsOrMilliseconds = minute > 0 || second > 0 || millisecond > 0;
1715 if (
1716 hour < (hasMinutesOrSecondsOrMilliseconds ? 24 : 25) &&
1717 minute < 60 && second < 60 && millisecond < 1000 &&
1718 month > -1 && month < 12 && hourOffset < 24 &&
1719 minuteOffset < 60 && // detect invalid offsets
1720 day > -1 &&
1721 day < (dayFromMonth(year, month + 1) - dayFromMonth(year, month))
1722 ) {
1723 result = (
1724 (dayFromMonth(year, month) + day) * 24 +
1725 hour +
1726 hourOffset * signOffset
1727 ) * 60;
1728 result = (
1729 (result + minute + minuteOffset * signOffset) * 60 +
1730 second
1731 ) * 1000 + millisecond;
1732 if (isLocalTime) {
1733 result = toUTC(result);
1734 }
1735 if (-8.64e15 <= result && result <= 8.64e15) {
1736 return result;
1737 }
1738 }
1739 return NaN;
1740 }
1741 return NativeDate.parse.apply(this, arguments);
1742 };
1743 defineProperties(DateShim, { parse: parseShim });
1744
1745 return DateShim;
1746 }(Date));
1747 /* global Date: false */
1748 }
1749
1750 // ES5 15.9.4.4
1751 // http://es5.github.com/#x15.9.4.4
1752 if (!Date.now) {
1753 Date.now = function now() {
1754 return new Date().getTime();
1755 };
1756 }
1757
1758 //
1759 // Number
1760 // ======
1761 //
1762
1763 // ES5.1 15.7.4.5
1764 // http://es5.github.com/#x15.7.4.5
1765 var hasToFixedBugs = NumberPrototype.toFixed && (
1766 (0.00008).toFixed(3) !== '0.000' ||
1767 (0.9).toFixed(0) !== '1' ||
1768 (1.255).toFixed(2) !== '1.25' ||
1769 (1000000000000000128).toFixed(0) !== '1000000000000000128'
1770 );
1771
1772 var toFixedHelpers = {
1773 base: 1e7,
1774 size: 6,
1775 data: [0, 0, 0, 0, 0, 0],
1776 multiply: function multiply(n, c) {
1777 var i = -1;
1778 var c2 = c;
1779 while (++i < toFixedHelpers.size) {
1780 c2 += n * toFixedHelpers.data[i];
1781 toFixedHelpers.data[i] = c2 % toFixedHelpers.base;
1782 c2 = Math.floor(c2 / toFixedHelpers.base);
1783 }
1784 },
1785 divide: function divide(n) {
1786 var i = toFixedHelpers.size;
1787 var c = 0;
1788 while (--i >= 0) {
1789 c += toFixedHelpers.data[i];
1790 toFixedHelpers.data[i] = Math.floor(c / n);
1791 c = (c % n) * toFixedHelpers.base;
1792 }
1793 },
1794 numToString: function numToString() {
1795 var i = toFixedHelpers.size;
1796 var s = '';
1797 while (--i >= 0) {
1798 if (s !== '' || i === 0 || toFixedHelpers.data[i] !== 0) {
1799 var t = $String(toFixedHelpers.data[i]);
1800 if (s === '') {
1801 s = t;
1802 } else {
1803 s += strSlice('0000000', 0, 7 - t.length) + t;
1804 }
1805 }
1806 }
1807 return s;
1808 },
1809 pow: function pow(x, n, acc) {
1810 return (n === 0 ? acc : (n % 2 === 1 ? pow(x, n - 1, acc * x) : pow(x * x, n / 2, acc)));
1811 },
1812 log: function log(x) {
1813 var n = 0;
1814 var x2 = x;
1815 while (x2 >= 4096) {
1816 n += 12;
1817 x2 /= 4096;
1818 }
1819 while (x2 >= 2) {
1820 n += 1;
1821 x2 /= 2;
1822 }
1823 return n;
1824 }
1825 };
1826
1827 var toFixedShim = function toFixed(fractionDigits) {
1828 var f, x, s, m, e, z, j, k;
1829
1830 // Test for NaN and round fractionDigits down
1831 f = $Number(fractionDigits);
1832 f = isActualNaN(f) ? 0 : Math.floor(f);
1833
1834 if (f < 0 || f > 20) {
1835 throw new RangeError('Number.toFixed called with invalid number of decimals');
1836 }
1837
1838 x = $Number(this);
1839
1840 if (isActualNaN(x)) {
1841 return 'NaN';
1842 }
1843
1844 // If it is too big or small, return the string value of the number
1845 if (x <= -1e21 || x >= 1e21) {
1846 return $String(x);
1847 }
1848
1849 s = '';
1850
1851 if (x < 0) {
1852 s = '-';
1853 x = -x;
1854 }
1855
1856 m = '0';
1857
1858 if (x > 1e-21) {
1859 // 1e-21 < x < 1e21
1860 // -70 < log2(x) < 70
1861 e = toFixedHelpers.log(x * toFixedHelpers.pow(2, 69, 1)) - 69;
1862 z = (e < 0 ? x * toFixedHelpers.pow(2, -e, 1) : x / toFixedHelpers.pow(2, e, 1));
1863 z *= 0x10000000000000; // Math.pow(2, 52);
1864 e = 52 - e;
1865
1866 // -18 < e < 122
1867 // x = z / 2 ^ e
1868 if (e > 0) {
1869 toFixedHelpers.multiply(0, z);
1870 j = f;
1871
1872 while (j >= 7) {
1873 toFixedHelpers.multiply(1e7, 0);
1874 j -= 7;
1875 }
1876
1877 toFixedHelpers.multiply(toFixedHelpers.pow(10, j, 1), 0);
1878 j = e - 1;
1879
1880 while (j >= 23) {
1881 toFixedHelpers.divide(1 << 23);
1882 j -= 23;
1883 }
1884
1885 toFixedHelpers.divide(1 << j);
1886 toFixedHelpers.multiply(1, 1);
1887 toFixedHelpers.divide(2);
1888 m = toFixedHelpers.numToString();
1889 } else {
1890 toFixedHelpers.multiply(0, z);
1891 toFixedHelpers.multiply(1 << (-e), 0);
1892 m = toFixedHelpers.numToString() + strSlice('0.00000000000000000000', 2, 2 + f);
1893 }
1894 }
1895
1896 if (f > 0) {
1897 k = m.length;
1898
1899 if (k <= f) {
1900 m = s + strSlice('0.0000000000000000000', 0, f - k + 2) + m;
1901 } else {
1902 m = s + strSlice(m, 0, k - f) + '.' + strSlice(m, k - f);
1903 }
1904 } else {
1905 m = s + m;
1906 }
1907
1908 return m;
1909 };
1910 defineProperties(NumberPrototype, { toFixed: toFixedShim }, hasToFixedBugs);
1911
1912 var hasToPrecisionUndefinedBug = (function () {
1913 try {
1914 return 1.0.toPrecision(undefined) === '1';
1915 } catch (e) {
1916 return true;
1917 }
1918 }());
1919 var originalToPrecision = NumberPrototype.toPrecision;
1920 defineProperties(NumberPrototype, {
1921 toPrecision: function toPrecision(precision) {
1922 return typeof precision === 'undefined' ? originalToPrecision.call(this) : originalToPrecision.call(this, precision);
1923 }
1924 }, hasToPrecisionUndefinedBug);
1925
1926 //
1927 // String
1928 // ======
1929 //
1930
1931 // ES5 15.5.4.14
1932 // http://es5.github.com/#x15.5.4.14
1933
1934 // [bugfix, IE lt 9, firefox 4, Konqueror, Opera, obscure browsers]
1935 // Many browsers do not split properly with regular expressions or they
1936 // do not perform the split correctly under obscure conditions.
1937 // See http://blog.stevenlevithan.com/archives/cross-browser-split
1938 // I've tested in many browsers and this seems to cover the deviant ones:
1939 // 'ab'.split(/(?:ab)*/) should be ["", ""], not [""]
1940 // '.'.split(/(.?)(.?)/) should be ["", ".", "", ""], not ["", ""]
1941 // 'tesst'.split(/(s)*/) should be ["t", undefined, "e", "s", "t"], not
1942 // [undefined, "t", undefined, "e", ...]
1943 // ''.split(/.?/) should be [], not [""]
1944 // '.'.split(/()()/) should be ["."], not ["", "", "."]
1945
1946 if (
1947 'ab'.split(/(?:ab)*/).length !== 2 ||
1948 '.'.split(/(.?)(.?)/).length !== 4 ||
1949 'tesst'.split(/(s)*/)[1] === 't' ||
1950 'test'.split(/(?:)/, -1).length !== 4 ||
1951 ''.split(/.?/).length ||
1952 '.'.split(/()()/).length > 1
1953 ) {
1954 (function () {
1955 var compliantExecNpcg = typeof (/()??/).exec('')[1] === 'undefined'; // NPCG: nonparticipating capturing group
1956 var maxSafe32BitInt = Math.pow(2, 32) - 1;
1957
1958 StringPrototype.split = function (separator, limit) {
1959 var string = String(this);
1960 if (typeof separator === 'undefined' && limit === 0) {
1961 return [];
1962 }
1963
1964 // If `separator` is not a regex, use native split
1965 if (!isRegex(separator)) {
1966 return strSplit(this, separator, limit);
1967 }
1968
1969 var output = [];
1970 var flags = (separator.ignoreCase ? 'i' : '') +
1971 (separator.multiline ? 'm' : '') +
1972 (separator.unicode ? 'u' : '') + // in ES6
1973 (separator.sticky ? 'y' : ''), // Firefox 3+ and ES6
1974 lastLastIndex = 0,
1975 // Make `global` and avoid `lastIndex` issues by working with a copy
1976 separator2, match, lastIndex, lastLength;
1977 var separatorCopy = new RegExp(separator.source, flags + 'g');
1978 if (!compliantExecNpcg) {
1979 // Doesn't need flags gy, but they don't hurt
1980 separator2 = new RegExp('^' + separatorCopy.source + '$(?!\\s)', flags);
1981 }
1982 /* Values for `limit`, per the spec:
1983 * If undefined: 4294967295 // maxSafe32BitInt
1984 * If 0, Infinity, or NaN: 0
1985 * If positive number: limit = Math.floor(limit); if (limit > 4294967295) limit -= 4294967296;
1986 * If negative number: 4294967296 - Math.floor(Math.abs(limit))
1987 * If other: Type-convert, then use the above rules
1988 */
1989 var splitLimit = typeof limit === 'undefined' ? maxSafe32BitInt : ES.ToUint32(limit);
1990 match = separatorCopy.exec(string);
1991 while (match) {
1992 // `separatorCopy.lastIndex` is not reliable cross-browser
1993 lastIndex = match.index + match[0].length;
1994 if (lastIndex > lastLastIndex) {
1995 pushCall(output, strSlice(string, lastLastIndex, match.index));
1996 // Fix browsers whose `exec` methods don't consistently return `undefined` for
1997 // nonparticipating capturing groups
1998 if (!compliantExecNpcg && match.length > 1) {
1999 /* eslint-disable no-loop-func */
2000 match[0].replace(separator2, function () {
2001 for (var i = 1; i < arguments.length - 2; i++) {
2002 if (typeof arguments[i] === 'undefined') {
2003 match[i] = void 0;
2004 }
2005 }
2006 });
2007 /* eslint-enable no-loop-func */
2008 }
2009 if (match.length > 1 && match.index < string.length) {
2010 array_push.apply(output, arraySlice(match, 1));
2011 }
2012 lastLength = match[0].length;
2013 lastLastIndex = lastIndex;
2014 if (output.length >= splitLimit) {
2015 break;
2016 }
2017 }
2018 if (separatorCopy.lastIndex === match.index) {
2019 separatorCopy.lastIndex++; // Avoid an infinite loop
2020 }
2021 match = separatorCopy.exec(string);
2022 }
2023 if (lastLastIndex === string.length) {
2024 if (lastLength || !separatorCopy.test('')) {
2025 pushCall(output, '');
2026 }
2027 } else {
2028 pushCall(output, strSlice(string, lastLastIndex));
2029 }
2030 return output.length > splitLimit ? arraySlice(output, 0, splitLimit) : output;
2031 };
2032 }());
2033
2034 // [bugfix, chrome]
2035 // If separator is undefined, then the result array contains just one String,
2036 // which is the this value (converted to a String). If limit is not undefined,
2037 // then the output array is truncated so that it contains no more than limit
2038 // elements.
2039 // "0".split(undefined, 0) -> []
2040 } else if ('0'.split(void 0, 0).length) {
2041 StringPrototype.split = function split(separator, limit) {
2042 if (typeof separator === 'undefined' && limit === 0) {
2043 return [];
2044 }
2045 return strSplit(this, separator, limit);
2046 };
2047 }
2048
2049 var str_replace = StringPrototype.replace;
2050 var replaceReportsGroupsCorrectly = (function () {
2051 var groups = [];
2052 'x'.replace(/x(.)?/g, function (match, group) {
2053 pushCall(groups, group);
2054 });
2055 return groups.length === 1 && typeof groups[0] === 'undefined';
2056 }());
2057
2058 if (!replaceReportsGroupsCorrectly) {
2059 StringPrototype.replace = function replace(searchValue, replaceValue) {
2060 var isFn = isCallable(replaceValue);
2061 var hasCapturingGroups = isRegex(searchValue) && (/\)[*?]/).test(searchValue.source);
2062 if (!isFn || !hasCapturingGroups) {
2063 return str_replace.call(this, searchValue, replaceValue);
2064 } else {
2065 var wrappedReplaceValue = function (match) {
2066 var length = arguments.length;
2067 var originalLastIndex = searchValue.lastIndex;
2068 searchValue.lastIndex = 0;
2069 var args = searchValue.exec(match) || [];
2070 searchValue.lastIndex = originalLastIndex;
2071 pushCall(args, arguments[length - 2], arguments[length - 1]);
2072 return replaceValue.apply(this, args);
2073 };
2074 return str_replace.call(this, searchValue, wrappedReplaceValue);
2075 }
2076 };
2077 }
2078
2079 // ECMA-262, 3rd B.2.3
2080 // Not an ECMAScript standard, although ECMAScript 3rd Edition has a
2081 // non-normative section suggesting uniform semantics and it should be
2082 // normalized across all browsers
2083 // [bugfix, IE lt 9] IE < 9 substr() with negative value not working in IE
2084 var string_substr = StringPrototype.substr;
2085 var hasNegativeSubstrBug = ''.substr && '0b'.substr(-1) !== 'b';
2086 defineProperties(StringPrototype, {
2087 substr: function substr(start, length) {
2088 var normalizedStart = start;
2089 if (start < 0) {
2090 normalizedStart = max(this.length + start, 0);
2091 }
2092 return string_substr.call(this, normalizedStart, length);
2093 }
2094 }, hasNegativeSubstrBug);
2095
2096 // ES5 15.5.4.20
2097 // whitespace from: http://es5.github.io/#x15.5.4.20
2098 var ws = '\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003' +
2099 '\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028' +
2100 '\u2029\uFEFF';
2101 var zeroWidth = '\u200b';
2102 var wsRegexChars = '[' + ws + ']';
2103 var trimBeginRegexp = new RegExp('^' + wsRegexChars + wsRegexChars + '*');
2104 var trimEndRegexp = new RegExp(wsRegexChars + wsRegexChars + '*$');
2105 var hasTrimWhitespaceBug = StringPrototype.trim && (ws.trim() || !zeroWidth.trim());
2106 defineProperties(StringPrototype, {
2107 // http://blog.stevenlevithan.com/archives/faster-trim-javascript
2108 // http://perfectionkills.com/whitespace-deviations/
2109 trim: function trim() {
2110 if (typeof this === 'undefined' || this === null) {
2111 throw new TypeError("can't convert " + this + ' to object');
2112 }
2113 return $String(this).replace(trimBeginRegexp, '').replace(trimEndRegexp, '');
2114 }
2115 }, hasTrimWhitespaceBug);
2116 var trim = call.bind(String.prototype.trim);
2117
2118 var hasLastIndexBug = StringPrototype.lastIndexOf && 'abcあい'.lastIndexOf('あい', 2) !== -1;
2119 defineProperties(StringPrototype, {
2120 lastIndexOf: function lastIndexOf(searchString) {
2121 if (typeof this === 'undefined' || this === null) {
2122 throw new TypeError("can't convert " + this + ' to object');
2123 }
2124 var S = $String(this);
2125 var searchStr = $String(searchString);
2126 var numPos = arguments.length > 1 ? $Number(arguments[1]) : NaN;
2127 var pos = isActualNaN(numPos) ? Infinity : ES.ToInteger(numPos);
2128 var start = min(max(pos, 0), S.length);
2129 var searchLen = searchStr.length;
2130 var k = start + searchLen;
2131 while (k > 0) {
2132 k = max(0, k - searchLen);
2133 var index = strIndexOf(strSlice(S, k, start + searchLen), searchStr);
2134 if (index !== -1) {
2135 return k + index;
2136 }
2137 }
2138 return -1;
2139 }
2140 }, hasLastIndexBug);
2141
2142 var originalLastIndexOf = StringPrototype.lastIndexOf;
2143 defineProperties(StringPrototype, {
2144 lastIndexOf: function lastIndexOf(searchString) {
2145 return originalLastIndexOf.apply(this, arguments);
2146 }
2147 }, StringPrototype.lastIndexOf.length !== 1);
2148
2149 // ES-5 15.1.2.2
2150 /* eslint-disable radix */
2151 if (parseInt(ws + '08') !== 8 || parseInt(ws + '0x16') !== 22) {
2152 /* eslint-enable radix */
2153 /* global parseInt: true */
2154 parseInt = (function (origParseInt) {
2155 var hexRegex = /^[\-+]?0[xX]/;
2156 return function parseInt(str, radix) {
2157 var string = trim(String(str));
2158 var defaultedRadix = $Number(radix) || (hexRegex.test(string) ? 16 : 10);
2159 return origParseInt(string, defaultedRadix);
2160 };
2161 }(parseInt));
2162 }
2163
2164 // https://es5.github.io/#x15.1.2.3
2165 if (1 / parseFloat('-0') !== -Infinity) {
2166 /* global parseFloat: true */
2167 parseFloat = (function (origParseFloat) {
2168 return function parseFloat(string) {
2169 var inputString = trim(String(string));
2170 var result = origParseFloat(inputString);
2171 return result === 0 && strSlice(inputString, 0, 1) === '-' ? -0 : result;
2172 };
2173 }(parseFloat));
2174 }
2175
2176 if (String(new RangeError('test')) !== 'RangeError: test') {
2177 var errorToStringShim = function toString() {
2178 if (typeof this === 'undefined' || this === null) {
2179 throw new TypeError("can't convert " + this + ' to object');
2180 }
2181 var name = this.name;
2182 if (typeof name === 'undefined') {
2183 name = 'Error';
2184 } else if (typeof name !== 'string') {
2185 name = $String(name);
2186 }
2187 var msg = this.message;
2188 if (typeof msg === 'undefined') {
2189 msg = '';
2190 } else if (typeof msg !== 'string') {
2191 msg = $String(msg);
2192 }
2193 if (!name) {
2194 return msg;
2195 }
2196 if (!msg) {
2197 return name;
2198 }
2199 return name + ': ' + msg;
2200 };
2201 // can't use defineProperties here because of toString enumeration issue in IE <= 8
2202 Error.prototype.toString = errorToStringShim;
2203 }
2204
2205 if (supportsDescriptors) {
2206 var ensureNonEnumerable = function (obj, prop) {
2207 if (isEnum(obj, prop)) {
2208 var desc = Object.getOwnPropertyDescriptor(obj, prop);
2209 if (desc.configurable) {
2210 desc.enumerable = false;
2211 Object.defineProperty(obj, prop, desc);
2212 }
2213 }
2214 };
2215 ensureNonEnumerable(Error.prototype, 'message');
2216 if (Error.prototype.message !== '') {
2217 Error.prototype.message = '';
2218 }
2219 ensureNonEnumerable(Error.prototype, 'name');
2220 }
2221
2222 if (String(/a/mig) !== '/a/gim') {
2223 var regexToString = function toString() {
2224 var str = '/' + this.source + '/';
2225 if (this.global) {
2226 str += 'g';
2227 }
2228 if (this.ignoreCase) {
2229 str += 'i';
2230 }
2231 if (this.multiline) {
2232 str += 'm';
2233 }
2234 return str;
2235 };
2236 // can't use defineProperties here because of toString enumeration issue in IE <= 8
2237 RegExp.prototype.toString = regexToString;
2238 }
2239 }));
2240
2241 },{}],4:[function(require,module,exports){
2242 // get successful control from form and assemble into object
2243 // http://www.w3.org/TR/html401/interact/forms.html#h-17.13.2
2244
2245 // types which indicate a submit action and are not successful controls
2246 // these will be ignored
2247 var k_r_submitter = /^(?:submit|button|image|reset|file)$/i;
2248
2249 // node names which could be successful controls
2250 var k_r_success_contrls = /^(?:input|select|textarea|keygen)/i;
2251
2252 // Matches bracket notation.
2253 var brackets = /(\[[^\[\]]*\])/g;
2254
2255 // serializes form fields
2256 // @param form MUST be an HTMLForm element
2257 // @param options is an optional argument to configure the serialization. Default output
2258 // with no options specified is a url encoded string
2259 // - hash: [true | false] Configure the output type. If true, the output will
2260 // be a js object.
2261 // - serializer: [function] Optional serializer function to override the default one.
2262 // The function takes 3 arguments (result, key, value) and should return new result
2263 // hash and url encoded str serializers are provided with this module
2264 // - disabled: [true | false]. If true serialize disabled fields.
2265 // - empty: [true | false]. If true serialize empty fields
2266 function serialize(form, options) {
2267 if (typeof options != 'object') {
2268 options = { hash: !!options };
2269 }
2270 else if (options.hash === undefined) {
2271 options.hash = true;
2272 }
2273
2274 var result = (options.hash) ? {} : '';
2275 var serializer = options.serializer || ((options.hash) ? hash_serializer : str_serialize);
2276
2277 var elements = form && form.elements ? form.elements : [];
2278
2279 //Object store each radio and set if it's empty or not
2280 var radio_store = Object.create(null);
2281
2282 for (var i=0 ; i<elements.length ; ++i) {
2283 var element = elements[i];
2284
2285 // ingore disabled fields
2286 if ((!options.disabled && element.disabled) || !element.name) {
2287 continue;
2288 }
2289 // ignore anyhting that is not considered a success field
2290 if (!k_r_success_contrls.test(element.nodeName) ||
2291 k_r_submitter.test(element.type)) {
2292 continue;
2293 }
2294
2295 var key = element.name;
2296 var val = element.value;
2297
2298 // we can't just use element.value for checkboxes cause some browsers lie to us
2299 // they say "on" for value when the box isn't checked
2300 if ((element.type === 'checkbox' || element.type === 'radio') && !element.checked) {
2301 val = undefined;
2302 }
2303
2304 // If we want empty elements
2305 if (options.empty) {
2306 // for checkbox
2307 if (element.type === 'checkbox' && !element.checked) {
2308 val = '';
2309 }
2310
2311 // for radio
2312 if (element.type === 'radio') {
2313 if (!radio_store[element.name] && !element.checked) {
2314 radio_store[element.name] = false;
2315 }
2316 else if (element.checked) {
2317 radio_store[element.name] = true;
2318 }
2319 }
2320
2321 // if options empty is true, continue only if its radio
2322 if (val == undefined && element.type == 'radio') {
2323 continue;
2324 }
2325 }
2326 else {
2327 // value-less fields are ignored unless options.empty is true
2328 if (!val) {
2329 continue;
2330 }
2331 }
2332
2333 // multi select boxes
2334 if (element.type === 'select-multiple') {
2335 val = [];
2336
2337 var selectOptions = element.options;
2338 var isSelectedOptions = false;
2339 for (var j=0 ; j<selectOptions.length ; ++j) {
2340 var option = selectOptions[j];
2341 var allowedEmpty = options.empty && !option.value;
2342 var hasValue = (option.value || allowedEmpty);
2343 if (option.selected && hasValue) {
2344 isSelectedOptions = true;
2345
2346 // If using a hash serializer be sure to add the
2347 // correct notation for an array in the multi-select
2348 // context. Here the name attribute on the select element
2349 // might be missing the trailing bracket pair. Both names
2350 // "foo" and "foo[]" should be arrays.
2351 if (options.hash && key.slice(key.length - 2) !== '[]') {
2352 result = serializer(result, key + '[]', option.value);
2353 }
2354 else {
2355 result = serializer(result, key, option.value);
2356 }
2357 }
2358 }
2359
2360 // Serialize if no selected options and options.empty is true
2361 if (!isSelectedOptions && options.empty) {
2362 result = serializer(result, key, '');
2363 }
2364
2365 continue;
2366 }
2367
2368 result = serializer(result, key, val);
2369 }
2370
2371 // Check for all empty radio buttons and serialize them with key=""
2372 if (options.empty) {
2373 for (var key in radio_store) {
2374 if (!radio_store[key]) {
2375 result = serializer(result, key, '');
2376 }
2377 }
2378 }
2379
2380 return result;
2381 }
2382
2383 function parse_keys(string) {
2384 var keys = [];
2385 var prefix = /^([^\[\]]*)/;
2386 var children = new RegExp(brackets);
2387 var match = prefix.exec(string);
2388
2389 if (match[1]) {
2390 keys.push(match[1]);
2391 }
2392
2393 while ((match = children.exec(string)) !== null) {
2394 keys.push(match[1]);
2395 }
2396
2397 return keys;
2398 }
2399
2400 function hash_assign(result, keys, value) {
2401 if (keys.length === 0) {
2402 result = value;
2403 return result;
2404 }
2405
2406 var key = keys.shift();
2407 var between = key.match(/^\[(.+?)\]$/);
2408
2409 if (key === '[]') {
2410 result = result || [];
2411
2412 if (Array.isArray(result)) {
2413 result.push(hash_assign(null, keys, value));
2414 }
2415 else {
2416 // This might be the result of bad name attributes like "[][foo]",
2417 // in this case the original `result` object will already be
2418 // assigned to an object literal. Rather than coerce the object to
2419 // an array, or cause an exception the attribute "_values" is
2420 // assigned as an array.
2421 result._values = result._values || [];
2422 result._values.push(hash_assign(null, keys, value));
2423 }
2424
2425 return result;
2426 }
2427
2428 // Key is an attribute name and can be assigned directly.
2429 if (!between) {
2430 result[key] = hash_assign(result[key], keys, value);
2431 }
2432 else {
2433 var string = between[1];
2434 // +var converts the variable into a number
2435 // better than parseInt because it doesn't truncate away trailing
2436 // letters and actually fails if whole thing is not a number
2437 var index = +string;
2438
2439 // If the characters between the brackets is not a number it is an
2440 // attribute name and can be assigned directly.
2441 if (isNaN(index)) {
2442 result = result || {};
2443 result[string] = hash_assign(result[string], keys, value);
2444 }
2445 else {
2446 result = result || [];
2447 result[index] = hash_assign(result[index], keys, value);
2448 }
2449 }
2450
2451 return result;
2452 }
2453
2454 // Object/hash encoding serializer.
2455 function hash_serializer(result, key, value) {
2456 var matches = key.match(brackets);
2457
2458 // Has brackets? Use the recursive assignment function to walk the keys,
2459 // construct any missing objects in the result tree and make the assignment
2460 // at the end of the chain.
2461 if (matches) {
2462 var keys = parse_keys(key);
2463 hash_assign(result, keys, value);
2464 }
2465 else {
2466 // Non bracket notation can make assignments directly.
2467 var existing = result[key];
2468
2469 // If the value has been assigned already (for instance when a radio and
2470 // a checkbox have the same name attribute) convert the previous value
2471 // into an array before pushing into it.
2472 //
2473 // NOTE: If this requirement were removed all hash creation and
2474 // assignment could go through `hash_assign`.
2475 if (existing) {
2476 if (!Array.isArray(existing)) {
2477 result[key] = [ existing ];
2478 }
2479
2480 result[key].push(value);
2481 }
2482 else {
2483 result[key] = value;
2484 }
2485 }
2486
2487 return result;
2488 }
2489
2490 // urlform encoding serializer
2491 function str_serialize(result, key, value) {
2492 // encode newlines as \r\n cause the html spec says so
2493 value = value.replace(/(\r)?\n/g, '\r\n');
2494 value = encodeURIComponent(value);
2495
2496 // spaces should be '+' rather than '%20'.
2497 value = value.replace(/%20/g, '+');
2498 return result + (result ? '&' : '') + encodeURIComponent(key) + '=' + value;
2499 }
2500
2501 module.exports = serialize;
2502
2503 },{}],5:[function(require,module,exports){
2504 /*!
2505 * EventEmitter v5.2.3 - git.io/ee
2506 * Unlicense - http://unlicense.org/
2507 * Oliver Caldwell - http://oli.me.uk/
2508 * @preserve
2509 */
2510
2511 ;(function (exports) {
2512 'use strict';
2513
2514 /**
2515 * Class for managing events.
2516 * Can be extended to provide event functionality in other classes.
2517 *
2518 * @class EventEmitter Manages event registering and emitting.
2519 */
2520 function EventEmitter() {}
2521
2522 // Shortcuts to improve speed and size
2523 var proto = EventEmitter.prototype;
2524 var originalGlobalValue = exports.EventEmitter;
2525
2526 /**
2527 * Finds the index of the listener for the event in its storage array.
2528 *
2529 * @param {Function[]} listeners Array of listeners to search through.
2530 * @param {Function} listener Method to look for.
2531 * @return {Number} Index of the specified listener, -1 if not found
2532 * @api private
2533 */
2534 function indexOfListener(listeners, listener) {
2535 var i = listeners.length;
2536 while (i--) {
2537 if (listeners[i].listener === listener) {
2538 return i;
2539 }
2540 }
2541
2542 return -1;
2543 }
2544
2545 /**
2546 * Alias a method while keeping the context correct, to allow for overwriting of target method.
2547 *
2548 * @param {String} name The name of the target method.
2549 * @return {Function} The aliased method
2550 * @api private
2551 */
2552 function alias(name) {
2553 return function aliasClosure() {
2554 return this[name].apply(this, arguments);
2555 };
2556 }
2557
2558 /**
2559 * Returns the listener array for the specified event.
2560 * Will initialise the event object and listener arrays if required.
2561 * Will return an object if you use a regex search. The object contains keys for each matched event. So /ba[rz]/ might return an object containing bar and baz. But only if you have either defined them with defineEvent or added some listeners to them.
2562 * Each property in the object response is an array of listener functions.
2563 *
2564 * @param {String|RegExp} evt Name of the event to return the listeners from.
2565 * @return {Function[]|Object} All listener functions for the event.
2566 */
2567 proto.getListeners = function getListeners(evt) {
2568 var events = this._getEvents();
2569 var response;
2570 var key;
2571
2572 // Return a concatenated array of all matching events if
2573 // the selector is a regular expression.
2574 if (evt instanceof RegExp) {
2575 response = {};
2576 for (key in events) {
2577 if (events.hasOwnProperty(key) && evt.test(key)) {
2578 response[key] = events[key];
2579 }
2580 }
2581 }
2582 else {
2583 response = events[evt] || (events[evt] = []);
2584 }
2585
2586 return response;
2587 };
2588
2589 /**
2590 * Takes a list of listener objects and flattens it into a list of listener functions.
2591 *
2592 * @param {Object[]} listeners Raw listener objects.
2593 * @return {Function[]} Just the listener functions.
2594 */
2595 proto.flattenListeners = function flattenListeners(listeners) {
2596 var flatListeners = [];
2597 var i;
2598
2599 for (i = 0; i < listeners.length; i += 1) {
2600 flatListeners.push(listeners[i].listener);
2601 }
2602
2603 return flatListeners;
2604 };
2605
2606 /**
2607 * Fetches the requested listeners via getListeners but will always return the results inside an object. This is mainly for internal use but others may find it useful.
2608 *
2609 * @param {String|RegExp} evt Name of the event to return the listeners from.
2610 * @return {Object} All listener functions for an event in an object.
2611 */
2612 proto.getListenersAsObject = function getListenersAsObject(evt) {
2613 var listeners = this.getListeners(evt);
2614 var response;
2615
2616 if (listeners instanceof Array) {
2617 response = {};
2618 response[evt] = listeners;
2619 }
2620
2621 return response || listeners;
2622 };
2623
2624 function isValidListener (listener) {
2625 if (typeof listener === 'function' || listener instanceof RegExp) {
2626 return true
2627 } else if (listener && typeof listener === 'object') {
2628 return isValidListener(listener.listener)
2629 } else {
2630 return false
2631 }
2632 }
2633
2634 /**
2635 * Adds a listener function to the specified event.
2636 * The listener will not be added if it is a duplicate.
2637 * If the listener returns true then it will be removed after it is called.
2638 * If you pass a regular expression as the event name then the listener will be added to all events that match it.
2639 *
2640 * @param {String|RegExp} evt Name of the event to attach the listener to.
2641 * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.
2642 * @return {Object} Current instance of EventEmitter for chaining.
2643 */
2644 proto.addListener = function addListener(evt, listener) {
2645 if (!isValidListener(listener)) {
2646 throw new TypeError('listener must be a function');
2647 }
2648
2649 var listeners = this.getListenersAsObject(evt);
2650 var listenerIsWrapped = typeof listener === 'object';
2651 var key;
2652
2653 for (key in listeners) {
2654 if (listeners.hasOwnProperty(key) && indexOfListener(listeners[key], listener) === -1) {
2655 listeners[key].push(listenerIsWrapped ? listener : {
2656 listener: listener,
2657 once: false
2658 });
2659 }
2660 }
2661
2662 return this;
2663 };
2664
2665 /**
2666 * Alias of addListener
2667 */
2668 proto.on = alias('addListener');
2669
2670 /**
2671 * Semi-alias of addListener. It will add a listener that will be
2672 * automatically removed after its first execution.
2673 *
2674 * @param {String|RegExp} evt Name of the event to attach the listener to.
2675 * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.
2676 * @return {Object} Current instance of EventEmitter for chaining.
2677 */
2678 proto.addOnceListener = function addOnceListener(evt, listener) {
2679 return this.addListener(evt, {
2680 listener: listener,
2681 once: true
2682 });
2683 };
2684
2685 /**
2686 * Alias of addOnceListener.
2687 */
2688 proto.once = alias('addOnceListener');
2689
2690 /**
2691 * Defines an event name. This is required if you want to use a regex to add a listener to multiple events at once. If you don't do this then how do you expect it to know what event to add to? Should it just add to every possible match for a regex? No. That is scary and bad.
2692 * You need to tell it what event names should be matched by a regex.
2693 *
2694 * @param {String} evt Name of the event to create.
2695 * @return {Object} Current instance of EventEmitter for chaining.
2696 */
2697 proto.defineEvent = function defineEvent(evt) {
2698 this.getListeners(evt);
2699 return this;
2700 };
2701
2702 /**
2703 * Uses defineEvent to define multiple events.
2704 *
2705 * @param {String[]} evts An array of event names to define.
2706 * @return {Object} Current instance of EventEmitter for chaining.
2707 */
2708 proto.defineEvents = function defineEvents(evts) {
2709 for (var i = 0; i < evts.length; i += 1) {
2710 this.defineEvent(evts[i]);
2711 }
2712 return this;
2713 };
2714
2715 /**
2716 * Removes a listener function from the specified event.
2717 * When passed a regular expression as the event name, it will remove the listener from all events that match it.
2718 *
2719 * @param {String|RegExp} evt Name of the event to remove the listener from.
2720 * @param {Function} listener Method to remove from the event.
2721 * @return {Object} Current instance of EventEmitter for chaining.
2722 */
2723 proto.removeListener = function removeListener(evt, listener) {
2724 var listeners = this.getListenersAsObject(evt);
2725 var index;
2726 var key;
2727
2728 for (key in listeners) {
2729 if (listeners.hasOwnProperty(key)) {
2730 index = indexOfListener(listeners[key], listener);
2731
2732 if (index !== -1) {
2733 listeners[key].splice(index, 1);
2734 }
2735 }
2736 }
2737
2738 return this;
2739 };
2740
2741 /**
2742 * Alias of removeListener
2743 */
2744 proto.off = alias('removeListener');
2745
2746 /**
2747 * Adds listeners in bulk using the manipulateListeners method.
2748 * If you pass an object as the first argument you can add to multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. You can also pass it an event name and an array of listeners to be added.
2749 * You can also pass it a regular expression to add the array of listeners to all events that match it.
2750 * Yeah, this function does quite a bit. That's probably a bad thing.
2751 *
2752 * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add to multiple events at once.
2753 * @param {Function[]} [listeners] An optional array of listener functions to add.
2754 * @return {Object} Current instance of EventEmitter for chaining.
2755 */
2756 proto.addListeners = function addListeners(evt, listeners) {
2757 // Pass through to manipulateListeners
2758 return this.manipulateListeners(false, evt, listeners);
2759 };
2760
2761 /**
2762 * Removes listeners in bulk using the manipulateListeners method.
2763 * If you pass an object as the first argument you can remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays.
2764 * You can also pass it an event name and an array of listeners to be removed.
2765 * You can also pass it a regular expression to remove the listeners from all events that match it.
2766 *
2767 * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to remove from multiple events at once.
2768 * @param {Function[]} [listeners] An optional array of listener functions to remove.
2769 * @return {Object} Current instance of EventEmitter for chaining.
2770 */
2771 proto.removeListeners = function removeListeners(evt, listeners) {
2772 // Pass through to manipulateListeners
2773 return this.manipulateListeners(true, evt, listeners);
2774 };
2775
2776 /**
2777 * Edits listeners in bulk. The addListeners and removeListeners methods both use this to do their job. You should really use those instead, this is a little lower level.
2778 * The first argument will determine if the listeners are removed (true) or added (false).
2779 * If you pass an object as the second argument you can add/remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays.
2780 * You can also pass it an event name and an array of listeners to be added/removed.
2781 * You can also pass it a regular expression to manipulate the listeners of all events that match it.
2782 *
2783 * @param {Boolean} remove True if you want to remove listeners, false if you want to add.
2784 * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add/remove from multiple events at once.
2785 * @param {Function[]} [listeners] An optional array of listener functions to add/remove.
2786 * @return {Object} Current instance of EventEmitter for chaining.
2787 */
2788 proto.manipulateListeners = function manipulateListeners(remove, evt, listeners) {
2789 var i;
2790 var value;
2791 var single = remove ? this.removeListener : this.addListener;
2792 var multiple = remove ? this.removeListeners : this.addListeners;
2793
2794 // If evt is an object then pass each of its properties to this method
2795 if (typeof evt === 'object' && !(evt instanceof RegExp)) {
2796 for (i in evt) {
2797 if (evt.hasOwnProperty(i) && (value = evt[i])) {
2798 // Pass the single listener straight through to the singular method
2799 if (typeof value === 'function') {
2800 single.call(this, i, value);
2801 }
2802 else {
2803 // Otherwise pass back to the multiple function
2804 multiple.call(this, i, value);
2805 }
2806 }
2807 }
2808 }
2809 else {
2810 // So evt must be a string
2811 // And listeners must be an array of listeners
2812 // Loop over it and pass each one to the multiple method
2813 i = listeners.length;
2814 while (i--) {
2815 single.call(this, evt, listeners[i]);
2816 }
2817 }
2818
2819 return this;
2820 };
2821
2822 /**
2823 * Removes all listeners from a specified event.
2824 * If you do not specify an event then all listeners will be removed.
2825 * That means every event will be emptied.
2826 * You can also pass a regex to remove all events that match it.
2827 *
2828 * @param {String|RegExp} [evt] Optional name of the event to remove all listeners for. Will remove from every event if not passed.
2829 * @return {Object} Current instance of EventEmitter for chaining.
2830 */
2831 proto.removeEvent = function removeEvent(evt) {
2832 var type = typeof evt;
2833 var events = this._getEvents();
2834 var key;
2835
2836 // Remove different things depending on the state of evt
2837 if (type === 'string') {
2838 // Remove all listeners for the specified event
2839 delete events[evt];
2840 }
2841 else if (evt instanceof RegExp) {
2842 // Remove all events matching the regex.
2843 for (key in events) {
2844 if (events.hasOwnProperty(key) && evt.test(key)) {
2845 delete events[key];
2846 }
2847 }
2848 }
2849 else {
2850 // Remove all listeners in all events
2851 delete this._events;
2852 }
2853
2854 return this;
2855 };
2856
2857 /**
2858 * Alias of removeEvent.
2859 *
2860 * Added to mirror the node API.
2861 */
2862 proto.removeAllListeners = alias('removeEvent');
2863
2864 /**
2865 * Emits an event of your choice.
2866 * When emitted, every listener attached to that event will be executed.
2867 * If you pass the optional argument array then those arguments will be passed to every listener upon execution.
2868 * Because it uses `apply`, your array of arguments will be passed as if you wrote them out separately.
2869 * So they will not arrive within the array on the other side, they will be separate.
2870 * You can also pass a regular expression to emit to all events that match it.
2871 *
2872 * @param {String|RegExp} evt Name of the event to emit and execute listeners for.
2873 * @param {Array} [args] Optional array of arguments to be passed to each listener.
2874 * @return {Object} Current instance of EventEmitter for chaining.
2875 */
2876 proto.emitEvent = function emitEvent(evt, args) {
2877 var listenersMap = this.getListenersAsObject(evt);
2878 var listeners;
2879 var listener;
2880 var i;
2881 var key;
2882 var response;
2883
2884 for (key in listenersMap) {
2885 if (listenersMap.hasOwnProperty(key)) {
2886 listeners = listenersMap[key].slice(0);
2887
2888 for (i = 0; i < listeners.length; i++) {
2889 // If the listener returns true then it shall be removed from the event
2890 // The function is executed either with a basic call or an apply if there is an args array
2891 listener = listeners[i];
2892
2893 if (listener.once === true) {
2894 this.removeListener(evt, listener.listener);
2895 }
2896
2897 response = listener.listener.apply(this, args || []);
2898
2899 if (response === this._getOnceReturnValue()) {
2900 this.removeListener(evt, listener.listener);
2901 }
2902 }
2903 }
2904 }
2905
2906 return this;
2907 };
2908
2909 /**
2910 * Alias of emitEvent
2911 */
2912 proto.trigger = alias('emitEvent');
2913
2914 /**
2915 * Subtly different from emitEvent in that it will pass its arguments on to the listeners, as opposed to taking a single array of arguments to pass on.
2916 * As with emitEvent, you can pass a regex in place of the event name to emit to all events that match it.
2917 *
2918 * @param {String|RegExp} evt Name of the event to emit and execute listeners for.
2919 * @param {...*} Optional additional arguments to be passed to each listener.
2920 * @return {Object} Current instance of EventEmitter for chaining.
2921 */
2922 proto.emit = function emit(evt) {
2923 var args = Array.prototype.slice.call(arguments, 1);
2924 return this.emitEvent(evt, args);
2925 };
2926
2927 /**
2928 * Sets the current value to check against when executing listeners. If a
2929 * listeners return value matches the one set here then it will be removed
2930 * after execution. This value defaults to true.
2931 *
2932 * @param {*} value The new value to check for when executing listeners.
2933 * @return {Object} Current instance of EventEmitter for chaining.
2934 */
2935 proto.setOnceReturnValue = function setOnceReturnValue(value) {
2936 this._onceReturnValue = value;
2937 return this;
2938 };
2939
2940 /**
2941 * Fetches the current value to check against when executing listeners. If
2942 * the listeners return value matches this one then it should be removed
2943 * automatically. It will return true by default.
2944 *
2945 * @return {*|Boolean} The current value to check for or the default, true.
2946 * @api private
2947 */
2948 proto._getOnceReturnValue = function _getOnceReturnValue() {
2949 if (this.hasOwnProperty('_onceReturnValue')) {
2950 return this._onceReturnValue;
2951 }
2952 else {
2953 return true;
2954 }
2955 };
2956
2957 /**
2958 * Fetches the events object and creates one if required.
2959 *
2960 * @return {Object} The events storage object.
2961 * @api private
2962 */
2963 proto._getEvents = function _getEvents() {
2964 return this._events || (this._events = {});
2965 };
2966
2967 /**
2968 * Reverts the global {@link EventEmitter} to its previous value and returns a reference to this version.
2969 *
2970 * @return {Function} Non conflicting EventEmitter class.
2971 */
2972 EventEmitter.noConflict = function noConflict() {
2973 exports.EventEmitter = originalGlobalValue;
2974 return EventEmitter;
2975 };
2976
2977 // Expose the class either via AMD, CommonJS or the global object
2978 if (typeof define === 'function' && define.amd) {
2979 define(function () {
2980 return EventEmitter;
2981 });
2982 }
2983 else if (typeof module === 'object' && module.exports){
2984 module.exports = EventEmitter;
2985 }
2986 else {
2987 exports.EventEmitter = EventEmitter;
2988 }
2989 }(this || {}));
2990
2991 },{}]},{},[2]);
2992 ; })();