metrics-graphics-rails 2.1.3.2 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +13 -5
- data/README.md +5 -1
- data/lib/metrics-graphics-rails/version.rb +1 -1
- data/lib/metrics-graphics-rails/view_helpers.rb +22 -5
- data/vendor/assets/javascripts/d3.3.5.4.js +9504 -0
- data/vendor/assets/javascripts/d3.js +3 -3
- data/vendor/assets/javascripts/metricsgraphics.js +917 -557
- data/vendor/assets/stylesheets/metricsgraphics.css +11 -0
- metadata +10 -9
@@ -1,16 +1,16 @@
|
|
1
1
|
!function() {
|
2
2
|
var d3 = {
|
3
|
-
version: "3.5.
|
3
|
+
version: "3.5.5"
|
4
4
|
};
|
5
5
|
var d3_arraySlice = [].slice, d3_array = function(list) {
|
6
6
|
return d3_arraySlice.call(list);
|
7
7
|
};
|
8
8
|
var d3_document = this.document;
|
9
9
|
function d3_documentElement(node) {
|
10
|
-
return node && (node.ownerDocument || node.document).documentElement;
|
10
|
+
return node && (node.ownerDocument || node.document || node).documentElement;
|
11
11
|
}
|
12
12
|
function d3_window(node) {
|
13
|
-
return node && node.ownerDocument
|
13
|
+
return node && (node.ownerDocument && node.ownerDocument.defaultView || node.document && node || node.defaultView);
|
14
14
|
}
|
15
15
|
if (d3_document) {
|
16
16
|
try {
|
@@ -9,7 +9,7 @@
|
|
9
9
|
root.MG = factory(root.d3, root.jQuery);
|
10
10
|
}
|
11
11
|
}(this, function(d3, $) {
|
12
|
-
window.MG = {version: '2.
|
12
|
+
window.MG = {version: '2.4.0'};
|
13
13
|
|
14
14
|
var charts = {};
|
15
15
|
|
@@ -27,6 +27,7 @@
|
|
27
27
|
var defaults = {};
|
28
28
|
defaults.all = {
|
29
29
|
missing_is_zero: false, // if true, missing values will be treated as zeros
|
30
|
+
missing_is_hidden: false, // if true, missing values will appear as broken segments
|
30
31
|
legend: '' , // an array identifying the labels for a chart's lines
|
31
32
|
legend_target: '', // if set, the specified element is populated with a legend
|
32
33
|
error: '', // if set, a graph will show an error icon and log the error to the console
|
@@ -45,6 +46,7 @@
|
|
45
46
|
small_text: false, // coerces small text regardless of graphic size
|
46
47
|
xax_count: 6, // number of x axis ticks
|
47
48
|
xax_tick_length: 5, // x axis tick length
|
49
|
+
xax_start_at_min: false,
|
48
50
|
yax_count: 5, // number of y axis ticks
|
49
51
|
yax_tick_length: 5, // y axis tick length
|
50
52
|
x_extended_ticks: false, // extends x axis ticks across chart - useful for tall charts
|
@@ -84,9 +86,11 @@
|
|
84
86
|
markers: null, // sets the marker lines
|
85
87
|
scalefns: {},
|
86
88
|
scales: {},
|
89
|
+
show_year_markers: false,
|
87
90
|
show_secondary_x_label: true,
|
88
91
|
target: '#viz',
|
89
92
|
interpolate: 'cardinal', // interpolation method to use when rendering lines
|
93
|
+
interpolate_tension: 0.7, // its range is from 0 to 1; increase if your data is irregular and you notice artifacts
|
90
94
|
custom_line_color_map: [], // allows arbitrary mapping of lines to colors, e.g. [2,3] will map line 1 to color 2 and line 2 to color 3
|
91
95
|
max_data_size: null, // explicitly specify the the max number of line series, for use with custom_line_color_map
|
92
96
|
aggregate_rollover: false, // links the lines in a multi-line chart
|
@@ -148,6 +152,7 @@
|
|
148
152
|
missing_text: 'Data currently missing or unavailable',
|
149
153
|
scalefns: {},
|
150
154
|
scales: {},
|
155
|
+
show_tooltips: true,
|
151
156
|
show_missing_background: true,
|
152
157
|
interpolate: 'cardinal'
|
153
158
|
};
|
@@ -257,14 +262,14 @@
|
|
257
262
|
this.enabled =
|
258
263
|
this.timeout =
|
259
264
|
this.hoverState =
|
260
|
-
this.$element = null
|
265
|
+
this.$element = null;
|
261
266
|
|
262
|
-
this.init('tooltip', element, options)
|
263
|
-
}
|
267
|
+
this.init('tooltip', element, options);
|
268
|
+
};
|
264
269
|
|
265
|
-
Tooltip.VERSION = '3.3.1'
|
270
|
+
Tooltip.VERSION = '3.3.1';
|
266
271
|
|
267
|
-
Tooltip.TRANSITION_DURATION = 150
|
272
|
+
Tooltip.TRANSITION_DURATION = 150;
|
268
273
|
|
269
274
|
Tooltip.DEFAULTS = {
|
270
275
|
animation: true,
|
@@ -280,200 +285,200 @@
|
|
280
285
|
selector: 'body',
|
281
286
|
padding: 0
|
282
287
|
}
|
283
|
-
}
|
288
|
+
};
|
284
289
|
|
285
290
|
Tooltip.prototype.init = function (type, element, options) {
|
286
|
-
this.enabled = true
|
287
|
-
this.type = type
|
288
|
-
this.$element = $(element)
|
289
|
-
this.options = this.getOptions(options)
|
290
|
-
this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport)
|
291
|
+
this.enabled = true;
|
292
|
+
this.type = type;
|
293
|
+
this.$element = $(element);
|
294
|
+
this.options = this.getOptions(options);
|
295
|
+
this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport);
|
291
296
|
|
292
|
-
var triggers = this.options.trigger.split(' ')
|
297
|
+
var triggers = this.options.trigger.split(' ');
|
293
298
|
|
294
299
|
for (var i = triggers.length; i--;) {
|
295
|
-
var trigger = triggers[i]
|
300
|
+
var trigger = triggers[i];
|
296
301
|
|
297
302
|
if (trigger == 'click') {
|
298
|
-
this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
|
303
|
+
this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this));
|
299
304
|
} else if (trigger != 'manual') {
|
300
|
-
var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin'
|
301
|
-
var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'
|
305
|
+
var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin';
|
306
|
+
var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout';
|
302
307
|
|
303
|
-
this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
|
304
|
-
this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
|
308
|
+
this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this));
|
309
|
+
this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this));
|
305
310
|
}
|
306
311
|
}
|
307
312
|
|
308
313
|
this.options.selector ?
|
309
314
|
(this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
|
310
|
-
this.fixTitle()
|
311
|
-
}
|
315
|
+
this.fixTitle();
|
316
|
+
};
|
312
317
|
|
313
318
|
Tooltip.prototype.getDefaults = function () {
|
314
|
-
return Tooltip.DEFAULTS
|
315
|
-
}
|
319
|
+
return Tooltip.DEFAULTS;
|
320
|
+
};
|
316
321
|
|
317
322
|
Tooltip.prototype.getOptions = function (options) {
|
318
|
-
options = $.extend({}, this.getDefaults(), this.$element.data(), options)
|
323
|
+
options = $.extend({}, this.getDefaults(), this.$element.data(), options);
|
319
324
|
|
320
325
|
if (options.delay && typeof options.delay == 'number') {
|
321
326
|
options.delay = {
|
322
327
|
show: options.delay,
|
323
328
|
hide: options.delay
|
324
|
-
}
|
329
|
+
};
|
325
330
|
}
|
326
331
|
|
327
|
-
return options
|
328
|
-
}
|
332
|
+
return options;
|
333
|
+
};
|
329
334
|
|
330
335
|
Tooltip.prototype.getDelegateOptions = function () {
|
331
|
-
var options = {}
|
332
|
-
var defaults = this.getDefaults()
|
336
|
+
var options = {};
|
337
|
+
var defaults = this.getDefaults();
|
333
338
|
|
334
339
|
this._options && $.each(this._options, function (key, value) {
|
335
|
-
if (defaults[key] != value) options[key] = value
|
336
|
-
})
|
340
|
+
if (defaults[key] != value) options[key] = value;
|
341
|
+
});
|
337
342
|
|
338
|
-
return options
|
339
|
-
}
|
343
|
+
return options;
|
344
|
+
};
|
340
345
|
|
341
346
|
Tooltip.prototype.enter = function (obj) {
|
342
347
|
var self = obj instanceof this.constructor ?
|
343
|
-
obj : $(obj.currentTarget).data('bs.' + this.type)
|
348
|
+
obj : $(obj.currentTarget).data('bs.' + this.type);
|
344
349
|
|
345
350
|
if (self && self.$tip && self.$tip.is(':visible')) {
|
346
|
-
self.hoverState = 'in'
|
347
|
-
return
|
351
|
+
self.hoverState = 'in';
|
352
|
+
return;
|
348
353
|
}
|
349
354
|
|
350
355
|
if (!self) {
|
351
|
-
self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
|
352
|
-
$(obj.currentTarget).data('bs.' + this.type, self)
|
356
|
+
self = new this.constructor(obj.currentTarget, this.getDelegateOptions());
|
357
|
+
$(obj.currentTarget).data('bs.' + this.type, self);
|
353
358
|
}
|
354
359
|
|
355
|
-
clearTimeout(self.timeout)
|
360
|
+
clearTimeout(self.timeout);
|
356
361
|
|
357
|
-
self.hoverState = 'in'
|
362
|
+
self.hoverState = 'in';
|
358
363
|
|
359
|
-
if (!self.options.delay || !self.options.delay.show) return self.show()
|
364
|
+
if (!self.options.delay || !self.options.delay.show) return self.show();
|
360
365
|
|
361
366
|
self.timeout = setTimeout(function () {
|
362
|
-
if (self.hoverState == 'in') self.show()
|
363
|
-
}, self.options.delay.show)
|
364
|
-
}
|
367
|
+
if (self.hoverState == 'in') self.show();
|
368
|
+
}, self.options.delay.show);
|
369
|
+
};
|
365
370
|
|
366
371
|
Tooltip.prototype.leave = function (obj) {
|
367
372
|
var self = obj instanceof this.constructor ?
|
368
|
-
obj : $(obj.currentTarget).data('bs.' + this.type)
|
373
|
+
obj : $(obj.currentTarget).data('bs.' + this.type);
|
369
374
|
|
370
375
|
if (!self) {
|
371
|
-
self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
|
372
|
-
$(obj.currentTarget).data('bs.' + this.type, self)
|
376
|
+
self = new this.constructor(obj.currentTarget, this.getDelegateOptions());
|
377
|
+
$(obj.currentTarget).data('bs.' + this.type, self);
|
373
378
|
}
|
374
379
|
|
375
|
-
clearTimeout(self.timeout)
|
380
|
+
clearTimeout(self.timeout);
|
376
381
|
|
377
|
-
self.hoverState = 'out'
|
382
|
+
self.hoverState = 'out';
|
378
383
|
|
379
|
-
if (!self.options.delay || !self.options.delay.hide) return self.hide()
|
384
|
+
if (!self.options.delay || !self.options.delay.hide) return self.hide();
|
380
385
|
|
381
386
|
self.timeout = setTimeout(function () {
|
382
|
-
if (self.hoverState == 'out') self.hide()
|
383
|
-
}, self.options.delay.hide)
|
384
|
-
}
|
387
|
+
if (self.hoverState == 'out') self.hide();
|
388
|
+
}, self.options.delay.hide);
|
389
|
+
};
|
385
390
|
|
386
391
|
Tooltip.prototype.show = function () {
|
387
|
-
var e = $.Event('show.bs.' + this.type)
|
392
|
+
var e = $.Event('show.bs.' + this.type);
|
388
393
|
|
389
394
|
if (this.hasContent() && this.enabled) {
|
390
|
-
this.$element.trigger(e)
|
395
|
+
this.$element.trigger(e);
|
391
396
|
|
392
|
-
var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0])
|
393
|
-
if (e.isDefaultPrevented() || !inDom) return
|
394
|
-
var that = this
|
397
|
+
var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0]);
|
398
|
+
if (e.isDefaultPrevented() || !inDom) return;
|
399
|
+
var that = this;
|
395
400
|
|
396
|
-
var $tip = this.tip()
|
401
|
+
var $tip = this.tip();
|
397
402
|
|
398
|
-
var tipId = this.getUID(this.type)
|
403
|
+
var tipId = this.getUID(this.type);
|
399
404
|
|
400
|
-
this.setContent()
|
401
|
-
$tip.attr('id', tipId)
|
402
|
-
this.$element.attr('aria-describedby', tipId)
|
405
|
+
this.setContent();
|
406
|
+
$tip.attr('id', tipId);
|
407
|
+
this.$element.attr('aria-describedby', tipId);
|
403
408
|
|
404
|
-
if (this.options.animation) $tip.addClass('fade')
|
409
|
+
if (this.options.animation) $tip.addClass('fade');
|
405
410
|
|
406
411
|
var placement = typeof this.options.placement == 'function' ?
|
407
412
|
this.options.placement.call(this, $tip[0], this.$element[0]) :
|
408
|
-
this.options.placement
|
413
|
+
this.options.placement;
|
409
414
|
|
410
|
-
var autoToken = /\s?auto?\s?/i
|
411
|
-
var autoPlace = autoToken.test(placement)
|
412
|
-
if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
|
415
|
+
var autoToken = /\s?auto?\s?/i;
|
416
|
+
var autoPlace = autoToken.test(placement);
|
417
|
+
if (autoPlace) placement = placement.replace(autoToken, '') || 'top';
|
413
418
|
|
414
419
|
$tip
|
415
420
|
.detach()
|
416
421
|
.css({ top: 0, left: 0, display: 'block' })
|
417
422
|
.addClass(placement)
|
418
|
-
.data('bs.' + this.type, this)
|
423
|
+
.data('bs.' + this.type, this);
|
419
424
|
|
420
|
-
this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
|
425
|
+
this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element);
|
421
426
|
|
422
|
-
var pos = this.getPosition()
|
423
|
-
var actualWidth = $tip[0].offsetWidth
|
424
|
-
var actualHeight = $tip[0].offsetHeight
|
427
|
+
var pos = this.getPosition();
|
428
|
+
var actualWidth = $tip[0].offsetWidth;
|
429
|
+
var actualHeight = $tip[0].offsetHeight;
|
425
430
|
|
426
431
|
if (autoPlace) {
|
427
|
-
var orgPlacement = placement
|
428
|
-
var $container = this.options.container ? $(this.options.container) : this.$element.parent()
|
429
|
-
var containerDim = this.getPosition($container)
|
432
|
+
var orgPlacement = placement;
|
433
|
+
var $container = this.options.container ? $(this.options.container) : this.$element.parent();
|
434
|
+
var containerDim = this.getPosition($container);
|
430
435
|
|
431
436
|
placement = placement == 'bottom' && pos.bottom + actualHeight > containerDim.bottom ? 'top' :
|
432
437
|
placement == 'top' && pos.top - actualHeight < containerDim.top ? 'bottom' :
|
433
438
|
placement == 'right' && pos.right + actualWidth > containerDim.width ? 'left' :
|
434
439
|
placement == 'left' && pos.left - actualWidth < containerDim.left ? 'right' :
|
435
|
-
placement
|
440
|
+
placement;
|
436
441
|
|
437
442
|
$tip
|
438
443
|
.removeClass(orgPlacement)
|
439
|
-
.addClass(placement)
|
444
|
+
.addClass(placement);
|
440
445
|
}
|
441
446
|
|
442
|
-
var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
|
447
|
+
var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight);
|
443
448
|
|
444
|
-
this.applyPlacement(calculatedOffset, placement)
|
449
|
+
this.applyPlacement(calculatedOffset, placement);
|
445
450
|
|
446
451
|
var complete = function () {
|
447
|
-
var prevHoverState = that.hoverState
|
448
|
-
that.$element.trigger('shown.bs.' + that.type)
|
449
|
-
that.hoverState = null
|
452
|
+
var prevHoverState = that.hoverState;
|
453
|
+
that.$element.trigger('shown.bs.' + that.type);
|
454
|
+
that.hoverState = null;
|
450
455
|
|
451
|
-
if (prevHoverState == 'out') that.leave(that)
|
452
|
-
}
|
456
|
+
if (prevHoverState == 'out') that.leave(that);
|
457
|
+
};
|
453
458
|
|
454
459
|
$.support.transition && this.$tip.hasClass('fade') ?
|
455
460
|
$tip
|
456
461
|
.one('bsTransitionEnd', complete)
|
457
462
|
.emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
|
458
|
-
complete()
|
463
|
+
complete();
|
459
464
|
}
|
460
|
-
}
|
465
|
+
};
|
461
466
|
|
462
467
|
Tooltip.prototype.applyPlacement = function (offset, placement) {
|
463
|
-
var $tip = this.tip()
|
464
|
-
var width = $tip[0].offsetWidth
|
465
|
-
var height = $tip[0].offsetHeight
|
468
|
+
var $tip = this.tip();
|
469
|
+
var width = $tip[0].offsetWidth;
|
470
|
+
var height = $tip[0].offsetHeight;
|
466
471
|
|
467
472
|
// manually read margins because getBoundingClientRect includes difference
|
468
|
-
var marginTop = parseInt($tip.css('margin-top'), 10)
|
469
|
-
var marginLeft = parseInt($tip.css('margin-left'), 10)
|
473
|
+
var marginTop = parseInt($tip.css('margin-top'), 10);
|
474
|
+
var marginLeft = parseInt($tip.css('margin-left'), 10);
|
470
475
|
|
471
476
|
// we must check for NaN for ie 8/9
|
472
|
-
if (isNaN(marginTop)) marginTop = 0
|
473
|
-
if (isNaN(marginLeft)) marginLeft = 0
|
477
|
+
if (isNaN(marginTop)) marginTop = 0;
|
478
|
+
if (isNaN(marginLeft)) marginLeft = 0;
|
474
479
|
|
475
|
-
offset.top = offset.top + marginTop
|
476
|
-
offset.left = offset.left + marginLeft
|
480
|
+
offset.top = offset.top + marginTop;
|
481
|
+
offset.left = offset.left + marginLeft;
|
477
482
|
|
478
483
|
// $.fn.offset doesn't round pixel values
|
479
484
|
// so we use setOffset directly with our own function B-0
|
@@ -482,199 +487,199 @@
|
|
482
487
|
$tip.css({
|
483
488
|
top: Math.round(props.top),
|
484
489
|
left: Math.round(props.left)
|
485
|
-
})
|
490
|
+
});
|
486
491
|
}
|
487
|
-
}, offset), 0)
|
492
|
+
}, offset), 0);
|
488
493
|
|
489
|
-
$tip.addClass('in')
|
494
|
+
$tip.addClass('in');
|
490
495
|
|
491
496
|
// check to see if placing tip in new offset caused the tip to resize itself
|
492
|
-
var actualWidth = $tip[0].offsetWidth
|
493
|
-
var actualHeight = $tip[0].offsetHeight
|
497
|
+
var actualWidth = $tip[0].offsetWidth;
|
498
|
+
var actualHeight = $tip[0].offsetHeight;
|
494
499
|
|
495
500
|
if (placement == 'top' && actualHeight != height) {
|
496
|
-
offset.top = offset.top + height - actualHeight
|
501
|
+
offset.top = offset.top + height - actualHeight;
|
497
502
|
}
|
498
503
|
|
499
|
-
var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)
|
504
|
+
var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight);
|
500
505
|
|
501
|
-
if (delta.left) offset.left += delta.left
|
502
|
-
else offset.top += delta.top
|
506
|
+
if (delta.left) offset.left += delta.left;
|
507
|
+
else offset.top += delta.top;
|
503
508
|
|
504
|
-
var isVertical = /top|bottom/.test(placement)
|
505
|
-
var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
|
506
|
-
var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight'
|
509
|
+
var isVertical = /top|bottom/.test(placement);
|
510
|
+
var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight;
|
511
|
+
var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight';
|
507
512
|
|
508
|
-
$tip.offset(offset)
|
509
|
-
this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical)
|
510
|
-
}
|
513
|
+
$tip.offset(offset);
|
514
|
+
this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical);
|
515
|
+
};
|
511
516
|
|
512
517
|
Tooltip.prototype.replaceArrow = function (delta, dimension, isHorizontal) {
|
513
518
|
this.arrow()
|
514
519
|
.css(isHorizontal ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')
|
515
|
-
.css(isHorizontal ? 'top' : 'left', '')
|
516
|
-
}
|
520
|
+
.css(isHorizontal ? 'top' : 'left', '');
|
521
|
+
};
|
517
522
|
|
518
523
|
Tooltip.prototype.setContent = function () {
|
519
|
-
var $tip = this.tip()
|
520
|
-
var title = this.getTitle()
|
524
|
+
var $tip = this.tip();
|
525
|
+
var title = this.getTitle();
|
521
526
|
|
522
|
-
$tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
|
523
|
-
$tip.removeClass('fade in top bottom left right')
|
524
|
-
}
|
527
|
+
$tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title);
|
528
|
+
$tip.removeClass('fade in top bottom left right');
|
529
|
+
};
|
525
530
|
|
526
531
|
Tooltip.prototype.hide = function (callback) {
|
527
|
-
var that = this
|
528
|
-
var $tip = this.tip()
|
529
|
-
var e = $.Event('hide.bs.' + this.type)
|
532
|
+
var that = this;
|
533
|
+
var $tip = this.tip();
|
534
|
+
var e = $.Event('hide.bs.' + this.type);
|
530
535
|
|
531
536
|
function complete() {
|
532
|
-
if (that.hoverState != 'in') $tip.detach()
|
537
|
+
if (that.hoverState != 'in') $tip.detach();
|
533
538
|
that.$element
|
534
539
|
.removeAttr('aria-describedby')
|
535
|
-
.trigger('hidden.bs.' + that.type)
|
536
|
-
callback && callback()
|
540
|
+
.trigger('hidden.bs.' + that.type);
|
541
|
+
callback && callback();
|
537
542
|
}
|
538
543
|
|
539
|
-
this.$element.trigger(e)
|
544
|
+
this.$element.trigger(e);
|
540
545
|
|
541
|
-
if (e.isDefaultPrevented()) return
|
546
|
+
if (e.isDefaultPrevented()) return;
|
542
547
|
|
543
|
-
$tip.removeClass('in')
|
548
|
+
$tip.removeClass('in');
|
544
549
|
|
545
550
|
$.support.transition && this.$tip.hasClass('fade') ?
|
546
551
|
$tip
|
547
552
|
.one('bsTransitionEnd', complete)
|
548
553
|
.emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
|
549
|
-
complete()
|
554
|
+
complete();
|
550
555
|
|
551
|
-
this.hoverState = null
|
556
|
+
this.hoverState = null;
|
552
557
|
|
553
|
-
return this
|
554
|
-
}
|
558
|
+
return this;
|
559
|
+
};
|
555
560
|
|
556
561
|
Tooltip.prototype.fixTitle = function () {
|
557
|
-
var $e = this.$element
|
562
|
+
var $e = this.$element;
|
558
563
|
if ($e.attr('title') || typeof ($e.attr('data-original-title')) != 'string') {
|
559
|
-
$e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
|
564
|
+
$e.attr('data-original-title', $e.attr('title') || '').attr('title', '');
|
560
565
|
}
|
561
|
-
}
|
566
|
+
};
|
562
567
|
|
563
568
|
Tooltip.prototype.hasContent = function () {
|
564
|
-
return this.getTitle()
|
565
|
-
}
|
569
|
+
return this.getTitle();
|
570
|
+
};
|
566
571
|
|
567
572
|
Tooltip.prototype.getPosition = function ($element) {
|
568
|
-
$element = $element || this.$element
|
573
|
+
$element = $element || this.$element;
|
569
574
|
|
570
|
-
var el = $element[0]
|
571
|
-
var isBody = el.tagName == 'BODY'
|
575
|
+
var el = $element[0];
|
576
|
+
var isBody = el.tagName == 'BODY';
|
572
577
|
|
573
|
-
var elRect = el.getBoundingClientRect()
|
578
|
+
var elRect = el.getBoundingClientRect();
|
574
579
|
if (elRect.width == null) {
|
575
580
|
// width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093
|
576
|
-
elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top })
|
581
|
+
elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top });
|
577
582
|
}
|
578
|
-
var elOffset = isBody ? { top: 0, left: 0 } : $element.offset()
|
579
|
-
var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() }
|
580
|
-
var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null
|
583
|
+
var elOffset = isBody ? { top: 0, left: 0 } : $element.offset();
|
584
|
+
var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() };
|
585
|
+
var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null;
|
581
586
|
|
582
|
-
return $.extend({}, elRect, scroll, outerDims, elOffset)
|
583
|
-
}
|
587
|
+
return $.extend({}, elRect, scroll, outerDims, elOffset);
|
588
|
+
};
|
584
589
|
|
585
590
|
Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
|
586
591
|
return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } :
|
587
592
|
placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } :
|
588
593
|
placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
|
589
|
-
/* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width }
|
594
|
+
/* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width };
|
590
595
|
|
591
|
-
}
|
596
|
+
};
|
592
597
|
|
593
598
|
Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
|
594
|
-
var delta = { top: 0, left: 0 }
|
595
|
-
if (!this.$viewport) return delta
|
599
|
+
var delta = { top: 0, left: 0 };
|
600
|
+
if (!this.$viewport) return delta;
|
596
601
|
|
597
|
-
var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
|
598
|
-
var viewportDimensions = this.getPosition(this.$viewport)
|
602
|
+
var viewportPadding = this.options.viewport && this.options.viewport.padding || 0;
|
603
|
+
var viewportDimensions = this.getPosition(this.$viewport);
|
599
604
|
|
600
605
|
if (/right|left/.test(placement)) {
|
601
|
-
var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll
|
602
|
-
var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
|
606
|
+
var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll;
|
607
|
+
var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight;
|
603
608
|
if (topEdgeOffset < viewportDimensions.top) { // top overflow
|
604
|
-
delta.top = viewportDimensions.top - topEdgeOffset
|
609
|
+
delta.top = viewportDimensions.top - topEdgeOffset;
|
605
610
|
} else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
|
606
|
-
delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset
|
611
|
+
delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset;
|
607
612
|
}
|
608
613
|
} else {
|
609
|
-
var leftEdgeOffset = pos.left - viewportPadding
|
610
|
-
var rightEdgeOffset = pos.left + viewportPadding + actualWidth
|
614
|
+
var leftEdgeOffset = pos.left - viewportPadding;
|
615
|
+
var rightEdgeOffset = pos.left + viewportPadding + actualWidth;
|
611
616
|
if (leftEdgeOffset < viewportDimensions.left) { // left overflow
|
612
|
-
delta.left = viewportDimensions.left - leftEdgeOffset
|
617
|
+
delta.left = viewportDimensions.left - leftEdgeOffset;
|
613
618
|
} else if (rightEdgeOffset > viewportDimensions.width) { // right overflow
|
614
|
-
delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
|
619
|
+
delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset;
|
615
620
|
}
|
616
621
|
}
|
617
622
|
|
618
|
-
return delta
|
619
|
-
}
|
623
|
+
return delta;
|
624
|
+
};
|
620
625
|
|
621
626
|
Tooltip.prototype.getTitle = function () {
|
622
|
-
var title
|
623
|
-
var $e = this.$element
|
624
|
-
var o = this.options
|
627
|
+
var title;
|
628
|
+
var $e = this.$element;
|
629
|
+
var o = this.options;
|
625
630
|
|
626
631
|
title = $e.attr('data-original-title')
|
627
|
-
|| (typeof o.title == 'function' ? o.title.call($e[0]) : o.title)
|
632
|
+
|| (typeof o.title == 'function' ? o.title.call($e[0]) : o.title);
|
628
633
|
|
629
|
-
return title
|
630
|
-
}
|
634
|
+
return title;
|
635
|
+
};
|
631
636
|
|
632
637
|
Tooltip.prototype.getUID = function (prefix) {
|
633
|
-
do prefix += ~~(Math.random() * 1000000)
|
634
|
-
while (document.getElementById(prefix))
|
635
|
-
return prefix
|
636
|
-
}
|
638
|
+
do prefix += ~~(Math.random() * 1000000);
|
639
|
+
while (document.getElementById(prefix));
|
640
|
+
return prefix;
|
641
|
+
};
|
637
642
|
|
638
643
|
Tooltip.prototype.tip = function () {
|
639
|
-
return (this.$tip = this.$tip || $(this.options.template))
|
640
|
-
}
|
644
|
+
return (this.$tip = this.$tip || $(this.options.template));
|
645
|
+
};
|
641
646
|
|
642
647
|
Tooltip.prototype.arrow = function () {
|
643
|
-
return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'))
|
644
|
-
}
|
648
|
+
return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'));
|
649
|
+
};
|
645
650
|
|
646
651
|
Tooltip.prototype.enable = function () {
|
647
|
-
this.enabled = true
|
648
|
-
}
|
652
|
+
this.enabled = true;
|
653
|
+
};
|
649
654
|
|
650
655
|
Tooltip.prototype.disable = function () {
|
651
|
-
this.enabled = false
|
652
|
-
}
|
656
|
+
this.enabled = false;
|
657
|
+
};
|
653
658
|
|
654
659
|
Tooltip.prototype.toggleEnabled = function () {
|
655
|
-
this.enabled = !this.enabled
|
656
|
-
}
|
660
|
+
this.enabled = !this.enabled;
|
661
|
+
};
|
657
662
|
|
658
663
|
Tooltip.prototype.toggle = function (e) {
|
659
|
-
var self = this
|
664
|
+
var self = this;
|
660
665
|
if (e) {
|
661
|
-
self = $(e.currentTarget).data('bs.' + this.type)
|
666
|
+
self = $(e.currentTarget).data('bs.' + this.type);
|
662
667
|
if (!self) {
|
663
|
-
self = new this.constructor(e.currentTarget, this.getDelegateOptions())
|
664
|
-
$(e.currentTarget).data('bs.' + this.type, self)
|
668
|
+
self = new this.constructor(e.currentTarget, this.getDelegateOptions());
|
669
|
+
$(e.currentTarget).data('bs.' + this.type, self);
|
665
670
|
}
|
666
671
|
}
|
667
672
|
|
668
|
-
self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
|
669
|
-
}
|
673
|
+
self.tip().hasClass('in') ? self.leave(self) : self.enter(self);
|
674
|
+
};
|
670
675
|
|
671
676
|
Tooltip.prototype.destroy = function () {
|
672
|
-
var that = this
|
673
|
-
clearTimeout(this.timeout)
|
677
|
+
var that = this;
|
678
|
+
clearTimeout(this.timeout);
|
674
679
|
this.hide(function () {
|
675
|
-
that.$element.off('.' + that.type).removeData('bs.' + that.type)
|
676
|
-
})
|
677
|
-
}
|
680
|
+
that.$element.off('.' + that.type).removeData('bs.' + that.type);
|
681
|
+
});
|
682
|
+
};
|
678
683
|
|
679
684
|
|
680
685
|
// TOOLTIP PLUGIN DEFINITION
|
@@ -682,35 +687,35 @@
|
|
682
687
|
|
683
688
|
function Plugin(option) {
|
684
689
|
return this.each(function () {
|
685
|
-
var $this = $(this)
|
686
|
-
var data = $this.data('bs.tooltip')
|
687
|
-
var options = typeof option == 'object' && option
|
688
|
-
var selector = options && options.selector
|
690
|
+
var $this = $(this);
|
691
|
+
var data = $this.data('bs.tooltip');
|
692
|
+
var options = typeof option == 'object' && option;
|
693
|
+
var selector = options && options.selector;
|
689
694
|
|
690
|
-
if (!data && option == 'destroy') return
|
695
|
+
if (!data && option == 'destroy') return;
|
691
696
|
if (selector) {
|
692
|
-
if (!data) $this.data('bs.tooltip', (data = {}))
|
693
|
-
if (!data[selector]) data[selector] = new Tooltip(this, options)
|
697
|
+
if (!data) $this.data('bs.tooltip', (data = {}));
|
698
|
+
if (!data[selector]) data[selector] = new Tooltip(this, options);
|
694
699
|
} else {
|
695
|
-
if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
|
700
|
+
if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)));
|
696
701
|
}
|
697
|
-
if (typeof option == 'string') data[option]()
|
698
|
-
})
|
702
|
+
if (typeof option == 'string') data[option]();
|
703
|
+
});
|
699
704
|
}
|
700
705
|
|
701
|
-
var old = $.fn.tooltip
|
706
|
+
var old = $.fn.tooltip;
|
702
707
|
|
703
|
-
$.fn.tooltip = Plugin
|
704
|
-
$.fn.tooltip.Constructor = Tooltip
|
708
|
+
$.fn.tooltip = Plugin;
|
709
|
+
$.fn.tooltip.Constructor = Tooltip;
|
705
710
|
|
706
711
|
|
707
712
|
// TOOLTIP NO CONFLICT
|
708
713
|
// ===================
|
709
714
|
|
710
715
|
$.fn.tooltip.noConflict = function () {
|
711
|
-
$.fn.tooltip = old
|
712
|
-
return this
|
713
|
-
}
|
716
|
+
$.fn.tooltip = old;
|
717
|
+
return this;
|
718
|
+
};
|
714
719
|
|
715
720
|
}(jQuery);
|
716
721
|
|
@@ -733,71 +738,71 @@
|
|
733
738
|
// ===============================
|
734
739
|
|
735
740
|
var Popover = function (element, options) {
|
736
|
-
this.init('popover', element, options)
|
737
|
-
}
|
741
|
+
this.init('popover', element, options);
|
742
|
+
};
|
738
743
|
|
739
|
-
if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
|
744
|
+
if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js');
|
740
745
|
|
741
|
-
Popover.VERSION = '3.3.1'
|
746
|
+
Popover.VERSION = '3.3.1';
|
742
747
|
|
743
748
|
Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {
|
744
749
|
placement: 'right',
|
745
750
|
trigger: 'click',
|
746
751
|
content: '',
|
747
752
|
template: '<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
|
748
|
-
})
|
753
|
+
});
|
749
754
|
|
750
755
|
|
751
756
|
// NOTE: POPOVER EXTENDS tooltip.js
|
752
757
|
// ================================
|
753
758
|
|
754
|
-
Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)
|
759
|
+
Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype);
|
755
760
|
|
756
|
-
Popover.prototype.constructor = Popover
|
761
|
+
Popover.prototype.constructor = Popover;
|
757
762
|
|
758
763
|
Popover.prototype.getDefaults = function () {
|
759
|
-
return Popover.DEFAULTS
|
760
|
-
}
|
764
|
+
return Popover.DEFAULTS;
|
765
|
+
};
|
761
766
|
|
762
767
|
Popover.prototype.setContent = function () {
|
763
|
-
var $tip = this.tip()
|
764
|
-
var title = this.getTitle()
|
765
|
-
var content = this.getContent()
|
768
|
+
var $tip = this.tip();
|
769
|
+
var title = this.getTitle();
|
770
|
+
var content = this.getContent();
|
766
771
|
|
767
|
-
$tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
|
772
|
+
$tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title);
|
768
773
|
$tip.find('.popover-content').children().detach().end()[ // we use append for html objects to maintain js events
|
769
774
|
this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text'
|
770
|
-
](content)
|
775
|
+
](content);
|
771
776
|
|
772
|
-
$tip.removeClass('fade top bottom left right in')
|
777
|
+
$tip.removeClass('fade top bottom left right in');
|
773
778
|
|
774
779
|
// IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do
|
775
780
|
// this manually by checking the contents.
|
776
|
-
if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()
|
777
|
-
}
|
781
|
+
if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide();
|
782
|
+
};
|
778
783
|
|
779
784
|
Popover.prototype.hasContent = function () {
|
780
|
-
return this.getTitle() || this.getContent()
|
781
|
-
}
|
785
|
+
return this.getTitle() || this.getContent();
|
786
|
+
};
|
782
787
|
|
783
788
|
Popover.prototype.getContent = function () {
|
784
|
-
var $e = this.$element
|
785
|
-
var o = this.options
|
789
|
+
var $e = this.$element;
|
790
|
+
var o = this.options;
|
786
791
|
|
787
792
|
return $e.attr('data-content')
|
788
793
|
|| (typeof o.content == 'function' ?
|
789
794
|
o.content.call($e[0]) :
|
790
|
-
o.content)
|
791
|
-
}
|
795
|
+
o.content);
|
796
|
+
};
|
792
797
|
|
793
798
|
Popover.prototype.arrow = function () {
|
794
|
-
return (this.$arrow = this.$arrow || this.tip().find('.arrow'))
|
795
|
-
}
|
799
|
+
return (this.$arrow = this.$arrow || this.tip().find('.arrow'));
|
800
|
+
};
|
796
801
|
|
797
802
|
Popover.prototype.tip = function () {
|
798
|
-
if (!this.$tip) this.$tip = $(this.options.template)
|
799
|
-
return this.$tip
|
800
|
-
}
|
803
|
+
if (!this.$tip) this.$tip = $(this.options.template);
|
804
|
+
return this.$tip;
|
805
|
+
};
|
801
806
|
|
802
807
|
|
803
808
|
// POPOVER PLUGIN DEFINITION
|
@@ -805,35 +810,35 @@
|
|
805
810
|
|
806
811
|
function Plugin(option) {
|
807
812
|
return this.each(function () {
|
808
|
-
var $this = $(this)
|
809
|
-
var data = $this.data('bs.popover')
|
810
|
-
var options = typeof option == 'object' && option
|
811
|
-
var selector = options && options.selector
|
813
|
+
var $this = $(this);
|
814
|
+
var data = $this.data('bs.popover');
|
815
|
+
var options = typeof option == 'object' && option;
|
816
|
+
var selector = options && options.selector;
|
812
817
|
|
813
|
-
if (!data && option == 'destroy') return
|
818
|
+
if (!data && option == 'destroy') return;
|
814
819
|
if (selector) {
|
815
|
-
if (!data) $this.data('bs.popover', (data = {}))
|
816
|
-
if (!data[selector]) data[selector] = new Popover(this, options)
|
820
|
+
if (!data) $this.data('bs.popover', (data = {}));
|
821
|
+
if (!data[selector]) data[selector] = new Popover(this, options);
|
817
822
|
} else {
|
818
|
-
if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
|
823
|
+
if (!data) $this.data('bs.popover', (data = new Popover(this, options)));
|
819
824
|
}
|
820
|
-
if (typeof option == 'string') data[option]()
|
821
|
-
})
|
825
|
+
if (typeof option == 'string') data[option]();
|
826
|
+
});
|
822
827
|
}
|
823
828
|
|
824
|
-
var old = $.fn.popover
|
829
|
+
var old = $.fn.popover;
|
825
830
|
|
826
|
-
$.fn.popover = Plugin
|
827
|
-
$.fn.popover.Constructor = Popover
|
831
|
+
$.fn.popover = Plugin;
|
832
|
+
$.fn.popover.Constructor = Popover;
|
828
833
|
|
829
834
|
|
830
835
|
// POPOVER NO CONFLICT
|
831
836
|
// ===================
|
832
837
|
|
833
838
|
$.fn.popover.noConflict = function () {
|
834
|
-
$.fn.popover = old
|
835
|
-
return this
|
836
|
-
}
|
839
|
+
$.fn.popover = old;
|
840
|
+
return this;
|
841
|
+
};
|
837
842
|
|
838
843
|
}(jQuery);
|
839
844
|
}
|
@@ -878,7 +883,7 @@
|
|
878
883
|
function y_rug(args) {
|
879
884
|
'use strict';
|
880
885
|
var svg = mg_get_svg_child_of(args.target);
|
881
|
-
|
886
|
+
|
882
887
|
var buffer_size = args.chart_type === 'point'
|
883
888
|
? args.buffer / 2
|
884
889
|
: args.buffer * 2 / 3;
|
@@ -931,6 +936,11 @@
|
|
931
936
|
max_y;
|
932
937
|
|
933
938
|
args.scalefns.yf = function(di) {
|
939
|
+
//since we want to show actual zeros when missing_is_hidden is on
|
940
|
+
if(args.missing_is_hidden && di['missing']) {
|
941
|
+
return args.scales.Y(di[args.y_accessor]) + 42.1234;
|
942
|
+
}
|
943
|
+
|
934
944
|
return args.scales.Y(di[args.y_accessor]);
|
935
945
|
};
|
936
946
|
|
@@ -1040,7 +1050,7 @@
|
|
1040
1050
|
};
|
1041
1051
|
} else { //percentage
|
1042
1052
|
yax_format = function(d_) {
|
1043
|
-
var n = d3.format('
|
1053
|
+
var n = d3.format('2p');
|
1044
1054
|
return n(d_);
|
1045
1055
|
};
|
1046
1056
|
}
|
@@ -1205,16 +1215,15 @@
|
|
1205
1215
|
var buffer_size = args.chart_type === 'point'
|
1206
1216
|
? args.buffer / 2
|
1207
1217
|
: args.buffer;
|
1208
|
-
|
1209
1218
|
var svg = mg_get_svg_child_of(args.target);
|
1210
1219
|
|
1211
|
-
var all_data=
|
1212
|
-
for (var i=0; i<args.data.length; i++) {
|
1213
|
-
|
1214
|
-
|
1215
|
-
|
1216
|
-
}
|
1217
|
-
|
1220
|
+
var all_data = mg_flatten_array(args.data)
|
1221
|
+
// for (var i=0; i<args.data.length; i++) {
|
1222
|
+
// for (var j=0; j<args.data[i].length; j++) {
|
1223
|
+
// all_data.push(args.data[i][j]);
|
1224
|
+
// }
|
1225
|
+
// }
|
1226
|
+
|
1218
1227
|
var rug = svg.selectAll('line.mg-x-rug').data(all_data);
|
1219
1228
|
|
1220
1229
|
//set the attributes that do not change after initialization, per
|
@@ -1251,7 +1260,12 @@
|
|
1251
1260
|
var max_x;
|
1252
1261
|
|
1253
1262
|
args.processed = {};
|
1254
|
-
|
1263
|
+
var all_data = [];
|
1264
|
+
for (var i = 0; i < args.data.length; i++) {
|
1265
|
+
for (var j = 0; j < args.data[i].length; j++) {
|
1266
|
+
all_data.push(args.data[i][j]);
|
1267
|
+
}
|
1268
|
+
}
|
1255
1269
|
args.scalefns.xf = function(di) {
|
1256
1270
|
return args.scales.X(di[args.x_accessor]);
|
1257
1271
|
};
|
@@ -1266,6 +1280,7 @@
|
|
1266
1280
|
args.scales.X = (args.time_series)
|
1267
1281
|
? d3.time.scale()
|
1268
1282
|
: d3.scale.linear();
|
1283
|
+
|
1269
1284
|
args.scales.X
|
1270
1285
|
.domain([args.processed.min_x, args.processed.max_x])
|
1271
1286
|
.range([args.left + args.buffer, args.width - args.right - args.buffer - args.additional_buffer]);
|
@@ -1445,9 +1460,7 @@
|
|
1445
1460
|
g.append('text')
|
1446
1461
|
.attr('class', 'label')
|
1447
1462
|
.attr('x', function() {
|
1448
|
-
return args.left + args.
|
1449
|
-
+ ((args.width - args.right - args.buffer)
|
1450
|
-
- (args.left + args.buffer)) / 2;
|
1463
|
+
return (args.left + args.width - args.right) / 2;
|
1451
1464
|
})
|
1452
1465
|
.attr('y', (args.height - args.bottom / 2).toFixed(2))
|
1453
1466
|
.attr('dy', '.50em')
|
@@ -1477,41 +1490,42 @@
|
|
1477
1490
|
if (args.xax_format) {
|
1478
1491
|
return args.xax_format;
|
1479
1492
|
}
|
1493
|
+
var test_point = mg_flatten_array(args.data)[0][args.x_accessor]
|
1480
1494
|
|
1481
|
-
|
1482
|
-
|
1483
|
-
|
1484
|
-
|
1485
|
-
|
1486
|
-
|
1487
|
-
|
1488
|
-
|
1489
|
-
|
1490
|
-
|
1491
|
-
|
1492
|
-
|
1493
|
-
|
1494
|
-
|
1495
|
-
|
1496
|
-
|
1497
|
-
|
1498
|
-
|
1499
|
-
|
1495
|
+
return function(d) {
|
1496
|
+
var diff;
|
1497
|
+
var main_time_format;
|
1498
|
+
var time_frame;
|
1499
|
+
|
1500
|
+
if (args.time_series) {
|
1501
|
+
diff = (args.processed.max_x - args.processed.min_x) / 1000;
|
1502
|
+
|
1503
|
+
if (diff < 60) {
|
1504
|
+
main_time_format = d3.time.format('%M:%S');
|
1505
|
+
time_frame = 'seconds';
|
1506
|
+
} else if (diff / (60 * 60) <= 24) {
|
1507
|
+
main_time_format = d3.time.format('%H:%M');
|
1508
|
+
time_frame = 'less-than-a-day';
|
1509
|
+
} else if (diff / (60 * 60) <= 24 * 4) {
|
1510
|
+
main_time_format = d3.time.format('%H:%M');
|
1511
|
+
time_frame = 'four-days';
|
1512
|
+
} else {
|
1513
|
+
main_time_format = d3.time.format('%b %d');
|
1514
|
+
time_frame = 'default';
|
1515
|
+
}
|
1500
1516
|
}
|
1501
|
-
}
|
1502
1517
|
|
1503
|
-
|
1504
|
-
|
1518
|
+
args.processed.main_x_time_format = main_time_format;
|
1519
|
+
args.processed.x_time_frame = time_frame;
|
1505
1520
|
|
1506
|
-
return function(d) {
|
1507
1521
|
var df = d3.time.format('%b %d');
|
1508
1522
|
var pf = d3.formatPrefix(d);
|
1509
1523
|
|
1510
1524
|
// format as date or not, of course user can pass in
|
1511
1525
|
// a custom function if desired
|
1512
|
-
if(
|
1513
|
-
return args.processed.main_x_time_format(d);
|
1514
|
-
} else if(
|
1526
|
+
if(test_point instanceof Date) {
|
1527
|
+
return args.processed.main_x_time_format(new Date(d));
|
1528
|
+
} else if (typeof test_point === 'number') {
|
1515
1529
|
if (d < 1.0) {
|
1516
1530
|
//don't scale tiny values
|
1517
1531
|
return args.xax_units + d3.round(d, args.decimals);
|
@@ -1527,17 +1541,32 @@
|
|
1527
1541
|
|
1528
1542
|
function mg_add_x_ticks(g, args) {
|
1529
1543
|
var last_i = args.scales.X.ticks(args.xax_count).length - 1;
|
1544
|
+
var ticks = args.scales.X.ticks(args.xax_count);
|
1545
|
+
|
1546
|
+
//force min to be the first tick rather than the first element in ticks
|
1547
|
+
if(args.xax_start_at_min) {
|
1548
|
+
ticks[0] = args.processed.min_x;
|
1549
|
+
}
|
1530
1550
|
|
1531
1551
|
if (args.chart_type !== 'bar' && !args.x_extended_ticks && !args.y_extended_ticks) {
|
1532
1552
|
//extend axis line across bottom, rather than from domain's min..max
|
1533
1553
|
g.append('line')
|
1534
|
-
.attr('x1',
|
1535
|
-
|
1536
|
-
|
1537
|
-
|
1538
|
-
|
1554
|
+
.attr('x1', function() {
|
1555
|
+
//start the axis line from the beginning, domain's min, or the auto-generated
|
1556
|
+
//ticks' first element, depending on whether xax_count is set to 0 or
|
1557
|
+
//xax_start_at_min is set to true
|
1558
|
+
if (args.xax_count === 0) {
|
1559
|
+
return args.left + args.buffer;
|
1560
|
+
}
|
1561
|
+
else if (args.xax_start_at_min) {
|
1562
|
+
return args.scales.X(args.processed.min_x).toFixed(2)
|
1563
|
+
}
|
1564
|
+
else {
|
1565
|
+
return (args.scales.X(args.scales.X.ticks(args.xax_count)[0])).toFixed(2);
|
1566
|
+
}
|
1567
|
+
})
|
1539
1568
|
.attr('x2',
|
1540
|
-
(args.
|
1569
|
+
(args.xax_count === 0)
|
1541
1570
|
? args.width - args.right - args.buffer
|
1542
1571
|
: (args.scales.X(args.scales.X.ticks(args.xax_count)[last_i])).toFixed(2)
|
1543
1572
|
)
|
@@ -1546,7 +1575,7 @@
|
|
1546
1575
|
}
|
1547
1576
|
|
1548
1577
|
g.selectAll('.mg-xax-ticks')
|
1549
|
-
.data(
|
1578
|
+
.data(ticks).enter()
|
1550
1579
|
.append('line')
|
1551
1580
|
.attr('x1', function(d) { return args.scales.X(d).toFixed(2); })
|
1552
1581
|
.attr('x2', function(d) { return args.scales.X(d).toFixed(2); })
|
@@ -1564,8 +1593,15 @@
|
|
1564
1593
|
}
|
1565
1594
|
|
1566
1595
|
function mg_add_x_tick_labels(g, args) {
|
1596
|
+
var ticks = args.scales.X.ticks(args.xax_count);
|
1597
|
+
|
1598
|
+
//force min to be the first tick rather than the first element in ticks
|
1599
|
+
if(args.xax_start_at_min) {
|
1600
|
+
ticks[0] = args.processed.min_x;
|
1601
|
+
}
|
1602
|
+
|
1567
1603
|
g.selectAll('.mg-xax-labels')
|
1568
|
-
.data(
|
1604
|
+
.data(ticks).enter()
|
1569
1605
|
.append('text')
|
1570
1606
|
.attr('x', function(d) { return args.scales.X(d).toFixed(2); })
|
1571
1607
|
.attr('y', (args.height - args.bottom + args.xax_tick_length * 7 / 3).toFixed(2))
|
@@ -1601,7 +1637,11 @@
|
|
1601
1637
|
|
1602
1638
|
var years = secondary_function(args.processed.min_x, args.processed.max_x);
|
1603
1639
|
|
1604
|
-
if
|
1640
|
+
//if xax_start_at_min is set
|
1641
|
+
if (args.xax_start_at_min && years.length === 0) {
|
1642
|
+
var first_tick = ticks[0];
|
1643
|
+
years = [first_tick];
|
1644
|
+
} else if (years.length === 0) {
|
1605
1645
|
var first_tick = args.scales.X.ticks(args.xax_count)[0];
|
1606
1646
|
years = [first_tick];
|
1607
1647
|
}
|
@@ -1611,7 +1651,7 @@
|
|
1611
1651
|
.classed('mg-year-marker', true)
|
1612
1652
|
.classed('mg-year-marker-small', args.use_small_class);
|
1613
1653
|
|
1614
|
-
if (time_frame === 'default') {
|
1654
|
+
if (time_frame === 'default' && args.show_year_markers) {
|
1615
1655
|
g.selectAll('.mg-year-marker')
|
1616
1656
|
.data(years).enter()
|
1617
1657
|
.append('line')
|
@@ -1624,12 +1664,18 @@
|
|
1624
1664
|
g.selectAll('.mg-year-marker')
|
1625
1665
|
.data(years).enter()
|
1626
1666
|
.append('text')
|
1627
|
-
.attr('x', function(d) {
|
1667
|
+
.attr('x', function(d, i) {
|
1668
|
+
if (args.xax_start_at_min && i == 0) {
|
1669
|
+
d = ticks[0];
|
1670
|
+
}
|
1671
|
+
|
1672
|
+
return args.scales.X(d).toFixed(2);
|
1673
|
+
})
|
1628
1674
|
.attr('y', (args.height - args.bottom + args.xax_tick_length * 7 / 1.3).toFixed(2))
|
1629
|
-
.attr('dy', args.use_small_class ? -3 : 0)
|
1675
|
+
.attr('dy', args.use_small_class ? -3 : 0)
|
1630
1676
|
.attr('text-anchor', 'middle')
|
1631
1677
|
.text(function(d) {
|
1632
|
-
return yformat(d);
|
1678
|
+
return yformat(new Date(d));
|
1633
1679
|
});
|
1634
1680
|
}
|
1635
1681
|
}
|
@@ -1643,7 +1689,9 @@
|
|
1643
1689
|
mapDtoX = function(d) { return d[args.x_accessor]; };
|
1644
1690
|
|
1645
1691
|
// clear the cached xax_format in case we need to recalculate
|
1646
|
-
|
1692
|
+
if(args.xax_format === null) {
|
1693
|
+
delete args.xax_format;
|
1694
|
+
}
|
1647
1695
|
|
1648
1696
|
if (args.chart_type === 'line' || args.chart_type === 'point' || args.chart_type === 'histogram') {
|
1649
1697
|
extent_x = d3.extent(all_data, mapDtoX);
|
@@ -1662,10 +1710,9 @@
|
|
1662
1710
|
});
|
1663
1711
|
}
|
1664
1712
|
//if data set is of length 1, expand the range so that we can build the x-axis
|
1665
|
-
|
1666
|
-
|
1667
|
-
|
1668
|
-
if (min_x === max_x) {
|
1713
|
+
if (min_x === max_x
|
1714
|
+
&& !(args.min_x && args.max_x)
|
1715
|
+
) {
|
1669
1716
|
if (min_x instanceof Date) {
|
1670
1717
|
var yesterday = MG.clone(min_x).setDate(min_x.getDate() - 1);
|
1671
1718
|
var tomorrow = MG.clone(min_x).setDate(min_x.getDate() + 1);
|
@@ -1722,7 +1769,10 @@
|
|
1722
1769
|
description: null
|
1723
1770
|
};
|
1724
1771
|
|
1725
|
-
|
1772
|
+
// If you pass in a dom element for args.target, the expectation
|
1773
|
+
// of a string elsewhere will break.
|
1774
|
+
|
1775
|
+
args = arguments[0];
|
1726
1776
|
if (!args) { args = {}; }
|
1727
1777
|
args = merge_with_defaults(args, defaults);
|
1728
1778
|
|
@@ -1738,12 +1788,15 @@
|
|
1738
1788
|
//but with the intention of using multiple values for multilines, etc.
|
1739
1789
|
|
1740
1790
|
//do we have a time_series?
|
1741
|
-
|
1742
|
-
|
1743
|
-
|
1744
|
-
|
1791
|
+
|
1792
|
+
function is_time_series(args) {
|
1793
|
+
var flat_data = [];
|
1794
|
+
var first_elem = mg_flatten_array(args.data)[0];
|
1795
|
+
return first_elem[args.x_accessor] instanceof Date;
|
1745
1796
|
}
|
1746
1797
|
|
1798
|
+
args.time_series = is_time_series(args);
|
1799
|
+
|
1747
1800
|
var svg_width = args.width;
|
1748
1801
|
var svg_height = args.height;
|
1749
1802
|
|
@@ -1753,7 +1806,7 @@
|
|
1753
1806
|
svg_width = get_width(args.target);
|
1754
1807
|
}
|
1755
1808
|
|
1756
|
-
if (args.
|
1809
|
+
if (args.full_height) {
|
1757
1810
|
svg_height = get_height(args.target);
|
1758
1811
|
}
|
1759
1812
|
|
@@ -1790,7 +1843,7 @@
|
|
1790
1843
|
svg.append('defs')
|
1791
1844
|
.attr('class', 'mg-clip-path')
|
1792
1845
|
.append('clipPath')
|
1793
|
-
.attr('
|
1846
|
+
.attr('id', 'mg-plot-window-' + mg_strip_punctuation(args.target))
|
1794
1847
|
.append('svg:rect')
|
1795
1848
|
.attr('x', args.left)
|
1796
1849
|
.attr('y', args.top)
|
@@ -1806,7 +1859,7 @@
|
|
1806
1859
|
svg.attr('height', svg_height);
|
1807
1860
|
}
|
1808
1861
|
|
1809
|
-
//
|
1862
|
+
// @todo need to reconsider how we handle automatic scaling
|
1810
1863
|
svg.attr('viewBox', '0 0 ' + svg_width + ' ' + svg_height);
|
1811
1864
|
|
1812
1865
|
if (args.full_width || args.full_height) {
|
@@ -1815,7 +1868,7 @@
|
|
1815
1868
|
|
1816
1869
|
// remove missing class
|
1817
1870
|
svg.classed('mg-missing', false);
|
1818
|
-
|
1871
|
+
|
1819
1872
|
// remove missing text
|
1820
1873
|
svg.selectAll('.mg-missing-text').remove();
|
1821
1874
|
svg.selectAll('.mg-missing-pane').remove();
|
@@ -1833,7 +1886,7 @@
|
|
1833
1886
|
//data_graphic() on the same target with 2 lines, remove the 3rd line
|
1834
1887
|
|
1835
1888
|
var i = 0;
|
1836
|
-
if (
|
1889
|
+
if (svg.selectAll('.mg-main-line')[0].length >= args.data.length) {
|
1837
1890
|
//now, the thing is we can't just remove, say, line3 if we have a custom
|
1838
1891
|
//line-color map, instead, see which are the lines to be removed, and delete those
|
1839
1892
|
if (args.custom_line_color_map.length > 0) {
|
@@ -1868,6 +1921,8 @@
|
|
1868
1921
|
return this;
|
1869
1922
|
}
|
1870
1923
|
|
1924
|
+
|
1925
|
+
|
1871
1926
|
function markers(args) {
|
1872
1927
|
'use strict';
|
1873
1928
|
var svg = mg_get_svg_child_of(args.target);
|
@@ -1883,18 +1938,11 @@
|
|
1883
1938
|
.attr('class', 'mg-markers');
|
1884
1939
|
|
1885
1940
|
gm.selectAll('.mg-markers')
|
1886
|
-
.data(args.markers.filter(
|
1887
|
-
return (args.scales.X(d[args.x_accessor]) > args.buffer + args.left)
|
1888
|
-
&& (args.scales.X(d[args.x_accessor]) < args.width - args.buffer - args.right);
|
1889
|
-
}))
|
1941
|
+
.data(args.markers.filter(inRange))
|
1890
1942
|
.enter()
|
1891
1943
|
.append('line')
|
1892
|
-
.attr('x1',
|
1893
|
-
|
1894
|
-
})
|
1895
|
-
.attr('x2', function(d) {
|
1896
|
-
return args.scales.X(d[args.x_accessor]).toFixed(2);
|
1897
|
-
})
|
1944
|
+
.attr('x1', xPositionFixed)
|
1945
|
+
.attr('x2', xPositionFixed)
|
1898
1946
|
.attr('y1', args.top)
|
1899
1947
|
.attr('y2', function() {
|
1900
1948
|
return args.height - args.bottom - args.buffer;
|
@@ -1902,20 +1950,32 @@
|
|
1902
1950
|
.attr('stroke-dasharray', '3,1');
|
1903
1951
|
|
1904
1952
|
gm.selectAll('.mg-markers')
|
1905
|
-
.data(args.markers.filter(
|
1906
|
-
return (args.scales.X(d[args.x_accessor]) > args.buffer + args.left)
|
1907
|
-
&& (args.scales.X(d[args.x_accessor]) < args.width - args.buffer - args.right);
|
1908
|
-
}))
|
1953
|
+
.data(args.markers.filter(inRange))
|
1909
1954
|
.enter()
|
1910
1955
|
.append('text')
|
1911
|
-
.attr('
|
1912
|
-
|
1913
|
-
})
|
1956
|
+
.attr('class', 'mg-marker-text')
|
1957
|
+
.attr('x', xPosition)
|
1914
1958
|
.attr('y', args.top - 8)
|
1915
1959
|
.attr('text-anchor', 'middle')
|
1916
1960
|
.text(function(d) {
|
1917
1961
|
return d.label;
|
1918
1962
|
});
|
1963
|
+
|
1964
|
+
preventHorizontalOverlap(gm.selectAll('.mg-marker-text')[0], args);
|
1965
|
+
}
|
1966
|
+
|
1967
|
+
|
1968
|
+
function xPosition(d) {
|
1969
|
+
return args.scales.X(d[args.x_accessor]);
|
1970
|
+
}
|
1971
|
+
|
1972
|
+
function xPositionFixed(d) {
|
1973
|
+
return xPosition(d).toFixed(2);
|
1974
|
+
}
|
1975
|
+
|
1976
|
+
function inRange(d) {
|
1977
|
+
return (args.scales.X(d[args.x_accessor]) > args.buffer + args.left)
|
1978
|
+
&& (args.scales.X(d[args.x_accessor]) < args.width - args.buffer - args.right);
|
1919
1979
|
}
|
1920
1980
|
|
1921
1981
|
if (args.baselines) {
|
@@ -1999,109 +2059,109 @@
|
|
1999
2059
|
// DROPDOWN CLASS DEFINITION
|
2000
2060
|
// =========================
|
2001
2061
|
|
2002
|
-
var backdrop = '.dropdown-backdrop'
|
2003
|
-
var toggle = '[data-toggle="dropdown"]'
|
2062
|
+
var backdrop = '.dropdown-backdrop';
|
2063
|
+
var toggle = '[data-toggle="dropdown"]';
|
2004
2064
|
var Dropdown = function (element) {
|
2005
|
-
$(element).on('click.bs.dropdown', this.toggle)
|
2006
|
-
}
|
2065
|
+
$(element).on('click.bs.dropdown', this.toggle);
|
2066
|
+
};
|
2007
2067
|
|
2008
|
-
Dropdown.VERSION = '3.3.1'
|
2068
|
+
Dropdown.VERSION = '3.3.1';
|
2009
2069
|
|
2010
2070
|
Dropdown.prototype.toggle = function (e) {
|
2011
|
-
var $this = $(this)
|
2071
|
+
var $this = $(this);
|
2012
2072
|
|
2013
|
-
if ($this.is('.disabled, :disabled')) return
|
2073
|
+
if ($this.is('.disabled, :disabled')) return;
|
2014
2074
|
|
2015
|
-
var $parent = getParent($this)
|
2016
|
-
var isActive = $parent.hasClass('open')
|
2075
|
+
var $parent = getParent($this);
|
2076
|
+
var isActive = $parent.hasClass('open');
|
2017
2077
|
|
2018
|
-
clearMenus()
|
2078
|
+
clearMenus();
|
2019
2079
|
|
2020
2080
|
if (!isActive) {
|
2021
2081
|
if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
|
2022
2082
|
// if mobile we use a backdrop because click events don't delegate
|
2023
|
-
$('<div class="dropdown-backdrop"/>').insertAfter($(this)).on('click', clearMenus)
|
2083
|
+
$('<div class="dropdown-backdrop"/>').insertAfter($(this)).on('click', clearMenus);
|
2024
2084
|
}
|
2025
2085
|
|
2026
|
-
var relatedTarget = { relatedTarget: this }
|
2027
|
-
$parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget))
|
2086
|
+
var relatedTarget = { relatedTarget: this };
|
2087
|
+
$parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget));
|
2028
2088
|
|
2029
|
-
if (e.isDefaultPrevented()) return
|
2089
|
+
if (e.isDefaultPrevented()) return;
|
2030
2090
|
|
2031
2091
|
$this
|
2032
2092
|
.trigger('focus')
|
2033
|
-
.attr('aria-expanded', 'true')
|
2093
|
+
.attr('aria-expanded', 'true');
|
2034
2094
|
|
2035
2095
|
$parent
|
2036
2096
|
.toggleClass('open')
|
2037
|
-
.trigger('shown.bs.dropdown', relatedTarget)
|
2097
|
+
.trigger('shown.bs.dropdown', relatedTarget);
|
2038
2098
|
}
|
2039
2099
|
|
2040
|
-
return false
|
2041
|
-
}
|
2100
|
+
return false;
|
2101
|
+
};
|
2042
2102
|
|
2043
2103
|
Dropdown.prototype.keydown = function (e) {
|
2044
|
-
if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return
|
2104
|
+
if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return;
|
2045
2105
|
|
2046
|
-
var $this = $(this)
|
2106
|
+
var $this = $(this);
|
2047
2107
|
|
2048
|
-
e.preventDefault()
|
2049
|
-
e.stopPropagation()
|
2108
|
+
e.preventDefault();
|
2109
|
+
e.stopPropagation();
|
2050
2110
|
|
2051
|
-
if ($this.is('.disabled, :disabled')) return
|
2111
|
+
if ($this.is('.disabled, :disabled')) return;
|
2052
2112
|
|
2053
|
-
var $parent = getParent($this)
|
2054
|
-
var isActive = $parent.hasClass('open')
|
2113
|
+
var $parent = getParent($this);
|
2114
|
+
var isActive = $parent.hasClass('open');
|
2055
2115
|
|
2056
2116
|
if ((!isActive && e.which != 27) || (isActive && e.which == 27)) {
|
2057
|
-
if (e.which == 27) $parent.find(toggle).trigger('focus')
|
2058
|
-
return $this.trigger('click')
|
2117
|
+
if (e.which == 27) $parent.find(toggle).trigger('focus');
|
2118
|
+
return $this.trigger('click');
|
2059
2119
|
}
|
2060
2120
|
|
2061
|
-
var desc = ' li:not(.divider):visible a'
|
2062
|
-
var $items = $parent.find('[role="menu"]' + desc + ', [role="listbox"]' + desc)
|
2121
|
+
var desc = ' li:not(.divider):visible a';
|
2122
|
+
var $items = $parent.find('[role="menu"]' + desc + ', [role="listbox"]' + desc);
|
2063
2123
|
|
2064
|
-
if (!$items.length) return
|
2124
|
+
if (!$items.length) return;
|
2065
2125
|
|
2066
|
-
var index = $items.index(e.target)
|
2126
|
+
var index = $items.index(e.target);
|
2067
2127
|
|
2068
|
-
if (e.which == 38 && index > 0) index
|
2069
|
-
if (e.which == 40 && index < $items.length - 1) index
|
2070
|
-
if (!~index) index = 0
|
2128
|
+
if (e.which == 38 && index > 0) index--; // up
|
2129
|
+
if (e.which == 40 && index < $items.length - 1) index++; // down
|
2130
|
+
if (!~index) index = 0;
|
2071
2131
|
|
2072
|
-
$items.eq(index).trigger('focus')
|
2073
|
-
}
|
2132
|
+
$items.eq(index).trigger('focus');
|
2133
|
+
};
|
2074
2134
|
|
2075
2135
|
function clearMenus(e) {
|
2076
|
-
if (e && e.which === 3) return
|
2077
|
-
$(backdrop).remove()
|
2136
|
+
if (e && e.which === 3) return;
|
2137
|
+
$(backdrop).remove();
|
2078
2138
|
$(toggle).each(function () {
|
2079
|
-
var $this = $(this)
|
2080
|
-
var $parent = getParent($this)
|
2081
|
-
var relatedTarget = { relatedTarget: this }
|
2139
|
+
var $this = $(this);
|
2140
|
+
var $parent = getParent($this);
|
2141
|
+
var relatedTarget = { relatedTarget: this };
|
2082
2142
|
|
2083
|
-
if (!$parent.hasClass('open')) return
|
2143
|
+
if (!$parent.hasClass('open')) return;
|
2084
2144
|
|
2085
|
-
$parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
|
2145
|
+
$parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget));
|
2086
2146
|
|
2087
|
-
if (e.isDefaultPrevented()) return
|
2147
|
+
if (e.isDefaultPrevented()) return;
|
2088
2148
|
|
2089
|
-
$this.attr('aria-expanded', 'false')
|
2090
|
-
$parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget)
|
2091
|
-
})
|
2149
|
+
$this.attr('aria-expanded', 'false');
|
2150
|
+
$parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget);
|
2151
|
+
});
|
2092
2152
|
}
|
2093
2153
|
|
2094
2154
|
function getParent($this) {
|
2095
|
-
var selector = $this.attr('data-target')
|
2155
|
+
var selector = $this.attr('data-target');
|
2096
2156
|
|
2097
2157
|
if (!selector) {
|
2098
|
-
selector = $this.attr('href')
|
2099
|
-
selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
|
2158
|
+
selector = $this.attr('href');
|
2159
|
+
selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, ''); // strip for ie7
|
2100
2160
|
}
|
2101
2161
|
|
2102
|
-
var $parent = selector && $(selector)
|
2162
|
+
var $parent = selector && $(selector);
|
2103
2163
|
|
2104
|
-
return $parent && $parent.length ? $parent : $this.parent()
|
2164
|
+
return $parent && $parent.length ? $parent : $this.parent();
|
2105
2165
|
}
|
2106
2166
|
|
2107
2167
|
|
@@ -2110,27 +2170,27 @@
|
|
2110
2170
|
|
2111
2171
|
function Plugin(option) {
|
2112
2172
|
return this.each(function () {
|
2113
|
-
var $this = $(this)
|
2114
|
-
var data = $this.data('bs.dropdown')
|
2173
|
+
var $this = $(this);
|
2174
|
+
var data = $this.data('bs.dropdown');
|
2115
2175
|
|
2116
|
-
if (!data) $this.data('bs.dropdown', (data = new Dropdown(this)))
|
2117
|
-
if (typeof option == 'string') data[option].call($this)
|
2118
|
-
})
|
2176
|
+
if (!data) $this.data('bs.dropdown', (data = new Dropdown(this)));
|
2177
|
+
if (typeof option == 'string') data[option].call($this);
|
2178
|
+
});
|
2119
2179
|
}
|
2120
2180
|
|
2121
|
-
var old = $.fn.dropdown
|
2181
|
+
var old = $.fn.dropdown;
|
2122
2182
|
|
2123
|
-
$.fn.dropdown = Plugin
|
2124
|
-
$.fn.dropdown.Constructor = Dropdown
|
2183
|
+
$.fn.dropdown = Plugin;
|
2184
|
+
$.fn.dropdown.Constructor = Dropdown;
|
2125
2185
|
|
2126
2186
|
|
2127
2187
|
// DROPDOWN NO CONFLICT
|
2128
2188
|
// ====================
|
2129
2189
|
|
2130
2190
|
$.fn.dropdown.noConflict = function () {
|
2131
|
-
$.fn.dropdown = old
|
2132
|
-
return this
|
2133
|
-
}
|
2191
|
+
$.fn.dropdown = old;
|
2192
|
+
return this;
|
2193
|
+
};
|
2134
2194
|
|
2135
2195
|
|
2136
2196
|
// APPLY TO STANDARD DROPDOWN ELEMENTS
|
@@ -2138,11 +2198,11 @@
|
|
2138
2198
|
|
2139
2199
|
$(document)
|
2140
2200
|
.on('click.bs.dropdown.data-api', clearMenus)
|
2141
|
-
.on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
|
2201
|
+
.on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation(); })
|
2142
2202
|
.on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)
|
2143
2203
|
.on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown)
|
2144
2204
|
.on('keydown.bs.dropdown.data-api', '[role="menu"]', Dropdown.prototype.keydown)
|
2145
|
-
.on('keydown.bs.dropdown.data-api', '[role="listbox"]', Dropdown.prototype.keydown)
|
2205
|
+
.on('keydown.bs.dropdown.data-api', '[role="listbox"]', Dropdown.prototype.keydown);
|
2146
2206
|
|
2147
2207
|
}(jQuery);
|
2148
2208
|
}
|
@@ -2289,6 +2349,17 @@
|
|
2289
2349
|
|
2290
2350
|
this.mainPlot = function() {
|
2291
2351
|
var svg = mg_get_svg_child_of(args.target);
|
2352
|
+
|
2353
|
+
//remove any old legends if they exist
|
2354
|
+
svg.selectAll('.mg-line-legend').remove();
|
2355
|
+
|
2356
|
+
var legend_group;
|
2357
|
+
var this_legend;
|
2358
|
+
if (args.legend) {
|
2359
|
+
legend_group = svg.append('g')
|
2360
|
+
.attr('class', 'mg-line-legend');
|
2361
|
+
}
|
2362
|
+
|
2292
2363
|
var g;
|
2293
2364
|
var data_median = 0;
|
2294
2365
|
var updateTransitionDuration = (args.transition_on_update) ? 1000 : 0;
|
@@ -2301,16 +2372,12 @@
|
|
2301
2372
|
.x(args.scalefns.xf)
|
2302
2373
|
.y0(args.scales.Y.range()[0])
|
2303
2374
|
.y1(args.scalefns.yf)
|
2304
|
-
.interpolate(args.interpolate)
|
2375
|
+
.interpolate(args.interpolate)
|
2376
|
+
.tension(args.interpolate_tension);
|
2305
2377
|
|
2306
2378
|
//confidence band
|
2307
2379
|
var confidence_area;
|
2308
|
-
|
2309
|
-
//if it already exists, remove it
|
2310
|
-
var existing_band = svg.selectAll('.mg-confidence-band');
|
2311
|
-
if (!existing_band.empty()) {
|
2312
|
-
existing_band.remove();
|
2313
|
-
}
|
2380
|
+
var existing_band = svg.select('.mg-confidence-band');
|
2314
2381
|
|
2315
2382
|
if (args.show_confidence_band) {
|
2316
2383
|
confidence_area = d3.svg.area()
|
@@ -2323,25 +2390,28 @@
|
|
2323
2390
|
var u = args.show_confidence_band[1];
|
2324
2391
|
return args.scales.Y(d[u]);
|
2325
2392
|
})
|
2326
|
-
.interpolate(args.interpolate)
|
2393
|
+
.interpolate(args.interpolate)
|
2394
|
+
.tension(args.interpolate_tension);
|
2327
2395
|
}
|
2328
2396
|
|
2329
2397
|
//main line
|
2330
2398
|
var line = d3.svg.line()
|
2331
2399
|
.x(args.scalefns.xf)
|
2332
2400
|
.y(args.scalefns.yf)
|
2333
|
-
.interpolate(args.interpolate)
|
2334
|
-
|
2401
|
+
.interpolate(args.interpolate)
|
2402
|
+
.tension(args.interpolate_tension);
|
2335
2403
|
//for animating line on first load
|
2336
2404
|
var flat_line = d3.svg.line()
|
2337
2405
|
.x(args.scalefns.xf)
|
2338
2406
|
.y(function() { return args.scales.Y(data_median); })
|
2339
|
-
.interpolate(args.interpolate)
|
2407
|
+
.interpolate(args.interpolate)
|
2408
|
+
.tension(args.interpolate_tension);
|
2340
2409
|
|
2341
2410
|
|
2342
2411
|
//for building the optional legend
|
2343
2412
|
var legend = '';
|
2344
2413
|
var this_data;
|
2414
|
+
var confidenceBand;
|
2345
2415
|
|
2346
2416
|
for (var i = args.data.length - 1; i >= 0; i--) {
|
2347
2417
|
this_data = args.data[i];
|
@@ -2356,10 +2426,20 @@
|
|
2356
2426
|
|
2357
2427
|
//add confidence band
|
2358
2428
|
if (args.show_confidence_band) {
|
2359
|
-
|
2360
|
-
|
2361
|
-
|
2362
|
-
|
2429
|
+
if (!existing_band.empty()) {
|
2430
|
+
confidenceBand = existing_band
|
2431
|
+
.transition()
|
2432
|
+
.duration(function() {
|
2433
|
+
return (args.transition_on_update) ? 1000 : 0;
|
2434
|
+
});
|
2435
|
+
} else {
|
2436
|
+
confidenceBand = svg.append('path')
|
2437
|
+
.attr('class', 'mg-confidence-band');
|
2438
|
+
}
|
2439
|
+
|
2440
|
+
confidenceBand
|
2441
|
+
.attr('d', confidence_area(args.data[i]))
|
2442
|
+
.attr('clip-path', 'url(#mg-plot-window-'+ mg_strip_punctuation(args.target)+')');
|
2363
2443
|
}
|
2364
2444
|
|
2365
2445
|
//add the area
|
@@ -2376,7 +2456,7 @@
|
|
2376
2456
|
.transition()
|
2377
2457
|
.duration(updateTransitionDuration)
|
2378
2458
|
.attr('d', area(args.data[i]))
|
2379
|
-
.attr('clip-path', 'url(#mg-plot-window)');
|
2459
|
+
.attr('clip-path', 'url(#mg-plot-window-'+ mg_strip_punctuation(args.target)+')');
|
2380
2460
|
} else { //otherwise, add the area
|
2381
2461
|
svg.append('path')
|
2382
2462
|
.attr('class', 'mg-main-area ' + 'mg-area' + (line_id) + '-color')
|
@@ -2424,14 +2504,92 @@
|
|
2424
2504
|
}
|
2425
2505
|
}
|
2426
2506
|
|
2507
|
+
var the_line = svg.select('.mg-line' + (line_id) + '-color');
|
2508
|
+
if (args.missing_is_hidden && the_line.attr('d') !== null) {
|
2509
|
+
var bits = the_line.attr('d').split('L');
|
2510
|
+
var zero = args.scales.Y(0) + 42.1234;
|
2511
|
+
var dasharray = [];
|
2512
|
+
var singleton_point_length = 2;
|
2513
|
+
|
2514
|
+
var x_y,
|
2515
|
+
x_y_plus_1,
|
2516
|
+
x,
|
2517
|
+
y,
|
2518
|
+
x_plus_1,
|
2519
|
+
y_plus_1,
|
2520
|
+
segment_length,
|
2521
|
+
cumulative_segment_length = 0;
|
2522
|
+
|
2523
|
+
bits[0] = bits[0].replace('M', '');
|
2524
|
+
bits[bits.length - 1] = bits[bits.length - 1].replace('Z', '');
|
2525
|
+
|
2526
|
+
//if we have a min_x, turn the line off first
|
2527
|
+
if (args.min_x) {
|
2528
|
+
dasharray.push(0);
|
2529
|
+
}
|
2530
|
+
|
2531
|
+
//build the stroke-dasharray pattern
|
2532
|
+
for (var j = 0; j < bits.length - 1; j++) {
|
2533
|
+
x_y = bits[j].split(',');
|
2534
|
+
x_y_plus_1 = bits[j + 1].split(',');
|
2535
|
+
x = Number(x_y[0]);
|
2536
|
+
y = Number(x_y[1]);
|
2537
|
+
x_plus_1 = Number(x_y_plus_1[0]);
|
2538
|
+
y_plus_1 = Number(x_y_plus_1[1]);
|
2539
|
+
|
2540
|
+
segment_length = Math.sqrt(Math.pow(x - x_plus_1, 2) + Math.pow(y - y_plus_1, 2));
|
2541
|
+
|
2542
|
+
//do we need to either cover or clear the current stroke
|
2543
|
+
if (y_plus_1 == zero && y != zero) {
|
2544
|
+
dasharray.push(cumulative_segment_length || singleton_point_length);
|
2545
|
+
cumulative_segment_length = (cumulative_segment_length)
|
2546
|
+
? segment_length
|
2547
|
+
: segment_length - singleton_point_length;
|
2548
|
+
} else if (y_plus_1 != zero && y == zero) { //switching on line
|
2549
|
+
dasharray.push(cumulative_segment_length += segment_length);
|
2550
|
+
cumulative_segment_length = 0;
|
2551
|
+
} else {
|
2552
|
+
cumulative_segment_length += segment_length;
|
2553
|
+
}
|
2554
|
+
}
|
2555
|
+
|
2556
|
+
//fear not, end bit of line, ye too shall be covered
|
2557
|
+
if (dasharray.length > 0) {
|
2558
|
+
dasharray.push(the_line.node().getTotalLength() - dasharray[dasharray.length - 1]);
|
2559
|
+
|
2560
|
+
svg.select('.mg-line' + (line_id) + '-color')
|
2561
|
+
.attr('stroke-dasharray', dasharray.join());
|
2562
|
+
}
|
2563
|
+
}
|
2564
|
+
|
2427
2565
|
//build legend
|
2428
2566
|
if (args.legend) {
|
2429
|
-
|
2430
|
-
|
2567
|
+
if (is_array(args.legend)) {
|
2568
|
+
this_legend = args.legend[i];
|
2569
|
+
} else if (is_function(args.legend)) {
|
2570
|
+
this_legend = args.legend(this_data);
|
2571
|
+
}
|
2572
|
+
|
2573
|
+
if (args.legend_target) {
|
2574
|
+
legend = "<span class='mg-line" + line_id + "-legend-color'>— "
|
2575
|
+
+ this_legend + " </span>" + legend;
|
2576
|
+
} else {
|
2577
|
+
var last_point = this_data[this_data.length-1];
|
2578
|
+
|
2579
|
+
legend_group.append('svg:text')
|
2580
|
+
.classed('mg-line' + (line_id) + '-legend-color', true)
|
2581
|
+
.attr('x', args.scalefns.xf(last_point))
|
2582
|
+
.attr('dx', args.buffer)
|
2583
|
+
.attr('y', args.scalefns.yf(last_point))
|
2584
|
+
.attr('dy', '.35em')
|
2585
|
+
.text(this_legend);
|
2586
|
+
|
2587
|
+
preventVerticalOverlap(legend_group.selectAll('.mg-line-legend text')[0], args);
|
2588
|
+
}
|
2431
2589
|
}
|
2432
2590
|
}
|
2433
2591
|
|
2434
|
-
if (args.
|
2592
|
+
if (args.legend_target) {
|
2435
2593
|
d3.select(args.legend_target).html(legend);
|
2436
2594
|
}
|
2437
2595
|
|
@@ -2668,8 +2826,27 @@
|
|
2668
2826
|
|
2669
2827
|
//if the dataset is of length 1, trigger the rollover for our solitary rollover rect
|
2670
2828
|
if (args.data.length == 1 && args.data[0].length == 1) {
|
2671
|
-
|
2829
|
+
svg.select('.mg-rollover-rect rect')
|
2672
2830
|
.on('mouseover')(args.data[0][0], 0);
|
2831
|
+
} else if (args.data.length > 1) {
|
2832
|
+
//otherwise, trigger it for an appropriate line in a multi-line chart
|
2833
|
+
for (var i = 0; i < args.data.length; i++) {
|
2834
|
+
var j = i + 1;
|
2835
|
+
|
2836
|
+
if (args.custom_line_color_map.length > 0
|
2837
|
+
&& args.custom_line_color_map[i] !== undefined
|
2838
|
+
) {
|
2839
|
+
j = args.custom_line_color_map[i];
|
2840
|
+
}
|
2841
|
+
|
2842
|
+
if (args.data[i].length == 1) {
|
2843
|
+
svg.selectAll('.mg-voronoi .mg-line' + j + '-color')
|
2844
|
+
.on('mouseover')(args.data[i][0], 0);
|
2845
|
+
|
2846
|
+
svg.selectAll('.mg-voronoi .mg-line' + j + '-color')
|
2847
|
+
.on('mouseout')(args.data[i][0], 0);
|
2848
|
+
}
|
2849
|
+
}
|
2673
2850
|
}
|
2674
2851
|
|
2675
2852
|
return this;
|
@@ -2693,20 +2870,17 @@
|
|
2693
2870
|
}
|
2694
2871
|
|
2695
2872
|
return function(d, i) {
|
2696
|
-
|
2697
2873
|
if (args.aggregate_rollover && args.data.length > 1) {
|
2698
|
-
|
2699
2874
|
// hide the circles in case a non-contiguous series is present
|
2700
2875
|
svg.selectAll('circle.mg-line-rollover-circle')
|
2701
2876
|
.style('opacity', 0);
|
2702
2877
|
|
2703
2878
|
d.values.forEach(function(datum) {
|
2704
|
-
|
2705
2879
|
if (datum[args.x_accessor] >= args.processed.min_x &&
|
2706
2880
|
datum[args.x_accessor] <= args.processed.max_x &&
|
2707
2881
|
datum[args.y_accessor] >= args.processed.min_y &&
|
2708
2882
|
datum[args.y_accessor] <= args.processed.max_y
|
2709
|
-
){
|
2883
|
+
) {
|
2710
2884
|
var circle = svg.select('circle.mg-line' + datum.line_id + '-color')
|
2711
2885
|
.attr({
|
2712
2886
|
'cx': function() {
|
@@ -2720,15 +2894,21 @@
|
|
2720
2894
|
.style('opacity', 1);
|
2721
2895
|
}
|
2722
2896
|
});
|
2723
|
-
} else
|
2897
|
+
} else if (args.missing_is_hidden
|
2898
|
+
&& d[args.y_accessor] == 0
|
2899
|
+
&& d['missing']
|
2900
|
+
) {
|
2724
2901
|
|
2902
|
+
//disable rollovers for hidden parts of the line
|
2903
|
+
return;
|
2904
|
+
} else {
|
2725
2905
|
//show circle on mouse-overed rect
|
2726
2906
|
if (d[args.x_accessor] >= args.processed.min_x &&
|
2727
2907
|
d[args.x_accessor] <= args.processed.max_x &&
|
2728
2908
|
d[args.y_accessor] >= args.processed.min_y &&
|
2729
2909
|
d[args.y_accessor] <= args.processed.max_y
|
2730
|
-
){
|
2731
|
-
svg.selectAll('circle.mg-line-rollover-circle')
|
2910
|
+
) {
|
2911
|
+
svg.selectAll('circle.mg-line-rollover-circle.mg-area' + d.line_id + '-color')
|
2732
2912
|
.attr('class', "")
|
2733
2913
|
.attr('class', 'mg-area' + d.line_id + '-color')
|
2734
2914
|
.classed('mg-line-rollover-circle', true)
|
@@ -2885,16 +3065,33 @@
|
|
2885
3065
|
});
|
2886
3066
|
}
|
2887
3067
|
|
2888
|
-
//remove active
|
2889
|
-
|
2890
|
-
.
|
2891
|
-
|
3068
|
+
//remove all active data points when aggregate_rollover is enabled
|
3069
|
+
if(args.aggregate_rollover) {
|
3070
|
+
svg.selectAll('circle.mg-line-rollover-circle')
|
3071
|
+
.style('opacity', function() {
|
3072
|
+
return 0;
|
3073
|
+
});
|
3074
|
+
//remove active data point text on mouse out, except if we have a single point
|
3075
|
+
} else {
|
3076
|
+
svg.selectAll('circle.mg-line-rollover-circle.mg-area' + (d.line_id) + '-color')
|
3077
|
+
.style('opacity', function() {
|
3078
|
+
var id = d.line_id - 1;
|
3079
|
+
|
3080
|
+
if (args.custom_line_color_map.length > 0
|
3081
|
+
&& args.custom_line_color_map.indexOf(d.line_id) !== undefined
|
3082
|
+
) {
|
3083
|
+
id = args.custom_line_color_map.indexOf(d.line_id);
|
3084
|
+
}
|
3085
|
+
|
3086
|
+
if (args.data[id].length == 1) {
|
3087
|
+
//if (args.data.length === 1 && args.data[0].length === 1) {
|
2892
3088
|
return 1;
|
2893
3089
|
}
|
2894
3090
|
else {
|
2895
3091
|
return 0;
|
2896
3092
|
}
|
2897
3093
|
});
|
3094
|
+
}
|
2898
3095
|
|
2899
3096
|
svg.select('.mg-active-datapoint')
|
2900
3097
|
.text('');
|
@@ -3270,8 +3467,8 @@
|
|
3270
3467
|
}
|
3271
3468
|
|
3272
3469
|
//trigger mouseover on all points for this class name in .linked charts
|
3273
|
-
if (args.linked && !globals.link) {
|
3274
|
-
globals.link = true;
|
3470
|
+
if (args.linked && !MG.globals.link) {
|
3471
|
+
MG.globals.link = true;
|
3275
3472
|
|
3276
3473
|
//trigger mouseover on matching point in .linked charts
|
3277
3474
|
d3.selectAll('.mg-voronoi .path-' + i)
|
@@ -3310,8 +3507,8 @@
|
|
3310
3507
|
var svg = mg_get_svg_child_of(args.target);
|
3311
3508
|
|
3312
3509
|
return function(d,i) {
|
3313
|
-
if (args.linked && globals.link) {
|
3314
|
-
globals.link = false;
|
3510
|
+
if (args.linked && MG.globals.link) {
|
3511
|
+
MG.globals.link = false;
|
3315
3512
|
|
3316
3513
|
d3.selectAll('.mg-voronoi .path-' + i)
|
3317
3514
|
.each(function() {
|
@@ -3394,7 +3591,7 @@
|
|
3394
3591
|
this.mainPlot = function() {
|
3395
3592
|
var svg = mg_get_svg_child_of(args.target);
|
3396
3593
|
var data = args.data[0];
|
3397
|
-
var barplot = svg.select('.mg-barplot');
|
3594
|
+
var barplot = svg.select('g.mg-barplot');
|
3398
3595
|
var fresh_render = barplot.empty();
|
3399
3596
|
|
3400
3597
|
var bars;
|
@@ -3407,69 +3604,84 @@
|
|
3407
3604
|
var transition_duration = args.transition_duration || 1000;
|
3408
3605
|
|
3409
3606
|
// draw the plot on first render
|
3410
|
-
if (
|
3607
|
+
if (barplot.empty()) {
|
3411
3608
|
barplot = svg.append('g')
|
3412
3609
|
.classed('mg-barplot', true);
|
3610
|
+
}
|
3413
3611
|
|
3414
|
-
|
3415
|
-
|
3416
|
-
.enter()
|
3417
|
-
.append('rect')
|
3418
|
-
.classed('mg-bar', true);
|
3612
|
+
bars = bars = barplot.selectAll('.mg-bar')
|
3613
|
+
.data(data);
|
3419
3614
|
|
3420
|
-
|
3421
|
-
predictor_bars = barplot.selectAll('.mg-bar-prediction')
|
3422
|
-
.data(data)
|
3423
|
-
.enter()
|
3424
|
-
.append('rect')
|
3425
|
-
.classed('mg-bar-prediction', true);
|
3426
|
-
}
|
3615
|
+
bars.exit().remove();
|
3427
3616
|
|
3428
|
-
|
3429
|
-
|
3430
|
-
|
3431
|
-
|
3432
|
-
|
3433
|
-
|
3434
|
-
|
3617
|
+
bars.enter().append('rect')
|
3618
|
+
.classed('mg-bar', true);
|
3619
|
+
|
3620
|
+
if (args.predictor_accessor) {
|
3621
|
+
predictor_bars = barplot.selectAll('.mg-bar-prediction')
|
3622
|
+
.data(data);
|
3623
|
+
|
3624
|
+
predictor_bars.exit().remove();
|
3625
|
+
|
3626
|
+
predictor_bars.enter().append('rect')
|
3627
|
+
.classed('mg-bar-prediction', true);
|
3435
3628
|
}
|
3436
|
-
// setup vars with the existing elements
|
3437
|
-
// TODO: deal with changing data sets - i.e. more/less, different labels etc.
|
3438
|
-
else {
|
3439
|
-
// move the barplot after the axes so it doesn't overlap
|
3440
|
-
//$(svg.node()).find('.mg-y-axis').after($(barplot.node()).detach());
|
3441
|
-
svg.select('.mg-y-axis').node().parentNode.appendChild(barplot.node());
|
3442
|
-
|
3443
|
-
console.log('waylee');
|
3444
|
-
bars = barplot.selectAll('rect.mg-bar');
|
3445
3629
|
|
3446
|
-
|
3447
|
-
|
3630
|
+
if (args.baseline_accessor) {
|
3631
|
+
baseline_marks = barplot.selectAll('.mg-bar-baseline')
|
3632
|
+
.data(data);
|
3633
|
+
|
3634
|
+
baseline_marks.exit().remove();
|
3635
|
+
|
3636
|
+
baseline_marks.enter().append('line')
|
3637
|
+
.classed('mg-bar-baseline', true);
|
3638
|
+
}
|
3639
|
+
|
3640
|
+
var appropriate_size;
|
3641
|
+
|
3642
|
+
|
3643
|
+
// setup transitions
|
3644
|
+
if (should_transition) {
|
3645
|
+
bars = bars.transition()
|
3646
|
+
.duration(transition_duration);
|
3647
|
+
|
3648
|
+
if (predictor_bars) {
|
3649
|
+
predictor_bars = predictor_bars.transition()
|
3650
|
+
.duration(transition_duration);
|
3448
3651
|
}
|
3449
3652
|
|
3450
|
-
if (
|
3451
|
-
baseline_marks =
|
3653
|
+
if (baseline_marks) {
|
3654
|
+
baseline_marks = baseline_marks.transition()
|
3655
|
+
.duration(transition_duration);
|
3452
3656
|
}
|
3453
3657
|
}
|
3454
3658
|
|
3455
|
-
var appropriate_size;
|
3456
3659
|
|
3457
3660
|
if (this.is_vertical) {
|
3458
3661
|
appropriate_size = args.scales.X.rangeBand()/1.5;
|
3459
3662
|
|
3460
3663
|
if (perform_load_animation) {
|
3461
|
-
bars.attr(
|
3462
|
-
|
3463
|
-
|
3664
|
+
bars.attr({
|
3665
|
+
height: 0,
|
3666
|
+
y: args.scales.Y(0)
|
3667
|
+
});
|
3464
3668
|
|
3465
|
-
|
3466
|
-
|
3467
|
-
|
3669
|
+
if (predictor_bars) {
|
3670
|
+
predictor_bars.attr({
|
3671
|
+
height: 0,
|
3672
|
+
y: args.scales.Y(0)
|
3673
|
+
});
|
3674
|
+
}
|
3675
|
+
|
3676
|
+
if (baseline_marks) {
|
3677
|
+
baseline_marks.attr({
|
3678
|
+
y1: args.scales.Y(0),
|
3679
|
+
y2: args.scales.Y(0)
|
3680
|
+
});
|
3681
|
+
}
|
3468
3682
|
}
|
3469
3683
|
|
3470
|
-
bars.attr('y',
|
3471
|
-
return args.scales.Y(0) - (args.scales.Y(0) - args.scalefns.yf(d));
|
3472
|
-
})
|
3684
|
+
bars.attr('y', args.scalefns.yf)
|
3473
3685
|
.attr('x', function(d) {
|
3474
3686
|
return args.scalefns.xf(d) + appropriate_size/2;
|
3475
3687
|
})
|
@@ -3478,21 +3690,12 @@
|
|
3478
3690
|
return 0 - (args.scalefns.yf(d) - args.scales.Y(0));
|
3479
3691
|
});
|
3480
3692
|
|
3693
|
+
|
3481
3694
|
if (args.predictor_accessor) {
|
3482
3695
|
pp = args.predictor_proportion;
|
3483
3696
|
pp0 = pp-1;
|
3484
3697
|
|
3485
|
-
|
3486
|
-
predictor_bars.attr('height', 0)
|
3487
|
-
.attr('y', args.scales.Y(0));
|
3488
|
-
}
|
3489
|
-
|
3490
|
-
if (should_transition) {
|
3491
|
-
predictor_bars = predictor_bars.transition()
|
3492
|
-
.duration(transition_duration);
|
3493
|
-
}
|
3494
|
-
|
3495
|
-
// thick line through bar;
|
3698
|
+
// thick line through bar;
|
3496
3699
|
predictor_bars
|
3497
3700
|
.attr('y', function(d) {
|
3498
3701
|
return args.scales.Y(0) - (args.scales.Y(0) - args.scales.Y(d[args.predictor_accessor]));
|
@@ -3509,15 +3712,6 @@
|
|
3509
3712
|
if (args.baseline_accessor) {
|
3510
3713
|
pp = args.predictor_proportion;
|
3511
3714
|
|
3512
|
-
if (perform_load_animation) {
|
3513
|
-
baseline_marks.attr({y1: args.scales.Y(0), y2: args.scales.Y(0)});
|
3514
|
-
}
|
3515
|
-
|
3516
|
-
if (should_transition) {
|
3517
|
-
baseline_marks = baseline_marks.transition()
|
3518
|
-
.duration(transition_duration);
|
3519
|
-
}
|
3520
|
-
|
3521
3715
|
baseline_marks
|
3522
3716
|
.attr('x1', function(d) {
|
3523
3717
|
return args.scalefns.xf(d)+appropriate_size/2-appropriate_size/pp + appropriate_size/2;
|
@@ -3533,11 +3727,17 @@
|
|
3533
3727
|
|
3534
3728
|
if (perform_load_animation) {
|
3535
3729
|
bars.attr('width', 0);
|
3536
|
-
}
|
3537
3730
|
|
3538
|
-
|
3539
|
-
|
3540
|
-
|
3731
|
+
if (predictor_bars) {
|
3732
|
+
predictor_bars.attr('width', 0);
|
3733
|
+
}
|
3734
|
+
|
3735
|
+
if (baseline_marks) {
|
3736
|
+
baseline_marks.attr({
|
3737
|
+
x1: args.scales.X(0),
|
3738
|
+
x2: args.scales.X(0)
|
3739
|
+
});
|
3740
|
+
}
|
3541
3741
|
}
|
3542
3742
|
|
3543
3743
|
bars.attr('x', args.scales.X(0))
|
@@ -3554,15 +3754,6 @@
|
|
3554
3754
|
pp = args.predictor_proportion;
|
3555
3755
|
pp0 = pp-1;
|
3556
3756
|
|
3557
|
-
if (perform_load_animation) {
|
3558
|
-
predictor_bars.attr('width', 0);
|
3559
|
-
}
|
3560
|
-
|
3561
|
-
if (should_transition) {
|
3562
|
-
predictor_bars = predictor_bars.transition()
|
3563
|
-
.duration(transition_duration);
|
3564
|
-
}
|
3565
|
-
|
3566
3757
|
// thick line through bar;
|
3567
3758
|
predictor_bars
|
3568
3759
|
.attr('x', args.scales.X(0))
|
@@ -3578,16 +3769,6 @@
|
|
3578
3769
|
if (args.baseline_accessor) {
|
3579
3770
|
pp = args.predictor_proportion;
|
3580
3771
|
|
3581
|
-
if (perform_load_animation) {
|
3582
|
-
baseline_marks
|
3583
|
-
.attr({x1: args.scales.X(0), x2: args.scales.X(0)});
|
3584
|
-
}
|
3585
|
-
|
3586
|
-
if (should_transition) {
|
3587
|
-
baseline_marks = baseline_marks.transition()
|
3588
|
-
.duration(transition_duration);
|
3589
|
-
}
|
3590
|
-
|
3591
3772
|
baseline_marks
|
3592
3773
|
.attr('x1', function(d) { return args.scales.X(d[args.baseline_accessor]); })
|
3593
3774
|
.attr('x2', function(d) { return args.scales.X(d[args.baseline_accessor]); })
|
@@ -3911,7 +4092,7 @@
|
|
3911
4092
|
|
3912
4093
|
if (this_format === 'percentage') formatter = d3.format('%p');
|
3913
4094
|
if (this_format === 'count') formatter = d3.format("0,000");
|
3914
|
-
if (this_format === 'temperature') formatter = function(t) { return t +'
|
4095
|
+
if (this_format === 'temperature') formatter = function(t) { return t +'°'; };
|
3915
4096
|
|
3916
4097
|
td_text = formatter(td_text);
|
3917
4098
|
}
|
@@ -3957,25 +4138,42 @@
|
|
3957
4138
|
this.args = args;
|
3958
4139
|
|
3959
4140
|
this.init = function(args) {
|
3960
|
-
|
4141
|
+
var svg_width,
|
4142
|
+
svg_height;
|
4143
|
+
|
4144
|
+
svg_width = args.width;
|
4145
|
+
svg_height = args.height;
|
4146
|
+
|
4147
|
+
if (args.full_width) {
|
4148
|
+
// get parent element
|
4149
|
+
svg_width = get_width(args.target);
|
4150
|
+
}
|
4151
|
+
|
4152
|
+
if (args.full_height) {
|
4153
|
+
svg_height = get_height(args.target);
|
4154
|
+
}
|
3961
4155
|
|
4156
|
+
chart_title(args);
|
3962
4157
|
// create svg if one doesn't exist
|
3963
4158
|
d3.select(args.target).selectAll('svg').data([args])
|
3964
4159
|
.enter().append('svg')
|
3965
|
-
.attr('width',
|
3966
|
-
.attr('height',
|
4160
|
+
.attr('width', svg_width)
|
4161
|
+
.attr('height', svg_height);
|
3967
4162
|
|
3968
4163
|
var svg = mg_get_svg_child_of(args.target);
|
3969
|
-
|
4164
|
+
|
3970
4165
|
// has the width or height changed?
|
3971
|
-
if (
|
3972
|
-
svg.attr('width',
|
4166
|
+
if (svg_width !== Number(svg.attr('width'))) {
|
4167
|
+
svg.attr('width', svg_width);
|
3973
4168
|
}
|
3974
4169
|
|
3975
|
-
if (
|
3976
|
-
svg.attr('height',
|
4170
|
+
if (svg_height !== Number(svg.attr('height'))) {
|
4171
|
+
svg.attr('height', svg_height);
|
3977
4172
|
}
|
3978
4173
|
|
4174
|
+
// @todo need to reconsider how we handle automatic scaling
|
4175
|
+
svg.attr('viewBox', '0 0 ' + svg_width + ' ' + svg_height);
|
4176
|
+
|
3979
4177
|
// delete child elements
|
3980
4178
|
d3.select(args.target).selectAll('svg *').remove();
|
3981
4179
|
|
@@ -3996,11 +4194,11 @@
|
|
3996
4194
|
|
3997
4195
|
args.scales.X = d3.scale.linear()
|
3998
4196
|
.domain([0, data.length])
|
3999
|
-
.range([args.left + args.buffer,
|
4197
|
+
.range([args.left + args.buffer, svg_width - args.right - args.buffer]);
|
4000
4198
|
|
4001
4199
|
args.scales.Y = d3.scale.linear()
|
4002
4200
|
.domain([-2, 2])
|
4003
|
-
.range([
|
4201
|
+
.range([svg_height - args.bottom - args.buffer*2, args.top]);
|
4004
4202
|
|
4005
4203
|
args.scalefns.xf = function(di) { return args.scales.X(di.x); };
|
4006
4204
|
args.scalefns.yf = function(di) { return args.scales.Y(di.y); };
|
@@ -4023,8 +4221,8 @@
|
|
4023
4221
|
.classed('mg-missing-background', true)
|
4024
4222
|
.attr('x', args.buffer)
|
4025
4223
|
.attr('y', args.buffer)
|
4026
|
-
.attr('width',
|
4027
|
-
.attr('height',
|
4224
|
+
.attr('width', svg_width-args.buffer*2)
|
4225
|
+
.attr('height', svg_height-args.buffer*2)
|
4028
4226
|
.attr('rx',15)
|
4029
4227
|
.attr('ry', 15);
|
4030
4228
|
|
@@ -4041,8 +4239,8 @@
|
|
4041
4239
|
svg.selectAll('.mg-missing-text').data([args.missing_text])
|
4042
4240
|
.enter().append('text')
|
4043
4241
|
.attr('class', 'mg-missing-text')
|
4044
|
-
.attr('x',
|
4045
|
-
.attr('y',
|
4242
|
+
.attr('x', svg_width / 2)
|
4243
|
+
.attr('y', svg_height / 2)
|
4046
4244
|
.attr('dy', '.50em')
|
4047
4245
|
.attr('text-anchor', 'middle')
|
4048
4246
|
.text(args.missing_text);
|
@@ -4058,18 +4256,32 @@
|
|
4058
4256
|
'use strict';
|
4059
4257
|
|
4060
4258
|
// We need to account for a few data format cases:
|
4061
|
-
// 1
|
4062
|
-
// 2
|
4063
|
-
// 3
|
4064
|
-
// 4
|
4065
|
-
|
4066
|
-
|
4067
|
-
|
4068
|
-
|
4069
|
-
|
4070
|
-
|
4259
|
+
// #1 [{key:__, value:__}, ...] // unnested obj-arrays
|
4260
|
+
// #2 [[{key:__, value:__}, ...], [{key:__, value:__}, ...]] // nested obj-arrays
|
4261
|
+
// #3 [[4323, 2343],..] // unnested 2d array
|
4262
|
+
// #4 [[[4323, 2343],..] , [[4323, 2343],..]] // nested 2d array
|
4263
|
+
|
4264
|
+
var _is_nested_array = is_array_of_arrays(args.data);
|
4265
|
+
|
4266
|
+
args.array_of_objects = false;
|
4267
|
+
args.array_of_arrays = false;
|
4268
|
+
args.nested_array_of_arrays = false;
|
4269
|
+
args.nested_array_of_objects = false;
|
4270
|
+
|
4271
|
+
if (_is_nested_array) {
|
4272
|
+
args.nested_array_of_objects = args.data.map(function(d){
|
4273
|
+
return is_array_of_objects_or_empty(d);
|
4274
|
+
}); // Case #2
|
4275
|
+
args.nested_array_of_arrays = args.data.map(function(d){
|
4276
|
+
return is_array_of_arrays(d);
|
4277
|
+
}) // Case #4
|
4278
|
+
} else {
|
4279
|
+
args.array_of_objects = is_array_of_objects(args.data); // Case #1
|
4280
|
+
args.array_of_arrays = is_array_of_arrays(args.data); // Case #3
|
4281
|
+
}
|
4071
4282
|
|
4072
|
-
|
4283
|
+
if (args.chart_type === 'line') {
|
4284
|
+
if (args.array_of_objects || args.array_of_arrays) {
|
4073
4285
|
args.data = [args.data];
|
4074
4286
|
}
|
4075
4287
|
} else {
|
@@ -4112,12 +4324,21 @@
|
|
4112
4324
|
function process_line(args) {
|
4113
4325
|
'use strict';
|
4114
4326
|
//do we have a time-series?
|
4115
|
-
var is_time_series = args.data
|
4116
|
-
|
4117
|
-
|
4327
|
+
var is_time_series = d3.sum(args.data.map(function(series) {
|
4328
|
+
return series.length > 0 && series[0][args.x_accessor] instanceof Date;
|
4329
|
+
})) > 0;
|
4330
|
+
|
4331
|
+
// var is_time_series = args.data[0][0][args.x_accessor] instanceof Date
|
4332
|
+
// ? true
|
4333
|
+
// : false;
|
4334
|
+
|
4335
|
+
//force linear interpolation when missing_is_hidden is enabled
|
4336
|
+
if (args.missing_is_hidden) {
|
4337
|
+
args.interpolate = 'linear';
|
4338
|
+
}
|
4118
4339
|
|
4119
4340
|
//are we replacing missing y values with zeros?
|
4120
|
-
if (args.missing_is_zero
|
4341
|
+
if ((args.missing_is_zero || args.missing_is_hidden)
|
4121
4342
|
&& args.chart_type === 'line'
|
4122
4343
|
&& is_time_series
|
4123
4344
|
) {
|
@@ -4162,6 +4383,7 @@
|
|
4162
4383
|
if (!existing_o) {
|
4163
4384
|
o[args.x_accessor] = new Date(d);
|
4164
4385
|
o[args.y_accessor] = 0;
|
4386
|
+
o['missing'] = true; //we want to distinguish between zero-value and missing observations
|
4165
4387
|
processed_data.push(o);
|
4166
4388
|
}
|
4167
4389
|
//otherwise, use the existing object for that date
|
@@ -4195,6 +4417,7 @@
|
|
4195
4417
|
|
4196
4418
|
// histogram data is always single dimension
|
4197
4419
|
var our_data = args.data[0];
|
4420
|
+
|
4198
4421
|
var extracted_data;
|
4199
4422
|
if (args.binned === false) {
|
4200
4423
|
// use d3's built-in layout.histogram functionality to compute what you need.
|
@@ -4263,7 +4486,6 @@
|
|
4263
4486
|
var data_accessor = args.bar_orientation === 'vertical' ? args.y_accessor : args.x_accessor;
|
4264
4487
|
|
4265
4488
|
args.categorical_variables = [];
|
4266
|
-
|
4267
4489
|
if (args.binned === false) {
|
4268
4490
|
if (typeof(our_data[0]) === 'object') {
|
4269
4491
|
// we are dealing with an array of objects. Extract the data value of interest.
|
@@ -4651,13 +4873,151 @@
|
|
4651
4873
|
return data;
|
4652
4874
|
};
|
4653
4875
|
|
4876
|
+
|
4877
|
+
function is_array(thing){
|
4878
|
+
return Object.prototype.toString.call(thing) === '[object Array]';
|
4879
|
+
}
|
4880
|
+
|
4881
|
+
function is_function(thing){
|
4882
|
+
return Object.prototype.toString.call(thing) === '[object Function]';
|
4883
|
+
}
|
4884
|
+
|
4885
|
+
function is_empty_array(thing){
|
4886
|
+
return is_array(thing) && thing.length==0;
|
4887
|
+
}
|
4888
|
+
|
4889
|
+
function is_object(thing){
|
4890
|
+
return Object.prototype.toString.call(thing) === '[object Object]';
|
4891
|
+
}
|
4892
|
+
|
4893
|
+
function is_array_of_arrays(data){
|
4894
|
+
var all_elements = data.map(function(d){return is_array(d)===true && d.length>0});
|
4895
|
+
return d3.sum(all_elements) === data.length;
|
4896
|
+
}
|
4897
|
+
|
4898
|
+
function is_array_of_objects(data){
|
4899
|
+
// is every element of data an object?
|
4900
|
+
var all_elements = data.map(function(d){return is_object(d)===true});
|
4901
|
+
return d3.sum(all_elements) === data.length;
|
4902
|
+
}
|
4903
|
+
|
4904
|
+
function is_array_of_objects_or_empty(data){
|
4905
|
+
return is_empty_array(data) || is_array_of_objects(data);
|
4906
|
+
}
|
4907
|
+
|
4908
|
+
|
4909
|
+
function preventHorizontalOverlap(labels, args) {
|
4910
|
+
if (!labels || labels.length == 1) {
|
4911
|
+
return;
|
4912
|
+
}
|
4913
|
+
|
4914
|
+
//see if each of our labels overlaps any of the other labels
|
4915
|
+
for (var i = 0; i < labels.length; i++) {
|
4916
|
+
//if so, nudge it up a bit, if the label it intersects hasn't already been nudged
|
4917
|
+
if (isHorizontallyOverlapping(labels[i], labels)) {
|
4918
|
+
var node = d3.select(labels[i]);
|
4919
|
+
var newY = +node.attr('y');
|
4920
|
+
if (newY + 8 == args.top) {
|
4921
|
+
newY = args.top - 16;
|
4922
|
+
}
|
4923
|
+
node.attr('y', newY);
|
4924
|
+
}
|
4925
|
+
}
|
4926
|
+
}
|
4927
|
+
|
4928
|
+
function preventVerticalOverlap(labels, args) {
|
4929
|
+
if (!labels || labels.length == 1) {
|
4930
|
+
return;
|
4931
|
+
}
|
4932
|
+
|
4933
|
+
labels.sort(function(b,a){
|
4934
|
+
return d3.select(a).attr('y') - d3.select(b).attr('y');
|
4935
|
+
});
|
4936
|
+
|
4937
|
+
labels.reverse();
|
4938
|
+
|
4939
|
+
var overlap_amount, label_i, label_j;
|
4940
|
+
|
4941
|
+
//see if each of our labels overlaps any of the other labels
|
4942
|
+
for (var i = 0; i < labels.length; i++) {
|
4943
|
+
//if so, nudge it up a bit, if the label it intersects hasn't already been nudged
|
4944
|
+
label_i = d3.select(labels[i]).text();
|
4945
|
+
|
4946
|
+
for (var j = 0; j < labels.length; j ++) {
|
4947
|
+
label_j = d3.select(labels[j]).text();
|
4948
|
+
overlap_amount = isVerticallyOverlapping(labels[i], labels[j]);
|
4949
|
+
|
4950
|
+
if (overlap_amount !== false && label_i !== label_j) {
|
4951
|
+
var node = d3.select(labels[i]);
|
4952
|
+
var newY = +node.attr('y');
|
4953
|
+
newY = newY + overlap_amount;
|
4954
|
+
node.attr('y', newY);
|
4955
|
+
}
|
4956
|
+
}
|
4957
|
+
}
|
4958
|
+
}
|
4959
|
+
|
4960
|
+
function isVerticallyOverlapping(element, sibling) {
|
4961
|
+
var element_bbox = element.getBoundingClientRect();
|
4962
|
+
var sibling_bbox = sibling.getBoundingClientRect();
|
4963
|
+
|
4964
|
+
if (element_bbox.top <= sibling_bbox.bottom && element_bbox.top >= sibling_bbox.top) {
|
4965
|
+
return sibling_bbox.bottom - element_bbox.top;
|
4966
|
+
}
|
4967
|
+
|
4968
|
+
return false;
|
4969
|
+
}
|
4970
|
+
|
4971
|
+
function isHorizontallyOverlapping(element, labels) {
|
4972
|
+
var element_bbox = element.getBoundingClientRect();
|
4973
|
+
|
4974
|
+
for (var i = 0; i < labels.length; i++) {
|
4975
|
+
if (labels[i] == element) {
|
4976
|
+
continue;
|
4977
|
+
}
|
4978
|
+
|
4979
|
+
//check to see if this label overlaps with any of the other labels
|
4980
|
+
var sibling_bbox = labels[i].getBoundingClientRect();
|
4981
|
+
if (element_bbox.top === sibling_bbox.top &&
|
4982
|
+
!(sibling_bbox.left > element_bbox.right || sibling_bbox.right < element_bbox.left)
|
4983
|
+
) {
|
4984
|
+
return true;
|
4985
|
+
}
|
4986
|
+
}
|
4987
|
+
|
4988
|
+
return false;
|
4989
|
+
}
|
4990
|
+
|
4654
4991
|
function mg_get_svg_child_of(selector_or_node) {
|
4655
4992
|
return d3.select(selector_or_node).select('svg');
|
4656
4993
|
}
|
4657
4994
|
|
4995
|
+
function mg_flatten_array(arr) {
|
4996
|
+
var flat_data = [];
|
4997
|
+
return flat_data.concat.apply(flat_data, arr);
|
4998
|
+
}
|
4999
|
+
|
4658
5000
|
function mg_strip_punctuation(s) {
|
4659
|
-
var
|
5001
|
+
var processed_s;
|
5002
|
+
|
5003
|
+
if (typeof(s) == 'string') {
|
5004
|
+
processed_s = s;
|
5005
|
+
} else {
|
5006
|
+
// args.target is
|
5007
|
+
if (s.id != '') {
|
5008
|
+
processed_s = s.id;
|
5009
|
+
} else if (args.target.className != '') {
|
5010
|
+
processed_s = s.className;
|
5011
|
+
} else if (args.target.nodeName !='') {
|
5012
|
+
processed_s = s.nodeName;
|
5013
|
+
} else {
|
5014
|
+
console.warn('The specified target element ' + s + ' has no unique attributes.');
|
5015
|
+
}
|
5016
|
+
}
|
5017
|
+
|
5018
|
+
var punctuationless = processed_s.replace(/[^a-zA-Z0-9 _]+/g, '');
|
4660
5019
|
var finalString = punctuationless.replace(/ +?/g, "");
|
5020
|
+
|
4661
5021
|
return finalString;
|
4662
5022
|
}
|
4663
5023
|
|