mouth 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. data/.gitignore +7 -0
  2. data/Capfile +26 -0
  3. data/Gemfile +3 -0
  4. data/MIT-LICENSE +20 -0
  5. data/README.md +138 -0
  6. data/Rakefile +19 -0
  7. data/TODO +32 -0
  8. data/bin/mouth +77 -0
  9. data/bin/mouth-console +18 -0
  10. data/bin/mouth-endoscope +18 -0
  11. data/lib/mouth.rb +61 -0
  12. data/lib/mouth/dashboard.rb +25 -0
  13. data/lib/mouth/endoscope.rb +120 -0
  14. data/lib/mouth/endoscope/public/222222_256x240_icons_icons.png +0 -0
  15. data/lib/mouth/endoscope/public/application.css +464 -0
  16. data/lib/mouth/endoscope/public/application.js +938 -0
  17. data/lib/mouth/endoscope/public/backbone.js +1158 -0
  18. data/lib/mouth/endoscope/public/d3.js +4707 -0
  19. data/lib/mouth/endoscope/public/d3.time.js +687 -0
  20. data/lib/mouth/endoscope/public/jquery-ui-1.8.16.custom.min.js +177 -0
  21. data/lib/mouth/endoscope/public/jquery.js +4 -0
  22. data/lib/mouth/endoscope/public/json2.js +480 -0
  23. data/lib/mouth/endoscope/public/keymaster.js +163 -0
  24. data/lib/mouth/endoscope/public/linen.js +46 -0
  25. data/lib/mouth/endoscope/public/seven.css +68 -0
  26. data/lib/mouth/endoscope/public/seven.js +291 -0
  27. data/lib/mouth/endoscope/public/underscore.js +931 -0
  28. data/lib/mouth/endoscope/views/dashboard.erb +67 -0
  29. data/lib/mouth/graph.rb +58 -0
  30. data/lib/mouth/instrument.rb +56 -0
  31. data/lib/mouth/record.rb +72 -0
  32. data/lib/mouth/runner.rb +89 -0
  33. data/lib/mouth/sequence.rb +284 -0
  34. data/lib/mouth/source.rb +76 -0
  35. data/lib/mouth/sucker.rb +235 -0
  36. data/lib/mouth/version.rb +3 -0
  37. data/mouth.gemspec +28 -0
  38. data/test/sequence_test.rb +163 -0
  39. data/test/sucker_test.rb +55 -0
  40. data/test/test_helper.rb +5 -0
  41. metadata +167 -0
@@ -0,0 +1,687 @@
1
+ (function(){d3.time = {};
2
+
3
+ var d3_time = Date;
4
+ d3.time.format = function(template) {
5
+ var n = template.length;
6
+
7
+ function format(date) {
8
+ var string = [],
9
+ i = -1,
10
+ j = 0,
11
+ c,
12
+ f;
13
+ while (++i < n) {
14
+ if (template.charCodeAt(i) == 37) {
15
+ string.push(
16
+ template.substring(j, i),
17
+ (f = d3_time_formats[c = template.charAt(++i)])
18
+ ? f(date) : c);
19
+ j = i + 1;
20
+ }
21
+ }
22
+ string.push(template.substring(j, i));
23
+ return string.join("");
24
+ }
25
+
26
+ format.parse = function(string) {
27
+ var date = new d3_time(1900, 0, 1),
28
+ i = d3_time_parse(date, template, string, 0);
29
+ if (i != string.length) return null;
30
+ if (date.hour12) {
31
+ var hours = date.getHours() % 12;
32
+ date.setHours(date.hour12pm ? hours + 12 : hours);
33
+ }
34
+ delete date.hour12;
35
+ delete date.hour12pm;
36
+ return date;
37
+ };
38
+
39
+ format.toString = function() {
40
+ return template;
41
+ };
42
+
43
+ return format;
44
+ };
45
+
46
+ function d3_time_parse(date, template, string, j) {
47
+ var c,
48
+ p,
49
+ i = 0,
50
+ n = template.length,
51
+ m = string.length;
52
+ while (i < n) {
53
+ if (j >= m) return -1;
54
+ c = template.charCodeAt(i++);
55
+ if (c == 37) {
56
+ p = d3_time_parsers[template.charAt(i++)];
57
+ if (!p || ((j = p(date, string, j)) < 0)) return -1;
58
+ } else if (c != string.charCodeAt(j++)) {
59
+ return -1;
60
+ }
61
+ }
62
+ return j;
63
+ }
64
+
65
+ var d3_time_zfill2 = d3.format("02d"),
66
+ d3_time_zfill3 = d3.format("03d"),
67
+ d3_time_zfill4 = d3.format("04d"),
68
+ d3_time_sfill2 = d3.format("2d");
69
+
70
+ var d3_time_formats = {
71
+ a: function(d) { return d3_time_weekdays[d.getDay()].substring(0, 3); },
72
+ A: function(d) { return d3_time_weekdays[d.getDay()]; },
73
+ b: function(d) { return d3_time_months[d.getMonth()].substring(0, 3); },
74
+ B: function(d) { return d3_time_months[d.getMonth()]; },
75
+ c: d3.time.format("%a %b %e %H:%M:%S %Y"),
76
+ d: function(d) { return d3_time_zfill2(d.getDate()); },
77
+ e: function(d) { return d3_time_sfill2(d.getDate()); },
78
+ H: function(d) { return d3_time_zfill2(d.getHours()); },
79
+ I: function(d) { return d3_time_zfill2(d.getHours() % 12 || 12); },
80
+ j: d3_time_dayOfYear,
81
+ L: function(d) { return d3_time_zfill3(d.getMilliseconds()); },
82
+ m: function(d) { return d3_time_zfill2(d.getMonth() + 1); },
83
+ M: function(d) { return d3_time_zfill2(d.getMinutes()); },
84
+ p: function(d) { return d.getHours() >= 12 ? "PM" : "AM"; },
85
+ S: function(d) { return d3_time_zfill2(d.getSeconds()); },
86
+ U: d3_time_weekNumberSunday,
87
+ w: function(d) { return d.getDay(); },
88
+ W: d3_time_weekNumberMonday,
89
+ x: d3.time.format("%m/%d/%y"),
90
+ X: d3.time.format("%H:%M:%S"),
91
+ y: function(d) { return d3_time_zfill2(d.getFullYear() % 100); },
92
+ Y: function(d) { return d3_time_zfill4(d.getFullYear() % 10000); },
93
+ Z: d3_time_zone,
94
+ "%": function(d) { return "%"; }
95
+ };
96
+
97
+ var d3_time_parsers = {
98
+ a: d3_time_parseWeekdayAbbrev,
99
+ A: d3_time_parseWeekday,
100
+ b: d3_time_parseMonthAbbrev,
101
+ B: d3_time_parseMonth,
102
+ c: d3_time_parseLocaleFull,
103
+ d: d3_time_parseDay,
104
+ e: d3_time_parseDay,
105
+ H: d3_time_parseHour24,
106
+ I: d3_time_parseHour12,
107
+ // j: function(d, s, i) { /*TODO day of year [001,366] */ return i; },
108
+ L: d3_time_parseMilliseconds,
109
+ m: d3_time_parseMonthNumber,
110
+ M: d3_time_parseMinutes,
111
+ p: d3_time_parseAmPm,
112
+ S: d3_time_parseSeconds,
113
+ // U: function(d, s, i) { /*TODO week number (sunday) [00,53] */ return i; },
114
+ // w: function(d, s, i) { /*TODO weekday [0,6] */ return i; },
115
+ // W: function(d, s, i) { /*TODO week number (monday) [00,53] */ return i; },
116
+ x: d3_time_parseLocaleDate,
117
+ X: d3_time_parseLocaleTime,
118
+ y: d3_time_parseYear,
119
+ Y: d3_time_parseFullYear
120
+ // ,
121
+ // Z: function(d, s, i) { /*TODO time zone */ return i; },
122
+ // "%": function(d, s, i) { /*TODO literal % */ return i; }
123
+ };
124
+
125
+ // Note: weekday is validated, but does not set the date.
126
+ function d3_time_parseWeekdayAbbrev(date, string, i) {
127
+ return string.substring(i, i += 3).toLowerCase() in d3_time_weekdayAbbrevLookup ? i : -1;
128
+ }
129
+
130
+ var d3_time_weekdayAbbrevLookup = {
131
+ sun: 3,
132
+ mon: 3,
133
+ tue: 3,
134
+ wed: 3,
135
+ thu: 3,
136
+ fri: 3,
137
+ sat: 3
138
+ };
139
+
140
+ // Note: weekday is validated, but does not set the date.
141
+ function d3_time_parseWeekday(date, string, i) {
142
+ d3_time_weekdayRe.lastIndex = 0;
143
+ var n = d3_time_weekdayRe.exec(string.substring(i, i + 10));
144
+ return n ? i += n[0].length : -1;
145
+ }
146
+
147
+ var d3_time_weekdayRe = /^(?:Sunday|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday)/ig;
148
+
149
+ var d3_time_weekdays = [
150
+ "Sunday",
151
+ "Monday",
152
+ "Tuesday",
153
+ "Wednesday",
154
+ "Thursday",
155
+ "Friday",
156
+ "Saturday"
157
+ ];
158
+
159
+ function d3_time_parseMonthAbbrev(date, string, i) {
160
+ var n = d3_time_monthAbbrevLookup[string.substring(i, i += 3).toLowerCase()];
161
+ return n == null ? -1 : (date.setMonth(n), i);
162
+ }
163
+
164
+ var d3_time_monthAbbrevLookup = {
165
+ jan: 0,
166
+ feb: 1,
167
+ mar: 2,
168
+ apr: 3,
169
+ may: 4,
170
+ jun: 5,
171
+ jul: 6,
172
+ aug: 7,
173
+ sep: 8,
174
+ oct: 9,
175
+ nov: 10,
176
+ dec: 11
177
+ };
178
+
179
+ function d3_time_parseMonth(date, string, i) {
180
+ d3_time_monthRe.lastIndex = 0;
181
+ var n = d3_time_monthRe.exec(string.substring(i, i + 12));
182
+ return n ? (date.setMonth(d3_time_monthLookup[n[0].toLowerCase()]), i += n[0].length) : -1;
183
+ }
184
+
185
+ var d3_time_monthRe = /^(?:January|February|March|April|May|June|July|August|September|October|November|December)/ig;
186
+
187
+ var d3_time_monthLookup = {
188
+ january: 0,
189
+ february: 1,
190
+ march: 2,
191
+ april: 3,
192
+ may: 4,
193
+ june: 5,
194
+ july: 6,
195
+ august: 7,
196
+ september: 8,
197
+ october: 9,
198
+ november: 10,
199
+ december: 11
200
+ };
201
+
202
+ var d3_time_months = [
203
+ "January",
204
+ "February",
205
+ "March",
206
+ "April",
207
+ "May",
208
+ "June",
209
+ "July",
210
+ "August",
211
+ "September",
212
+ "October",
213
+ "November",
214
+ "December"
215
+ ];
216
+
217
+ function d3_time_parseLocaleFull(date, string, i) {
218
+ return d3_time_parse(date, d3_time_formats.c.toString(), string, i);
219
+ }
220
+
221
+ function d3_time_parseLocaleDate(date, string, i) {
222
+ return d3_time_parse(date, d3_time_formats.x.toString(), string, i);
223
+ }
224
+
225
+ function d3_time_parseLocaleTime(date, string, i) {
226
+ return d3_time_parse(date, d3_time_formats.X.toString(), string, i);
227
+ }
228
+
229
+ function d3_time_parseFullYear(date, string, i) {
230
+ d3_time_numberRe.lastIndex = 0;
231
+ var n = d3_time_numberRe.exec(string.substring(i, i + 4));
232
+ return n ? (date.setFullYear(n[0]), i += n[0].length) : -1;
233
+ }
234
+
235
+ function d3_time_parseYear(date, string, i) {
236
+ d3_time_numberRe.lastIndex = 0;
237
+ var n = d3_time_numberRe.exec(string.substring(i, i + 2));
238
+ return n ? (date.setFullYear(d3_time_century() + +n[0]), i += n[0].length) : -1;
239
+ }
240
+
241
+ function d3_time_century() {
242
+ return ~~(new Date().getFullYear() / 1000) * 1000;
243
+ }
244
+
245
+ function d3_time_parseMonthNumber(date, string, i) {
246
+ d3_time_numberRe.lastIndex = 0;
247
+ var n = d3_time_numberRe.exec(string.substring(i, i + 2));
248
+ return n ? (date.setMonth(n[0] - 1), i += n[0].length) : -1;
249
+ }
250
+
251
+ function d3_time_parseDay(date, string, i) {
252
+ d3_time_numberRe.lastIndex = 0;
253
+ var n = d3_time_numberRe.exec(string.substring(i, i + 2));
254
+ return n ? (date.setDate(+n[0]), i += n[0].length) : -1;
255
+ }
256
+
257
+ // Note: we don't validate that the hour is in the range [0,23].
258
+ function d3_time_parseHour24(date, string, i) {
259
+ d3_time_numberRe.lastIndex = 0;
260
+ var n = d3_time_numberRe.exec(string.substring(i, i + 2));
261
+ return n ? (date.setHours(+n[0]), i += n[0].length) : -1;
262
+ }
263
+
264
+ // Note: we don't validate that the hour is in the range [1,12].
265
+ function d3_time_parseHour12(date, string, i) {
266
+ date.hour12 = true;
267
+ return d3_time_parseHour24(date, string, i);
268
+ }
269
+
270
+ function d3_time_parseMinutes(date, string, i) {
271
+ d3_time_numberRe.lastIndex = 0;
272
+ var n = d3_time_numberRe.exec(string.substring(i, i + 2));
273
+ return n ? (date.setMinutes(+n[0]), i += n[0].length) : -1;
274
+ }
275
+
276
+ function d3_time_parseSeconds(date, string, i) {
277
+ d3_time_numberRe.lastIndex = 0;
278
+ var n = d3_time_numberRe.exec(string.substring(i, i + 2));
279
+ return n ? (date.setSeconds(+n[0]), i += n[0].length) : -1;
280
+ }
281
+
282
+ function d3_time_parseMilliseconds(date, string, i) {
283
+ d3_time_numberRe.lastIndex = 0;
284
+ var n = d3_time_numberRe.exec(string.substring(i, i + 3));
285
+ return n ? (date.setMilliseconds(+n[0]), i += n[0].length) : -1;
286
+ }
287
+
288
+ // Note: we don't look at the next directive.
289
+ var d3_time_numberRe = /\s*\d+/;
290
+
291
+ function d3_time_parseAmPm(date, string, i) {
292
+ var n = d3_time_amPmLookup[string.substring(i, i += 2).toLowerCase()];
293
+ return n == null ? -1 : (date.hour12pm = n, i);
294
+ }
295
+
296
+ var d3_time_amPmLookup = {
297
+ am: 0,
298
+ pm: 1
299
+ };
300
+
301
+ function d3_time_year(d) {
302
+ return new d3_time(d.getFullYear(), 0, 1);
303
+ }
304
+
305
+ function d3_time_daysElapsed(d0, d1) {
306
+ return ~~((d1 - d0) / 864e5 - (d1.getTimezoneOffset() - d0.getTimezoneOffset()) / 1440);
307
+ }
308
+
309
+ function d3_time_dayOfYear(d) {
310
+ return d3_time_zfill3(1 + d3_time_daysElapsed(d3_time_year(d), d));
311
+ }
312
+
313
+ function d3_time_weekNumberSunday(d) {
314
+ var d0 = d3_time_year(d);
315
+ return d3_time_zfill2(~~((d3_time_daysElapsed(d0, d) + d0.getDay()) / 7));
316
+ }
317
+
318
+ function d3_time_weekNumberMonday(d) {
319
+ var d0 = d3_time_year(d);
320
+ return d3_time_zfill2(~~((d3_time_daysElapsed(d0, d) + (d0.getDay() + 6) % 7) / 7));
321
+ }
322
+
323
+ // TODO table of time zone offset names?
324
+ function d3_time_zone(d) {
325
+ var z = d.getTimezoneOffset(),
326
+ zs = z > 0 ? "-" : "+",
327
+ zh = ~~(Math.abs(z) / 60),
328
+ zm = Math.abs(z) % 60;
329
+ return zs + d3_time_zfill2(zh) + d3_time_zfill2(zm);
330
+ }
331
+ d3.time.format.utc = function(template) {
332
+ var local = d3.time.format(template);
333
+
334
+ function format(date) {
335
+ try {
336
+ d3_time = d3_time_format_utc;
337
+ var utc = new d3_time();
338
+ utc._ = date;
339
+ return local(utc);
340
+ } finally {
341
+ d3_time = Date;
342
+ }
343
+ }
344
+
345
+ format.parse = function(string) {
346
+ try {
347
+ d3_time = d3_time_format_utc;
348
+ var date = local.parse(string);
349
+ return date && date._;
350
+ } finally {
351
+ d3_time = Date;
352
+ }
353
+ };
354
+
355
+ format.toString = local.toString;
356
+
357
+ return format;
358
+ };
359
+
360
+ function d3_time_format_utc() {
361
+ this._ = new Date(Date.UTC.apply(this, arguments));
362
+ }
363
+
364
+ d3_time_format_utc.prototype = {
365
+ getDate: function() { return this._.getUTCDate(); },
366
+ getDay: function() { return this._.getUTCDay(); },
367
+ getFullYear: function() { return this._.getUTCFullYear(); },
368
+ getHours: function() { return this._.getUTCHours(); },
369
+ getMilliseconds: function() { return this._.getUTCMilliseconds(); },
370
+ getMinutes: function() { return this._.getUTCMinutes(); },
371
+ getMonth: function() { return this._.getUTCMonth(); },
372
+ getSeconds: function() { return this._.getUTCSeconds(); },
373
+ getTimezoneOffset: function() { return 0; },
374
+ valueOf: function() { return this._.getTime(); },
375
+ setDate: function(x) { this._.setUTCDate(x); },
376
+ setDay: function(x) { this._.setUTCDay(x); },
377
+ setFullYear: function(x) { this._.setUTCFullYear(x); },
378
+ setHours: function(x) { this._.setUTCHours(x); },
379
+ setMilliseconds: function(x) { this._.setUTCMilliseconds(x); },
380
+ setMinutes: function(x) { this._.setUTCMinutes(x); },
381
+ setMonth: function(x) { this._.setUTCMonth(x); },
382
+ setSeconds: function(x) { this._.setUTCSeconds(x); }
383
+ };
384
+ var d3_time_formatIso = d3.time.format.utc("%Y-%m-%dT%H:%M:%S.%LZ");
385
+
386
+ d3.time.format.iso = Date.prototype.toISOString ? d3_time_formatIsoNative : d3_time_formatIso;
387
+
388
+ function d3_time_formatIsoNative(date) {
389
+ return date.toISOString();
390
+ }
391
+
392
+ d3_time_formatIsoNative.parse = function(string) {
393
+ return new Date(string);
394
+ };
395
+
396
+ d3_time_formatIsoNative.toString = d3_time_formatIso.toString;
397
+ function d3_time_range(floor, step, number) {
398
+ return function(t0, t1, dt) {
399
+ var time = floor(t0), times = [];
400
+ if (time < t0) step(time);
401
+ if (dt > 1) {
402
+ while (time < t1) {
403
+ var date = new Date(+time);
404
+ if (!(number(date) % dt)) times.push(date);
405
+ step(time);
406
+ }
407
+ } else {
408
+ while (time < t1) times.push(new Date(+time)), step(time);
409
+ }
410
+ return times;
411
+ };
412
+ }
413
+ d3.time.second = function(date) {
414
+ return new Date(~~(date / 1e3) * 1e3);
415
+ };
416
+
417
+ d3.time.second.utc = d3.time.second;
418
+ d3.time.seconds = d3_time_range(d3.time.second, function(date) {
419
+ date.setTime(date.getTime() + 1e3);
420
+ }, function(date) {
421
+ return date.getSeconds();
422
+ });
423
+
424
+ d3.time.seconds.utc = d3.time.seconds;
425
+ d3.time.minute = function(date) {
426
+ return new Date(~~(date / 6e4) * 6e4);
427
+ };
428
+
429
+ d3.time.minute.utc = d3.time.minute;d3.time.minutes = d3_time_range(d3.time.minute, d3_time_minutesStep, function(date) {
430
+ return date.getMinutes();
431
+ });
432
+
433
+ d3.time.minutes.utc = d3_time_range(d3.time.minute, d3_time_minutesStep, function(date) {
434
+ return date.getUTCMinutes();
435
+ });
436
+
437
+ function d3_time_minutesStep(date) {
438
+ date.setTime(date.getTime() + 6e4); // assumes no leap seconds
439
+ }
440
+ d3.time.hour = function(date) {
441
+ var offset = date.getTimezoneOffset() / 60;
442
+ return new Date((~~(date / 36e5 - offset) + offset) * 36e5);
443
+ };
444
+
445
+ d3.time.hour.utc = function(date) {
446
+ return new Date(~~(date / 36e5) * 36e5);
447
+ };
448
+ d3.time.hours = d3_time_range(d3.time.hour, d3_time_hoursStep, function(date) {
449
+ return date.getHours();
450
+ });
451
+
452
+ d3.time.hours.utc = d3_time_range(d3.time.hour.utc, d3_time_hoursStep, function(date) {
453
+ return date.getUTCHours();
454
+ });
455
+
456
+ function d3_time_hoursStep(date) {
457
+ date.setTime(date.getTime() + 36e5);
458
+ }
459
+ d3.time.day = function(date) {
460
+ return new Date(date.getFullYear(), date.getMonth(), date.getDate());
461
+ };
462
+
463
+ d3.time.day.utc = function(date) {
464
+ return new Date(~~(date / 864e5) * 864e5);
465
+ };
466
+ d3.time.days = d3_time_range(d3.time.day, function(date) {
467
+ date.setDate(date.getDate() + 1);
468
+ }, function(date) {
469
+ return date.getDate() - 1;
470
+ });
471
+
472
+ d3.time.days.utc = d3_time_range(d3.time.day.utc, function(date) {
473
+ date.setUTCDate(date.getUTCDate() + 1);
474
+ }, function(date) {
475
+ return date.getUTCDate() - 1;
476
+ });
477
+ d3.time.week = function(date) {
478
+ (date = d3.time.day(date)).setDate(date.getDate() - date.getDay());
479
+ return date;
480
+ };
481
+
482
+ d3.time.week.utc = function(date) {
483
+ (date = d3.time.day.utc(date)).setUTCDate(date.getUTCDate() - date.getUTCDay());
484
+ return date;
485
+ };
486
+ d3.time.weeks = d3_time_range(d3.time.week, function(date) {
487
+ date.setDate(date.getDate() + 7);
488
+ }, function(date) {
489
+ return ~~((date - new Date(date.getFullYear(), 0, 1)) / 6048e5);
490
+ });
491
+
492
+ d3.time.weeks.utc = d3_time_range(d3.time.week.utc, function(date) {
493
+ date.setUTCDate(date.getUTCDate() + 7);
494
+ }, function(date) {
495
+ return ~~((date - Date.UTC(date.getUTCFullYear(), 0, 1)) / 6048e5);
496
+ });
497
+ d3.time.month = function(date) {
498
+ return new Date(date.getFullYear(), date.getMonth(), 1);
499
+ };
500
+
501
+ d3.time.month.utc = function(date) {
502
+ return new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), 1));
503
+ };
504
+ d3.time.months = d3_time_range(d3.time.month, function(date) {
505
+ date.setMonth(date.getMonth() + 1);
506
+ }, function(date) {
507
+ return date.getMonth();
508
+ });
509
+
510
+ d3.time.months.utc = d3_time_range(d3.time.month.utc, function(date) {
511
+ date.setUTCMonth(date.getUTCMonth() + 1);
512
+ }, function(date) {
513
+ return date.getUTCMonth();
514
+ });
515
+ d3.time.year = function(date) {
516
+ return new Date(date.getFullYear(), 0, 1);
517
+ };
518
+
519
+ d3.time.year.utc = function(date) {
520
+ return new Date(Date.UTC(date.getUTCFullYear(), 0, 1));
521
+ };
522
+ d3.time.years = d3_time_range(d3.time.year, function(date) {
523
+ date.setFullYear(date.getFullYear() + 1);
524
+ }, function(date) {
525
+ return date.getFullYear();
526
+ });
527
+
528
+ d3.time.years.utc = d3_time_range(d3.time.year.utc, function(date) {
529
+ date.setUTCFullYear(date.getUTCFullYear() + 1);
530
+ }, function(date) {
531
+ return date.getUTCFullYear();
532
+ });
533
+ // TODO nice
534
+ function d3_time_scale(linear, methods, format) {
535
+
536
+ function scale(x) {
537
+ return linear(x);
538
+ }
539
+
540
+ scale.invert = function(x) {
541
+ return d3_time_scaleDate(linear.invert(x));
542
+ };
543
+
544
+ scale.domain = function(x) {
545
+ if (!arguments.length) return linear.domain().map(d3_time_scaleDate);
546
+ linear.domain(x);
547
+ return scale;
548
+ };
549
+
550
+ scale.ticks = function(m, k) {
551
+ var extent = d3_time_scaleExtent(scale.domain());
552
+ if (typeof m !== "function") {
553
+ var span = extent[1] - extent[0],
554
+ target = span / m,
555
+ i = d3.bisect(d3_time_scaleSteps, target, 1, d3_time_scaleSteps.length - 1);
556
+ if (Math.log(target / d3_time_scaleSteps[i - 1]) < Math.log(d3_time_scaleSteps[i] / target)) --i;
557
+ m = methods[i];
558
+ k = m[1];
559
+ m = m[0];
560
+ }
561
+ return m(extent[0], extent[1], k);
562
+ };
563
+
564
+ scale.tickFormat = function() {
565
+ return format;
566
+ };
567
+
568
+ scale.copy = function() {
569
+ return d3_time_scale(linear.copy(), methods, format);
570
+ };
571
+
572
+ // TOOD expose d3_scale_linear_rebind?
573
+ return d3.rebind(scale, linear, "range", "rangeRound", "interpolate", "clamp");
574
+ }
575
+
576
+ // TODO expose d3_scaleExtent?
577
+ function d3_time_scaleExtent(domain) {
578
+ var start = domain[0], stop = domain[domain.length - 1];
579
+ return start < stop ? [start, stop] : [stop, start];
580
+ }
581
+
582
+ function d3_time_scaleDate(t) {
583
+ return new Date(t);
584
+ }
585
+
586
+ function d3_time_scaleFormat(formats) {
587
+ return function(date) {
588
+ var i = formats.length - 1, f = formats[i];
589
+ while (!f[1](date)) f = formats[--i];
590
+ return f[0](date);
591
+ };
592
+ }
593
+
594
+ var d3_time_scaleSteps = [
595
+ 1e3, // 1-second
596
+ 5e3, // 5-second
597
+ 15e3, // 15-second
598
+ 3e4, // 30-second
599
+ 6e4, // 1-minute
600
+ 3e5, // 5-minute
601
+ 9e5, // 15-minute
602
+ 18e5, // 30-minute
603
+ 36e5, // 1-hour
604
+ 108e5, // 3-hour
605
+ 216e5, // 6-hour
606
+ 432e5, // 12-hour
607
+ 864e5, // 1-day
608
+ 1728e5, // 2-day
609
+ 6048e5, // 1-week
610
+ 1728e6, // 1-month
611
+ 7776e6, // 3-month
612
+ 31536e6 // 1-year
613
+ ];
614
+
615
+ var d3_time_scaleLocalMethods = [
616
+ [d3.time.seconds, 1],
617
+ [d3.time.seconds, 5],
618
+ [d3.time.seconds, 15],
619
+ [d3.time.seconds, 30],
620
+ [d3.time.minutes, 1],
621
+ [d3.time.minutes, 5],
622
+ [d3.time.minutes, 15],
623
+ [d3.time.minutes, 30],
624
+ [d3.time.hours, 1],
625
+ [d3.time.hours, 3],
626
+ [d3.time.hours, 6],
627
+ [d3.time.hours, 12],
628
+ [d3.time.days, 1],
629
+ [d3.time.days, 2],
630
+ [d3.time.weeks, 1],
631
+ [d3.time.months, 1],
632
+ [d3.time.months, 3],
633
+ [d3.time.years, 1]
634
+ ];
635
+
636
+ var d3_time_scaleLocalFormats = [
637
+ [d3.time.format("%Y"), function(d) { return true; }],
638
+ [d3.time.format("%B"), function(d) { return d.getMonth(); }],
639
+ [d3.time.format("%b %d"), function(d) { return d.getDate() != 1; }],
640
+ [d3.time.format("%a %d"), function(d) { return d.getDay() && d.getDate() != 1; }],
641
+ [d3.time.format("%I %p"), function(d) { return d.getHours(); }],
642
+ [d3.time.format("%I:%M"), function(d) { return d.getMinutes(); }],
643
+ [d3.time.format(":%S"), function(d) { return d.getSeconds() || d.getMilliseconds(); }]
644
+ ];
645
+
646
+ var d3_time_scaleLocalFormat = d3_time_scaleFormat(d3_time_scaleLocalFormats);
647
+
648
+ d3.time.scale = function() {
649
+ return d3_time_scale(d3.scale.linear(), d3_time_scaleLocalMethods, d3_time_scaleLocalFormat);
650
+ };
651
+ var d3_time_scaleUTCMethods = [
652
+ [d3.time.seconds.utc, 1],
653
+ [d3.time.seconds.utc, 5],
654
+ [d3.time.seconds.utc, 15],
655
+ [d3.time.seconds.utc, 30],
656
+ [d3.time.minutes.utc, 1],
657
+ [d3.time.minutes.utc, 5],
658
+ [d3.time.minutes.utc, 15],
659
+ [d3.time.minutes.utc, 30],
660
+ [d3.time.hours.utc, 1],
661
+ [d3.time.hours.utc, 3],
662
+ [d3.time.hours.utc, 6],
663
+ [d3.time.hours.utc, 12],
664
+ [d3.time.days.utc, 1],
665
+ [d3.time.days.utc, 2],
666
+ [d3.time.weeks.utc, 1],
667
+ [d3.time.months.utc, 1],
668
+ [d3.time.months.utc, 3],
669
+ [d3.time.years.utc, 1]
670
+ ];
671
+
672
+ var d3_time_scaleUTCFormats = [
673
+ [d3.time.format.utc("%Y"), function(d) { return true; }],
674
+ [d3.time.format.utc("%B"), function(d) { return d.getUTCMonth(); }],
675
+ [d3.time.format.utc("%b %d"), function(d) { return d.getUTCDate() != 1; }],
676
+ [d3.time.format.utc("%a %d"), function(d) { return d.getUTCDay() && d.getUTCDate() != 1; }],
677
+ [d3.time.format.utc("%I %p"), function(d) { return d.getUTCHours(); }],
678
+ [d3.time.format.utc("%I:%M"), function(d) { return d.getUTCMinutes(); }],
679
+ [d3.time.format.utc(":%S"), function(d) { return d.getUTCSeconds() || d.getUTCMilliseconds(); }]
680
+ ];
681
+
682
+ var d3_time_scaleUTCFormat = d3_time_scaleFormat(d3_time_scaleUTCFormats);
683
+
684
+ d3.time.scale.utc = function() {
685
+ return d3_time_scale(d3.scale.linear(), d3_time_scaleUTCMethods, d3_time_scaleUTCFormat);
686
+ };
687
+ })();