smashing 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of smashing might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/README.md +10 -0
- data/bin/smashing +9 -0
- data/javascripts/batman.jquery.js +163 -0
- data/javascripts/batman.js +13680 -0
- data/javascripts/dashing.coffee +130 -0
- data/javascripts/es5-shim.js +1021 -0
- data/javascripts/jquery.js +4 -0
- data/lib/dashing.rb +6 -0
- data/lib/dashing/app.rb +181 -0
- data/lib/dashing/cli.rb +109 -0
- data/lib/dashing/downloader.rb +18 -0
- data/templates/dashboard/%name%.erb.tt +7 -0
- data/templates/job/%name%.rb +4 -0
- data/templates/project/.gitignore +2 -0
- data/templates/project/Gemfile +6 -0
- data/templates/project/README.md +1 -0
- data/templates/project/assets/fonts/FontAwesome.otf +0 -0
- data/templates/project/assets/fonts/fontawesome-webfont.eot +0 -0
- data/templates/project/assets/fonts/fontawesome-webfont.svg +655 -0
- data/templates/project/assets/fonts/fontawesome-webfont.ttf +0 -0
- data/templates/project/assets/fonts/fontawesome-webfont.woff +0 -0
- data/templates/project/assets/fonts/fontawesome-webfont.woff2 +0 -0
- data/templates/project/assets/images/logo.png +0 -0
- data/templates/project/assets/javascripts/application.coffee +25 -0
- data/templates/project/assets/javascripts/d3-3.2.8.js +5 -0
- data/templates/project/assets/javascripts/dashing.gridster.coffee +37 -0
- data/templates/project/assets/javascripts/gridster/jquery.gridster.min.js +2 -0
- data/templates/project/assets/javascripts/gridster/jquery.leanModal.min.js +5 -0
- data/templates/project/assets/javascripts/jquery.knob.js +646 -0
- data/templates/project/assets/javascripts/rickshaw-1.4.3.min.js +2 -0
- data/templates/project/assets/stylesheets/application.scss +258 -0
- data/templates/project/assets/stylesheets/font-awesome.css +2086 -0
- data/templates/project/assets/stylesheets/jquery.gridster.min.css +2 -0
- data/templates/project/config.ru +18 -0
- data/templates/project/dashboards/layout.erb +32 -0
- data/templates/project/dashboards/sample.erb +25 -0
- data/templates/project/dashboards/sampletv.erb +56 -0
- data/templates/project/jobs/buzzwords.rb +9 -0
- data/templates/project/jobs/convergence.rb +14 -0
- data/templates/project/jobs/sample.rb +13 -0
- data/templates/project/jobs/twitter.rb +28 -0
- data/templates/project/lib/.empty_directory +1 -0
- data/templates/project/public/404.html +26 -0
- data/templates/project/public/favicon.ico +0 -0
- data/templates/project/widgets/clock/clock.coffee +18 -0
- data/templates/project/widgets/clock/clock.html +2 -0
- data/templates/project/widgets/clock/clock.scss +13 -0
- data/templates/project/widgets/comments/comments.coffee +24 -0
- data/templates/project/widgets/comments/comments.html +7 -0
- data/templates/project/widgets/comments/comments.scss +33 -0
- data/templates/project/widgets/graph/graph.coffee +37 -0
- data/templates/project/widgets/graph/graph.html +5 -0
- data/templates/project/widgets/graph/graph.scss +65 -0
- data/templates/project/widgets/iframe/iframe.coffee +9 -0
- data/templates/project/widgets/iframe/iframe.html +1 -0
- data/templates/project/widgets/iframe/iframe.scss +8 -0
- data/templates/project/widgets/image/image.coffee +9 -0
- data/templates/project/widgets/image/image.html +1 -0
- data/templates/project/widgets/image/image.scss +13 -0
- data/templates/project/widgets/list/list.coffee +6 -0
- data/templates/project/widgets/list/list.html +18 -0
- data/templates/project/widgets/list/list.scss +60 -0
- data/templates/project/widgets/meter/meter.coffee +14 -0
- data/templates/project/widgets/meter/meter.html +7 -0
- data/templates/project/widgets/meter/meter.scss +35 -0
- data/templates/project/widgets/number/number.coffee +24 -0
- data/templates/project/widgets/number/number.html +11 -0
- data/templates/project/widgets/number/number.scss +39 -0
- data/templates/project/widgets/text/text.coffee +1 -0
- data/templates/project/widgets/text/text.html +7 -0
- data/templates/project/widgets/text/text.scss +32 -0
- data/templates/widget/%name%/%name%.coffee.tt +9 -0
- data/templates/widget/%name%/%name%.html +1 -0
- data/templates/widget/%name%/%name%.scss.tt +3 -0
- metadata +347 -0
@@ -0,0 +1,130 @@
|
|
1
|
+
#= require jquery
|
2
|
+
#= require es5-shim
|
3
|
+
#= require batman
|
4
|
+
#= require batman.jquery
|
5
|
+
|
6
|
+
|
7
|
+
Batman.Filters.prettyNumber = (num) ->
|
8
|
+
num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") unless isNaN(num)
|
9
|
+
|
10
|
+
Batman.Filters.dashize = (str) ->
|
11
|
+
dashes_rx1 = /([A-Z]+)([A-Z][a-z])/g;
|
12
|
+
dashes_rx2 = /([a-z\d])([A-Z])/g;
|
13
|
+
|
14
|
+
return str.replace(dashes_rx1, '$1_$2').replace(dashes_rx2, '$1_$2').replace(/_/g, '-').toLowerCase()
|
15
|
+
|
16
|
+
Batman.Filters.shortenedNumber = (num) ->
|
17
|
+
return num if isNaN(num)
|
18
|
+
if num >= 1000000000
|
19
|
+
(num / 1000000000).toFixed(1) + 'B'
|
20
|
+
else if num >= 1000000
|
21
|
+
(num / 1000000).toFixed(1) + 'M'
|
22
|
+
else if num >= 1000
|
23
|
+
(num / 1000).toFixed(1) + 'K'
|
24
|
+
else
|
25
|
+
num
|
26
|
+
|
27
|
+
class window.Dashing extends Batman.App
|
28
|
+
@on 'reload', (data) ->
|
29
|
+
window.location.reload(true)
|
30
|
+
|
31
|
+
@root ->
|
32
|
+
Dashing.params = Batman.URI.paramsFromQuery(window.location.search.slice(1));
|
33
|
+
|
34
|
+
class Dashing.Widget extends Batman.View
|
35
|
+
constructor: ->
|
36
|
+
# Set the view path
|
37
|
+
@constructor::source = Batman.Filters.underscore(@constructor.name)
|
38
|
+
super
|
39
|
+
|
40
|
+
@mixin($(@node).data())
|
41
|
+
Dashing.widgets[@id] ||= []
|
42
|
+
Dashing.widgets[@id].push(@)
|
43
|
+
|
44
|
+
type = Batman.Filters.dashize(@view)
|
45
|
+
$(@node).addClass("widget widget-#{type} #{@id}")
|
46
|
+
|
47
|
+
@accessor 'updatedAtMessage', ->
|
48
|
+
if updatedAt = @get('updatedAt')
|
49
|
+
timestamp = new Date(updatedAt * 1000)
|
50
|
+
hours = timestamp.getHours()
|
51
|
+
minutes = ("0" + timestamp.getMinutes()).slice(-2)
|
52
|
+
"Last updated at #{hours}:#{minutes}"
|
53
|
+
|
54
|
+
@::on 'ready', ->
|
55
|
+
Dashing.Widget.fire 'ready'
|
56
|
+
|
57
|
+
# In case the events from the server came before the widget was rendered
|
58
|
+
lastData = Dashing.lastEvents[@id]
|
59
|
+
if lastData
|
60
|
+
@mixin(lastData)
|
61
|
+
@onData(lastData)
|
62
|
+
|
63
|
+
receiveData: (data) =>
|
64
|
+
@mixin(data)
|
65
|
+
@onData(data)
|
66
|
+
|
67
|
+
onData: (data) =>
|
68
|
+
# Widgets override this to handle incoming data
|
69
|
+
|
70
|
+
Dashing.AnimatedValue =
|
71
|
+
get: Batman.Property.defaultAccessor.get
|
72
|
+
set: (k, to) ->
|
73
|
+
if !to? || isNaN(to)
|
74
|
+
@[k] = to
|
75
|
+
else
|
76
|
+
timer = "interval_#{k}"
|
77
|
+
num = if (!isNaN(@[k]) && @[k]?) then @[k] else 0
|
78
|
+
unless @[timer] || num == to
|
79
|
+
to = parseFloat(to)
|
80
|
+
num = parseFloat(num)
|
81
|
+
up = to > num
|
82
|
+
num_interval = Math.abs(num - to) / 90
|
83
|
+
@[timer] =
|
84
|
+
setInterval =>
|
85
|
+
num = if up then Math.ceil(num+num_interval) else Math.floor(num-num_interval)
|
86
|
+
if (up && num > to) || (!up && num < to)
|
87
|
+
num = to
|
88
|
+
clearInterval(@[timer])
|
89
|
+
@[timer] = null
|
90
|
+
delete @[timer]
|
91
|
+
@[k] = num
|
92
|
+
@set k, to
|
93
|
+
, 10
|
94
|
+
@[k] = num
|
95
|
+
|
96
|
+
Dashing.widgets = widgets = {}
|
97
|
+
Dashing.lastEvents = lastEvents = {}
|
98
|
+
Dashing.debugMode = false
|
99
|
+
|
100
|
+
source = new EventSource('events')
|
101
|
+
source.addEventListener 'open', (e) ->
|
102
|
+
console.log("Connection opened", e)
|
103
|
+
|
104
|
+
source.addEventListener 'error', (e)->
|
105
|
+
console.log("Connection error", e)
|
106
|
+
if (e.currentTarget.readyState == EventSource.CLOSED)
|
107
|
+
console.log("Connection closed")
|
108
|
+
setTimeout (->
|
109
|
+
window.location.reload()
|
110
|
+
), 5*60*1000
|
111
|
+
|
112
|
+
source.addEventListener 'message', (e) ->
|
113
|
+
data = JSON.parse(e.data)
|
114
|
+
if lastEvents[data.id]?.updatedAt != data.updatedAt
|
115
|
+
if Dashing.debugMode
|
116
|
+
console.log("Received data for #{data.id}", data)
|
117
|
+
lastEvents[data.id] = data
|
118
|
+
if widgets[data.id]?.length > 0
|
119
|
+
for widget in widgets[data.id]
|
120
|
+
widget.receiveData(data)
|
121
|
+
|
122
|
+
source.addEventListener 'dashboards', (e) ->
|
123
|
+
data = JSON.parse(e.data)
|
124
|
+
if Dashing.debugMode
|
125
|
+
console.log("Received data for dashboards", data)
|
126
|
+
if data.dashboard is '*' or window.location.pathname is "/#{data.dashboard}"
|
127
|
+
Dashing.fire data.event, data
|
128
|
+
|
129
|
+
$(document).ready ->
|
130
|
+
Dashing.run()
|
@@ -0,0 +1,1021 @@
|
|
1
|
+
// vim: ts=4 sts=4 sw=4 expandtab
|
2
|
+
// -- kriskowal Kris Kowal Copyright (C) 2009-2011 MIT License
|
3
|
+
// -- tlrobinson Tom Robinson Copyright (C) 2009-2010 MIT License (Narwhal Project)
|
4
|
+
// -- dantman Daniel Friesen Copyright (C) 2010 XXX TODO License or CLA
|
5
|
+
// -- fschaefer Florian Schäfer Copyright (C) 2010 MIT License
|
6
|
+
// -- Gozala Irakli Gozalishvili Copyright (C) 2010 MIT License
|
7
|
+
// -- kitcambridge Kit Cambridge Copyright (C) 2011 MIT License
|
8
|
+
// -- kossnocorp Sasha Koss XXX TODO License or CLA
|
9
|
+
// -- bryanforbes Bryan Forbes XXX TODO License or CLA
|
10
|
+
// -- killdream Quildreen Motta Copyright (C) 2011 MIT Licence
|
11
|
+
// -- michaelficarra Michael Ficarra Copyright (C) 2011 3-clause BSD License
|
12
|
+
// -- sharkbrainguy Gerard Paapu Copyright (C) 2011 MIT License
|
13
|
+
// -- bbqsrc Brendan Molloy XXX TODO License or CLA
|
14
|
+
// -- iwyg XXX TODO License or CLA
|
15
|
+
// -- DomenicDenicola Domenic Denicola XXX TODO License or CLA
|
16
|
+
// -- xavierm02 Montillet Xavier XXX TODO License or CLA
|
17
|
+
// -- Raynos Raynos XXX TODO License or CLA
|
18
|
+
// -- samsonjs Sami Samhuri XXX TODO License or CLA
|
19
|
+
// -- rwldrn Rick Waldron Copyright (C) 2011 MIT License
|
20
|
+
// -- lexer Alexey Zakharov XXX TODO License or CLA
|
21
|
+
|
22
|
+
/*!
|
23
|
+
Copyright (c) 2009, 280 North Inc. http://280north.com/
|
24
|
+
MIT License. http://github.com/280north/narwhal/blob/master/README.md
|
25
|
+
*/
|
26
|
+
|
27
|
+
// Module systems magic dance
|
28
|
+
(function (definition) {
|
29
|
+
// RequireJS
|
30
|
+
if (typeof define == "function") {
|
31
|
+
define(definition);
|
32
|
+
// CommonJS and <script>
|
33
|
+
} else {
|
34
|
+
definition();
|
35
|
+
}
|
36
|
+
})(function () {
|
37
|
+
|
38
|
+
/**
|
39
|
+
* Brings an environment as close to ECMAScript 5 compliance
|
40
|
+
* as is possible with the facilities of erstwhile engines.
|
41
|
+
*
|
42
|
+
* ES5 Draft
|
43
|
+
* http://www.ecma-international.org/publications/files/drafts/tc39-2009-050.pdf
|
44
|
+
*
|
45
|
+
* NOTE: this is a draft, and as such, the URL is subject to change. If the
|
46
|
+
* link is broken, check in the parent directory for the latest TC39 PDF.
|
47
|
+
* http://www.ecma-international.org/publications/files/drafts/
|
48
|
+
*
|
49
|
+
* Previous ES5 Draft
|
50
|
+
* http://www.ecma-international.org/publications/files/drafts/tc39-2009-025.pdf
|
51
|
+
* This is a broken link to the previous draft of ES5 on which most of the
|
52
|
+
* numbered specification references and quotes herein were taken. Updating
|
53
|
+
* these references and quotes to reflect the new document would be a welcome
|
54
|
+
* volunteer project.
|
55
|
+
*
|
56
|
+
* @module
|
57
|
+
*/
|
58
|
+
|
59
|
+
/*whatsupdoc*/
|
60
|
+
|
61
|
+
//
|
62
|
+
// Function
|
63
|
+
// ========
|
64
|
+
//
|
65
|
+
|
66
|
+
// ES-5 15.3.4.5
|
67
|
+
// http://www.ecma-international.org/publications/files/drafts/tc39-2009-025.pdf
|
68
|
+
|
69
|
+
if (!Function.prototype.bind) {
|
70
|
+
Function.prototype.bind = function bind(that) { // .length is 1
|
71
|
+
// 1. Let Target be the this value.
|
72
|
+
var target = this;
|
73
|
+
// 2. If IsCallable(Target) is false, throw a TypeError exception.
|
74
|
+
if (typeof target != "function")
|
75
|
+
throw new TypeError(); // TODO message
|
76
|
+
// 3. Let A be a new (possibly empty) internal list of all of the
|
77
|
+
// argument values provided after thisArg (arg1, arg2 etc), in order.
|
78
|
+
// XXX slicedArgs will stand in for "A" if used
|
79
|
+
var args = slice.call(arguments, 1); // for normal call
|
80
|
+
// 4. Let F be a new native ECMAScript object.
|
81
|
+
// 9. Set the [[Prototype]] internal property of F to the standard
|
82
|
+
// built-in Function prototype object as specified in 15.3.3.1.
|
83
|
+
// 10. Set the [[Call]] internal property of F as described in
|
84
|
+
// 15.3.4.5.1.
|
85
|
+
// 11. Set the [[Construct]] internal property of F as described in
|
86
|
+
// 15.3.4.5.2.
|
87
|
+
// 12. Set the [[HasInstance]] internal property of F as described in
|
88
|
+
// 15.3.4.5.3.
|
89
|
+
// 13. The [[Scope]] internal property of F is unused and need not
|
90
|
+
// exist.
|
91
|
+
var bound = function () {
|
92
|
+
|
93
|
+
if (this instanceof bound) {
|
94
|
+
// 15.3.4.5.2 [[Construct]]
|
95
|
+
// When the [[Construct]] internal method of a function object,
|
96
|
+
// F that was created using the bind function is called with a
|
97
|
+
// list of arguments ExtraArgs the following steps are taken:
|
98
|
+
// 1. Let target be the value of F's [[TargetFunction]]
|
99
|
+
// internal property.
|
100
|
+
// 2. If target has no [[Construct]] internal method, a
|
101
|
+
// TypeError exception is thrown.
|
102
|
+
// 3. Let boundArgs be the value of F's [[BoundArgs]] internal
|
103
|
+
// property.
|
104
|
+
// 4. Let args be a new list containing the same values as the
|
105
|
+
// list boundArgs in the same order followed by the same
|
106
|
+
// values as the list ExtraArgs in the same order.
|
107
|
+
|
108
|
+
var F = function(){};
|
109
|
+
F.prototype = target.prototype;
|
110
|
+
var self = new F;
|
111
|
+
|
112
|
+
var result = target.apply(
|
113
|
+
self,
|
114
|
+
args.concat(slice.call(arguments))
|
115
|
+
);
|
116
|
+
if (result !== null && Object(result) === result)
|
117
|
+
return result;
|
118
|
+
return self;
|
119
|
+
|
120
|
+
} else {
|
121
|
+
// 15.3.4.5.1 [[Call]]
|
122
|
+
// When the [[Call]] internal method of a function object, F,
|
123
|
+
// which was created using the bind function is called with a
|
124
|
+
// this value and a list of arguments ExtraArgs the following
|
125
|
+
// steps are taken:
|
126
|
+
// 1. Let boundArgs be the value of F's [[BoundArgs]] internal
|
127
|
+
// property.
|
128
|
+
// 2. Let boundThis be the value of F's [[BoundThis]] internal
|
129
|
+
// property.
|
130
|
+
// 3. Let target be the value of F's [[TargetFunction]] internal
|
131
|
+
// property.
|
132
|
+
// 4. Let args be a new list containing the same values as the list
|
133
|
+
// boundArgs in the same order followed by the same values as
|
134
|
+
// the list ExtraArgs in the same order. 5. Return the
|
135
|
+
// result of calling the [[Call]] internal method of target
|
136
|
+
// providing boundThis as the this value and providing args
|
137
|
+
// as the arguments.
|
138
|
+
|
139
|
+
// equiv: target.call(this, ...boundArgs, ...args)
|
140
|
+
return target.apply(
|
141
|
+
that,
|
142
|
+
args.concat(slice.call(arguments))
|
143
|
+
);
|
144
|
+
|
145
|
+
}
|
146
|
+
|
147
|
+
};
|
148
|
+
// XXX bound.length is never writable, so don't even try
|
149
|
+
//
|
150
|
+
// 16. The length own property of F is given attributes as specified in
|
151
|
+
// 15.3.5.1.
|
152
|
+
// TODO
|
153
|
+
// 17. Set the [[Extensible]] internal property of F to true.
|
154
|
+
// TODO
|
155
|
+
// 18. Call the [[DefineOwnProperty]] internal method of F with
|
156
|
+
// arguments "caller", PropertyDescriptor {[[Value]]: null,
|
157
|
+
// [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]:
|
158
|
+
// false}, and false.
|
159
|
+
// TODO
|
160
|
+
// 19. Call the [[DefineOwnProperty]] internal method of F with
|
161
|
+
// arguments "arguments", PropertyDescriptor {[[Value]]: null,
|
162
|
+
// [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]:
|
163
|
+
// false}, and false.
|
164
|
+
// TODO
|
165
|
+
// NOTE Function objects created using Function.prototype.bind do not
|
166
|
+
// have a prototype property.
|
167
|
+
// XXX can't delete it in pure-js.
|
168
|
+
return bound;
|
169
|
+
};
|
170
|
+
}
|
171
|
+
|
172
|
+
// Shortcut to an often accessed properties, in order to avoid multiple
|
173
|
+
// dereference that costs universally.
|
174
|
+
// _Please note: Shortcuts are defined after `Function.prototype.bind` as we
|
175
|
+
// us it in defining shortcuts.
|
176
|
+
var call = Function.prototype.call;
|
177
|
+
var prototypeOfArray = Array.prototype;
|
178
|
+
var prototypeOfObject = Object.prototype;
|
179
|
+
var slice = prototypeOfArray.slice;
|
180
|
+
var toString = call.bind(prototypeOfObject.toString);
|
181
|
+
var owns = call.bind(prototypeOfObject.hasOwnProperty);
|
182
|
+
|
183
|
+
// If JS engine supports accessors creating shortcuts.
|
184
|
+
var defineGetter;
|
185
|
+
var defineSetter;
|
186
|
+
var lookupGetter;
|
187
|
+
var lookupSetter;
|
188
|
+
var supportsAccessors;
|
189
|
+
if ((supportsAccessors = owns(prototypeOfObject, "__defineGetter__"))) {
|
190
|
+
defineGetter = call.bind(prototypeOfObject.__defineGetter__);
|
191
|
+
defineSetter = call.bind(prototypeOfObject.__defineSetter__);
|
192
|
+
lookupGetter = call.bind(prototypeOfObject.__lookupGetter__);
|
193
|
+
lookupSetter = call.bind(prototypeOfObject.__lookupSetter__);
|
194
|
+
}
|
195
|
+
|
196
|
+
//
|
197
|
+
// Array
|
198
|
+
// =====
|
199
|
+
//
|
200
|
+
|
201
|
+
// ES5 15.4.3.2
|
202
|
+
if (!Array.isArray) {
|
203
|
+
Array.isArray = function isArray(obj) {
|
204
|
+
return toString(obj) == "[object Array]";
|
205
|
+
};
|
206
|
+
}
|
207
|
+
|
208
|
+
// The IsCallable() check in the Array functions
|
209
|
+
// has been replaced with a strict check on the
|
210
|
+
// internal class of the object to trap cases where
|
211
|
+
// the provided function was actually a regular
|
212
|
+
// expression literal, which in V8 and
|
213
|
+
// JavaScriptCore is a typeof "function". Only in
|
214
|
+
// V8 are regular expression literals permitted as
|
215
|
+
// reduce parameters, so it is desirable in the
|
216
|
+
// general case for the shim to match the more
|
217
|
+
// strict and common behavior of rejecting regular
|
218
|
+
// expressions.
|
219
|
+
|
220
|
+
// ES5 15.4.4.18
|
221
|
+
// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/array/foreach
|
222
|
+
if (!Array.prototype.forEach) {
|
223
|
+
Array.prototype.forEach = function forEach(fun /*, thisp*/) {
|
224
|
+
var self = toObject(this),
|
225
|
+
thisp = arguments[1],
|
226
|
+
i = 0,
|
227
|
+
length = self.length >>> 0;
|
228
|
+
|
229
|
+
// If no callback function or if callback is not a callable function
|
230
|
+
if (toString(fun) != "[object Function]") {
|
231
|
+
throw new TypeError(); // TODO message
|
232
|
+
}
|
233
|
+
|
234
|
+
while (i < length) {
|
235
|
+
if (i in self) {
|
236
|
+
// Invoke the callback function with call, passing arguments:
|
237
|
+
// context, property value, property key, thisArg object context
|
238
|
+
fun.call(thisp, self[i], i, self);
|
239
|
+
}
|
240
|
+
i++;
|
241
|
+
}
|
242
|
+
};
|
243
|
+
}
|
244
|
+
|
245
|
+
// ES5 15.4.4.19
|
246
|
+
// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/map
|
247
|
+
if (!Array.prototype.map) {
|
248
|
+
Array.prototype.map = function map(fun /*, thisp*/) {
|
249
|
+
var self = toObject(this),
|
250
|
+
length = self.length >>> 0,
|
251
|
+
result = Array(length),
|
252
|
+
thisp = arguments[1];
|
253
|
+
|
254
|
+
// If no callback function or if callback is not a callable function
|
255
|
+
if (toString(fun) != "[object Function]") {
|
256
|
+
throw new TypeError(); // TODO message
|
257
|
+
}
|
258
|
+
|
259
|
+
for (var i = 0; i < length; i++) {
|
260
|
+
if (i in self)
|
261
|
+
result[i] = fun.call(thisp, self[i], i, self);
|
262
|
+
}
|
263
|
+
return result;
|
264
|
+
};
|
265
|
+
}
|
266
|
+
|
267
|
+
// ES5 15.4.4.20
|
268
|
+
if (!Array.prototype.filter) {
|
269
|
+
Array.prototype.filter = function filter(fun /*, thisp */) {
|
270
|
+
var self = toObject(this),
|
271
|
+
length = self.length >>> 0,
|
272
|
+
result = [],
|
273
|
+
thisp = arguments[1];
|
274
|
+
|
275
|
+
// If no callback function or if callback is not a callable function
|
276
|
+
if (toString(fun) != "[object Function]") {
|
277
|
+
throw new TypeError(); // TODO message
|
278
|
+
}
|
279
|
+
|
280
|
+
for (var i = 0; i < length; i++) {
|
281
|
+
if (i in self && fun.call(thisp, self[i], i, self))
|
282
|
+
result.push(self[i]);
|
283
|
+
}
|
284
|
+
return result;
|
285
|
+
};
|
286
|
+
}
|
287
|
+
|
288
|
+
// ES5 15.4.4.16
|
289
|
+
if (!Array.prototype.every) {
|
290
|
+
Array.prototype.every = function every(fun /*, thisp */) {
|
291
|
+
var self = toObject(this),
|
292
|
+
length = self.length >>> 0,
|
293
|
+
thisp = arguments[1];
|
294
|
+
|
295
|
+
// If no callback function or if callback is not a callable function
|
296
|
+
if (toString(fun) != "[object Function]") {
|
297
|
+
throw new TypeError(); // TODO message
|
298
|
+
}
|
299
|
+
|
300
|
+
for (var i = 0; i < length; i++) {
|
301
|
+
if (i in self && !fun.call(thisp, self[i], i, self))
|
302
|
+
return false;
|
303
|
+
}
|
304
|
+
return true;
|
305
|
+
};
|
306
|
+
}
|
307
|
+
|
308
|
+
// ES5 15.4.4.17
|
309
|
+
// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/some
|
310
|
+
if (!Array.prototype.some) {
|
311
|
+
Array.prototype.some = function some(fun /*, thisp */) {
|
312
|
+
var self = toObject(this),
|
313
|
+
length = self.length >>> 0,
|
314
|
+
thisp = arguments[1];
|
315
|
+
|
316
|
+
// If no callback function or if callback is not a callable function
|
317
|
+
if (toString(fun) != "[object Function]") {
|
318
|
+
throw new TypeError(); // TODO message
|
319
|
+
}
|
320
|
+
|
321
|
+
for (var i = 0; i < length; i++) {
|
322
|
+
if (i in self && fun.call(thisp, self[i], i, self))
|
323
|
+
return true;
|
324
|
+
}
|
325
|
+
return false;
|
326
|
+
};
|
327
|
+
}
|
328
|
+
|
329
|
+
// ES5 15.4.4.21
|
330
|
+
// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduce
|
331
|
+
if (!Array.prototype.reduce) {
|
332
|
+
Array.prototype.reduce = function reduce(fun /*, initial*/) {
|
333
|
+
var self = toObject(this),
|
334
|
+
length = self.length >>> 0;
|
335
|
+
|
336
|
+
// If no callback function or if callback is not a callable function
|
337
|
+
if (toString(fun) != "[object Function]") {
|
338
|
+
throw new TypeError(); // TODO message
|
339
|
+
}
|
340
|
+
|
341
|
+
// no value to return if no initial value and an empty array
|
342
|
+
if (!length && arguments.length == 1)
|
343
|
+
throw new TypeError(); // TODO message
|
344
|
+
|
345
|
+
var i = 0;
|
346
|
+
var result;
|
347
|
+
if (arguments.length >= 2) {
|
348
|
+
result = arguments[1];
|
349
|
+
} else {
|
350
|
+
do {
|
351
|
+
if (i in self) {
|
352
|
+
result = self[i++];
|
353
|
+
break;
|
354
|
+
}
|
355
|
+
|
356
|
+
// if array contains no values, no initial value to return
|
357
|
+
if (++i >= length)
|
358
|
+
throw new TypeError(); // TODO message
|
359
|
+
} while (true);
|
360
|
+
}
|
361
|
+
|
362
|
+
for (; i < length; i++) {
|
363
|
+
if (i in self)
|
364
|
+
result = fun.call(void 0, result, self[i], i, self);
|
365
|
+
}
|
366
|
+
|
367
|
+
return result;
|
368
|
+
};
|
369
|
+
}
|
370
|
+
|
371
|
+
// ES5 15.4.4.22
|
372
|
+
// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduceRight
|
373
|
+
if (!Array.prototype.reduceRight) {
|
374
|
+
Array.prototype.reduceRight = function reduceRight(fun /*, initial*/) {
|
375
|
+
var self = toObject(this),
|
376
|
+
length = self.length >>> 0;
|
377
|
+
|
378
|
+
// If no callback function or if callback is not a callable function
|
379
|
+
if (toString(fun) != "[object Function]") {
|
380
|
+
throw new TypeError(); // TODO message
|
381
|
+
}
|
382
|
+
|
383
|
+
// no value to return if no initial value, empty array
|
384
|
+
if (!length && arguments.length == 1)
|
385
|
+
throw new TypeError(); // TODO message
|
386
|
+
|
387
|
+
var result, i = length - 1;
|
388
|
+
if (arguments.length >= 2) {
|
389
|
+
result = arguments[1];
|
390
|
+
} else {
|
391
|
+
do {
|
392
|
+
if (i in self) {
|
393
|
+
result = self[i--];
|
394
|
+
break;
|
395
|
+
}
|
396
|
+
|
397
|
+
// if array contains no values, no initial value to return
|
398
|
+
if (--i < 0)
|
399
|
+
throw new TypeError(); // TODO message
|
400
|
+
} while (true);
|
401
|
+
}
|
402
|
+
|
403
|
+
do {
|
404
|
+
if (i in this)
|
405
|
+
result = fun.call(void 0, result, self[i], i, self);
|
406
|
+
} while (i--);
|
407
|
+
|
408
|
+
return result;
|
409
|
+
};
|
410
|
+
}
|
411
|
+
|
412
|
+
// ES5 15.4.4.14
|
413
|
+
// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf
|
414
|
+
if (!Array.prototype.indexOf) {
|
415
|
+
Array.prototype.indexOf = function indexOf(sought /*, fromIndex */ ) {
|
416
|
+
var self = toObject(this),
|
417
|
+
length = self.length >>> 0;
|
418
|
+
|
419
|
+
if (!length)
|
420
|
+
return -1;
|
421
|
+
|
422
|
+
var i = 0;
|
423
|
+
if (arguments.length > 1)
|
424
|
+
i = toInteger(arguments[1]);
|
425
|
+
|
426
|
+
// handle negative indices
|
427
|
+
i = i >= 0 ? i : length - Math.abs(i);
|
428
|
+
for (; i < length; i++) {
|
429
|
+
if (i in self && self[i] === sought) {
|
430
|
+
return i;
|
431
|
+
}
|
432
|
+
}
|
433
|
+
return -1;
|
434
|
+
};
|
435
|
+
}
|
436
|
+
|
437
|
+
// ES5 15.4.4.15
|
438
|
+
if (!Array.prototype.lastIndexOf) {
|
439
|
+
Array.prototype.lastIndexOf = function lastIndexOf(sought /*, fromIndex */) {
|
440
|
+
var self = toObject(this),
|
441
|
+
length = self.length >>> 0;
|
442
|
+
|
443
|
+
if (!length)
|
444
|
+
return -1;
|
445
|
+
var i = length - 1;
|
446
|
+
if (arguments.length > 1)
|
447
|
+
i = toInteger(arguments[1]);
|
448
|
+
// handle negative indices
|
449
|
+
i = i >= 0 ? i : length - Math.abs(i);
|
450
|
+
for (; i >= 0; i--) {
|
451
|
+
if (i in self && sought === self[i])
|
452
|
+
return i;
|
453
|
+
}
|
454
|
+
return -1;
|
455
|
+
};
|
456
|
+
}
|
457
|
+
|
458
|
+
//
|
459
|
+
// Object
|
460
|
+
// ======
|
461
|
+
//
|
462
|
+
|
463
|
+
// ES5 15.2.3.2
|
464
|
+
if (!Object.getPrototypeOf) {
|
465
|
+
// https://github.com/kriskowal/es5-shim/issues#issue/2
|
466
|
+
// http://ejohn.org/blog/objectgetprototypeof/
|
467
|
+
// recommended by fschaefer on github
|
468
|
+
Object.getPrototypeOf = function getPrototypeOf(object) {
|
469
|
+
return object.__proto__ || (
|
470
|
+
object.constructor ?
|
471
|
+
object.constructor.prototype :
|
472
|
+
prototypeOfObject
|
473
|
+
);
|
474
|
+
};
|
475
|
+
}
|
476
|
+
|
477
|
+
// ES5 15.2.3.3
|
478
|
+
if (!Object.getOwnPropertyDescriptor) {
|
479
|
+
var ERR_NON_OBJECT = "Object.getOwnPropertyDescriptor called on a " +
|
480
|
+
"non-object: ";
|
481
|
+
Object.getOwnPropertyDescriptor = function getOwnPropertyDescriptor(object, property) {
|
482
|
+
if ((typeof object != "object" && typeof object != "function") || object === null)
|
483
|
+
throw new TypeError(ERR_NON_OBJECT + object);
|
484
|
+
// If object does not owns property return undefined immediately.
|
485
|
+
if (!owns(object, property))
|
486
|
+
return;
|
487
|
+
|
488
|
+
var descriptor, getter, setter;
|
489
|
+
|
490
|
+
// If object has a property then it's for sure both `enumerable` and
|
491
|
+
// `configurable`.
|
492
|
+
descriptor = { enumerable: true, configurable: true };
|
493
|
+
|
494
|
+
// If JS engine supports accessor properties then property may be a
|
495
|
+
// getter or setter.
|
496
|
+
if (supportsAccessors) {
|
497
|
+
// Unfortunately `__lookupGetter__` will return a getter even
|
498
|
+
// if object has own non getter property along with a same named
|
499
|
+
// inherited getter. To avoid misbehavior we temporary remove
|
500
|
+
// `__proto__` so that `__lookupGetter__` will return getter only
|
501
|
+
// if it's owned by an object.
|
502
|
+
var prototype = object.__proto__;
|
503
|
+
object.__proto__ = prototypeOfObject;
|
504
|
+
|
505
|
+
var getter = lookupGetter(object, property);
|
506
|
+
var setter = lookupSetter(object, property);
|
507
|
+
|
508
|
+
// Once we have getter and setter we can put values back.
|
509
|
+
object.__proto__ = prototype;
|
510
|
+
|
511
|
+
if (getter || setter) {
|
512
|
+
if (getter) descriptor.get = getter;
|
513
|
+
if (setter) descriptor.set = setter;
|
514
|
+
|
515
|
+
// If it was accessor property we're done and return here
|
516
|
+
// in order to avoid adding `value` to the descriptor.
|
517
|
+
return descriptor;
|
518
|
+
}
|
519
|
+
}
|
520
|
+
|
521
|
+
// If we got this far we know that object has an own property that is
|
522
|
+
// not an accessor so we set it as a value and return descriptor.
|
523
|
+
descriptor.value = object[property];
|
524
|
+
return descriptor;
|
525
|
+
};
|
526
|
+
}
|
527
|
+
|
528
|
+
// ES5 15.2.3.4
|
529
|
+
if (!Object.getOwnPropertyNames) {
|
530
|
+
Object.getOwnPropertyNames = function getOwnPropertyNames(object) {
|
531
|
+
return Object.keys(object);
|
532
|
+
};
|
533
|
+
}
|
534
|
+
|
535
|
+
// ES5 15.2.3.5
|
536
|
+
if (!Object.create) {
|
537
|
+
Object.create = function create(prototype, properties) {
|
538
|
+
var object;
|
539
|
+
if (prototype === null) {
|
540
|
+
object = { "__proto__": null };
|
541
|
+
} else {
|
542
|
+
if (typeof prototype != "object")
|
543
|
+
throw new TypeError("typeof prototype["+(typeof prototype)+"] != 'object'");
|
544
|
+
var Type = function () {};
|
545
|
+
Type.prototype = prototype;
|
546
|
+
object = new Type();
|
547
|
+
// IE has no built-in implementation of `Object.getPrototypeOf`
|
548
|
+
// neither `__proto__`, but this manually setting `__proto__` will
|
549
|
+
// guarantee that `Object.getPrototypeOf` will work as expected with
|
550
|
+
// objects created using `Object.create`
|
551
|
+
object.__proto__ = prototype;
|
552
|
+
}
|
553
|
+
if (properties !== void 0)
|
554
|
+
Object.defineProperties(object, properties);
|
555
|
+
return object;
|
556
|
+
};
|
557
|
+
}
|
558
|
+
|
559
|
+
// ES5 15.2.3.6
|
560
|
+
|
561
|
+
// Patch for WebKit and IE8 standard mode
|
562
|
+
// Designed by hax <hax.github.com>
|
563
|
+
// related issue: https://github.com/kriskowal/es5-shim/issues#issue/5
|
564
|
+
// IE8 Reference:
|
565
|
+
// http://msdn.microsoft.com/en-us/library/dd282900.aspx
|
566
|
+
// http://msdn.microsoft.com/en-us/library/dd229916.aspx
|
567
|
+
// WebKit Bugs:
|
568
|
+
// https://bugs.webkit.org/show_bug.cgi?id=36423
|
569
|
+
|
570
|
+
function doesDefinePropertyWork(object) {
|
571
|
+
try {
|
572
|
+
Object.defineProperty(object, "sentinel", {});
|
573
|
+
return "sentinel" in object;
|
574
|
+
} catch (exception) {
|
575
|
+
// returns falsy
|
576
|
+
}
|
577
|
+
}
|
578
|
+
|
579
|
+
// check whether defineProperty works if it's given. Otherwise,
|
580
|
+
// shim partially.
|
581
|
+
if (Object.defineProperty) {
|
582
|
+
var definePropertyWorksOnObject = doesDefinePropertyWork({});
|
583
|
+
var definePropertyWorksOnDom = typeof document == "undefined" ||
|
584
|
+
doesDefinePropertyWork(document.createElement("div"));
|
585
|
+
if (!definePropertyWorksOnObject || !definePropertyWorksOnDom) {
|
586
|
+
var definePropertyFallback = Object.defineProperty;
|
587
|
+
}
|
588
|
+
}
|
589
|
+
|
590
|
+
if (!Object.defineProperty || definePropertyFallback) {
|
591
|
+
var ERR_NON_OBJECT_DESCRIPTOR = "Property description must be an object: ";
|
592
|
+
var ERR_NON_OBJECT_TARGET = "Object.defineProperty called on non-object: "
|
593
|
+
var ERR_ACCESSORS_NOT_SUPPORTED = "getters & setters can not be defined " +
|
594
|
+
"on this javascript engine";
|
595
|
+
|
596
|
+
Object.defineProperty = function defineProperty(object, property, descriptor) {
|
597
|
+
if ((typeof object != "object" && typeof object != "function") || object === null)
|
598
|
+
throw new TypeError(ERR_NON_OBJECT_TARGET + object);
|
599
|
+
if ((typeof descriptor != "object" && typeof descriptor != "function") || descriptor === null)
|
600
|
+
throw new TypeError(ERR_NON_OBJECT_DESCRIPTOR + descriptor);
|
601
|
+
|
602
|
+
// make a valiant attempt to use the real defineProperty
|
603
|
+
// for I8's DOM elements.
|
604
|
+
if (definePropertyFallback) {
|
605
|
+
try {
|
606
|
+
return definePropertyFallback.call(Object, object, property, descriptor);
|
607
|
+
} catch (exception) {
|
608
|
+
// try the shim if the real one doesn't work
|
609
|
+
}
|
610
|
+
}
|
611
|
+
|
612
|
+
// If it's a data property.
|
613
|
+
if (owns(descriptor, "value")) {
|
614
|
+
// fail silently if "writable", "enumerable", or "configurable"
|
615
|
+
// are requested but not supported
|
616
|
+
/*
|
617
|
+
// alternate approach:
|
618
|
+
if ( // can't implement these features; allow false but not true
|
619
|
+
!(owns(descriptor, "writable") ? descriptor.writable : true) ||
|
620
|
+
!(owns(descriptor, "enumerable") ? descriptor.enumerable : true) ||
|
621
|
+
!(owns(descriptor, "configurable") ? descriptor.configurable : true)
|
622
|
+
)
|
623
|
+
throw new RangeError(
|
624
|
+
"This implementation of Object.defineProperty does not " +
|
625
|
+
"support configurable, enumerable, or writable."
|
626
|
+
);
|
627
|
+
*/
|
628
|
+
|
629
|
+
if (supportsAccessors && (lookupGetter(object, property) ||
|
630
|
+
lookupSetter(object, property)))
|
631
|
+
{
|
632
|
+
// As accessors are supported only on engines implementing
|
633
|
+
// `__proto__` we can safely override `__proto__` while defining
|
634
|
+
// a property to make sure that we don't hit an inherited
|
635
|
+
// accessor.
|
636
|
+
var prototype = object.__proto__;
|
637
|
+
object.__proto__ = prototypeOfObject;
|
638
|
+
// Deleting a property anyway since getter / setter may be
|
639
|
+
// defined on object itself.
|
640
|
+
delete object[property];
|
641
|
+
object[property] = descriptor.value;
|
642
|
+
// Setting original `__proto__` back now.
|
643
|
+
object.__proto__ = prototype;
|
644
|
+
} else {
|
645
|
+
object[property] = descriptor.value;
|
646
|
+
}
|
647
|
+
} else {
|
648
|
+
if (!supportsAccessors)
|
649
|
+
throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED);
|
650
|
+
// If we got that far then getters and setters can be defined !!
|
651
|
+
if (owns(descriptor, "get"))
|
652
|
+
defineGetter(object, property, descriptor.get);
|
653
|
+
if (owns(descriptor, "set"))
|
654
|
+
defineSetter(object, property, descriptor.set);
|
655
|
+
}
|
656
|
+
|
657
|
+
return object;
|
658
|
+
};
|
659
|
+
}
|
660
|
+
|
661
|
+
// ES5 15.2.3.7
|
662
|
+
if (!Object.defineProperties) {
|
663
|
+
Object.defineProperties = function defineProperties(object, properties) {
|
664
|
+
for (var property in properties) {
|
665
|
+
if (owns(properties, property))
|
666
|
+
Object.defineProperty(object, property, properties[property]);
|
667
|
+
}
|
668
|
+
return object;
|
669
|
+
};
|
670
|
+
}
|
671
|
+
|
672
|
+
// ES5 15.2.3.8
|
673
|
+
if (!Object.seal) {
|
674
|
+
Object.seal = function seal(object) {
|
675
|
+
// this is misleading and breaks feature-detection, but
|
676
|
+
// allows "securable" code to "gracefully" degrade to working
|
677
|
+
// but insecure code.
|
678
|
+
return object;
|
679
|
+
};
|
680
|
+
}
|
681
|
+
|
682
|
+
// ES5 15.2.3.9
|
683
|
+
if (!Object.freeze) {
|
684
|
+
Object.freeze = function freeze(object) {
|
685
|
+
// this is misleading and breaks feature-detection, but
|
686
|
+
// allows "securable" code to "gracefully" degrade to working
|
687
|
+
// but insecure code.
|
688
|
+
return object;
|
689
|
+
};
|
690
|
+
}
|
691
|
+
|
692
|
+
// detect a Rhino bug and patch it
|
693
|
+
try {
|
694
|
+
Object.freeze(function () {});
|
695
|
+
} catch (exception) {
|
696
|
+
Object.freeze = (function freeze(freezeObject) {
|
697
|
+
return function freeze(object) {
|
698
|
+
if (typeof object == "function") {
|
699
|
+
return object;
|
700
|
+
} else {
|
701
|
+
return freezeObject(object);
|
702
|
+
}
|
703
|
+
};
|
704
|
+
})(Object.freeze);
|
705
|
+
}
|
706
|
+
|
707
|
+
// ES5 15.2.3.10
|
708
|
+
if (!Object.preventExtensions) {
|
709
|
+
Object.preventExtensions = function preventExtensions(object) {
|
710
|
+
// this is misleading and breaks feature-detection, but
|
711
|
+
// allows "securable" code to "gracefully" degrade to working
|
712
|
+
// but insecure code.
|
713
|
+
return object;
|
714
|
+
};
|
715
|
+
}
|
716
|
+
|
717
|
+
// ES5 15.2.3.11
|
718
|
+
if (!Object.isSealed) {
|
719
|
+
Object.isSealed = function isSealed(object) {
|
720
|
+
return false;
|
721
|
+
};
|
722
|
+
}
|
723
|
+
|
724
|
+
// ES5 15.2.3.12
|
725
|
+
if (!Object.isFrozen) {
|
726
|
+
Object.isFrozen = function isFrozen(object) {
|
727
|
+
return false;
|
728
|
+
};
|
729
|
+
}
|
730
|
+
|
731
|
+
// ES5 15.2.3.13
|
732
|
+
if (!Object.isExtensible) {
|
733
|
+
Object.isExtensible = function isExtensible(object) {
|
734
|
+
// 1. If Type(O) is not Object throw a TypeError exception.
|
735
|
+
if (Object(object) === object) {
|
736
|
+
throw new TypeError(); // TODO message
|
737
|
+
}
|
738
|
+
// 2. Return the Boolean value of the [[Extensible]] internal property of O.
|
739
|
+
var name = '';
|
740
|
+
while (owns(object, name)) {
|
741
|
+
name += '?';
|
742
|
+
}
|
743
|
+
object[name] = true;
|
744
|
+
var returnValue = owns(object, name);
|
745
|
+
delete object[name];
|
746
|
+
return returnValue;
|
747
|
+
};
|
748
|
+
}
|
749
|
+
|
750
|
+
// ES5 15.2.3.14
|
751
|
+
// http://whattheheadsaid.com/2010/10/a-safer-object-keys-compatibility-implementation
|
752
|
+
if (!Object.keys) {
|
753
|
+
|
754
|
+
var hasDontEnumBug = true,
|
755
|
+
dontEnums = [
|
756
|
+
"toString",
|
757
|
+
"toLocaleString",
|
758
|
+
"valueOf",
|
759
|
+
"hasOwnProperty",
|
760
|
+
"isPrototypeOf",
|
761
|
+
"propertyIsEnumerable",
|
762
|
+
"constructor"
|
763
|
+
],
|
764
|
+
dontEnumsLength = dontEnums.length;
|
765
|
+
|
766
|
+
for (var key in {"toString": null})
|
767
|
+
hasDontEnumBug = false;
|
768
|
+
|
769
|
+
Object.keys = function keys(object) {
|
770
|
+
|
771
|
+
if ((typeof object != "object" && typeof object != "function") || object === null)
|
772
|
+
throw new TypeError("Object.keys called on a non-object");
|
773
|
+
|
774
|
+
var keys = [];
|
775
|
+
for (var name in object) {
|
776
|
+
if (owns(object, name)) {
|
777
|
+
keys.push(name);
|
778
|
+
}
|
779
|
+
}
|
780
|
+
|
781
|
+
if (hasDontEnumBug) {
|
782
|
+
for (var i = 0, ii = dontEnumsLength; i < ii; i++) {
|
783
|
+
var dontEnum = dontEnums[i];
|
784
|
+
if (owns(object, dontEnum)) {
|
785
|
+
keys.push(dontEnum);
|
786
|
+
}
|
787
|
+
}
|
788
|
+
}
|
789
|
+
|
790
|
+
return keys;
|
791
|
+
};
|
792
|
+
|
793
|
+
}
|
794
|
+
|
795
|
+
//
|
796
|
+
// Date
|
797
|
+
// ====
|
798
|
+
//
|
799
|
+
|
800
|
+
// ES5 15.9.5.43
|
801
|
+
// Format a Date object as a string according to a simplified subset of the ISO 8601
|
802
|
+
// standard as defined in 15.9.1.15.
|
803
|
+
if (!Date.prototype.toISOString) {
|
804
|
+
Date.prototype.toISOString = function toISOString() {
|
805
|
+
var result, length, value;
|
806
|
+
if (!isFinite(this))
|
807
|
+
throw new RangeError;
|
808
|
+
|
809
|
+
// the date time string format is specified in 15.9.1.15.
|
810
|
+
result = [this.getUTCFullYear(), this.getUTCMonth() + 1, this.getUTCDate(),
|
811
|
+
this.getUTCHours(), this.getUTCMinutes(), this.getUTCSeconds()];
|
812
|
+
|
813
|
+
length = result.length;
|
814
|
+
while (length--) {
|
815
|
+
value = result[length];
|
816
|
+
// pad months, days, hours, minutes, and seconds to have two digits.
|
817
|
+
if (value < 10)
|
818
|
+
result[length] = "0" + value;
|
819
|
+
}
|
820
|
+
// pad milliseconds to have three digits.
|
821
|
+
return result.slice(0, 3).join("-") + "T" + result.slice(3).join(":") + "." +
|
822
|
+
("000" + this.getUTCMilliseconds()).slice(-3) + "Z";
|
823
|
+
}
|
824
|
+
}
|
825
|
+
|
826
|
+
// ES5 15.9.4.4
|
827
|
+
if (!Date.now) {
|
828
|
+
Date.now = function now() {
|
829
|
+
return new Date().getTime();
|
830
|
+
};
|
831
|
+
}
|
832
|
+
|
833
|
+
// ES5 15.9.5.44
|
834
|
+
if (!Date.prototype.toJSON) {
|
835
|
+
Date.prototype.toJSON = function toJSON(key) {
|
836
|
+
// This function provides a String representation of a Date object for
|
837
|
+
// use by JSON.stringify (15.12.3). When the toJSON method is called
|
838
|
+
// with argument key, the following steps are taken:
|
839
|
+
|
840
|
+
// 1. Let O be the result of calling ToObject, giving it the this
|
841
|
+
// value as its argument.
|
842
|
+
// 2. Let tv be ToPrimitive(O, hint Number).
|
843
|
+
// 3. If tv is a Number and is not finite, return null.
|
844
|
+
// XXX
|
845
|
+
// 4. Let toISO be the result of calling the [[Get]] internal method of
|
846
|
+
// O with argument "toISOString".
|
847
|
+
// 5. If IsCallable(toISO) is false, throw a TypeError exception.
|
848
|
+
if (typeof this.toISOString != "function")
|
849
|
+
throw new TypeError(); // TODO message
|
850
|
+
// 6. Return the result of calling the [[Call]] internal method of
|
851
|
+
// toISO with O as the this value and an empty argument list.
|
852
|
+
return this.toISOString();
|
853
|
+
|
854
|
+
// NOTE 1 The argument is ignored.
|
855
|
+
|
856
|
+
// NOTE 2 The toJSON function is intentionally generic; it does not
|
857
|
+
// require that its this value be a Date object. Therefore, it can be
|
858
|
+
// transferred to other kinds of objects for use as a method. However,
|
859
|
+
// it does require that any such object have a toISOString method. An
|
860
|
+
// object is free to use the argument key to filter its
|
861
|
+
// stringification.
|
862
|
+
};
|
863
|
+
}
|
864
|
+
|
865
|
+
// 15.9.4.2 Date.parse (string)
|
866
|
+
// 15.9.1.15 Date Time String Format
|
867
|
+
// Date.parse
|
868
|
+
// based on work shared by Daniel Friesen (dantman)
|
869
|
+
// http://gist.github.com/303249
|
870
|
+
if (isNaN(Date.parse("2011-06-15T21:40:05+06:00"))) {
|
871
|
+
// XXX global assignment won't work in embeddings that use
|
872
|
+
// an alternate object for the context.
|
873
|
+
Date = (function(NativeDate) {
|
874
|
+
|
875
|
+
// Date.length === 7
|
876
|
+
var Date = function Date(Y, M, D, h, m, s, ms) {
|
877
|
+
var length = arguments.length;
|
878
|
+
if (this instanceof NativeDate) {
|
879
|
+
var date = length == 1 && String(Y) === Y ? // isString(Y)
|
880
|
+
// We explicitly pass it through parse:
|
881
|
+
new NativeDate(Date.parse(Y)) :
|
882
|
+
// We have to manually make calls depending on argument
|
883
|
+
// length here
|
884
|
+
length >= 7 ? new NativeDate(Y, M, D, h, m, s, ms) :
|
885
|
+
length >= 6 ? new NativeDate(Y, M, D, h, m, s) :
|
886
|
+
length >= 5 ? new NativeDate(Y, M, D, h, m) :
|
887
|
+
length >= 4 ? new NativeDate(Y, M, D, h) :
|
888
|
+
length >= 3 ? new NativeDate(Y, M, D) :
|
889
|
+
length >= 2 ? new NativeDate(Y, M) :
|
890
|
+
length >= 1 ? new NativeDate(Y) :
|
891
|
+
new NativeDate();
|
892
|
+
// Prevent mixups with unfixed Date object
|
893
|
+
date.constructor = Date;
|
894
|
+
return date;
|
895
|
+
}
|
896
|
+
return NativeDate.apply(this, arguments);
|
897
|
+
};
|
898
|
+
|
899
|
+
// 15.9.1.15 Date Time String Format. This pattern does not implement
|
900
|
+
// extended years (15.9.1.15.1), as `Date.UTC` cannot parse them.
|
901
|
+
var isoDateExpression = new RegExp("^" +
|
902
|
+
"(\\d{4})" + // four-digit year capture
|
903
|
+
"(?:-(\\d{2})" + // optional month capture
|
904
|
+
"(?:-(\\d{2})" + // optional day capture
|
905
|
+
"(?:" + // capture hours:minutes:seconds.milliseconds
|
906
|
+
"T(\\d{2})" + // hours capture
|
907
|
+
":(\\d{2})" + // minutes capture
|
908
|
+
"(?:" + // optional :seconds.milliseconds
|
909
|
+
":(\\d{2})" + // seconds capture
|
910
|
+
"(?:\\.(\\d{3}))?" + // milliseconds capture
|
911
|
+
")?" +
|
912
|
+
"(?:" + // capture UTC offset component
|
913
|
+
"Z|" + // UTC capture
|
914
|
+
"(?:" + // offset specifier +/-hours:minutes
|
915
|
+
"([-+])" + // sign capture
|
916
|
+
"(\\d{2})" + // hours offset capture
|
917
|
+
":(\\d{2})" + // minutes offset capture
|
918
|
+
")" +
|
919
|
+
")?)?)?)?" +
|
920
|
+
"$");
|
921
|
+
|
922
|
+
// Copy any custom methods a 3rd party library may have added
|
923
|
+
for (var key in NativeDate)
|
924
|
+
Date[key] = NativeDate[key];
|
925
|
+
|
926
|
+
// Copy "native" methods explicitly; they may be non-enumerable
|
927
|
+
Date.now = NativeDate.now;
|
928
|
+
Date.UTC = NativeDate.UTC;
|
929
|
+
Date.prototype = NativeDate.prototype;
|
930
|
+
Date.prototype.constructor = Date;
|
931
|
+
|
932
|
+
// Upgrade Date.parse to handle simplified ISO 8601 strings
|
933
|
+
Date.parse = function parse(string) {
|
934
|
+
var match = isoDateExpression.exec(string);
|
935
|
+
if (match) {
|
936
|
+
match.shift(); // kill match[0], the full match
|
937
|
+
// parse months, days, hours, minutes, seconds, and milliseconds
|
938
|
+
for (var i = 1; i < 7; i++) {
|
939
|
+
// provide default values if necessary
|
940
|
+
match[i] = +(match[i] || (i < 3 ? 1 : 0));
|
941
|
+
// match[1] is the month. Months are 0-11 in JavaScript
|
942
|
+
// `Date` objects, but 1-12 in ISO notation, so we
|
943
|
+
// decrement.
|
944
|
+
if (i == 1)
|
945
|
+
match[i]--;
|
946
|
+
}
|
947
|
+
|
948
|
+
// parse the UTC offset component
|
949
|
+
var minuteOffset = +match.pop(), hourOffset = +match.pop(), sign = match.pop();
|
950
|
+
|
951
|
+
// compute the explicit time zone offset if specified
|
952
|
+
var offset = 0;
|
953
|
+
if (sign) {
|
954
|
+
// detect invalid offsets and return early
|
955
|
+
if (hourOffset > 23 || minuteOffset > 59)
|
956
|
+
return NaN;
|
957
|
+
|
958
|
+
// express the provided time zone offset in minutes. The offset is
|
959
|
+
// negative for time zones west of UTC; positive otherwise.
|
960
|
+
offset = (hourOffset * 60 + minuteOffset) * 6e4 * (sign == "+" ? -1 : 1);
|
961
|
+
}
|
962
|
+
|
963
|
+
// compute a new UTC date value, accounting for the optional offset
|
964
|
+
return NativeDate.UTC.apply(this, match) + offset;
|
965
|
+
}
|
966
|
+
return NativeDate.parse.apply(this, arguments);
|
967
|
+
};
|
968
|
+
|
969
|
+
return Date;
|
970
|
+
})(Date);
|
971
|
+
}
|
972
|
+
|
973
|
+
//
|
974
|
+
// String
|
975
|
+
// ======
|
976
|
+
//
|
977
|
+
|
978
|
+
// ES5 15.5.4.20
|
979
|
+
var ws = "\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003" +
|
980
|
+
"\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028" +
|
981
|
+
"\u2029\uFEFF";
|
982
|
+
if (!String.prototype.trim || ws.trim()) {
|
983
|
+
// http://blog.stevenlevithan.com/archives/faster-trim-javascript
|
984
|
+
// http://perfectionkills.com/whitespace-deviations/
|
985
|
+
ws = "[" + ws + "]";
|
986
|
+
var trimBeginRegexp = new RegExp("^" + ws + ws + "*"),
|
987
|
+
trimEndRegexp = new RegExp(ws + ws + "*$");
|
988
|
+
String.prototype.trim = function trim() {
|
989
|
+
return String(this).replace(trimBeginRegexp, "").replace(trimEndRegexp, "");
|
990
|
+
};
|
991
|
+
}
|
992
|
+
|
993
|
+
//
|
994
|
+
// Util
|
995
|
+
// ======
|
996
|
+
//
|
997
|
+
|
998
|
+
// http://jsperf.com/to-integer
|
999
|
+
var toInteger = function (n) {
|
1000
|
+
n = +n;
|
1001
|
+
if (n !== n) // isNaN
|
1002
|
+
n = -1;
|
1003
|
+
else if (n !== 0 && n !== (1/0) && n !== -(1/0))
|
1004
|
+
n = (n > 0 || -1) * Math.floor(Math.abs(n));
|
1005
|
+
return n;
|
1006
|
+
};
|
1007
|
+
|
1008
|
+
var prepareString = "a"[0] != "a",
|
1009
|
+
// ES5 9.9
|
1010
|
+
toObject = function (o) {
|
1011
|
+
if (o == null) { // this matches both null and undefined
|
1012
|
+
throw new TypeError(); // TODO message
|
1013
|
+
}
|
1014
|
+
// If the implementation doesn't support by-index access of
|
1015
|
+
// string characters (ex. IE < 7), split the string
|
1016
|
+
if (prepareString && typeof o == "string" && o) {
|
1017
|
+
return o.split("");
|
1018
|
+
}
|
1019
|
+
return Object(o);
|
1020
|
+
};
|
1021
|
+
});
|