Skip to content

[WIP] Frame + Animate API #717

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 94 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
94 commits
Select commit Hold shift + click to select a range
f3fee88
Reuse SVG DOM elements for scatter traces
rreusser Jun 22, 2016
f50c295
Implement plotly .animate() and keyframe API
rreusser Jun 30, 2016
3054cb5
Reuse SVG DOM elements for scatter traces
rreusser Jun 22, 2016
fb04b65
Implement plotly .animate() and keyframe API
rreusser Jun 30, 2016
28be237
Merge branch 'merge-animate-api-take-3' into animate-api-take-3
rreusser Jul 5, 2016
3e18a98
Clean up frame API tests and corner cases
rreusser Jul 6, 2016
01b9287
Implement Lib.expandObjectPaths
rreusser Jul 6, 2016
42467ec
Frame merging logic
rreusser Jul 6, 2016
0542213
Clean up object identity sloppiness in frame computation
rreusser Jul 7, 2016
cdfec13
Remove dependence of frame logic on gd
rreusser Jul 7, 2016
c7be054
Really simple .animate function
rreusser Jul 7, 2016
e4363a2
Add .animate tests
rreusser Jul 7, 2016
2fd9c26
Start adding back transition behavior
rreusser Jul 7, 2016
b4a553b
Fix animation tests; lint
rreusser Jul 8, 2016
aec44c6
Animation cleanup
rreusser Jul 8, 2016
e031c27
Avoid transitioning axes if no change
rreusser Jul 8, 2016
bd949e6
Transfer animation code over to new PR
rreusser Jul 11, 2016
9132eb6
Fix bad json
rreusser Jul 11, 2016
a4e8282
Fix scatter line issue
rreusser Jul 12, 2016
86ca5d6
Expand the trace update to all interdependent traces #717
rreusser Jul 14, 2016
dd995a9
Fix lint issues
rreusser Jul 14, 2016
cef8bd5
Reorder path fill drawing
rreusser Jul 14, 2016
2fb95a7
Add config to disable line simplification
rreusser Jul 14, 2016
bf2aeec
Error bar styling tweaks
rreusser Jul 18, 2016
bf079e9
Cut losses; make error bars basically work
rreusser Jul 18, 2016
bb8893f
Merge remote-tracking branch 'upstream/master' into animate-api-take-3
rreusser Jul 21, 2016
8717877
Fix for issue 702.
nielsenb-jf Jul 12, 2016
d5a8834
Move injectStyles and helpers to lib/plotcss_utils
nielsenb-jf Jul 21, 2016
34b0ca3
Merge remote-tracking branch 'upstream/master' into animate-api-take-3
rreusser Jul 22, 2016
f218e09
Handle case where cssRules are undefined.
nielsenb-jf Jul 22, 2016
8f4e11e
clear promise queue on restyle and relayout (not after Plotly.plot)
etpinard Jul 25, 2016
30a3fbe
fix mapbox access token tests
etpinard Jul 25, 2016
c7a68e7
Merge remote-tracking branch 'upstream/master' into animate-api-take-3
rreusser Jul 25, 2016
e762bf4
Merge remote-tracking branch 'upstream/master' into animate-api-take-3
rreusser Jul 26, 2016
79e6e4b
Add 'in' to filter transform
rreusser Jul 26, 2016
feb7636
Clean up scatter trace lines
rreusser Jul 26, 2016
ff37557
Fix lint errors
rreusser Jul 26, 2016
1086023
Fix frame API tests and set queueLength as needed
rreusser Jul 26, 2016
977afdd
Add missing scattergeo attribute
rreusser Jul 27, 2016
246f815
Add missing scatterternay attribute
rreusser Jul 27, 2016
db8a1c5
Remove animation mock
rreusser Jul 27, 2016
bc7fe74
Catch degenerate trace-fill-linking case
rreusser Jul 27, 2016
48eec0c
Merge pull request #776 from plotly/mapbox-access-token-catches
etpinard Jul 28, 2016
85c2e20
Merge pull request #764 from nielsenb-jf/fix_child_window
etpinard Jul 28, 2016
6376166
lint: flatten range selector suite
etpinard Jul 28, 2016
10a655d
rangeselector: skip non-object buttons items
etpinard Jul 28, 2016
5904af2
Update README.md
etpinard Jul 28, 2016
c09cbb3
isPlainObject: by pass prototype check in nw.js environments
etpinard Jul 28, 2016
e1f6818
enfore isPlainObject in src files
etpinard Jul 28, 2016
9e2f251
HTML encode attributes in <tspan>s and <a>s
scjody Jul 29, 2016
4e2761c
Add tests of <tspan> generation
scjody Jul 29, 2016
763485c
Add test that relative links work
scjody Jul 29, 2016
8fc47ef
Merge pull request #791 from plotly/html-encode-attributes
scjody Jul 29, 2016
c9a6549
Merge pull request #792 from plotly/enforce-is-plain-object
etpinard Jul 29, 2016
2102d02
Merge branch 'master' into rangeselector-buttons
etpinard Jul 29, 2016
a992b59
Merge pull request #793 from plotly/rangeselector-buttons
etpinard Jul 29, 2016
0aab643
Reuse SVG DOM elements for scatter traces
rreusser Jul 29, 2016
d7e4e1a
Implement plotly .animate() and keyframe API
rreusser Jul 29, 2016
b39f221
Reuse SVG DOM elements for scatter traces
rreusser Jul 29, 2016
1767a73
Implement plotly .animate() and keyframe API
rreusser Jul 29, 2016
c2e1710
Clean up frame API tests and corner cases
rreusser Jul 6, 2016
9ea6850
Implement Lib.expandObjectPaths
rreusser Jul 6, 2016
bcb3ce2
Frame merging logic
rreusser Jul 6, 2016
78b37e2
Clean up object identity sloppiness in frame computation
rreusser Jul 7, 2016
57fe960
Remove dependence of frame logic on gd
rreusser Jul 7, 2016
f483788
Really simple .animate function
rreusser Jul 7, 2016
d2d7099
Add .animate tests
rreusser Jul 7, 2016
ea7c037
Start adding back transition behavior
rreusser Jul 7, 2016
9773720
Fix animation tests; lint
rreusser Jul 8, 2016
17529ab
Animation cleanup
rreusser Jul 8, 2016
9955625
Avoid transitioning axes if no change
rreusser Jul 8, 2016
93eeaa8
Transfer animation code over to new PR
rreusser Jul 11, 2016
9643811
Fix bad json
rreusser Jul 11, 2016
7e2e2d8
Fix scatter line issue
rreusser Jul 12, 2016
2cecc66
Expand the trace update to all interdependent traces #717
rreusser Jul 14, 2016
fd5a3bc
Fix lint issues
rreusser Jul 14, 2016
13053a3
Reorder path fill drawing
rreusser Jul 14, 2016
15b47f6
Add config to disable line simplification
rreusser Jul 14, 2016
e887faa
Error bar styling tweaks
rreusser Jul 18, 2016
f2ffa2a
Cut losses; make error bars basically work
rreusser Jul 18, 2016
2b0c537
Add 'in' to filter transform
rreusser Jul 26, 2016
fb87b42
Clean up scatter trace lines
rreusser Jul 29, 2016
8cf4395
Fix lint errors
rreusser Jul 26, 2016
99ee7d9
Fix frame API tests and set queueLength as needed
rreusser Jul 26, 2016
bcd2fbf
Add missing scattergeo attribute
rreusser Jul 27, 2016
7319c83
Add missing scatterternay attribute
rreusser Jul 27, 2016
248736e
Remove animation mock
rreusser Jul 27, 2016
6afc339
Catch degenerate trace-fill-linking case
rreusser Jul 27, 2016
6e426e7
Clean up scatter trace line enter/exit
rreusser Aug 1, 2016
0180730
Add dummy line attrs to scattergl/scatter3d
rreusser Aug 1, 2016
1166ac7
Merge branch 'animate-api-take-3' of github.com:plotly/plotly.js into…
rreusser Aug 1, 2016
3ee4bf5
Restore missing function
rreusser Aug 1, 2016
085203d
Fix lint issues
rreusser Aug 1, 2016
266f21a
Fix lint error for the last time
rreusser Aug 1, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 15 additions & 6 deletions src/lib/extend.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,19 @@ var isPlainObject = require('./is_plain_object.js');
var isArray = Array.isArray;

exports.extendFlat = function() {
return _extend(arguments, false, false);
return _extend(arguments, false, false, false);
};

exports.extendDeep = function() {
return _extend(arguments, true, false);
return _extend(arguments, true, false, false);
};

exports.extendDeepAll = function() {
return _extend(arguments, true, true);
return _extend(arguments, true, true, false);
};

exports.extendDeepNoArrays = function() {
return _extend(arguments, true, false, true);
};

/*
Expand All @@ -41,7 +45,7 @@ exports.extendDeepAll = function() {
* Warning: this might result in infinite loops.
*
*/
function _extend(inputs, isDeep, keepAllKeys) {
function _extend(inputs, isDeep, keepAllKeys, noArrayCopies) {
var target = inputs[0],
length = inputs.length;

Expand All @@ -54,8 +58,13 @@ function _extend(inputs, isDeep, keepAllKeys) {
src = target[key];
copy = input[key];

// Stop early and just transfer the array if array copies are disallowed:
if(noArrayCopies && isArray(copy)) {
target[key] = copy;
}

// recurse if we're merging plain objects or arrays
if(isDeep && copy && (isPlainObject(copy) || (copyIsArray = isArray(copy)))) {
else if(isDeep && copy && (isPlainObject(copy) || (copyIsArray = isArray(copy)))) {
if(copyIsArray) {
copyIsArray = false;
clone = src && isArray(src) ? src : [];
Expand All @@ -64,7 +73,7 @@ function _extend(inputs, isDeep, keepAllKeys) {
}

// never move original objects, clone them
target[key] = _extend([clone, copy], isDeep, keepAllKeys);
target[key] = _extend([clone, copy], isDeep, keepAllKeys, noArrayCopies);
}

// don't bring in undefined values, except for extendDeepAll
Expand Down
34 changes: 34 additions & 0 deletions src/lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ var extendModule = require('./extend');
lib.extendFlat = extendModule.extendFlat;
lib.extendDeep = extendModule.extendDeep;
lib.extendDeepAll = extendModule.extendDeepAll;
lib.extendDeepNoArrays = extendModule.extendDeepNoArrays;

var loggersModule = require('./loggers');
lib.log = loggersModule.log;
Expand Down Expand Up @@ -541,6 +542,39 @@ lib.objectFromPath = function(path, value) {

return obj;
};
/**
* Iterate through an object in-place, converting dotted properties to objects.
*
* @example
* lib.expandObjectPaths('nested.test[2].path', 'value');
* // returns { nested: { test: [null, null, { path: 'value' }]}
*
*/
// Store this to avoid recompiling regex on every prop since this may happen many
// many times for animations.
// TODO: Premature optimization? Remove?
var dottedPropertyRegex = /^([^\.]*)\../;

lib.expandObjectPaths = function(data) {
var match, key, prop, datum;
if(typeof data === 'object' && !Array.isArray(data)) {
for(key in data) {
if(data.hasOwnProperty(key)) {
if((match = key.match(dottedPropertyRegex))) {
datum = data[key];
prop = match[1];

delete data[key];

data[prop] = lib.extendDeepNoArrays(data[prop] || {}, lib.objectFromPath(key, lib.expandObjectPaths(datum))[prop]);
} else {
data[key] = lib.expandObjectPaths(data[key]);
}
}
}
}
return data;
};

/**
* Converts value to string separated by the provided separators.
Expand Down
2 changes: 1 addition & 1 deletion src/lib/merge_keyframes.js → src/lib/merge_frames.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ var extend = require('./extend');
*
* Returns: a third object with the merged content
*/
module.exports = function mergeKeyframes(target, source) {
module.exports = function mergeFrames(target, source) {
var result;

result = extend.extendDeep({}, target);
Expand Down
21 changes: 21 additions & 0 deletions test/jasmine/tests/extend_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ var extendModule = require('@src/lib/extend.js');
var extendFlat = extendModule.extendFlat;
var extendDeep = extendModule.extendDeep;
var extendDeepAll = extendModule.extendDeepAll;
var extendDeepNoArrays = extendModule.extendDeepNoArrays;

var str = 'me a test',
integer = 10,
Expand Down Expand Up @@ -418,3 +419,23 @@ describe('extendDeepAll', function() {
expect(ori.arr[2]).toBe(undefined);
});
});

describe('extendDeepNoArrays', function() {
'use strict';

it('does not copy arrays', function() {
var src = {foo: {bar: [1, 2, 3], baz: [5, 4, 3]}};
var tar = {foo: {bar: [4, 5, 6], bop: [8, 2, 1]}};
var ext = extendDeepNoArrays(tar, src);

expect(ext).not.toBe(src);
expect(ext).toBe(tar);

expect(ext.foo).not.toBe(src.foo);
expect(ext.foo).toBe(tar.foo);

expect(ext.foo.bar).toBe(src.foo.bar);
expect(ext.foo.baz).toBe(src.foo.baz);
expect(ext.foo.bop).toBe(tar.foo.bop);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fantastic 🎉

});
});
63 changes: 63 additions & 0 deletions test/jasmine/tests/lib_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,69 @@ describe('Test lib.js:', function() {
});
});

describe('expandObjectPaths', function() {
it('returns the original object', function() {
var x = {};
expect(Lib.expandObjectPaths(x)).toBe(x);
});

it('unpacks top-level paths', function() {
var input = {'marker.color': 'red', 'marker.size': [1, 2, 3]};
var expected = {marker: {color: 'red', size: [1, 2, 3]}};
expect(Lib.expandObjectPaths(input)).toEqual(expected);
});

it('unpacks recursively', function() {
var input = {'marker.color': {'red.certainty': 'definitely'}};
var expected = {marker: {color: {red: {certainty: 'definitely'}}}};
expect(Lib.expandObjectPaths(input)).toEqual(expected);
});

it('unpacks deep paths', function() {
var input = {'foo.bar.baz': 'red'};
var expected = {foo: {bar: {baz: 'red'}}};
expect(Lib.expandObjectPaths(input)).toEqual(expected);
});

it('unpacks non-top-level deep paths', function() {
var input = {color: {'foo.bar.baz': 'red'}};
var expected = {color: {foo: {bar: {baz: 'red'}}}};
expect(Lib.expandObjectPaths(input)).toEqual(expected);
});

it('merges dotted properties into objects', function() {
var input = {marker: {color: 'red'}, 'marker.size': 8};
var expected = {marker: {color: 'red', size: 8}};
expect(Lib.expandObjectPaths(input)).toEqual(expected);
});

it('merges objects into dotted properties', function() {
var input = {'marker.size': 8, marker: {color: 'red'}};
var expected = {marker: {color: 'red', size: 8}};
expect(Lib.expandObjectPaths(input)).toEqual(expected);
});

it('retains the identity of nested objects', function() {
var input = {marker: {size: 8}};
var origNested = input.marker;
var expanded = Lib.expandObjectPaths(input);
var newNested = expanded.marker;

expect(input).toBe(expanded);
expect(origNested).toBe(newNested);
});

it('retains the identity of nested arrays', function() {
var input = {'marker.size': [1, 2, 3]};
var origArray = input['marker.size'];
var expanded = Lib.expandObjectPaths(input);
var newArray = expanded.marker.size;

expect(input).toBe(expanded);
expect(origArray).toBe(newArray);
});
});

describe('coerce', function() {
var coerce = Lib.coerce,
out;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
var mergeKeyframes = require('@src/lib/merge_keyframes');
var mergeFrames = require('@src/lib/merge_frames');

describe('Test mergeKeyframes', function() {
describe('Test mergeFrames', function() {
'use strict';

it('returns a new object', function() {
var f1 = {};
var f2 = {};
var result = mergeKeyframes(f1, f2);
var result = mergeFrames(f1, f2);
expect(result).toEqual({});
expect(result).not.toBe(f1);
expect(result).not.toBe(f2);
Expand All @@ -15,15 +15,15 @@ describe('Test mergeKeyframes', function() {
it('overrides properties of target with those of source', function() {
var tar = {xaxis: {range: [0, 1]}};
var src = {xaxis: {range: [3, 4]}};
var out = mergeKeyframes(tar, src);
var out = mergeFrames(tar, src);

expect(out).toEqual({xaxis: {range: [3, 4]}});
});

it('merges dotted properties', function() {
var tar = {};
var src = {'xaxis.range': [0, 1]};
var out = mergeKeyframes(tar, src);
var out = mergeFrames(tar, src);

expect(out).toEqual({'xaxis.range': [0, 1]});
});
Expand All @@ -32,15 +32,15 @@ describe('Test mergeKeyframes', function() {
it('xaxis.range', function() {
var tar = {xaxis: {range: [0, 1]}};
var src = {'xaxis.range': [3, 4]};
var out = mergeKeyframes(tar, src);
var out = mergeFrames(tar, src);

expect(out).toEqual({xaxis: {range: [3, 4]}});
});

it('xaxis.range.0', function() {
var tar = {xaxis: {range: [0, 1]}};
var src = {'xaxis.range.0': 3};
var out = mergeKeyframes(tar, src);
var out = mergeFrames(tar, src);

expect(out).toEqual({xaxis: {range: [3, 1]}});
});
Expand Down