metrics-graphics-rails 2.1.3.2 → 2.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|