From bf28ad9db8b7f8a299e0da1c9375503c1a354cfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Mon, 8 Aug 2016 18:16:50 -0400 Subject: [PATCH 01/17] move Plotly.register in plot_api/register.js --- src/core.js | 5 +++- src/plot_api/register.js | 65 ++++++++++++++++++++++++++++++++++++++++ src/plotly.js | 60 ++----------------------------------- 3 files changed, 71 insertions(+), 59 deletions(-) create mode 100644 src/plot_api/register.js diff --git a/src/core.js b/src/core.js index 2ff78c0b583..ce1a755eae3 100644 --- a/src/core.js +++ b/src/core.js @@ -30,11 +30,14 @@ exports.deleteTraces = Plotly.deleteTraces; exports.moveTraces = Plotly.moveTraces; exports.purge = Plotly.purge; exports.setPlotConfig = require('./plot_api/set_plot_config'); -exports.register = Plotly.register; +exports.register = require('./plot_api/register'); exports.toImage = require('./plot_api/to_image'); exports.downloadImage = require('./snapshot/download'); exports.validate = require('./plot_api/validate'); +// scatter is the only trace included by default +exports.register(require('./traces/scatter')); + // plot icons exports.Icons = require('../build/ploticon'); diff --git a/src/plot_api/register.js b/src/plot_api/register.js new file mode 100644 index 00000000000..ee64a02c1c9 --- /dev/null +++ b/src/plot_api/register.js @@ -0,0 +1,65 @@ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Plots = require('../plots/plots'); +var Lib = require('../lib'); + + +module.exports = function register(_modules) { + if(!_modules) { + throw new Error('No argument passed to Plotly.register.'); + } + else if(_modules && !Array.isArray(_modules)) { + _modules = [_modules]; + } + + for(var i = 0; i < _modules.length; i++) { + var newModule = _modules[i]; + + if(!newModule) { + throw new Error('Invalid module was attempted to be registered!'); + } + + switch(newModule.moduleType) { + case 'trace': + Plots.register(newModule, newModule.name, newModule.categories, newModule.meta); + + if(!Plots.subplotsRegistry[newModule.basePlotModule.name]) { + Plots.registerSubplot(newModule.basePlotModule); + } + + break; + + case 'transform': + if(typeof newModule.name !== 'string') { + throw new Error('Transform module *name* must be a string.'); + } + + var prefix = 'Transform module ' + newModule.name; + + if(typeof newModule.transform !== 'function') { + throw new Error(prefix + ' is missing a *transform* function.'); + } + if(!Lib.isPlainObject(newModule.attributes)) { + Lib.log(prefix + ' registered without an *attributes* object.'); + } + if(typeof newModule.supplyDefaults !== 'function') { + Lib.log(prefix + ' registered without a *supplyDefaults* function.'); + } + + Plots.transformsRegistry[newModule.name] = newModule; + + break; + + default: + throw new Error('Invalid module was attempted to be registered!'); + } + } +}; diff --git a/src/plotly.js b/src/plotly.js index acd4581142b..f7a2ac832fb 100644 --- a/src/plotly.js +++ b/src/plotly.js @@ -22,7 +22,7 @@ require('es6-promise').polyfill(); // lib functions -var Lib = exports.Lib = require('./lib'); +exports.Lib = require('./lib'); exports.util = require('./lib/svg_text_utils'); exports.Queue = require('./lib/queue'); @@ -34,8 +34,7 @@ exports.MathJaxConfig = require('./fonts/mathjax_config'); exports.defaultConfig = require('./plot_api/plot_config'); // plots -var Plots = exports.Plots = require('./plots/plots'); - +exports.Plots = require('./plots/plots'); exports.Axes = require('./plots/cartesian/axes'); exports.Fx = require('./plots/cartesian/graph_interact'); @@ -52,61 +51,6 @@ exports.Images = require('./components/images'); exports.UpdateMenus = require('./components/updatemenus'); exports.ModeBar = require('./components/modebar'); -exports.register = function register(_modules) { - if(!_modules) { - throw new Error('No argument passed to Plotly.register.'); - } - else if(_modules && !Array.isArray(_modules)) { - _modules = [_modules]; - } - - for(var i = 0; i < _modules.length; i++) { - var newModule = _modules[i]; - - if(!newModule) { - throw new Error('Invalid module was attempted to be registered!'); - } - - switch(newModule.moduleType) { - case 'trace': - Plots.register(newModule, newModule.name, newModule.categories, newModule.meta); - - if(!Plots.subplotsRegistry[newModule.basePlotModule.name]) { - Plots.registerSubplot(newModule.basePlotModule); - } - - break; - - case 'transform': - if(typeof newModule.name !== 'string') { - throw new Error('Transform module *name* must be a string.'); - } - - var prefix = 'Transform module ' + newModule.name; - - if(typeof newModule.transform !== 'function') { - throw new Error(prefix + ' is missing a *transform* function.'); - } - if(!Lib.isPlainObject(newModule.attributes)) { - Lib.log(prefix + ' registered without an *attributes* object.'); - } - if(typeof newModule.supplyDefaults !== 'function') { - Lib.log(prefix + ' registered without a *supplyDefaults* function.'); - } - - Plots.transformsRegistry[newModule.name] = newModule; - - break; - - default: - throw new Error('Invalid module was attempted to be registered!'); - } - } -}; - -// Scatter is the only trace included by default -exports.register(require('./traces/scatter')); - // plot api require('./plot_api/plot_api'); exports.PlotSchema = require('./plot_api/plot_schema'); From 00536f43b5da075a8147e24965a5218cca011ad3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Tue, 9 Aug 2016 15:28:58 -0400 Subject: [PATCH 02/17] lint: split registry switch block into routines --- src/plot_api/register.js | 54 ++++++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/src/plot_api/register.js b/src/plot_api/register.js index ee64a02c1c9..99b8e53d5b2 100644 --- a/src/plot_api/register.js +++ b/src/plot_api/register.js @@ -29,33 +29,11 @@ module.exports = function register(_modules) { switch(newModule.moduleType) { case 'trace': - Plots.register(newModule, newModule.name, newModule.categories, newModule.meta); - - if(!Plots.subplotsRegistry[newModule.basePlotModule.name]) { - Plots.registerSubplot(newModule.basePlotModule); - } - + registerTraceModule(newModule); break; case 'transform': - if(typeof newModule.name !== 'string') { - throw new Error('Transform module *name* must be a string.'); - } - - var prefix = 'Transform module ' + newModule.name; - - if(typeof newModule.transform !== 'function') { - throw new Error(prefix + ' is missing a *transform* function.'); - } - if(!Lib.isPlainObject(newModule.attributes)) { - Lib.log(prefix + ' registered without an *attributes* object.'); - } - if(typeof newModule.supplyDefaults !== 'function') { - Lib.log(prefix + ' registered without a *supplyDefaults* function.'); - } - - Plots.transformsRegistry[newModule.name] = newModule; - + registerTransformModule(newModule); break; default: @@ -63,3 +41,31 @@ module.exports = function register(_modules) { } } }; + +function registerTraceModule(newModule) { + Plots.register(newModule, newModule.name, newModule.categories, newModule.meta); + + if(!Plots.subplotsRegistry[newModule.basePlotModule.name]) { + Plots.registerSubplot(newModule.basePlotModule); + } +} + +function registerTransformModule(newModule) { + if(typeof newModule.name !== 'string') { + throw new Error('Transform module *name* must be a string.'); + } + + var prefix = 'Transform module ' + newModule.name; + + if(typeof newModule.transform !== 'function') { + throw new Error(prefix + ' is missing a *transform* function.'); + } + if(!Lib.isPlainObject(newModule.attributes)) { + Lib.log(prefix + ' registered without an *attributes* object.'); + } + if(typeof newModule.supplyDefaults !== 'function') { + Lib.log(prefix + ' registered without a *supplyDefaults* function.'); + } + + Plots.transformsRegistry[newModule.name] = newModule; +} From 910e17c756062d95d50f3698008520802009663f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Tue, 9 Aug 2016 15:31:29 -0400 Subject: [PATCH 03/17] move registry objects and helper method to src/registry.js - this will help free Plots of some circular dependencies - make sure the ref back Registry contents in Plots for backward compatibility --- src/plot_api/register.js | 10 +-- src/plots/plots.js | 126 ++++------------------------------- src/registry.js | 137 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 154 insertions(+), 119 deletions(-) create mode 100644 src/registry.js diff --git a/src/plot_api/register.js b/src/plot_api/register.js index 99b8e53d5b2..94b29ae9cfb 100644 --- a/src/plot_api/register.js +++ b/src/plot_api/register.js @@ -8,7 +8,7 @@ 'use strict'; -var Plots = require('../plots/plots'); +var Registry = require('../registry'); var Lib = require('../lib'); @@ -43,10 +43,10 @@ module.exports = function register(_modules) { }; function registerTraceModule(newModule) { - Plots.register(newModule, newModule.name, newModule.categories, newModule.meta); + Registry.register(newModule, newModule.name, newModule.categories, newModule.meta); - if(!Plots.subplotsRegistry[newModule.basePlotModule.name]) { - Plots.registerSubplot(newModule.basePlotModule); + if(!Registry.subplotsRegistry[newModule.basePlotModule.name]) { + Registry.registerSubplot(newModule.basePlotModule); } } @@ -67,5 +67,5 @@ function registerTransformModule(newModule) { Lib.log(prefix + ' registered without a *supplyDefaults* function.'); } - Plots.transformsRegistry[newModule.name] = newModule; + Registry.transformsRegistry[newModule.name] = newModule; } diff --git a/src/plots/plots.js b/src/plots/plots.js index a5c34a36dd9..b638df76dc7 100644 --- a/src/plots/plots.js +++ b/src/plots/plots.js @@ -13,134 +13,32 @@ var d3 = require('d3'); var isNumeric = require('fast-isnumeric'); var Plotly = require('../plotly'); +var Registry = require('../registry'); var Lib = require('../lib'); var Color = require('../components/color'); var plots = module.exports = {}; -var modules = plots.modules = {}, - allTypes = plots.allTypes = [], - allCategories = plots.allCategories = {}, - subplotsRegistry = plots.subplotsRegistry = {}, - transformsRegistry = plots.transformsRegistry = {}; +// Expose registry methods that used to be on Plots for backward-compatibility +plots.modules = Registry.modules; +plots.allTypes = Registry.allTypes; +plots.allCategories = Registry.allCategories; +plots.subplotsRegistry = Registry.subplotsRegistry; +plots.transformsRegistry = Registry.transformsRegistry; +plots.traceIs = Registry.traceIs; +plots.getModule = Registry.getModule; plots.attributes = require('./attributes'); -plots.attributes.type.values = allTypes; +plots.attributes.type.values = plots.allTypes; plots.fontAttrs = require('./font_attributes'); plots.layoutAttributes = require('./layout_attributes'); // TODO make this a plot attribute? plots.fontWeight = 'normal'; -/** - * plots.register: register a module as the handler for a trace type - * - * @param {object} _module the module that will handle plotting this trace type - * @param {string} thisType - * @param {array of strings} categoriesIn all the categories this type is in, - * tested by calls: Plotly.Plots.traceIs(trace, oneCategory) - * @param {object} meta meta information about the trace type - */ -plots.register = function(_module, thisType, categoriesIn, meta) { - if(modules[thisType]) { - Lib.log('Type ' + thisType + ' already registered'); - return; - } - - var categoryObj = {}; - for(var i = 0; i < categoriesIn.length; i++) { - categoryObj[categoriesIn[i]] = true; - allCategories[categoriesIn[i]] = true; - } - - modules[thisType] = { - _module: _module, - categories: categoryObj - }; - - if(meta && Object.keys(meta).length) { - modules[thisType].meta = meta; - } - - allTypes.push(thisType); -}; - -function getTraceType(traceType) { - if(typeof traceType === 'object') traceType = traceType.type; - return traceType; -} - -plots.getModule = function(trace) { - if(trace.r !== undefined) { - Lib.warn('Tried to put a polar trace ' + - 'on an incompatible graph of cartesian ' + - 'data. Ignoring this dataset.', trace - ); - return false; - } - - var _module = modules[getTraceType(trace)]; - if(!_module) return false; - return _module._module; -}; - - -/** - * plots.traceIs: is this trace type in this category? - * - * traceType: a trace (object) or trace type (string) - * category: a category (string) - */ -plots.traceIs = function traceIs(traceType, category) { - traceType = getTraceType(traceType); - - if(traceType === 'various') return false; // FIXME +var subplotsRegistry = plots.subplotsRegistry; +var transformsRegistry = plots.transformsRegistry; - var _module = modules[traceType]; - - if(!_module) { - if(traceType !== undefined) { - Lib.log('Unrecognized trace type ' + traceType + '.'); - } - _module = modules[plots.attributes.type.dflt]; - } - - return !!_module.categories[category]; -}; - - -/** - * plots.registerSubplot: register a subplot type - * - * @param {object} _module subplot module: - * - * @param {string or array of strings} attr - * attribute name in traces and layout - * @param {string or array of strings} idRoot - * root of id (setting the possible value for attrName) - * @param {object} attributes - * attribute(s) for traces of this subplot type - * - * In trace objects `attr` is the object key taking a valid `id` as value - * (the set of all valid ids is generated below and stored in idRegex). - * - * In the layout object, a or several valid `attr` name(s) can be keys linked - * to a nested attribute objects - * (the set of all valid attr names is generated below and stored in attrRegex). - * - * TODO use these in Lib.coerce - */ -plots.registerSubplot = function(_module) { - var plotType = _module.name; - - if(subplotsRegistry[plotType]) { - Lib.log('Plot type ' + plotType + ' already registered.'); - return; - } - - // not sure what's best for the 'cartesian' type at this point - subplotsRegistry[plotType] = _module; -}; /** * Find subplot ids in data. diff --git a/src/registry.js b/src/registry.js new file mode 100644 index 00000000000..73f511f38cb --- /dev/null +++ b/src/registry.js @@ -0,0 +1,137 @@ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = require('./lib'); +var basePlotAttributes = require('./plots/attributes'); + +exports.modules = {}; +exports.allTypes = []; +exports.allCategories = {}; +exports.subplotsRegistry = {}; +exports.transformsRegistry = {}; + +/** + * register a module as the handler for a trace type + * + * @param {object} _module the module that will handle plotting this trace type + * @param {string} thisType + * @param {array of strings} categoriesIn all the categories this type is in, + * tested by calls: traceIs(trace, oneCategory) + * @param {object} meta meta information about the trace type + */ +exports.register = function(_module, thisType, categoriesIn, meta) { + if(exports.modules[thisType]) { + Lib.log('Type ' + thisType + ' already registered'); + return; + } + + var categoryObj = {}; + for(var i = 0; i < categoriesIn.length; i++) { + categoryObj[categoriesIn[i]] = true; + exports.allCategories[categoriesIn[i]] = true; + } + + exports.modules[thisType] = { + _module: _module, + categories: categoryObj + }; + + if(meta && Object.keys(meta).length) { + exports.modules[thisType].meta = meta; + } + + exports.allTypes.push(thisType); +}; + +/** + * register a subplot type + * + * @param {object} _module subplot module: + * + * @param {string or array of strings} attr + * attribute name in traces and layout + * @param {string or array of strings} idRoot + * root of id (setting the possible value for attrName) + * @param {object} attributes + * attribute(s) for traces of this subplot type + * + * In trace objects `attr` is the object key taking a valid `id` as value + * (the set of all valid ids is generated below and stored in idRegex). + * + * In the layout object, a or several valid `attr` name(s) can be keys linked + * to a nested attribute objects + * (the set of all valid attr names is generated below and stored in attrRegex). + */ +exports.registerSubplot = function(_module) { + var plotType = _module.name; + + if(exports.subplotsRegistry[plotType]) { + Lib.log('Plot type ' + plotType + ' already registered.'); + return; + } + + // not sure what's best for the 'cartesian' type at this point + exports.subplotsRegistry[plotType] = _module; +}; + +/** + * Get registered module using trace object or trace type + * + * @param {object||string} trace + * trace object with prop 'type' or trace type as a string + * @return {object} + * module object corresponding to trace type + */ +exports.getModule = function(trace) { + if(trace.r !== undefined) { + Lib.warn('Tried to put a polar trace ' + + 'on an incompatible graph of cartesian ' + + 'data. Ignoring this dataset.', trace + ); + return false; + } + + var _module = exports.modules[getTraceType(trace)]; + if(!_module) return false; + return _module._module; +}; + +/** + * Determine if this trace type is in a given category + * + * @param {object||string} traceType + * a trace (object) or trace type (string) + * @param {string} category + * category in question + * @return {boolean} + */ +exports.traceIs = function(traceType, category) { + traceType = getTraceType(traceType); + + if(traceType === 'various') return false; // FIXME + + var _module = exports.modules[traceType]; + + if(!_module) { + if(traceType !== undefined) { + Lib.log('Unrecognized trace type ' + traceType + '.'); + } + + _module = exports.modules[basePlotAttributes.type.dflt]; + } + + return !!_module.categories[category]; +}; + +function getTraceType(traceType) { + if(typeof traceType === 'object') traceType = traceType.type; + return traceType; +} From 11f475eadb8e364b9a9350cc59714453f83b19cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Tue, 9 Aug 2016 16:23:15 -0400 Subject: [PATCH 04/17] move Registry tests, plots_test.js -> register_test.js --- test/jasmine/tests/plots_test.js | 134 ----------------------- test/jasmine/tests/register_test.js | 163 +++++++++++++++++++++++++--- 2 files changed, 150 insertions(+), 147 deletions(-) diff --git a/test/jasmine/tests/plots_test.js b/test/jasmine/tests/plots_test.js index abc63b05fe0..af2c1f42ea4 100644 --- a/test/jasmine/tests/plots_test.js +++ b/test/jasmine/tests/plots_test.js @@ -245,140 +245,6 @@ describe('Test Plots', function() { }); }); - describe('Plots.register, getModule, and traceIs', function() { - beforeEach(function() { - this.modulesKeys = Object.keys(Plots.modules); - this.allTypesKeys = Object.keys(Plots.allTypes); - this.allCategoriesKeys = Object.keys(Plots.allCategories); - - this.fakeModule = { - calc: function() { return 42; }, - plot: function() { return 1000000; } - }; - this.fakeModule2 = { - plot: function() { throw new Error('nope!'); } - }; - - Plots.register(this.fakeModule, 'newtype', ['red', 'green']); - - spyOn(console, 'warn'); - }); - - afterEach(function() { - function revertObj(obj, initialKeys) { - Object.keys(obj).forEach(function(k) { - if(initialKeys.indexOf(k) === -1) delete obj[k]; - }); - } - - revertObj(Plots.modules, this.modulesKeys); - revertObj(Plots.allTypes, this.allTypesKeys); - revertObj(Plots.allCategories, this.allCategoriesKeys); - }); - - it('should not reregister a type', function() { - Plots.register(this.fakeModule2, 'newtype', ['yellow', 'blue']); - expect(Plots.allCategories.yellow).toBeUndefined(); - }); - - it('should find the module for a type', function() { - expect(Plots.getModule('newtype')).toBe(this.fakeModule); - expect(Plots.getModule({type: 'newtype'})).toBe(this.fakeModule); - }); - - it('should return false for types it doesn\'t know', function() { - expect(Plots.getModule('notatype')).toBe(false); - expect(Plots.getModule({type: 'notatype'})).toBe(false); - expect(Plots.getModule({type: 'newtype', r: 'this is polar'})).toBe(false); - }); - - it('should find the categories for this type', function() { - expect(Plots.traceIs('newtype', 'red')).toBe(true); - expect(Plots.traceIs({type: 'newtype'}, 'red')).toBe(true); - }); - - it('should not find other real categories', function() { - expect(Plots.traceIs('newtype', 'cartesian')).toBe(false); - expect(Plots.traceIs({type: 'newtype'}, 'cartesian')).toBe(false); - expect(console.warn).not.toHaveBeenCalled(); - }); - }); - - describe('Plots.registerSubplot', function() { - var fake = { - name: 'fake', - attr: 'abc', - idRoot: 'cba', - attrRegex: /^abc([2-9]|[1-9][0-9]+)?$/, - idRegex: /^cba([2-9]|[1-9][0-9]+)?$/, - attributes: { stuff: { 'more stuff': 102102 } } - }; - - Plots.registerSubplot(fake); - - var subplotsRegistry = Plots.subplotsRegistry; - - it('should register attr, idRoot and attributes', function() { - expect(subplotsRegistry.fake.attr).toEqual('abc'); - expect(subplotsRegistry.fake.idRoot).toEqual('cba'); - expect(subplotsRegistry.fake.attributes) - .toEqual({stuff: { 'more stuff': 102102 }}); - }); - - describe('registered subplot type attribute regex', function() { - it('should compile to correct attribute regex string', function() { - expect(subplotsRegistry.fake.attrRegex.toString()) - .toEqual('/^abc([2-9]|[1-9][0-9]+)?$/'); - }); - - var shouldPass = [ - 'abc', 'abc2', 'abc3', 'abc10', 'abc9', 'abc100', 'abc2002' - ]; - var shouldFail = [ - '0abc', 'abc0', 'abc1', 'abc021321', 'abc00021321' - ]; - - shouldPass.forEach(function(s) { - it('considers ' + JSON.stringify(s) + 'as a correct attribute name', function() { - expect(subplotsRegistry.fake.attrRegex.test(s)).toBe(true); - }); - }); - - shouldFail.forEach(function(s) { - it('considers ' + JSON.stringify(s) + 'as an incorrect attribute name', function() { - expect(subplotsRegistry.fake.attrRegex.test(s)).toBe(false); - }); - }); - }); - - describe('registered subplot type id regex', function() { - it('should compile to correct id regular expression', function() { - expect(subplotsRegistry.fake.idRegex.toString()) - .toEqual('/^cba([2-9]|[1-9][0-9]+)?$/'); - }); - - var shouldPass = [ - 'cba', 'cba2', 'cba3', 'cba10', 'cba9', 'cba100', 'cba2002' - ]; - var shouldFail = [ - '0cba', 'cba0', 'cba1', 'cba021321', 'cba00021321' - ]; - - shouldPass.forEach(function(s) { - it('considers ' + JSON.stringify(s) + 'as a correct attribute name', function() { - expect(subplotsRegistry.fake.idRegex.test(s)).toBe(true); - }); - }); - - shouldFail.forEach(function(s) { - it('considers ' + JSON.stringify(s) + 'as an incorrect attribute name', function() { - expect(subplotsRegistry.fake.idRegex.test(s)).toBe(false); - }); - }); - }); - - }); - describe('Plots.resize', function() { var gd; diff --git a/test/jasmine/tests/register_test.js b/test/jasmine/tests/register_test.js index dd1356dc50a..9d9df33bdb0 100644 --- a/test/jasmine/tests/register_test.js +++ b/test/jasmine/tests/register_test.js @@ -1,15 +1,152 @@ var Plotly = require('@lib/index'); +var Registry = require('@src/registry'); -describe('the register function', function() { +describe('Test Registry', function() { 'use strict'; - var Plots = Plotly.Plots; + describe('register, getModule, and traceIs', function() { + beforeEach(function() { + this.modulesKeys = Object.keys(Registry.modules); + this.allTypesKeys = Object.keys(Registry.allTypes); + this.allCategoriesKeys = Object.keys(Registry.allCategories); + + this.fakeModule = { + calc: function() { return 42; }, + plot: function() { return 1000000; } + }; + this.fakeModule2 = { + plot: function() { throw new Error('nope!'); } + }; + + Registry.register(this.fakeModule, 'newtype', ['red', 'green']); + + spyOn(console, 'warn'); + }); + + afterEach(function() { + function revertObj(obj, initialKeys) { + Object.keys(obj).forEach(function(k) { + if(initialKeys.indexOf(k) === -1) delete obj[k]; + }); + } + + revertObj(Registry.modules, this.modulesKeys); + revertObj(Registry.allTypes, this.allTypesKeys); + revertObj(Registry.allCategories, this.allCategoriesKeys); + }); + + it('should not reregister a type', function() { + Registry.register(this.fakeModule2, 'newtype', ['yellow', 'blue']); + expect(Registry.allCategories.yellow).toBeUndefined(); + }); + + it('should find the module for a type', function() { + expect(Registry.getModule('newtype')).toBe(this.fakeModule); + expect(Registry.getModule({type: 'newtype'})).toBe(this.fakeModule); + }); + + it('should return false for types it doesn\'t know', function() { + expect(Registry.getModule('notatype')).toBe(false); + expect(Registry.getModule({type: 'notatype'})).toBe(false); + expect(Registry.getModule({type: 'newtype', r: 'this is polar'})).toBe(false); + }); + + it('should find the categories for this type', function() { + expect(Registry.traceIs('newtype', 'red')).toBe(true); + expect(Registry.traceIs({type: 'newtype'}, 'red')).toBe(true); + }); + + it('should not find other real categories', function() { + expect(Registry.traceIs('newtype', 'cartesian')).toBe(false); + expect(Registry.traceIs({type: 'newtype'}, 'cartesian')).toBe(false); + expect(console.warn).not.toHaveBeenCalled(); + }); + }); + + describe('Registry.registerSubplot', function() { + var fake = { + name: 'fake', + attr: 'abc', + idRoot: 'cba', + attrRegex: /^abc([2-9]|[1-9][0-9]+)?$/, + idRegex: /^cba([2-9]|[1-9][0-9]+)?$/, + attributes: { stuff: { 'more stuff': 102102 } } + }; + + Registry.registerSubplot(fake); + + var subplotsRegistry = Registry.subplotsRegistry; + + it('should register attr, idRoot and attributes', function() { + expect(subplotsRegistry.fake.attr).toEqual('abc'); + expect(subplotsRegistry.fake.idRoot).toEqual('cba'); + expect(subplotsRegistry.fake.attributes) + .toEqual({stuff: { 'more stuff': 102102 }}); + }); + + describe('registered subplot type attribute regex', function() { + it('should compile to correct attribute regex string', function() { + expect(subplotsRegistry.fake.attrRegex.toString()) + .toEqual('/^abc([2-9]|[1-9][0-9]+)?$/'); + }); + + var shouldPass = [ + 'abc', 'abc2', 'abc3', 'abc10', 'abc9', 'abc100', 'abc2002' + ]; + var shouldFail = [ + '0abc', 'abc0', 'abc1', 'abc021321', 'abc00021321' + ]; + + shouldPass.forEach(function(s) { + it('considers ' + JSON.stringify(s) + 'as a correct attribute name', function() { + expect(subplotsRegistry.fake.attrRegex.test(s)).toBe(true); + }); + }); + + shouldFail.forEach(function(s) { + it('considers ' + JSON.stringify(s) + 'as an incorrect attribute name', function() { + expect(subplotsRegistry.fake.attrRegex.test(s)).toBe(false); + }); + }); + }); + + describe('registered subplot type id regex', function() { + it('should compile to correct id regular expression', function() { + expect(subplotsRegistry.fake.idRegex.toString()) + .toEqual('/^cba([2-9]|[1-9][0-9]+)?$/'); + }); + + var shouldPass = [ + 'cba', 'cba2', 'cba3', 'cba10', 'cba9', 'cba100', 'cba2002' + ]; + var shouldFail = [ + '0cba', 'cba0', 'cba1', 'cba021321', 'cba00021321' + ]; + + shouldPass.forEach(function(s) { + it('considers ' + JSON.stringify(s) + 'as a correct attribute name', function() { + expect(subplotsRegistry.fake.idRegex.test(s)).toBe(true); + }); + }); + + shouldFail.forEach(function(s) { + it('considers ' + JSON.stringify(s) + 'as an incorrect attribute name', function() { + expect(subplotsRegistry.fake.idRegex.test(s)).toBe(false); + }); + }); + }); + + }); +}); + +describe('the register function', function() { + 'use strict'; beforeEach(function() { - this.modulesKeys = Object.keys(Plots.modules); - this.allTypesKeys = Object.keys(Plots.allTypes); - this.allCategoriesKeys = Object.keys(Plots.allCategories); - this.allTransformsKeys = Object.keys(Plots.transformsRegistry); + this.modulesKeys = Object.keys(Registry.modules); + this.allTypesKeys = Object.keys(Registry.allTypes); + this.allCategoriesKeys = Object.keys(Registry.allCategories); + this.allTransformsKeys = Object.keys(Registry.transformsRegistry); }); afterEach(function() { @@ -19,10 +156,10 @@ describe('the register function', function() { }); } - revertObj(Plots.modules, this.modulesKeys); - revertObj(Plots.allTypes, this.allTypesKeys); - revertObj(Plots.allCategories, this.allCategoriesKeys); - revertObj(Plots.transformsRegistry, this.allTransformsKeys); + revertObj(Registry.modules, this.modulesKeys); + revertObj(Registry.allTypes, this.allTypesKeys); + revertObj(Registry.allCategories, this.allCategoriesKeys); + revertObj(Registry.transformsRegistry, this.allTransformsKeys); }); it('should throw an error when no argument is given', function() { @@ -44,7 +181,7 @@ describe('the register function', function() { Plotly.register(mockTrace1); }).not.toThrow(); - expect(Plotly.Plots.getModule('mockTrace1')).toBe(mockTrace1); + expect(Registry.getModule('mockTrace1')).toBe(mockTrace1); }); it('should work with an array of modules', function() { @@ -60,7 +197,7 @@ describe('the register function', function() { Plotly.register([mockTrace2]); }).not.toThrow(); - expect(Plotly.Plots.getModule('mockTrace2')).toBe(mockTrace2); + expect(Registry.getModule('mockTrace2')).toBe(mockTrace2); }); it('should throw an error when an invalid module is given', function() { @@ -99,6 +236,6 @@ describe('the register function', function() { Plotly.register(transformModule); }).not.toThrow(); - expect(Plots.transformsRegistry['mah-transform']).toBeDefined(); + expect(Registry.transformsRegistry['mah-transform']).toBeDefined(); }); }); From 4a3f2540822a080e5577308deb0f095f768f08e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Tue, 9 Aug 2016 16:22:29 -0400 Subject: [PATCH 05/17] rm some unnecessary deps on Plots --- src/components/legend/defaults.js | 3 ++- src/plots/cartesian/layout_defaults.js | 3 ++- src/plots/gl3d/scene.js | 4 +--- src/plots/layout_attributes.js | 5 ++--- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/components/legend/defaults.js b/src/components/legend/defaults.js index 71b53b89643..eef34acff78 100644 --- a/src/components/legend/defaults.js +++ b/src/components/legend/defaults.js @@ -13,6 +13,7 @@ var Lib = require('../../lib'); var Plots = require('../../plots/plots'); var attributes = require('./attributes'); +var basePlotLayoutAttributes = require('../../plots/layout_attributes'); var helpers = require('./helpers'); @@ -53,7 +54,7 @@ module.exports = function legendDefaults(layoutIn, layoutOut, fullData) { } var showLegend = Lib.coerce(layoutIn, layoutOut, - Plots.layoutAttributes, 'showlegend', visibleTraces > 1); + basePlotLayoutAttributes, 'showlegend', visibleTraces > 1); if(showLegend === false) return; diff --git a/src/plots/cartesian/layout_defaults.js b/src/plots/cartesian/layout_defaults.js index 4278e2d467a..ac9647833bb 100644 --- a/src/plots/cartesian/layout_defaults.js +++ b/src/plots/cartesian/layout_defaults.js @@ -12,6 +12,7 @@ var Lib = require('../../lib'); var Plots = require('../plots'); var Color = require('../../components/color'); +var basePlotLayoutAttributes = require('../layout_attributes'); var RangeSlider = require('../../components/rangeslider'); var RangeSelector = require('../../components/rangeselector'); @@ -112,7 +113,7 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) { // TODO: bgcolor for each subplot, to inherit from the main one var plot_bgcolor = Color.background; if(xaList.length && yaList.length) { - plot_bgcolor = Lib.coerce(layoutIn, layoutOut, Plots.layoutAttributes, 'plot_bgcolor'); + plot_bgcolor = Lib.coerce(layoutIn, layoutOut, basePlotLayoutAttributes, 'plot_bgcolor'); } var bgColor = Color.combine(plot_bgcolor, layoutOut.paper_bgcolor); diff --git a/src/plots/gl3d/scene.js b/src/plots/gl3d/scene.js index f799c40543b..088bcb7e3fd 100644 --- a/src/plots/gl3d/scene.js +++ b/src/plots/gl3d/scene.js @@ -13,7 +13,6 @@ var createPlot = require('gl-plot3d'); var Lib = require('../../lib'); -var Plots = require('../../plots/plots'); var Axes = require('../../plots/cartesian/axes'); var Fx = require('../../plots/cartesian/graph_interact'); @@ -399,8 +398,7 @@ proto.plot = function(sceneData, fullLayout, layout) { if(trace) { trace.update(data); } else { - var traceModule = Plots.getModule(data.type); - trace = traceModule.plot(this, data); + trace = data._module.plot(this, data); this.traces[data.uid] = trace; } trace.name = data.name; diff --git a/src/plots/layout_attributes.js b/src/plots/layout_attributes.js index 33aa018153b..896e3a6649d 100644 --- a/src/plots/layout_attributes.js +++ b/src/plots/layout_attributes.js @@ -8,12 +8,11 @@ 'use strict'; -var fontAttrs = require('./font_attributes'); -var colorAttrs = require('../components/color/attributes'); - var Lib = require('../lib'); var extendFlat = Lib.extendFlat; +var fontAttrs = require('./font_attributes'); +var colorAttrs = require('../components/color/attributes'); module.exports = { font: { From 161af7ec98d8cf84d7294a16186a9096f4d5b494 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Tue, 9 Aug 2016 16:23:36 -0400 Subject: [PATCH 06/17] sub Plots[method] -> Registry[method] --- src/components/colorbar/draw.js | 3 ++- src/components/drawing/index.js | 4 ++-- src/components/errorbars/calc.js | 4 ++-- src/components/errorbars/defaults.js | 4 ++-- src/components/legend/defaults.js | 6 +++--- src/components/legend/draw.js | 7 +++--- src/components/legend/get_legend_data.js | 5 ++--- src/components/legend/helpers.js | 4 ++-- src/components/legend/style.js | 8 +++---- src/plot_api/plot_api.js | 27 ++++++++++++------------ src/plot_api/plot_schema.js | 19 +++++++++-------- src/plots/cartesian/axes.js | 7 +++--- src/plots/cartesian/axis_defaults.js | 6 +++--- src/plots/cartesian/axis_ids.js | 3 ++- src/plots/cartesian/layout_defaults.js | 12 +++++------ src/traces/bar/layout_defaults.js | 4 ++-- src/traces/bar/set_positions.js | 4 ++-- src/traces/box/layout_defaults.js | 4 ++-- src/traces/box/set_positions.js | 4 ++-- src/traces/heatmap/calc.js | 12 +++++------ src/traces/heatmap/plot.js | 4 ++-- src/traces/pie/base_plot.js | 4 ++-- 22 files changed, 79 insertions(+), 76 deletions(-) diff --git a/src/components/colorbar/draw.js b/src/components/colorbar/draw.js index 3d287532a51..4c56f35dd00 100644 --- a/src/components/colorbar/draw.js +++ b/src/components/colorbar/draw.js @@ -14,6 +14,7 @@ var tinycolor = require('tinycolor2'); var Plotly = require('../../plotly'); var Plots = require('../../plots/plots'); +var Registry = require('../../registry'); var Axes = require('../../plots/cartesian/axes'); var dragElement = require('../dragelement'); var Lib = require('../../lib'); @@ -436,7 +437,7 @@ module.exports = function draw(gd, id) { function drawTitle(titleClass, titleOpts) { var trace = getTrace(), propName; - if(Plots.traceIs(trace, 'markerColorscale')) { + if(Registry.traceIs(trace, 'markerColorscale')) { propName = 'marker.colorbar.title'; } else propName = 'colorbar.title'; diff --git a/src/components/drawing/index.js b/src/components/drawing/index.js index 2c9a6a6261c..e906f2d792e 100644 --- a/src/components/drawing/index.js +++ b/src/components/drawing/index.js @@ -12,7 +12,7 @@ var d3 = require('d3'); var isNumeric = require('fast-isnumeric'); -var Plots = require('../../plots/plots'); +var Registry = require('../../registry'); var Color = require('../color'); var Colorscale = require('../colorscale'); var Lib = require('../../lib'); @@ -183,7 +183,7 @@ drawing.pointStyle = function(s, trace) { // only scatter & box plots get marker path and opacity // bars, histograms don't - if(Plots.traceIs(trace, 'symbols')) { + if(Registry.traceIs(trace, 'symbols')) { var sizeFn = makeBubbleSizeFn(trace); s.attr('d', function(d) { diff --git a/src/components/errorbars/calc.js b/src/components/errorbars/calc.js index be95c5e6f08..c86fea1cfd5 100644 --- a/src/components/errorbars/calc.js +++ b/src/components/errorbars/calc.js @@ -11,7 +11,7 @@ var isNumeric = require('fast-isnumeric'); -var Plots = require('../../plots/plots'); +var Registry = require('../../registry'); var Axes = require('../../plots/cartesian/axes'); var makeComputeError = require('./compute_error'); @@ -24,7 +24,7 @@ module.exports = function calc(gd) { var calcTrace = calcdata[i], trace = calcTrace[0].trace; - if(!Plots.traceIs(trace, 'errorBarsOK')) continue; + if(!Registry.traceIs(trace, 'errorBarsOK')) continue; var xa = Axes.getFromId(gd, trace.xaxis), ya = Axes.getFromId(gd, trace.yaxis); diff --git a/src/components/errorbars/defaults.js b/src/components/errorbars/defaults.js index 2146b8ca2d4..52691dbd55e 100644 --- a/src/components/errorbars/defaults.js +++ b/src/components/errorbars/defaults.js @@ -10,7 +10,7 @@ var isNumeric = require('fast-isnumeric'); -var Plots = require('../../plots/plots'); +var Registry = require('../../registry'); var Lib = require('../../lib'); var attributes = require('./attributes'); @@ -70,6 +70,6 @@ module.exports = function(traceIn, traceOut, defaultColor, opts) { if(!opts.inherit || !containerOut[copyAttr]) { coerce('color', defaultColor); coerce('thickness'); - coerce('width', Plots.traceIs(traceOut, 'gl3d') ? 0 : 4); + coerce('width', Registry.traceIs(traceOut, 'gl3d') ? 0 : 4); } }; diff --git a/src/components/legend/defaults.js b/src/components/legend/defaults.js index eef34acff78..39e9bd80c70 100644 --- a/src/components/legend/defaults.js +++ b/src/components/legend/defaults.js @@ -9,8 +9,8 @@ 'use strict'; +var Registry = require('../../registry'); var Lib = require('../../lib'); -var Plots = require('../../plots/plots'); var attributes = require('./attributes'); var basePlotLayoutAttributes = require('../../plots/layout_attributes'); @@ -34,10 +34,10 @@ module.exports = function legendDefaults(layoutIn, layoutOut, fullData) { if(helpers.legendGetsTrace(trace)) { visibleTraces++; // always show the legend by default if there's a pie - if(Plots.traceIs(trace, 'pie')) visibleTraces++; + if(Registry.traceIs(trace, 'pie')) visibleTraces++; } - if((Plots.traceIs(trace, 'bar') && layoutOut.barmode === 'stack') || + if((Registry.traceIs(trace, 'bar') && layoutOut.barmode === 'stack') || ['tonextx', 'tonexty'].indexOf(trace.fill) !== -1) { defaultOrder = helpers.isGrouped({traceorder: defaultOrder}) ? 'grouped+reversed' : 'reversed'; diff --git a/src/components/legend/draw.js b/src/components/legend/draw.js index 1cb17bd8880..f71411229c0 100644 --- a/src/components/legend/draw.js +++ b/src/components/legend/draw.js @@ -14,6 +14,7 @@ var d3 = require('d3'); var Plotly = require('../../plotly'); var Lib = require('../../lib'); var Plots = require('../../plots/plots'); +var Registry = require('../../registry'); var dragElement = require('../dragelement'); var Drawing = require('../drawing'); var Color = require('../color'); @@ -108,7 +109,7 @@ module.exports = function draw(gd) { traces.call(style) .style('opacity', function(d) { var trace = d[0].trace; - if(Plots.traceIs(trace, 'pie')) { + if(Registry.traceIs(trace, 'pie')) { return hiddenSlices.indexOf(d[0].label) !== -1 ? 0.5 : 1; } else { return trace.visible === 'legendonly' ? 0.5 : 1; @@ -337,7 +338,7 @@ function drawTexts(g, gd) { var legendItem = g.data()[0][0], fullLayout = gd._fullLayout, trace = legendItem.trace, - isPie = Plots.traceIs(trace, 'pie'), + isPie = Registry.traceIs(trace, 'pie'), traceIndex = trace.index, name = isPie ? legendItem.label : trace.name; @@ -400,7 +401,7 @@ function setupTraceToggle(g, gd) { tracei, newVisible; - if(Plots.traceIs(trace, 'pie')) { + if(Registry.traceIs(trace, 'pie')) { var thisLabel = legendItem.label, thisLabelIndex = hiddenSlices.indexOf(thisLabel); diff --git a/src/components/legend/get_legend_data.js b/src/components/legend/get_legend_data.js index a8ca0748c07..6fe7164cc2e 100644 --- a/src/components/legend/get_legend_data.js +++ b/src/components/legend/get_legend_data.js @@ -9,8 +9,7 @@ 'use strict'; -var Plots = require('../../plots/plots'); - +var Registry = require('../../registry'); var helpers = require('./helpers'); @@ -49,7 +48,7 @@ module.exports = function getLegendData(calcdata, opts) { if(!helpers.legendGetsTrace(trace) || !trace.showlegend) continue; - if(Plots.traceIs(trace, 'pie')) { + if(Registry.traceIs(trace, 'pie')) { if(!slicesShown[lgroup]) slicesShown[lgroup] = {}; for(j = 0; j < cd.length; j++) { diff --git a/src/components/legend/helpers.js b/src/components/legend/helpers.js index 5a481fca152..2c4813a05de 100644 --- a/src/components/legend/helpers.js +++ b/src/components/legend/helpers.js @@ -9,11 +9,11 @@ 'use strict'; -var Plots = require('../../plots/plots'); +var Registry = require('../../registry'); exports.legendGetsTrace = function legendGetsTrace(trace) { - return trace.visible && Plots.traceIs(trace, 'showLegend'); + return trace.visible && Registry.traceIs(trace, 'showLegend'); }; exports.isGrouped = function isGrouped(legendLayout) { diff --git a/src/components/legend/style.js b/src/components/legend/style.js index d5299f24e63..83c6f65ce1e 100644 --- a/src/components/legend/style.js +++ b/src/components/legend/style.js @@ -11,8 +11,8 @@ var d3 = require('d3'); +var Registry = require('../../registry'); var Lib = require('../../lib'); -var Plots = require('../../plots/plots'); var Drawing = require('../drawing'); var Color = require('../color'); @@ -165,7 +165,7 @@ function styleBars(d) { markerLine = marker.line || {}, barpath = d3.select(this).select('g.legendpoints') .selectAll('path.legendbar') - .data(Plots.traceIs(trace, 'bar') ? [d] : []); + .data(Registry.traceIs(trace, 'bar') ? [d] : []); barpath.enter().append('path').classed('legendbar', true) .attr('d', 'M6,6H-6V-6H6Z') .attr('transform', 'translate(20,0)'); @@ -187,7 +187,7 @@ function styleBoxes(d) { var trace = d[0].trace, pts = d3.select(this).select('g.legendpoints') .selectAll('path.legendbox') - .data(Plots.traceIs(trace, 'box') && trace.visible ? [d] : []); + .data(Registry.traceIs(trace, 'box') && trace.visible ? [d] : []); pts.enter().append('path').classed('legendbox', true) // if we want the median bar, prepend M6,0H-6 .attr('d', 'M6,6H-6V-6H6Z') @@ -210,7 +210,7 @@ function stylePies(d) { var trace = d[0].trace, pts = d3.select(this).select('g.legendpoints') .selectAll('path.legendpie') - .data(Plots.traceIs(trace, 'pie') && trace.visible ? [d] : []); + .data(Registry.traceIs(trace, 'pie') && trace.visible ? [d] : []); pts.enter().append('path').classed('legendpie', true) .attr('d', 'M6,6H-6V-6H6Z') .attr('transform', 'translate(20,0)'); diff --git a/src/plot_api/plot_api.js b/src/plot_api/plot_api.js index b5646736fc8..a04001fde56 100644 --- a/src/plot_api/plot_api.js +++ b/src/plot_api/plot_api.js @@ -18,6 +18,7 @@ var Lib = require('../lib'); var Events = require('../lib/events'); var Queue = require('../lib/queue'); +var Registry = require('../registry'); var Plots = require('../plots/plots'); var Fx = require('../plots/cartesian/graph_interact'); var Polar = require('../plots/polar'); @@ -262,7 +263,7 @@ Plotly.plot = function(gd, data, layout, config) { isVisible = (trace.visible === true), uid = trace.uid; - if(!isVisible || !Plots.traceIs(trace, '2dMap')) { + if(!isVisible || !Registry.traceIs(trace, '2dMap')) { fullLayout._paper.selectAll( '.hm' + uid + ',.contour' + uid + @@ -705,7 +706,7 @@ function cleanData(data, existingData) { if(trace.error_y && 'opacity' in trace.error_y) { var dc = Color.defaults, yeColor = trace.error_y.color || - (Plots.traceIs(trace, 'bar') ? Color.defaultLine : dc[tracei % dc.length]); + (Registry.traceIs(trace, 'bar') ? Color.defaultLine : dc[tracei % dc.length]); trace.error_y.color = Color.addOpacity( Color.rgb(yeColor), Color.opacity(yeColor) * trace.error_y.opacity); @@ -715,7 +716,7 @@ function cleanData(data, existingData) { // convert bardir to orientation, and put the data into // the axes it's eventually going to be used with if('bardir' in trace) { - if(trace.bardir === 'h' && (Plots.traceIs(trace, 'bar') || + if(trace.bardir === 'h' && (Registry.traceIs(trace, 'bar') || trace.type.substr(0, 9) === 'histogram')) { trace.orientation = 'h'; swapXYData(trace); @@ -745,11 +746,11 @@ function cleanData(data, existingData) { if(trace.yaxis) trace.yaxis = Plotly.Axes.cleanId(trace.yaxis, 'y'); // scene ids scene1 -> scene - if(Plots.traceIs(trace, 'gl3d') && trace.scene) { + if(Registry.traceIs(trace, 'gl3d') && trace.scene) { trace.scene = Plots.subplotsRegistry.gl3d.cleanId(trace.scene); } - if(!Plots.traceIs(trace, 'pie')) { + if(!Registry.traceIs(trace, 'pie')) { if(Array.isArray(trace.textposition)) { trace.textposition = trace.textposition.map(cleanTextPosition); } @@ -759,11 +760,11 @@ function cleanData(data, existingData) { } // fix typo in colorscale definition - if(Plots.traceIs(trace, '2dMap')) { + if(Registry.traceIs(trace, '2dMap')) { if(trace.colorscale === 'YIGnBu') trace.colorscale = 'YlGnBu'; if(trace.colorscale === 'YIOrRd') trace.colorscale = 'YlOrRd'; } - if(Plots.traceIs(trace, 'markerColorscale') && trace.marker) { + if(Registry.traceIs(trace, 'markerColorscale') && trace.marker) { var cont = trace.marker; if(cont.colorscale === 'YIGnBu') cont.colorscale = 'YlGnBu'; if(cont.colorscale === 'YIOrRd') cont.colorscale = 'YlOrRd'; @@ -1607,7 +1608,7 @@ Plotly.restyle = function restyle(gd, astr, val, traces) { 'marker.line.showscale', 'marker.line.cauto', 'marker.line.autocolorscale', 'marker.line.reversescale' ]; for(i = 0; i < traces.length; i++) { - if(Plots.traceIs(gd._fullData[traces[i]], 'box')) { + if(Registry.traceIs(gd._fullData[traces[i]], 'box')) { recalcAttrs.push('name'); break; } @@ -1850,7 +1851,7 @@ Plotly.restyle = function restyle(gd, astr, val, traces) { // super kludgy - but if all pies are gone we won't remove them otherwise fullLayout._pielayer.selectAll('g.trace').remove(); - } else if(Plots.traceIs(cont, 'cartesian')) { + } else if(Registry.traceIs(cont, 'cartesian')) { Lib.nestedProperty(cont, 'marker.colors') .set(Lib.nestedProperty(cont, 'marker.color').get()); //look for axes that are no longer in use and delete them @@ -1926,7 +1927,7 @@ Plotly.restyle = function restyle(gd, astr, val, traces) { for(i = 0; i < traces.length; i++) { var trace = gd.data[traces[i]]; - if(Plots.traceIs(trace, 'cartesian')) { + if(Registry.traceIs(trace, 'cartesian')) { addToAxlist(trace.xaxis || 'x'); addToAxlist(trace.yaxis || 'y'); @@ -1954,7 +1955,7 @@ Plotly.restyle = function restyle(gd, astr, val, traces) { axLetter = axId.charAt(0), axAttr = axLetter + 'axis'; for(var j = 0; j < gd.data.length; j++) { - if(Plots.traceIs(gd.data[j], 'cartesian') && + if(Registry.traceIs(gd.data[j], 'cartesian') && (gd.data[j][axAttr] || axLetter) === axId) { continue axisLoop; } @@ -2017,7 +2018,7 @@ Plotly.restyle = function restyle(gd, astr, val, traces) { var trace = cd[0].trace, cb = cd[0].t.cb; - if(Plots.traceIs(trace, 'contour')) { + if(Registry.traceIs(trace, 'contour')) { cb.line({ width: trace.contours.showlines !== false ? trace.line.width : 0, @@ -2026,7 +2027,7 @@ Plotly.restyle = function restyle(gd, astr, val, traces) { cb._opts.line.color : trace.line.color }); } - if(Plots.traceIs(trace, 'markerColorscale')) { + if(Registry.traceIs(trace, 'markerColorscale')) { cb.options(trace.marker.colorbar)(); } else cb.options(trace.colorbar)(); diff --git a/src/plot_api/plot_schema.js b/src/plot_api/plot_schema.js index 43fe2293dd6..231b4ed4234 100644 --- a/src/plot_api/plot_schema.js +++ b/src/plot_api/plot_schema.js @@ -10,6 +10,7 @@ 'use strict'; var Plotly = require('../plotly'); +var Registry = require('../registry'); var Plots = require('../plots/plots'); var Lib = require('../lib'); @@ -41,13 +42,13 @@ var PlotSchema = module.exports = {}; PlotSchema.get = function() { - Plots.allTypes + Registry.allTypes .concat('area') // FIXME polar 'area' attributes .forEach(getTraceAttributes); getLayoutAttributes(); - Object.keys(Plots.transformsRegistry).forEach(getTransformAttributes); + Object.keys(Registry.transformsRegistry).forEach(getTransformAttributes); getDefs(); @@ -142,7 +143,7 @@ function getLayoutAttributes() { } function getTransformAttributes(name) { - var _module = Plots.transformsRegistry[name], + var _module = Registry.transformsRegistry[name], _schema = {}; _schema = coupleAttrs(_schema, _module.attributes || {}, 'attributes', '*'); @@ -248,10 +249,10 @@ function getModule(arg) { if('type' in arg) { return (arg.type === 'area') ? // FIXME { attributes: polarAreaAttrs } : - Plots.getModule({type: arg.type}); + Registry.getModule({type: arg.type}); } - var subplotsRegistry = Plots.subplotsRegistry, + var subplotsRegistry = Registry.subplotsRegistry, _module = arg.module; if(subplotsRegistry[_module]) return subplotsRegistry[_module]; @@ -268,7 +269,7 @@ function removeUnderscoreAttrs(attributes) { function getMeta(type) { if(type === 'area') return {}; // FIXME - return Plots.modules[type].meta || {}; + return Registry.modules[type].meta || {}; } function assignPolarLayoutAttrs(layoutAttributes) { @@ -285,9 +286,9 @@ function assignPolarLayoutAttrs(layoutAttributes) { function getSubplotRegistry(traceType) { if(traceType === 'area') return {}; // FIXME - var subplotsRegistry = Plots.subplotsRegistry, + var subplotsRegistry = Registry.subplotsRegistry, subplotType = Object.keys(subplotsRegistry).filter(function(subplotType) { - return Plots.traceIs({type: traceType}, subplotType); + return Registry.traceIs({type: traceType}, subplotType); })[0]; if(subplotType === undefined) return {}; @@ -296,7 +297,7 @@ function getSubplotRegistry(traceType) { } function handleSubplotObjs(layoutAttributes) { - var subplotsRegistry = Plots.subplotsRegistry; + var subplotsRegistry = Registry.subplotsRegistry; Object.keys(layoutAttributes).forEach(function(k) { Object.keys(subplotsRegistry).forEach(function(subplotType) { diff --git a/src/plots/cartesian/axes.js b/src/plots/cartesian/axes.js index d6ffb8cc97f..85ca6443b49 100644 --- a/src/plots/cartesian/axes.js +++ b/src/plots/cartesian/axes.js @@ -12,7 +12,7 @@ var d3 = require('d3'); var isNumeric = require('fast-isnumeric'); -var Plotly = require('../../plotly'); +var Registry = require('../../registry'); var Lib = require('../../lib'); var svgTextUtils = require('../../lib/svg_text_utils'); var Titles = require('../../components/titles'); @@ -1212,8 +1212,7 @@ axes.getSubplots = function(gd, ax) { var trace = data[i]; if(trace.visible === false || trace.visible === 'legendonly' || - !(Plotly.Plots.traceIs(trace, 'cartesian') || - Plotly.Plots.traceIs(trace, 'gl2d')) + !(Registry.traceIs(trace, 'cartesian') || Registry.traceIs(trace, 'gl2d')) ) continue; var xId = trace.xaxis || 'x', @@ -1762,7 +1761,7 @@ axes.doTicks = function(gd, axid, skipTitle) { function traceHasBarsOrFill(trace, subplot) { if(trace.visible !== true || trace.xaxis + trace.yaxis !== subplot) return false; - if(Plotly.Plots.traceIs(trace, 'bar') && trace.orientation === {x: 'h', y: 'v'}[axletter]) return true; + if(Registry.traceIs(trace, 'bar') && trace.orientation === {x: 'h', y: 'v'}[axletter]) return true; return trace.fill && trace.fill.charAt(trace.fill.length - 1) === axletter; } diff --git a/src/plots/cartesian/axis_defaults.js b/src/plots/cartesian/axis_defaults.js index 080e9eb9355..015ec9d7cd0 100644 --- a/src/plots/cartesian/axis_defaults.js +++ b/src/plots/cartesian/axis_defaults.js @@ -12,8 +12,8 @@ var isNumeric = require('fast-isnumeric'); var colorMix = require('tinycolor2').mix; +var Registry = require('../../registry'); var Lib = require('../../lib'); -var Plots = require('../plots'); var lightFraction = require('../../components/color/attributes').lightFraction; var layoutAttributes = require('./layout_attributes'); @@ -177,7 +177,7 @@ function setAutoType(ax, data) { for(var i = 0; i < data.length; i++) { trace = data[i]; - if(!Plots.traceIs(trace, 'box') || + if(!Registry.traceIs(trace, 'box') || (trace[axLetter + 'axis'] || axLetter) !== id) continue; if(trace[posLetter] !== undefined) boxPositions.push(trace[posLetter][0]); @@ -200,7 +200,7 @@ function isBoxWithoutPositionCoords(trace, axLetter) { var posLetter = getBoxPosLetter(trace); return ( - Plots.traceIs(trace, 'box') && + Registry.traceIs(trace, 'box') && axLetter === posLetter && trace[posLetter] === undefined && trace[posLetter + '0'] === undefined diff --git a/src/plots/cartesian/axis_ids.js b/src/plots/cartesian/axis_ids.js index 58d3a6330c1..2194cb93d7b 100644 --- a/src/plots/cartesian/axis_ids.js +++ b/src/plots/cartesian/axis_ids.js @@ -8,6 +8,7 @@ 'use strict'; +var Registry = require('../../registry'); var Plots = require('../plots'); var Lib = require('../../lib'); @@ -105,7 +106,7 @@ exports.getFromTrace = function(gd, fullTrace, type) { var fullLayout = gd._fullLayout; var ax = null; - if(Plots.traceIs(fullTrace, 'gl3d')) { + if(Registry.traceIs(fullTrace, 'gl3d')) { var scene = fullTrace.scene; if(scene.substr(0, 5) === 'scene') { ax = fullLayout[scene][type + 'axis']; diff --git a/src/plots/cartesian/layout_defaults.js b/src/plots/cartesian/layout_defaults.js index ac9647833bb..e7d5a5d559c 100644 --- a/src/plots/cartesian/layout_defaults.js +++ b/src/plots/cartesian/layout_defaults.js @@ -9,8 +9,8 @@ 'use strict'; +var Registry = require('../../registry'); var Lib = require('../../lib'); -var Plots = require('../plots'); var Color = require('../../components/color'); var basePlotLayoutAttributes = require('../layout_attributes'); @@ -39,11 +39,11 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) { var trace = fullData[i]; var listX, listY; - if(Plots.traceIs(trace, 'cartesian')) { + if(Registry.traceIs(trace, 'cartesian')) { listX = xaListCartesian; listY = yaListCartesian; } - else if(Plots.traceIs(trace, 'gl2d')) { + else if(Registry.traceIs(trace, 'gl2d')) { listX = xaListGl2d; listY = yaListGl2d; } @@ -57,12 +57,12 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) { if(yaName && listY.indexOf(yaName) === -1) listY.push(yaName); // check for default formatting tweaks - if(Plots.traceIs(trace, '2dMap')) { + if(Registry.traceIs(trace, '2dMap')) { outerTicks[xaName] = true; outerTicks[yaName] = true; } - if(Plots.traceIs(trace, 'oriented')) { + if(Registry.traceIs(trace, 'oriented')) { var positionAxis = trace.orientation === 'h' ? yaName : xaName; noGrids[positionAxis] = true; } @@ -96,7 +96,7 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) { // make sure that plots with orphan cartesian axes // are considered 'cartesian' if(xaListCartesian.length && yaListCartesian.length) { - Lib.pushUnique(layoutOut._basePlotModules, Plots.subplotsRegistry.cartesian); + Lib.pushUnique(layoutOut._basePlotModules, Registry.subplotsRegistry.cartesian); } function axSort(a, b) { diff --git a/src/traces/bar/layout_defaults.js b/src/traces/bar/layout_defaults.js index e26b5d2ffd1..8c6d6c3ff23 100644 --- a/src/traces/bar/layout_defaults.js +++ b/src/traces/bar/layout_defaults.js @@ -9,7 +9,7 @@ 'use strict'; -var Plots = require('../../plots/plots'); +var Registry = require('../../registry'); var Axes = require('../../plots/cartesian/axes'); var Lib = require('../../lib'); @@ -28,7 +28,7 @@ module.exports = function(layoutIn, layoutOut, fullData) { for(var i = 0; i < fullData.length; i++) { var trace = fullData[i]; - if(Plots.traceIs(trace, 'bar')) hasBars = true; + if(Registry.traceIs(trace, 'bar')) hasBars = true; else continue; // if we have at least 2 grouped bar traces on the same subplot, diff --git a/src/traces/bar/set_positions.js b/src/traces/bar/set_positions.js index 2a670a63536..b6d09a714a9 100644 --- a/src/traces/bar/set_positions.js +++ b/src/traces/bar/set_positions.js @@ -11,7 +11,7 @@ var isNumeric = require('fast-isnumeric'); -var Plots = require('../../plots/plots'); +var Registry = require('../../registry'); var Axes = require('../../plots/cartesian/axes'); var Lib = require('../../lib'); @@ -37,7 +37,7 @@ module.exports = function setPositions(gd, plotinfo) { gd._fullData.forEach(function(trace, i) { if(trace.visible === true && - Plots.traceIs(trace, 'bar') && + Registry.traceIs(trace, 'bar') && trace.orientation === dir && trace.xaxis === xa._id && trace.yaxis === ya._id) { diff --git a/src/traces/box/layout_defaults.js b/src/traces/box/layout_defaults.js index 18b2d1b0b0c..974d6f190dc 100644 --- a/src/traces/box/layout_defaults.js +++ b/src/traces/box/layout_defaults.js @@ -8,7 +8,7 @@ 'use strict'; -var Plots = require('../../plots/plots'); +var Registry = require('../../registry'); var Lib = require('../../lib'); var layoutAttributes = require('./layout_attributes'); @@ -19,7 +19,7 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) { var hasBoxes; for(var i = 0; i < fullData.length; i++) { - if(Plots.traceIs(fullData[i], 'box')) { + if(Registry.traceIs(fullData[i], 'box')) { hasBoxes = true; break; } diff --git a/src/traces/box/set_positions.js b/src/traces/box/set_positions.js index 1666b0450b4..cb803850add 100644 --- a/src/traces/box/set_positions.js +++ b/src/traces/box/set_positions.js @@ -8,7 +8,7 @@ 'use strict'; -var Plots = require('../../plots/plots'); +var Registry = require('../../registry'); var Axes = require('../../plots/cartesian/axes'); var Lib = require('../../lib'); @@ -40,7 +40,7 @@ module.exports = function setPositions(gd, plotinfo) { t = cd[0].t; trace = cd[0].trace; - if(trace.visible === true && Plots.traceIs(trace, 'box') && + if(trace.visible === true && Registry.traceIs(trace, 'box') && !t.emptybox && trace.orientation === orientation && trace.xaxis === xa._id && diff --git a/src/traces/heatmap/calc.js b/src/traces/heatmap/calc.js index 72a0dfb2033..f66ec004ffc 100644 --- a/src/traces/heatmap/calc.js +++ b/src/traces/heatmap/calc.js @@ -11,9 +11,9 @@ var isNumeric = require('fast-isnumeric'); +var Registry = require('../../registry'); var Lib = require('../../lib'); var Axes = require('../../plots/cartesian/axes'); -var Plots = require('../../plots/plots'); var histogram2dCalc = require('../histogram2d/calc'); var colorscaleCalc = require('../../components/colorscale/calc'); @@ -27,8 +27,8 @@ module.exports = function calc(gd, trace) { // run makeCalcdata on x and y even for heatmaps, in case of category mappings var xa = Axes.getFromId(gd, trace.xaxis || 'x'), ya = Axes.getFromId(gd, trace.yaxis || 'y'), - isContour = Plots.traceIs(trace, 'contour'), - isHist = Plots.traceIs(trace, 'histogram'), + isContour = Registry.traceIs(trace, 'contour'), + isHist = Registry.traceIs(trace, 'histogram'), zsmooth = isContour ? 'best' : trace.zsmooth, x, x0, @@ -166,9 +166,9 @@ function cleanZ(trace) { function makeBoundArray(trace, arrayIn, v0In, dvIn, numbricks, ax) { var arrayOut = [], - isContour = Plots.traceIs(trace, 'contour'), - isHist = Plots.traceIs(trace, 'histogram'), - isGL2D = Plots.traceIs(trace, 'gl2d'), + isContour = Registry.traceIs(trace, 'contour'), + isHist = Registry.traceIs(trace, 'histogram'), + isGL2D = Registry.traceIs(trace, 'gl2d'), v0, dv, i; diff --git a/src/traces/heatmap/plot.js b/src/traces/heatmap/plot.js index bc13f66d163..bbaf993b299 100644 --- a/src/traces/heatmap/plot.js +++ b/src/traces/heatmap/plot.js @@ -12,8 +12,8 @@ var d3 = require('d3'); var tinycolor = require('tinycolor2'); +var Registry = require('../../registry'); var Lib = require('../../lib'); -var Plots = require('../../plots/plots'); var getColorscale = require('../../components/colorscale/get_scale'); var xmlnsNamespaces = require('../../constants/xmlns_namespaces'); @@ -50,7 +50,7 @@ function plotOne(gd, plotinfo, cd) { scl = getColorscale(trace.colorscale), x = cd[0].x, y = cd[0].y, - isContour = Plots.traceIs(trace, 'contour'), + isContour = Registry.traceIs(trace, 'contour'), zsmooth = isContour ? 'best' : trace.zsmooth, // get z dims diff --git a/src/traces/pie/base_plot.js b/src/traces/pie/base_plot.js index c53f3e8ae8f..b4c24cb7701 100644 --- a/src/traces/pie/base_plot.js +++ b/src/traces/pie/base_plot.js @@ -8,13 +8,13 @@ 'use strict'; -var Plots = require('../../plots/plots'); +var Registry = require('../../registry'); exports.name = 'pie'; exports.plot = function(gd) { - var Pie = Plots.getModule('pie'); + var Pie = Registry.getModule('pie'); var cdPie = getCdModule(gd.calcdata, Pie); if(cdPie.length) Pie.plot(gd, cdPie); From 2382c0456574e624be620cde2eaadde971aa3b15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Wed, 10 Aug 2016 18:15:52 -0400 Subject: [PATCH 07/17] rm a few exported objects in src/plotly.js: by: - requiring svgTextUtils in plot_api.js - moving a injected modules in to src/core.js - requiring some module directly in src/core.js instead of through src/plotly.js --- src/core.js | 15 ++++++++++++--- src/plot_api/plot_api.js | 5 +++-- src/plotly.js | 16 ---------------- 3 files changed, 15 insertions(+), 21 deletions(-) diff --git a/src/core.js b/src/core.js index ce1a755eae3..5778237baef 100644 --- a/src/core.js +++ b/src/core.js @@ -17,6 +17,15 @@ var Plotly = require('./plotly'); // package version injected by `npm run preprocess` exports.version = '1.16.2'; +// inject promise polyfill +require('es6-promise').polyfill(); + +// inject plot css +require('../build/plotcss'); + +// inject default MathJax config +require('./fonts/mathjax_config'); + // plot api exports.plot = Plotly.plot; exports.newPlot = Plotly.newPlot; @@ -44,9 +53,9 @@ exports.Icons = require('../build/ploticon'); // unofficial 'beta' plot methods, use at your own risk exports.Plots = Plotly.Plots; exports.Fx = Plotly.Fx; -exports.Snapshot = Plotly.Snapshot; -exports.PlotSchema = Plotly.PlotSchema; -exports.Queue = Plotly.Queue; +exports.Snapshot = require('./snapshot'); +exports.PlotSchema = require('./plot_api/plot_schema'); +exports.Queue = require('./lib/queue'); // export d3 used in the bundle exports.d3 = require('d3'); diff --git a/src/plot_api/plot_api.js b/src/plot_api/plot_api.js index a04001fde56..e3f6d73c466 100644 --- a/src/plot_api/plot_api.js +++ b/src/plot_api/plot_api.js @@ -36,6 +36,7 @@ var Shapes = require('../components/shapes'); var Titles = require('../components/titles'); var ModeBar = require('../components/modebar'); var xmlnsNamespaces = require('../constants/xmlns_namespaces'); +var svgTextUtils = require('../lib/svg_text_utils'); /** @@ -453,7 +454,7 @@ function plotPolar(gd, data, layout) { var placeholderText = 'Click to enter title'; var titleLayout = function() { - this.call(Plotly.util.convertToTspans); + this.call(svgTextUtils.convertToTspans); //TODO: html/mathjax //TODO: center title }; @@ -479,7 +480,7 @@ function plotPolar(gd, data, layout) { } var setContenteditable = function() { - this.call(Plotly.util.makeEditable) + this.call(svgTextUtils.makeEditable) .on('edit', function(text) { gd.framework({layout: {title: text}}); this.attr({'data-unformatted': text}) diff --git a/src/plotly.js b/src/plotly.js index f7a2ac832fb..3f8cba139c0 100644 --- a/src/plotly.js +++ b/src/plotly.js @@ -18,19 +18,7 @@ * */ -// promise polyfill -require('es6-promise').polyfill(); - -// lib functions -exports.Lib = require('./lib'); -exports.util = require('./lib/svg_text_utils'); -exports.Queue = require('./lib/queue'); - -// plot css -require('../build/plotcss'); - // configuration -exports.MathJaxConfig = require('./fonts/mathjax_config'); exports.defaultConfig = require('./plot_api/plot_config'); // plots @@ -53,7 +41,3 @@ exports.ModeBar = require('./components/modebar'); // plot api require('./plot_api/plot_api'); -exports.PlotSchema = require('./plot_api/plot_schema'); - -// imaging routines -exports.Snapshot = require('./snapshot'); From 710f3122e1959028dc0f9a92d54b21bd432bfc6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Wed, 10 Aug 2016 18:16:17 -0400 Subject: [PATCH 08/17] rm circular dep in plot_image/to_image.js --- src/plot_api/to_image.js | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/plot_api/to_image.js b/src/plot_api/to_image.js index 5be7957a2c0..2f910af0b00 100644 --- a/src/plot_api/to_image.js +++ b/src/plot_api/to_image.js @@ -12,8 +12,11 @@ var isNumeric = require('fast-isnumeric'); var Plotly = require('../plotly'); var Lib = require('../lib'); -var Snapshot = require('../snapshot'); +var helpers = require('../snapshot/helpers'); +var clonePlot = require('../snapshot/cloneplot'); +var toSVG = require('../snapshot/tosvg'); +var svgToImg = require('../snapshot/svgtoimg'); /** * @param {object} gd figure Object @@ -48,7 +51,7 @@ function toImage(gd, opts) { } // first clone the GD so we can operate in a clean environment - var clone = Snapshot.clone(gd, {format: 'png', height: opts.height, width: opts.width}); + var clone = clonePlot(gd, {format: 'png', height: opts.height, width: opts.width}); var clonedGd = clone.td; // put the cloned div somewhere off screen before attaching to DOM @@ -57,16 +60,16 @@ function toImage(gd, opts) { document.body.appendChild(clonedGd); function wait() { - var delay = Snapshot.getDelay(clonedGd._fullLayout); + var delay = helpers.getDelay(clonedGd._fullLayout); return new Promise(function(resolve, reject) { setTimeout(function() { - var svg = Snapshot.toSVG(clonedGd); + var svg = toSVG(clonedGd); var canvas = document.createElement('canvas'); canvas.id = Lib.randstr(); - Snapshot.svgToImg({ + svgToImg({ format: opts.format, width: clonedGd._fullLayout.width, height: clonedGd._fullLayout.height, @@ -88,7 +91,7 @@ function toImage(gd, opts) { }); } - var redrawFunc = Snapshot.getRedrawFunc(clonedGd); + var redrawFunc = helpers.getRedrawFunc(clonedGd); Plotly.plot(clonedGd, clone.data, clone.layout, clone.config) .then(redrawFunc) From c6aa0fb7f1d749cb00b8667718049cfc04d470d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Thu, 11 Aug 2016 14:26:12 -0400 Subject: [PATCH 09/17] register: add support for component modules --- src/plot_api/register.js | 8 ++++++++ src/registry.js | 1 + 2 files changed, 9 insertions(+) diff --git a/src/plot_api/register.js b/src/plot_api/register.js index 94b29ae9cfb..4451bc17020 100644 --- a/src/plot_api/register.js +++ b/src/plot_api/register.js @@ -36,6 +36,10 @@ module.exports = function register(_modules) { registerTransformModule(newModule); break; + case 'component': + registerComponentModule(newModule); + break; + default: throw new Error('Invalid module was attempted to be registered!'); } @@ -69,3 +73,7 @@ function registerTransformModule(newModule) { Registry.transformsRegistry[newModule.name] = newModule; } + +function registerComponentModule(newModule) { + Registry.componentsRegistry[newModule.name] = newModule; +} diff --git a/src/registry.js b/src/registry.js index 73f511f38cb..f4ac1d43d40 100644 --- a/src/registry.js +++ b/src/registry.js @@ -17,6 +17,7 @@ exports.allTypes = []; exports.allCategories = {}; exports.subplotsRegistry = {}; exports.transformsRegistry = {}; +exports.componentsRegistry = {}; /** * register a module as the handler for a trace type From 68268e3e0ce4dec10400b4e03573edfd2613f0d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Thu, 11 Aug 2016 14:31:16 -0400 Subject: [PATCH 10/17] register components modules - legend, annotations, shapes, images, rangeslider, rangeselector and updatemenus are now registerd in src/core.js - add 'moduleType' and 'name' properties to component modules - rename 'attributes' prop -> 'layoutAttributes' (for consistency) - rename 'supplyLayoutDefaults' -> 'handleDefaults' when component defaults are required in another default module --- src/components/annotations/index.js | 3 +++ src/components/images/index.js | 2 ++ src/components/legend/index.js | 5 +++++ src/components/rangeselector/defaults.js | 2 +- src/components/rangeselector/index.js | 8 ++++++-- src/components/rangeslider/defaults.js | 2 +- src/components/rangeslider/index.js | 10 +++++++--- src/components/shapes/index.js | 3 +++ src/components/updatemenus/index.js | 4 ++++ src/core.js | 11 +++++++++++ test/jasmine/tests/range_selector_test.js | 8 ++++---- test/jasmine/tests/range_slider_test.js | 18 +++++++++--------- 12 files changed, 56 insertions(+), 20 deletions(-) diff --git a/src/components/annotations/index.js b/src/components/annotations/index.js index 0cbba50192a..ce239f1cdd7 100644 --- a/src/components/annotations/index.js +++ b/src/components/annotations/index.js @@ -11,6 +11,9 @@ var Plotly = require('../../plotly'); +exports.moduleType = 'component'; + +exports.name = 'annotations'; exports.ARROWPATHS = require('./arrow_paths'); diff --git a/src/components/images/index.js b/src/components/images/index.js index 227b2ee1b03..4d087e5ed36 100644 --- a/src/components/images/index.js +++ b/src/components/images/index.js @@ -15,6 +15,8 @@ var attributes = require('./attributes'); module.exports = { + moduleType: 'component', + name: 'images', draw: draw, layoutAttributes: attributes, supplyLayoutDefaults: supplyLayoutDefaults diff --git a/src/components/legend/index.js b/src/components/legend/index.js index 4b033d1bad9..6a9ba017e6c 100644 --- a/src/components/legend/index.js +++ b/src/components/legend/index.js @@ -12,6 +12,11 @@ var legend = module.exports = {}; + +legend.moduleType = 'component'; + +legend.name = 'legend'; + legend.layoutAttributes = require('./attributes'); legend.supplyLayoutDefaults = require('./defaults'); diff --git a/src/components/rangeselector/defaults.js b/src/components/rangeselector/defaults.js index fb486fdaa4c..762d2a6ecbb 100644 --- a/src/components/rangeselector/defaults.js +++ b/src/components/rangeselector/defaults.js @@ -16,7 +16,7 @@ var buttonAttrs = require('./button_attributes'); var constants = require('./constants'); -module.exports = function rangeSelectorDefaults(containerIn, containerOut, layout, counterAxes) { +module.exports = function handleDefaults(containerIn, containerOut, layout, counterAxes) { var selectorIn = containerIn.rangeselector || {}, selectorOut = containerOut.rangeselector = {}; diff --git a/src/components/rangeselector/index.js b/src/components/rangeselector/index.js index f9518eb46b1..c284f8cc251 100644 --- a/src/components/rangeselector/index.js +++ b/src/components/rangeselector/index.js @@ -9,8 +9,12 @@ 'use strict'; -exports.attributes = require('./attributes'); +exports.moduleType = 'component'; -exports.supplyLayoutDefaults = require('./defaults'); +exports.name = 'rangeselector'; + +exports.layoutAttributes = require('./attributes'); + +exports.handleDefaults = require('./defaults'); exports.draw = require('./draw'); diff --git a/src/components/rangeslider/defaults.js b/src/components/rangeslider/defaults.js index c06502b7068..936eb030680 100644 --- a/src/components/rangeslider/defaults.js +++ b/src/components/rangeslider/defaults.js @@ -12,7 +12,7 @@ var Lib = require('../../lib'); var attributes = require('./attributes'); -module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, axName, counterAxes) { +module.exports = function handleDefaults(layoutIn, layoutOut, axName, counterAxes) { if(!layoutIn[axName].rangeslider) return; var containerIn = Lib.isPlainObject(layoutIn[axName].rangeslider) ? diff --git a/src/components/rangeslider/index.js b/src/components/rangeslider/index.js index 26ef6b1d069..cfcf373ceb0 100644 --- a/src/components/rangeslider/index.js +++ b/src/components/rangeslider/index.js @@ -12,12 +12,16 @@ var Plots = require('../../plots/plots'); var createSlider = require('./create_slider'); -var supplyLayoutDefaults = require('./defaults'); +var layoutAttributes = require('./attributes'); +var handleDefaults = require('./defaults'); module.exports = { - draw: draw, - supplyLayoutDefaults: supplyLayoutDefaults + moduleType: 'component', + name: 'rangeslider', + layoutAttributes: layoutAttributes, + handleDefaults: handleDefaults, + draw: draw }; function draw(gd) { diff --git a/src/components/shapes/index.js b/src/components/shapes/index.js index 6afd6de5f95..d19fd283fba 100644 --- a/src/components/shapes/index.js +++ b/src/components/shapes/index.js @@ -9,6 +9,9 @@ 'use strict'; +exports.moduleType = 'component'; + +exports.name = 'shapes'; exports.layoutAttributes = require('./attributes'); diff --git a/src/components/updatemenus/index.js b/src/components/updatemenus/index.js index fc2bdc4436f..2efe17a714c 100644 --- a/src/components/updatemenus/index.js +++ b/src/components/updatemenus/index.js @@ -9,6 +9,10 @@ 'use strict'; +exports.moduleType = 'component'; + +exports.name = 'updatemenus'; + exports.layoutAttributes = require('./attributes'); exports.supplyLayoutDefaults = require('./defaults'); diff --git a/src/core.js b/src/core.js index 5778237baef..046e186e438 100644 --- a/src/core.js +++ b/src/core.js @@ -47,6 +47,17 @@ exports.validate = require('./plot_api/validate'); // scatter is the only trace included by default exports.register(require('./traces/scatter')); +// register all registrable components modules +exports.register([ + require('./components/legend'), + require('./components/annotations'), + require('./components/shapes'), + require('./components/images'), + require('./components/updatemenus'), + require('./components/rangeslider'), + require('./components/rangeselector') +]); + // plot icons exports.Icons = require('../build/ploticon'); diff --git a/test/jasmine/tests/range_selector_test.js b/test/jasmine/tests/range_selector_test.js index bfc17b46457..8672b92414e 100644 --- a/test/jasmine/tests/range_selector_test.js +++ b/test/jasmine/tests/range_selector_test.js @@ -14,7 +14,7 @@ var mouseEvent = require('../assets/mouse_event'); describe('range selector defaults:', function() { 'use strict'; - var supplyLayoutDefaults = RangeSelector.supplyLayoutDefaults; + var handleDefaults = RangeSelector.handleDefaults; function supply(containerIn, containerOut) { containerOut.domain = [0, 1]; @@ -25,7 +25,7 @@ describe('range selector defaults:', function() { var counterAxes = ['yaxis']; - supplyLayoutDefaults(containerIn, containerOut, layout, counterAxes); + handleDefaults(containerIn, containerOut, layout, counterAxes); } it('should set \'visible\' to false when no buttons are present', function() { @@ -139,7 +139,7 @@ describe('range selector defaults:', function() { }; var counterAxes = ['yaxis']; - supplyLayoutDefaults(containerIn, containerOut, layout, counterAxes); + handleDefaults(containerIn, containerOut, layout, counterAxes); expect(containerOut.rangeselector.x).toEqual(0); expect(containerOut.rangeselector.y).toBeCloseTo(0.47); @@ -170,7 +170,7 @@ describe('range selector defaults:', function() { }; var counterAxes = ['yaxis', 'yaxis2', 'yaxis3']; - supplyLayoutDefaults(containerIn, containerOut, layout, counterAxes); + handleDefaults(containerIn, containerOut, layout, counterAxes); expect(containerOut.rangeselector.x).toEqual(0.5); expect(containerOut.rangeselector.y).toBeCloseTo(0.87); diff --git a/test/jasmine/tests/range_slider_test.js b/test/jasmine/tests/range_slider_test.js index 2ca0ebe89c3..87ff2604b84 100644 --- a/test/jasmine/tests/range_slider_test.js +++ b/test/jasmine/tests/range_slider_test.js @@ -214,7 +214,7 @@ describe('the range slider', function() { }); }); - describe('supplyLayoutDefaults function', function() { + describe('handleDefaults function', function() { it('should not coerce anything if rangeslider isn\'t set', function() { var layoutIn = { xaxis: {}, yaxis: {}}, @@ -223,7 +223,7 @@ describe('the range slider', function() { counterAxes = ['yaxis'], expected = { xaxis: {}, yaxis: {}}; - RangeSlider.supplyLayoutDefaults(layoutIn, layoutOut, axName, counterAxes); + RangeSlider.handleDefaults(layoutIn, layoutOut, axName, counterAxes); expect(layoutIn).toEqual(expected); }); @@ -235,7 +235,7 @@ describe('the range slider', function() { counterAxes = ['yaxis'], expected = { xaxis: { rangeslider: { visible: true }}, yaxis: {}}; - RangeSlider.supplyLayoutDefaults(layoutIn, layoutOut, axName, counterAxes); + RangeSlider.handleDefaults(layoutIn, layoutOut, axName, counterAxes); expect(layoutIn).toEqual(expected); }); @@ -261,7 +261,7 @@ describe('the range slider', function() { } }; - RangeSlider.supplyLayoutDefaults(layoutIn, layoutOut, axName, counterAxes); + RangeSlider.handleDefaults(layoutIn, layoutOut, axName, counterAxes); expect(layoutOut).toEqual(expected); }); @@ -287,7 +287,7 @@ describe('the range slider', function() { } }; - RangeSlider.supplyLayoutDefaults(layoutIn, layoutOut, axName, counterAxes); + RangeSlider.handleDefaults(layoutIn, layoutOut, axName, counterAxes); expect(layoutOut).toEqual(expected); }); @@ -319,7 +319,7 @@ describe('the range slider', function() { } }; - RangeSlider.supplyLayoutDefaults(layoutIn, layoutOut, axName, counterAxes); + RangeSlider.handleDefaults(layoutIn, layoutOut, axName, counterAxes); expect(layoutOut).toEqual(expected); }); @@ -344,7 +344,7 @@ describe('the range slider', function() { yaxis2: { fixedrange: true } }; - RangeSlider.supplyLayoutDefaults(layoutIn, layoutOut, axName, counterAxes); + RangeSlider.handleDefaults(layoutIn, layoutOut, axName, counterAxes); expect(layoutOut).toEqual(expected); }); @@ -369,7 +369,7 @@ describe('the range slider', function() { yaxis: { fixedrange: true } }; - RangeSlider.supplyLayoutDefaults(layoutIn, layoutOut, axName, counterAxes); + RangeSlider.handleDefaults(layoutIn, layoutOut, axName, counterAxes); expect(layoutOut).toEqual(expected); }); @@ -394,7 +394,7 @@ describe('the range slider', function() { yaxis: { fixedrange: true } }; - RangeSlider.supplyLayoutDefaults(layoutIn, layoutOut, axName, counterAxes); + RangeSlider.handleDefaults(layoutIn, layoutOut, axName, counterAxes); expect(layoutOut).toEqual(expected); }); From 4f754aab88ff2e457cc0caabf6a0f54cea197c55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Thu, 11 Aug 2016 14:31:44 -0400 Subject: [PATCH 11/17] lib: add Lib.noop method --- src/lib/index.js | 3 +++ src/plots/gl3d/layout/axis_defaults.js | 3 +-- src/plots/gl3d/set_convert.js | 5 ++--- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/lib/index.js b/src/lib/index.js index e2b0a6f8f95..f4df4f7b4df 100644 --- a/src/lib/index.js +++ b/src/lib/index.js @@ -121,6 +121,9 @@ lib.bBoxIntersect = function(a, b, pad) { // minor convenience/performance booster for d3... lib.identity = function(d) { return d; }; +// minor convenience helper +lib.noop = function() {}; + // random string generator lib.randstr = function randstr(existing, bits, base) { /* diff --git a/src/plots/gl3d/layout/axis_defaults.js b/src/plots/gl3d/layout/axis_defaults.js index 8332efa8bd9..df6857ec47a 100644 --- a/src/plots/gl3d/layout/axis_defaults.js +++ b/src/plots/gl3d/layout/axis_defaults.js @@ -17,7 +17,6 @@ var layoutAttributes = require('./axis_attributes'); var handleAxisDefaults = require('../../cartesian/axis_defaults'); var axesNames = ['xaxis', 'yaxis', 'zaxis']; -var noop = function() {}; // TODO: hard-coded lightness fraction based on gridline default colors // that differ from other subplot types. @@ -53,7 +52,7 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, options) { coerce('gridcolor', colorMix(containerOut.color, options.bgColor, gridLightness).toRgbString()); coerce('title', axName[0]); // shouldn't this be on-par with 2D? - containerOut.setScale = noop; + containerOut.setScale = Lib.noop; if(coerce('showspikes')) { coerce('spikesides'); diff --git a/src/plots/gl3d/set_convert.js b/src/plots/gl3d/set_convert.js index c5dcddfe3ec..6e6fe8bb82b 100644 --- a/src/plots/gl3d/set_convert.js +++ b/src/plots/gl3d/set_convert.js @@ -9,12 +9,11 @@ 'use strict'; +var Lib = require('../../lib'); var Axes = require('../cartesian/axes'); -var noop = function() {}; - module.exports = function setConvert(containerOut) { Axes.setConvert(containerOut); - containerOut.setScale = noop; + containerOut.setScale = Lib.noop; }; From 0aa87c498d7b5538f3daaa276a6aaf2957c62b70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Thu, 11 Aug 2016 14:40:54 -0400 Subject: [PATCH 12/17] add Registry.getComponentMethod + use it in plot_api / plots --- src/plot_api/plot_api.js | 53 ++++++++++++++++++++-------------------- src/plots/plots.js | 20 +++++++-------- src/registry.js | 18 +++++++++++++- 3 files changed, 52 insertions(+), 39 deletions(-) diff --git a/src/plot_api/plot_api.js b/src/plot_api/plot_api.js index e3f6d73c466..3eefcf87982 100644 --- a/src/plot_api/plot_api.js +++ b/src/plot_api/plot_api.js @@ -26,13 +26,6 @@ var Polar = require('../plots/polar'); var Color = require('../components/color'); var Drawing = require('../components/drawing'); var ErrorBars = require('../components/errorbars'); -var Annotations = require('../components/annotations'); -var Images = require('../components/images'); -var Legend = require('../components/legend'); -var RangeSlider = require('../components/rangeslider'); -var RangeSelector = require('../components/rangeselector'); -var UpdateMenus = require('../components/updatemenus'); -var Shapes = require('../components/shapes'); var Titles = require('../components/titles'); var ModeBar = require('../components/modebar'); var xmlnsNamespaces = require('../constants/xmlns_namespaces'); @@ -183,9 +176,9 @@ Plotly.plot = function(gd, data, layout, config) { var calcdata = gd.calcdata; var i, cd, trace; - Legend.draw(gd); - RangeSelector.draw(gd); - UpdateMenus.draw(gd); + Registry.getComponentMethod('legend', 'draw')(gd); + Registry.getComponentMethod('rangeselector', 'draw')(gd); + Registry.getComponentMethod('updatemenus', 'draw')(gd); for(i = 0; i < calcdata.length; i++) { cd = calcdata[i]; @@ -234,8 +227,8 @@ Plotly.plot = function(gd, data, layout, config) { // TODO: autosize extra for text markers return Lib.syncOrAsync([ - Shapes.calcAutorange, - Annotations.calcAutorange, + Registry.getComponentMethod('shapes', 'calcAutorange'), + Registry.getComponentMethod('annotations', 'calcAutorange'), doAutoRange ], gd); } @@ -287,8 +280,8 @@ Plotly.plot = function(gd, data, layout, config) { Plots.style(gd); // show annotations and shapes - Shapes.draw(gd); - Annotations.draw(gd); + Registry.getComponentMethod('shapes', 'draw')(gd); + Registry.getComponentMethod('annoations', 'draw')(gd); // source links Plots.addLinks(gd); @@ -303,13 +296,13 @@ Plotly.plot = function(gd, data, layout, config) { // correctly sized and the whole plot re-margined. gd._replotting must // be set to false before these will work properly. function finalDraw() { - Shapes.draw(gd); - Images.draw(gd); - Annotations.draw(gd); - Legend.draw(gd); - RangeSlider.draw(gd); - RangeSelector.draw(gd); - UpdateMenus.draw(gd); + Registry.getComponentMethod('shapes', 'draw')(gd); + Registry.getComponentMethod('images', 'draw')(gd); + Registry.getComponentMethod('annotations', 'draw')(gd); + Registry.getComponentMethod('legend', 'draw')(gd); + Registry.getComponentMethod('rangeslider', 'draw')(gd); + Registry.getComponentMethod('rangeselector', 'draw')(gd); + Registry.getComponentMethod('updatemenus', 'draw')(gd); } function cleanUp() { @@ -2007,8 +2000,10 @@ Plotly.restyle = function restyle(gd, astr, val, traces) { arraysToCalcdata = (((cdi[0] || {}).trace || {})._module || {}).arraysToCalcdata; if(arraysToCalcdata) arraysToCalcdata(cdi); } + Plots.style(gd); - Legend.draw(gd); + Registry.getComponentMethod('legend', 'draw')(gd); + return Plots.previousPromises(gd); }); } @@ -2285,8 +2280,8 @@ Plotly.relayout = function relayout(gd, astr, val) { var objNum = p.parts[1], objType = p.parts[0], objList = layout[objType] || [], - objModule = Plotly[Lib.titleCase(objType)], obji = objList[objNum] || {}; + // if p.parts is just an annotation number, and val is either // 'add' or an entire annotation to add, the undo is 'remove' // if val is 'remove' then undo is the whole annotation object @@ -2303,21 +2298,25 @@ Plotly.relayout = function relayout(gd, astr, val) { } else Lib.log('???', aobj); } + if((refAutorange(obji, 'x') || refAutorange(obji, 'y')) && !Lib.containsAny(ai, ['color', 'opacity', 'align', 'dash'])) { docalc = true; } + // TODO: combine all edits to a given annotation / shape into one call // as it is we get separate calls for x and y (or ax and ay) on move - objModule.drawOne(gd, objNum, p.parts.slice(2).join('.'), aobj[ai]); + + var drawOne = Registry.getComponentMethod(objType, 'drawOne'); + drawOne(gd, objNum, p.parts.slice(2).join('.'), aobj[ai]); delete aobj[ai]; } else if(p.parts[0] === 'images') { var update = Lib.objectFromPath(ai, vi); Lib.extendDeepAll(gd.layout, update); - Images.supplyLayoutDefaults(gd.layout, gd._fullLayout); - Images.draw(gd); + Registry.getComponentMethod('images', 'supplyLayoutDefaults')(gd.layout, gd._fullLayout); + Registry.getComponentMethod('images', 'draw')(gd); } else if(p.parts[0] === 'mapbox' && p.parts[1] === 'layers') { Lib.extendDeepAll(gd.layout, Lib.objectFromPath(ai, vi)); @@ -2429,7 +2428,7 @@ Plotly.relayout = function relayout(gd, astr, val) { if(dolegend) { seq.push(function doLegend() { - Legend.draw(gd); + Registry.getComponentMethod('legend', 'draw')(gd); return Plots.previousPromises(gd); }); } diff --git a/src/plots/plots.js b/src/plots/plots.js index b638df76dc7..65ecec5e10c 100644 --- a/src/plots/plots.js +++ b/src/plots/plots.js @@ -163,8 +163,8 @@ plots.redrawText = function(gd) { return new Promise(function(resolve) { setTimeout(function() { - Plotly.Annotations.draw(gd); - Plotly.Legend.draw(gd); + Registry.getComponentMethod('annotations', 'draw')(gd); + Registry.getComponentMethod('legend', 'draw')(gd); (gd.calcdata || []).forEach(function(d) { if(d[0] && d[0].t && d[0].t.cb) d[0].t.cb(); @@ -763,17 +763,15 @@ plots.supplyLayoutModuleDefaults = function(layoutIn, layoutOut, fullData) { } } - // TODO register these - // Legend must come after traces (e.g. it depends on 'barmode') - var moduleLayoutDefaults = [ - 'Fx', 'Annotations', 'Shapes', 'Legend', 'Images', 'UpdateMenus' - ]; + // should FX be a component? + Plotly.Fx.supplyLayoutDefaults(layoutIn, layoutOut, fullData); - for(i = 0; i < moduleLayoutDefaults.length; i++) { - _module = moduleLayoutDefaults[i]; + var components = Object.keys(Registry.componentsRegistry); + for(i = 0; i < components.length; i++) { + _module = Registry.componentsRegistry[components[i]]; - if(Plotly[_module]) { - Plotly[_module].supplyLayoutDefaults(layoutIn, layoutOut, fullData); + if(_module.supplyLayoutDefaults) { + _module.supplyLayoutDefaults(layoutIn, layoutOut, fullData); } } }; diff --git a/src/registry.js b/src/registry.js index f4ac1d43d40..0e430e5a63b 100644 --- a/src/registry.js +++ b/src/registry.js @@ -122,7 +122,7 @@ exports.traceIs = function(traceType, category) { var _module = exports.modules[traceType]; if(!_module) { - if(traceType !== undefined) { + if(traceType && traceType !== 'area') { Lib.log('Unrecognized trace type ' + traceType + '.'); } @@ -132,6 +132,22 @@ exports.traceIs = function(traceType, category) { return !!_module.categories[category]; }; +/** + * Retrieve component module method + * + * @param {string} name + * name of component (as declared in component module) + * @param {string} method + * name of component module method + * @return {function} + */ +exports.getComponentMethod = function(name, method) { + var _module = exports.componentsRegistry[name]; + + if(!_module) return Lib.noop; + return _module[method]; +}; + function getTraceType(traceType) { if(typeof traceType === 'object') traceType = traceType.type; return traceType; From 65ffb525e123aca1a91b70fc53397fcd5b207643 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Thu, 11 Aug 2016 14:42:40 -0400 Subject: [PATCH 13/17] require only range slider/selector default handlers cartesian defaults - so that they are called only when the range slider/selector components are registered --- src/plots/cartesian/layout_defaults.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/plots/cartesian/layout_defaults.js b/src/plots/cartesian/layout_defaults.js index e7d5a5d559c..a3078d94897 100644 --- a/src/plots/cartesian/layout_defaults.js +++ b/src/plots/cartesian/layout_defaults.js @@ -14,9 +14,6 @@ var Lib = require('../../lib'); var Color = require('../../components/color'); var basePlotLayoutAttributes = require('../layout_attributes'); -var RangeSlider = require('../../components/rangeslider'); -var RangeSelector = require('../../components/rangeselector'); - var constants = require('./constants'); var layoutAttributes = require('./layout_attributes'); var handleAxisDefaults = require('./axis_defaults'); @@ -157,16 +154,19 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) { }); // quick second pass for range slider and selector defaults + var rangeSliderDefaults = Registry.getComponentMethod('rangeslider', 'handleDefaults'), + rangeSelectorDefaults = Registry.getComponentMethod('rangeselector', 'handleDefaults'); + axesList.forEach(function(axName) { var axLetter = axName.charAt(0), axLayoutIn = layoutIn[axName], axLayoutOut = layoutOut[axName], counterAxes = {x: yaList, y: xaList}[axLetter]; - RangeSlider.supplyLayoutDefaults(layoutIn, layoutOut, axName, counterAxes); + rangeSliderDefaults(layoutIn, layoutOut, axName, counterAxes); if(axLetter === 'x' && axLayoutOut.type === 'date') { - RangeSelector.supplyLayoutDefaults(axLayoutIn, axLayoutOut, layoutOut, counterAxes); + rangeSelectorDefaults(axLayoutIn, axLayoutOut, layoutOut, counterAxes); } }); }; From d11c8f912833887b0a34d93515fbc27deb56e433 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Thu, 11 Aug 2016 14:43:29 -0400 Subject: [PATCH 14/17] lint plot_schema.js --- src/plot_api/plot_schema.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/plot_api/plot_schema.js b/src/plot_api/plot_schema.js index 231b4ed4234..1c77a1d3c3d 100644 --- a/src/plot_api/plot_schema.js +++ b/src/plot_api/plot_schema.js @@ -14,6 +14,10 @@ var Registry = require('../registry'); var Plots = require('../plots/plots'); var Lib = require('../lib'); +// FIXME polar attribute are not part of Plotly yet +var polarAreaAttrs = require('../plots/polar/area_attributes'); +var polarAxisAttrs = require('../plots/polar/axis_attributes'); + var extendFlat = Lib.extendFlat; var extendDeep = Lib.extendDeep; var extendDeepAll = Lib.extendDeepAll; @@ -34,9 +38,6 @@ var plotSchema = { defs: {} }; -// FIXME polar attribute are not part of Plotly yet -var polarAreaAttrs = require('../plots/polar/area_attributes'), - polarAxisAttrs = require('../plots/polar/axis_attributes'); var PlotSchema = module.exports = {}; @@ -169,7 +170,7 @@ function coupleAttrs(attrsIn, attrsOut, whichAttrs, type) { if(k === NESTED_MODULE) { Object.keys(attrsIn[k]).forEach(function(kk) { - nestedModule = getModule({module: attrsIn[k][kk]}); + nestedModule = getModule({_module: attrsIn[k][kk]}); if(nestedModule === undefined) return; nestedAttrs = nestedModule[whichAttrs]; @@ -187,7 +188,7 @@ function coupleAttrs(attrsIn, attrsOut, whichAttrs, type) { Object.keys(attrsIn[k]).forEach(function(kk) { if(kk !== type) return; - composedModule = getModule({module: attrsIn[k][kk]}); + composedModule = getModule({_module: attrsIn[k][kk]}); if(composedModule === undefined) return; composedAttrs = composedModule[whichAttrs]; @@ -253,7 +254,8 @@ function getModule(arg) { } var subplotsRegistry = Registry.subplotsRegistry, - _module = arg.module; + componentsRegistry = Registry.componentsRegistry, + _module = arg._module; if(subplotsRegistry[_module]) return subplotsRegistry[_module]; else if('module' in arg) return Plotly[_module]; From a1ea3658de01e04795ef3497f05325b97e907bd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Thu, 11 Aug 2016 14:43:50 -0400 Subject: [PATCH 15/17] use componentsRegistry in plot schema --- src/plot_api/plot_schema.js | 5 ++++- src/plots/cartesian/layout_attributes.js | 9 ++++----- src/plots/layout_attributes.js | 14 +++++++------- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/plot_api/plot_schema.js b/src/plot_api/plot_schema.js index 1c77a1d3c3d..7a6ca5030b1 100644 --- a/src/plot_api/plot_schema.js +++ b/src/plot_api/plot_schema.js @@ -258,7 +258,10 @@ function getModule(arg) { _module = arg._module; if(subplotsRegistry[_module]) return subplotsRegistry[_module]; - else if('module' in arg) return Plotly[_module]; + else if(componentsRegistry[_module]) return componentsRegistry[_module]; + + // look it internal Plotly if all previous attempts fail + return Plotly[_module]; } function removeUnderscoreAttrs(attributes) { diff --git a/src/plots/cartesian/layout_attributes.js b/src/plots/cartesian/layout_attributes.js index b4c4d134bc3..126c3a437f2 100644 --- a/src/plots/cartesian/layout_attributes.js +++ b/src/plots/cartesian/layout_attributes.js @@ -11,8 +11,6 @@ var fontAttrs = require('../font_attributes'); var colorAttrs = require('../../components/color/attributes'); var extendFlat = require('../../lib/extend').extendFlat; -var rangeSliderAttrs = require('../../components/rangeslider/attributes'); -var rangeSelectorAttrs = require('../../components/rangeselector/attributes'); var constants = require('./constants'); @@ -97,9 +95,6 @@ module.exports = { ].join(' ') }, - rangeslider: rangeSliderAttrs, - rangeselector: rangeSelectorAttrs, - fixedrange: { valType: 'boolean', dflt: false, @@ -498,6 +493,10 @@ module.exports = { ].join(' ') }, + _nestedModules: { + 'rangeslider': 'rangeslider', + 'rangeselector': 'rangeselector', + }, _deprecated: { autotick: { diff --git a/src/plots/layout_attributes.js b/src/plots/layout_attributes.js index 896e3a6649d..3aaba1ed04d 100644 --- a/src/plots/layout_attributes.js +++ b/src/plots/layout_attributes.js @@ -171,18 +171,18 @@ module.exports = { '*': 'Fx' }, - // TODO merge with moduleLayoutDefaults in plots.js _nestedModules: { 'xaxis': 'Axes', 'yaxis': 'Axes', 'scene': 'gl3d', 'geo': 'geo', - 'legend': 'Legend', - 'annotations': 'Annotations', - 'shapes': 'Shapes', - 'images': 'Images', - 'updatemenus': 'UpdateMenus', 'ternary': 'ternary', - 'mapbox': 'mapbox' + 'mapbox': 'mapbox', + + 'legend': 'legend', + 'annotations': 'annotations', + 'shapes': 'shapes', + 'images': 'images', + 'updatemenus': 'updatemenus' } }; From 39c32d00f5d72c067f65b8d7114c6d650c355d9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Thu, 18 Aug 2016 17:29:24 -0400 Subject: [PATCH 16/17] doc: improve comment about trace type 'various' --- src/registry.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/registry.js b/src/registry.js index 0e430e5a63b..4b59b261581 100644 --- a/src/registry.js +++ b/src/registry.js @@ -117,7 +117,8 @@ exports.getModule = function(trace) { exports.traceIs = function(traceType, category) { traceType = getTraceType(traceType); - if(traceType === 'various') return false; // FIXME + // old plot.ly workspace hack, nothing to see here + if(traceType === 'various') return false; var _module = exports.modules[traceType]; From 489513bab64f4e6ac1afbcd9f9e510ca35d4d3be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Thu, 18 Aug 2016 17:29:44 -0400 Subject: [PATCH 17/17] plots: extend export obj with Registry instead of hard-coding --- src/plots/plots.js | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/plots/plots.js b/src/plots/plots.js index a8d0ddfe63b..107dc0b2655 100644 --- a/src/plots/plots.js +++ b/src/plots/plots.js @@ -19,14 +19,8 @@ var Color = require('../components/color'); var plots = module.exports = {}; -// Expose registry methods that used to be on Plots for backward-compatibility -plots.modules = Registry.modules; -plots.allTypes = Registry.allTypes; -plots.allCategories = Registry.allCategories; -plots.subplotsRegistry = Registry.subplotsRegistry; -plots.transformsRegistry = Registry.transformsRegistry; -plots.traceIs = Registry.traceIs; -plots.getModule = Registry.getModule; +// Expose registry methods on Plots for backward-compatibility +Lib.extendFlat(plots, Registry); plots.attributes = require('./attributes'); plots.attributes.type.values = plots.allTypes;