Skip to content

Commit 2102d02

Browse files
committed
Merge branch 'master' into rangeselector-buttons
2 parents 10a655d + c9a6549 commit 2102d02

File tree

26 files changed

+382
-96
lines changed

26 files changed

+382
-96
lines changed

build/plotcss.js

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
'use strict';
22

3-
var Plotly = require('../src/plotly');
43
var rules = {
54
"X,X div": "font-family:'Open Sans', verdana, arial, sans-serif;margin:0;padding:0;",
65
"X input,X button": "font-family:'Open Sans', verdana, arial, sans-serif;",
@@ -54,9 +53,4 @@ var rules = {
5453
"Y .notifier-close:hover": "color:#444;text-decoration:none;cursor:pointer;"
5554
};
5655

57-
for(var selector in rules) {
58-
var fullSelector = selector.replace(/^,/,' ,')
59-
.replace(/X/g, '.js-plotly-plot .plotly')
60-
.replace(/Y/g, '.plotly-notifier');
61-
Plotly.Lib.addStyleRule(fullSelector, rules[selector]);
62-
}
56+
module.exports = rules;

src/components/colorbar/has_colorbar.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,9 @@
99

1010
'use strict';
1111

12+
var Lib = require('../../lib');
13+
1214

1315
module.exports = function hasColorbar(container) {
14-
return (
15-
typeof container.colorbar === 'object' &&
16-
container.colorbar !== null
17-
);
16+
return Lib.isPlainObject(container.colorbar);
1817
};

src/components/colorscale/has_colorscale.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,12 @@ module.exports = function hasColorscale(trace, containerStr) {
3333
}
3434

3535
return (
36-
(typeof container === 'object' && container !== null) && (
36+
Lib.isPlainObject(container) && (
3737
isArrayWithOneNumber ||
3838
container.showscale === true ||
3939
(isNumeric(container.cmin) && isNumeric(container.cmax)) ||
4040
isValidScale(container.colorscale) ||
41-
(typeof container.colorbar === 'object' && container.colorbar !== null)
41+
Lib.isPlainObject(container.colorbar)
4242
)
4343
);
4444
};

src/components/dragelement/index.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ dragElement.init = function init(options) {
8686

8787
if(options.prepFn) options.prepFn(e, startX, startY);
8888

89-
dragCover = coverSlip();
89+
dragCover = coverSlip(gd);
9090

9191
dragCover.onmousemove = onMove;
9292
dragCover.onmouseup = onDone;
@@ -139,7 +139,7 @@ dragElement.init = function init(options) {
139139
if(options.doneFn) options.doneFn(gd._dragged, numClicks);
140140

141141
if(!gd._dragged) {
142-
var e2 = document.createEvent('MouseEvents');
142+
var e2 = gd._document.createEvent('MouseEvents');
143143
e2.initEvent('click', true, true);
144144
initialTarget.dispatchEvent(e2);
145145
}
@@ -159,8 +159,8 @@ dragElement.init = function init(options) {
159159
options.element.style.pointerEvents = 'all';
160160
};
161161

162-
function coverSlip() {
163-
var cover = document.createElement('div');
162+
function coverSlip(gd) {
163+
var cover = gd._document.createElement('div');
164164

165165
cover.className = 'dragcover';
166166
var cStyle = cover.style;
@@ -172,7 +172,7 @@ function coverSlip() {
172172
cStyle.zIndex = 999999999;
173173
cStyle.background = 'none';
174174

175-
document.body.appendChild(cover);
175+
gd._document.body.appendChild(cover);
176176

177177
return cover;
178178
}

src/components/modebar/buttons.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,19 +50,19 @@ modeBarButtons.toImage = {
5050
click: function(gd) {
5151
var format = 'png';
5252

53-
Lib.notifier('Taking snapshot - this may take a few seconds', 'long');
53+
Lib.notifier(gd, 'Taking snapshot - this may take a few seconds', 'long');
5454

5555
if(Lib.isIE()) {
56-
Lib.notifier('IE only supports svg. Changing format to svg.', 'long');
56+
Lib.notifier(gd, 'IE only supports svg. Changing format to svg.', 'long');
5757
format = 'svg';
5858
}
5959

6060
downloadImage(gd, {'format': format})
6161
.then(function(filename) {
62-
Lib.notifier('Snapshot succeeded - ' + filename, 'long');
62+
Lib.notifier(gd, 'Snapshot succeeded - ' + filename, 'long');
6363
})
6464
.catch(function() {
65-
Lib.notifier('Sorry there was a problem downloading your snapshot!', 'long');
65+
Lib.notifier(gd, 'Sorry there was a problem downloading your snapshot!', 'long');
6666
});
6767
}
6868
};

src/components/rangeslider/create_slider.js

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ module.exports = function createSlider(gd) {
3333
var minStart = 0,
3434
maxStart = width;
3535

36-
var slider = document.createElementNS(svgNS, 'g');
36+
var slider = gd._document.createElementNS(svgNS, 'g');
3737
helpers.setAttributes(slider, {
3838
'class': 'range-slider',
3939
'data-min': minStart,
@@ -43,7 +43,7 @@ module.exports = function createSlider(gd) {
4343
});
4444

4545

46-
var sliderBg = document.createElementNS(svgNS, 'rect'),
46+
var sliderBg = gd._document.createElementNS(svgNS, 'rect'),
4747
borderCorrect = options.borderwidth % 2 === 0 ? options.borderwidth : options.borderwidth - 1;
4848
helpers.setAttributes(sliderBg, {
4949
'fill': options.bgcolor,
@@ -56,7 +56,7 @@ module.exports = function createSlider(gd) {
5656
});
5757

5858

59-
var maskMin = document.createElementNS(svgNS, 'rect');
59+
var maskMin = gd._document.createElementNS(svgNS, 'rect');
6060
helpers.setAttributes(maskMin, {
6161
'x': 0,
6262
'width': minStart,
@@ -65,7 +65,7 @@ module.exports = function createSlider(gd) {
6565
});
6666

6767

68-
var maskMax = document.createElementNS(svgNS, 'rect');
68+
var maskMax = gd._document.createElementNS(svgNS, 'rect');
6969
helpers.setAttributes(maskMax, {
7070
'x': maxStart,
7171
'width': width - maxStart,
@@ -74,9 +74,9 @@ module.exports = function createSlider(gd) {
7474
});
7575

7676

77-
var grabberMin = document.createElementNS(svgNS, 'g'),
78-
grabAreaMin = document.createElementNS(svgNS, 'rect'),
79-
handleMin = document.createElementNS(svgNS, 'rect');
77+
var grabberMin = gd._document.createElementNS(svgNS, 'g'),
78+
grabAreaMin = gd._document.createElementNS(svgNS, 'rect'),
79+
handleMin = gd._document.createElementNS(svgNS, 'rect');
8080
helpers.setAttributes(grabberMin, { 'transform': 'translate(' + (minStart - handleWidth - 1) + ')' });
8181
helpers.setAttributes(grabAreaMin, {
8282
'width': 10,
@@ -97,9 +97,9 @@ module.exports = function createSlider(gd) {
9797
helpers.appendChildren(grabberMin, [handleMin, grabAreaMin]);
9898

9999

100-
var grabberMax = document.createElementNS(svgNS, 'g'),
101-
grabAreaMax = document.createElementNS(svgNS, 'rect'),
102-
handleMax = document.createElementNS(svgNS, 'rect');
100+
var grabberMax = gd._document.createElementNS(svgNS, 'g'),
101+
grabAreaMax = gd._document.createElementNS(svgNS, 'rect'),
102+
handleMax = gd._document.createElementNS(svgNS, 'rect');
103103
helpers.setAttributes(grabberMax, { 'transform': 'translate(' + maxStart + ')' });
104104
helpers.setAttributes(grabAreaMax, {
105105
'width': 10,
@@ -120,7 +120,7 @@ module.exports = function createSlider(gd) {
120120
helpers.appendChildren(grabberMax, [handleMax, grabAreaMax]);
121121

122122

123-
var slideBox = document.createElementNS(svgNS, 'rect');
123+
var slideBox = gd._document.createElementNS(svgNS, 'rect');
124124
helpers.setAttributes(slideBox, {
125125
'x': minStart,
126126
'width': maxStart - minStart,
@@ -137,8 +137,8 @@ module.exports = function createSlider(gd) {
137137
minVal = slider.getAttribute('data-min'),
138138
maxVal = slider.getAttribute('data-max');
139139

140-
window.addEventListener('mousemove', mouseMove);
141-
window.addEventListener('mouseup', mouseUp);
140+
gd._document.defaultView.addEventListener('mousemove', mouseMove);
141+
gd._document.defaultView.addEventListener('mouseup', mouseUp);
142142

143143
function mouseMove(e) {
144144
var delta = +e.clientX - startX,
@@ -189,8 +189,8 @@ module.exports = function createSlider(gd) {
189189
}
190190

191191
function mouseUp() {
192-
window.removeEventListener('mousemove', mouseMove);
193-
window.removeEventListener('mouseup', mouseUp);
192+
gd._document.defaultView.removeEventListener('mousemove', mouseMove);
193+
gd._document.defaultView.removeEventListener('mouseup', mouseUp);
194194
slider.style.cursor = 'auto';
195195
}
196196
});
@@ -222,8 +222,8 @@ module.exports = function createSlider(gd) {
222222

223223
function setDataRange(dataMin, dataMax) {
224224

225-
if(window.requestAnimationFrame) {
226-
window.requestAnimationFrame(function() {
225+
if(gd._document.defaultView.requestAnimationFrame) {
226+
gd._document.defaultView.requestAnimationFrame(function() {
227227
Plotly.relayout(gd, 'xaxis.range', [dataMin, dataMax]);
228228
});
229229
} else {

src/components/rangeslider/defaults.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,9 @@ var attributes = require('./attributes');
1313

1414

1515
module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, axName, counterAxes) {
16-
1716
if(!layoutIn[axName].rangeslider) return;
1817

19-
var containerIn = typeof layoutIn[axName].rangeslider === 'object' ?
18+
var containerIn = Lib.isPlainObject(layoutIn[axName].rangeslider) ?
2019
layoutIn[axName].rangeslider : {},
2120
containerOut = layoutOut[axName].rangeslider = {};
2221

src/lib/index.js

Lines changed: 3 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ lib.log = loggersModule.log;
6464
lib.warn = loggersModule.warn;
6565
lib.error = loggersModule.error;
6666

67+
var cssModule = require('./plotcss_utils');
68+
lib.injectStyles = cssModule.injectStyles;
69+
6770
lib.notifier = require('./notifier');
6871

6972
/**
@@ -388,30 +391,6 @@ lib.removeElement = function(el) {
388391
if(elParent) elParent.removeChild(el);
389392
};
390393

391-
/**
392-
* for dynamically adding style rules
393-
* makes one stylesheet that contains all rules added
394-
* by all calls to this function
395-
*/
396-
lib.addStyleRule = function(selector, styleString) {
397-
if(!lib.styleSheet) {
398-
var style = document.createElement('style');
399-
// WebKit hack :(
400-
style.appendChild(document.createTextNode(''));
401-
document.head.appendChild(style);
402-
lib.styleSheet = style.sheet;
403-
}
404-
var styleSheet = lib.styleSheet;
405-
406-
if(styleSheet.insertRule) {
407-
styleSheet.insertRule(selector + '{' + styleString + '}', 0);
408-
}
409-
else if(styleSheet.addRule) {
410-
styleSheet.addRule(selector, styleString, 0);
411-
}
412-
else lib.warn('addStyleRule failed');
413-
};
414-
415394
lib.getTranslate = function(element) {
416395

417396
var re = /.*\btranslate\((\d*\.?\d*)[^\d]*(\d*\.?\d*)[^\d].*/,

src/lib/is_plain_object.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,15 @@
1111

1212
// more info: http://stackoverflow.com/questions/18531624/isplainobject-thing
1313
module.exports = function isPlainObject(obj) {
14+
15+
// We need to be a little less strict in the `imagetest` container because
16+
// of how async image requests are handled.
17+
//
18+
// N.B. isPlainObject(new Constructor()) will return true in `imagetest`
19+
if(window && window.process && window.process.versions) {
20+
return Object.prototype.toString.call(obj) === '[object Object]';
21+
}
22+
1423
return (
1524
Object.prototype.toString.call(obj) === '[object Object]' &&
1625
Object.getPrototypeOf(obj) === Object.prototype

src/lib/notifier.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,13 @@ var NOTEDATA = [];
1616

1717
/**
1818
* notifier
19+
* @param {object} gd figure Object
1920
* @param {String} text The person's user name
2021
* @param {Number} [delay=1000] The delay time in milliseconds
2122
* or 'long' which provides 2000 ms delay time.
2223
* @return {undefined} this function does not return a value
2324
*/
24-
module.exports = function(text, displayLength) {
25+
module.exports = function(gd, text, displayLength) {
2526
if(NOTEDATA.indexOf(text) !== -1) return;
2627

2728
NOTEDATA.push(text);
@@ -30,7 +31,7 @@ module.exports = function(text, displayLength) {
3031
if(isNumeric(displayLength)) ts = displayLength;
3132
else if(displayLength === 'long') ts = 3000;
3233

33-
var notifierContainer = d3.select('body')
34+
var notifierContainer = d3.select(gd._document.body)
3435
.selectAll('.plotly-notifier')
3536
.data([0]);
3637
notifierContainer.enter()

src/lib/plotcss_utils.js

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/**
2+
* Copyright 2012-2016, Plotly, Inc.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the MIT license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*/
8+
9+
10+
'use strict';
11+
12+
var lib = require('./index');
13+
var plotcss = require('../../build/plotcss');
14+
15+
// Inject styling information into the document containing the graph div
16+
exports.injectStyles = function injectStyles(gd) {
17+
// If the graph div has already been styled, bail
18+
if(gd._plotCSSLoaded) return;
19+
20+
var targetSelectors = exports.getAllRuleSelectors(gd._document);
21+
var targetStyleSheet = null;
22+
23+
if(gd._document.getElementsByTagName('style').length === 0) {
24+
var style = gd._document.createElement('style');
25+
// WebKit hack :(
26+
style.appendChild(gd._document.createTextNode(''));
27+
gd._document.head.appendChild(style);
28+
targetStyleSheet = style.sheet;
29+
}
30+
else {
31+
// Just grab the first style element to append to
32+
targetStyleSheet = gd._document.getElementsByTagName('style')[0].sheet;
33+
}
34+
35+
for(var selector in plotcss) {
36+
var fullSelector = exports.buildFullSelector(selector);
37+
38+
// Don't duplicate selectors
39+
if(targetSelectors.indexOf(fullSelector) === -1) {
40+
if(targetStyleSheet.insertRule) {
41+
targetStyleSheet.insertRule(fullSelector + '{' + plotcss[selector] + '}', 0);
42+
}
43+
else if(targetStyleSheet.addRule) {
44+
targetStyleSheet.addRule(fullSelector, plotcss[selector], 0);
45+
}
46+
else lib.warn('injectStyles failed');
47+
}
48+
}
49+
50+
gd._plotCSSLoaded = true;
51+
};
52+
53+
// expands a plotcss selector
54+
exports.buildFullSelector = function buildFullSelector(selector) {
55+
var fullSelector = selector.replace(/,/, ', ')
56+
.replace(/:after/g, '::after')
57+
.replace(/:before/g, '::before')
58+
.replace(/X/g, '.js-plotly-plot .plotly')
59+
.replace(/Y/g, '.plotly-notifier');
60+
61+
return fullSelector;
62+
};
63+
64+
// Gets all the rules currently attached to the document
65+
exports.getAllRuleSelectors = function getAllRuleSelectors(sourceDocument) {
66+
var allSelectors = [];
67+
68+
for(var i = 0; i < sourceDocument.styleSheets.length; i++) {
69+
var styleSheet = sourceDocument.styleSheets[i];
70+
71+
if(!styleSheet.cssRules) continue; // It's possible for rules to be undefined
72+
73+
for(var j = 0; j < styleSheet.cssRules.length; j++) {
74+
var cssRule = styleSheet.cssRules[j];
75+
76+
allSelectors.push(cssRule.selectorText);
77+
}
78+
}
79+
80+
return allSelectors;
81+
};

0 commit comments

Comments
 (0)