From 21271bdbc247b346d28ec4ca153965d561d4b9d9 Mon Sep 17 00:00:00 2001 From: Spencer Date: Fri, 4 Sep 2015 17:22:22 -0700 Subject: [PATCH 1/6] Update TODOs --- TODO.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/TODO.md b/TODO.md index 57f94f6..f1e9486 100644 --- a/TODO.md +++ b/TODO.md @@ -48,9 +48,9 @@ - [ ] Stacked Area - [X] Transition Enter State with Previous Scale - [X] How to handle Ordinal Scales where value didn't exist previously? (closest index?) -- [ ] Add Animation Easing Functions - - [ ] Basic Quad Easing - - [ ] Elastic Easing - - [ ] Linear Easing +- [X] Add Animation Easing Functions + - [X] Basic Quad Easing + - [X] Elastic Easing + - [X] Linear Easing - [ ] Auto Height/Width options for -- [ ] Canvas High DPI: http://www.html5rocks.com/en/tutorials/canvas/hidpi/ \ No newline at end of file +- [ ] Canvas High DPI: http://www.html5rocks.com/en/tutorials/canvas/hidpi/ From 0d43b30f3f992206b5352934d0fbac75ef107f2d Mon Sep 17 00:00:00 2001 From: Spencer Date: Fri, 4 Sep 2015 17:22:41 -0700 Subject: [PATCH 2/6] <3 Globals --- tests/dummy/app/routes/bubble-1.js | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/dummy/app/routes/bubble-1.js b/tests/dummy/app/routes/bubble-1.js index 0fca7c0..9876a5e 100644 --- a/tests/dummy/app/routes/bubble-1.js +++ b/tests/dummy/app/routes/bubble-1.js @@ -32,7 +32,6 @@ export default Ember.Route.extend({ return g(10); }, setupController(controller, model) { - window.c = this; controller.set('model', model); } }); From 462666b9c2bd453fdc72ec1c7ae1b6f5f0439a1c Mon Sep 17 00:00:00 2001 From: Spencer Date: Fri, 4 Sep 2015 17:23:57 -0700 Subject: [PATCH 3/6] Introduce e3-layout / e3-layout/identity --- addon/components/e3-layout.js | 72 +++++++++++++++++++ addon/components/e3-layout/identity.js | 30 ++++++++ app/components/e3-layout.js | 1 + app/components/e3-layout/identity.js | 1 + .../integration/components/e3-layout-test.js | 26 +++++++ .../components/e3-layout/identity-test.js | 26 +++++++ 6 files changed, 156 insertions(+) create mode 100644 addon/components/e3-layout.js create mode 100644 addon/components/e3-layout/identity.js create mode 100644 app/components/e3-layout.js create mode 100644 app/components/e3-layout/identity.js create mode 100644 tests/integration/components/e3-layout-test.js create mode 100644 tests/integration/components/e3-layout/identity-test.js diff --git a/addon/components/e3-layout.js b/addon/components/e3-layout.js new file mode 100644 index 0000000..ca12df2 --- /dev/null +++ b/addon/components/e3-layout.js @@ -0,0 +1,72 @@ +import Ember from 'ember'; +const {guidFor} = Ember; +let stop = 0; +let e3Layout = Ember.Component.extend({ + tagName: '', + + /* + At minimum, we should provide data array to a layout. + */ + attrs: { + data: null + }, + + /* + Any attributes changed; recalculate the layout. + */ + didUpdateAttrs() { + this.getAttr('_e3Context').updateMeta( + 'layouts', + this.getAttr('name'), + this._generateLayout() + ); + }, + + /* + Internal private hook to trigger the layout's implementation of the + using component's `generateLayout()` + */ + _generateLayout() { + let data = this.getData(); + return this.generateLayout(data); + }, + + /* + Hook to get the data that will be used to generate the layout. + */ + getData() { + return this.getAttr('data'); + }, + + /* + Generate item layout + */ + _generateItemLayout(data) { + return this.generateItemLayout(data); + }, + + /* + Actually generate the layout + */ + generateLayout(data) { + let guidMap = Object.create(null); + + // For each item, create a layout. + data.forEach(item => { + let guid = guidFor(item); + guidMap[guid] = this._generateItemLayout(item); + }); + + return function(item) { + return guidMap[guidFor(item)]; + }; + }, + + generateItemLayout(data) {} +}); + +e3Layout.reopenClass({ + positionalParams: ['_e3Context', 'name'] +}); + +export default e3Layout; diff --git a/addon/components/e3-layout/identity.js b/addon/components/e3-layout/identity.js new file mode 100644 index 0000000..5b0386b --- /dev/null +++ b/addon/components/e3-layout/identity.js @@ -0,0 +1,30 @@ +import Ember from 'ember'; +import layout from '../e3-layout'; + + +/* + This is more or less a utility layout that will take x & y scales and + create a layour for objects based on that layout. + */ +export default layout.extend({ + name: 'identity', + + attrs: { + x: null, + y: null + }, + + generateItemLayout(item) { + let xScale = this.getAttr('x'); + let yScale = this.getAttr('y'); + + if(!xScale || !yScale) { + return; + } + + return { + x: xScale(item), + y: yScale(item) + }; + } +}); diff --git a/app/components/e3-layout.js b/app/components/e3-layout.js new file mode 100644 index 0000000..7f2872b --- /dev/null +++ b/app/components/e3-layout.js @@ -0,0 +1 @@ +export { default } from 'ember-e3/components/e3-layout'; \ No newline at end of file diff --git a/app/components/e3-layout/identity.js b/app/components/e3-layout/identity.js new file mode 100644 index 0000000..7a19399 --- /dev/null +++ b/app/components/e3-layout/identity.js @@ -0,0 +1 @@ +export { default } from 'ember-e3/components/e3-layout/identity'; \ No newline at end of file diff --git a/tests/integration/components/e3-layout-test.js b/tests/integration/components/e3-layout-test.js new file mode 100644 index 0000000..799031b --- /dev/null +++ b/tests/integration/components/e3-layout-test.js @@ -0,0 +1,26 @@ +import { moduleForComponent, test } from 'ember-qunit'; +import hbs from 'htmlbars-inline-precompile'; + +moduleForComponent('e3-layout', 'Integration | Component | e3 layout', { + integration: true +}); + +test('it renders', function(assert) { + assert.expect(2); + + // Set any properties with this.set('myProperty', 'value'); + // Handle any actions with this.on('myAction', function(val) { ... }); + + this.render(hbs`{{e3-layout}}`); + + assert.equal(this.$().text().trim(), ''); + + // Template block usage: + this.render(hbs` + {{#e3-layout}} + template block text + {{/e3-layout}} + `); + + assert.equal(this.$().text().trim(), 'template block text'); +}); diff --git a/tests/integration/components/e3-layout/identity-test.js b/tests/integration/components/e3-layout/identity-test.js new file mode 100644 index 0000000..4fb87df --- /dev/null +++ b/tests/integration/components/e3-layout/identity-test.js @@ -0,0 +1,26 @@ +import { moduleForComponent, test } from 'ember-qunit'; +import hbs from 'htmlbars-inline-precompile'; + +moduleForComponent('e3-layout/identity', 'Integration | Component | e3 layout/identity', { + integration: true +}); + +test('it renders', function(assert) { + assert.expect(2); + + // Set any properties with this.set('myProperty', 'value'); + // Handle any actions with this.on('myAction', function(val) { ... }); + + this.render(hbs`{{e3-layout/identity}}`); + + assert.equal(this.$().text().trim(), ''); + + // Template block usage: + this.render(hbs` + {{#e3-layout/identity}} + template block text + {{/e3-layout/identity}} + `); + + assert.equal(this.$().text().trim(), 'template block text'); +}); From b2f286b2454ad12df3e820780edd1916116ffe48 Mon Sep 17 00:00:00 2001 From: Spencer Date: Fri, 4 Sep 2015 17:24:12 -0700 Subject: [PATCH 4/6] Add e3-bind-layout --- addon/helpers/e3-bind-layout.js | 26 +++++++++++++++++++++++ app/helpers/e3-bind-layout.js | 1 + tests/unit/helpers/e3-bind-layout-test.js | 10 +++++++++ 3 files changed, 37 insertions(+) create mode 100644 addon/helpers/e3-bind-layout.js create mode 100644 app/helpers/e3-bind-layout.js create mode 100644 tests/unit/helpers/e3-bind-layout-test.js diff --git a/addon/helpers/e3-bind-layout.js b/addon/helpers/e3-bind-layout.js new file mode 100644 index 0000000..c064d8e --- /dev/null +++ b/addon/helpers/e3-bind-layout.js @@ -0,0 +1,26 @@ +import Ember from 'ember'; + +/* + A layout is a function that takes a model as an input, and returns an object + that represents the position for that object. Most likey, the returned result + of the layout is something like + { + x: {INTEGER}, + y: {INTEGER} + } + */ +export function e3BindLayout(params/*, hash*/) { + let [layout, layoutProp] = params; + + if(layout) { + return function(data) { + let itemLayout = layout(data); + console.log(itemLayout); + if(itemLayout) { + return itemLayout[layoutProp]; + } + }; + } +} + +export default Ember.Helper.helper(e3BindLayout); diff --git a/app/helpers/e3-bind-layout.js b/app/helpers/e3-bind-layout.js new file mode 100644 index 0000000..c739da6 --- /dev/null +++ b/app/helpers/e3-bind-layout.js @@ -0,0 +1 @@ +export { default, e3BindLayout } from 'ember-e3/helpers/e3-bind-layout'; diff --git a/tests/unit/helpers/e3-bind-layout-test.js b/tests/unit/helpers/e3-bind-layout-test.js new file mode 100644 index 0000000..f14d144 --- /dev/null +++ b/tests/unit/helpers/e3-bind-layout-test.js @@ -0,0 +1,10 @@ +import { e3BindLayout } from '../../../helpers/e3-bind-layout'; +import { module, test } from 'qunit'; + +module('Unit | Helper | e3 bind layout'); + +// Replace this with your real tests. +test('it works', function(assert) { + var result = e3BindLayout(42); + assert.ok(result); +}); From 2561eb773c393f42bbf55a6b1b8c875396ed4964 Mon Sep 17 00:00:00 2001 From: Spencer Date: Fri, 4 Sep 2015 17:24:41 -0700 Subject: [PATCH 5/6] Add Layout Example This is going to end up being a "force direction" example...but just wanted to get a simple layout example working first. --- addon/utils/shadow/scales/ordinal.js | 4 +- tests/dummy/app/router.js | 1 + tests/dummy/app/routes/force-direction.js | 37 +++++++++++++++++++ tests/dummy/app/templates/force-direction.hbs | 28 ++++++++++++++ 4 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 tests/dummy/app/routes/force-direction.js create mode 100644 tests/dummy/app/templates/force-direction.hbs diff --git a/addon/utils/shadow/scales/ordinal.js b/addon/utils/shadow/scales/ordinal.js index 6ce2fc5..1e317cb 100644 --- a/addon/utils/shadow/scales/ordinal.js +++ b/addon/utils/shadow/scales/ordinal.js @@ -48,7 +48,7 @@ export default function shadowScalesOrdinal(range = [0,1], domain = [0,1], optio } // Create the lookup map. - let map = {}; + let map = Object.create(null); let stepSpacing = (spaceBetween / max(1, (bands - 1))); // Create a lookup in the map for each item in the domain. @@ -95,4 +95,4 @@ function calculateMissingPosition(lookedUpVal, domain, sort) { } return found; -} \ No newline at end of file +} diff --git a/tests/dummy/app/router.js b/tests/dummy/app/router.js index 593863c..4e1ca2a 100644 --- a/tests/dummy/app/router.js +++ b/tests/dummy/app/router.js @@ -16,6 +16,7 @@ Router.map(function() { this.route('grouped-bars'); this.route('invert'); this.route('nytimes-strikeouts'); + this.route('force-direction'); }); export default Router; diff --git a/tests/dummy/app/routes/force-direction.js b/tests/dummy/app/routes/force-direction.js new file mode 100644 index 0000000..9876a5e --- /dev/null +++ b/tests/dummy/app/routes/force-direction.js @@ -0,0 +1,37 @@ +import Ember from 'ember'; +let ID = 0; +// TODO: Use faker or something here. +function g(number) { + let res = []; + while(--number >= 0) { + res.push(o()); + } + return res; +} + +function o() { + return { + id: ++ID, + value: Math.random() * 100, + temperature: Math.random() * 100 + }; +} + +export default Ember.Route.extend({ + actions: { + add() { + let model = this.controller.get('model'); + model.push(o()); + this.controller.set('model', model.slice(0)); + }, + clear() { + this.controller.set('model', []); + } + }, + model() { + return g(10); + }, + setupController(controller, model) { + controller.set('model', model); + } +}); diff --git a/tests/dummy/app/templates/force-direction.hbs b/tests/dummy/app/templates/force-direction.hbs new file mode 100644 index 0000000..79687f8 --- /dev/null +++ b/tests/dummy/app/templates/force-direction.hbs @@ -0,0 +1,28 @@ +

Force Direction (in progress)

+

+{{#e3-container type='svg' height=400 width=800 as |ctx meta|}} + + {{e3-scale/linear ctx 'x' + domain=(e3-extent model key='value' padding=0.2 min-delta=5) + range=ctx.horizontalRange + }} + {{e3-scale/linear ctx 'y' + domain=(e3-extent model key='temperature' padding=0.3 min-delta=5) + range=ctx.verticalRange + }} + + {{e3-layout/identity ctx 'identity' + data=model + x=(e3-bind-scale meta.scales.x 'value') + y=(e3-bind-scale meta.scales.y 'temperature') + }} + + + {{#each model as |data|}} + {{e3-shape/circle ctx + data=data + x=(e3-bind-layout meta.layouts.identity 'x') + y=(e3-bind-layout meta.layouts.identity 'y') + }} + {{/each}} +{{/e3-container}} From a2465fdbc05e0c1f593c5b255b80348e4983c930 Mon Sep 17 00:00:00 2001 From: Spencer Date: Fri, 4 Sep 2015 17:29:55 -0700 Subject: [PATCH 6/6] Pass Tests / Basic e3-bind-layout test --- addon/components/e3-layout.js | 4 ++-- addon/components/e3-layout/identity.js | 4 +--- addon/helpers/e3-bind-layout.js | 1 - tests/unit/helpers/e3-bind-layout-test.js | 8 +++++++- 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/addon/components/e3-layout.js b/addon/components/e3-layout.js index ca12df2..cc92baa 100644 --- a/addon/components/e3-layout.js +++ b/addon/components/e3-layout.js @@ -1,6 +1,6 @@ import Ember from 'ember'; const {guidFor} = Ember; -let stop = 0; + let e3Layout = Ember.Component.extend({ tagName: '', @@ -62,7 +62,7 @@ let e3Layout = Ember.Component.extend({ }; }, - generateItemLayout(data) {} + generateItemLayout(/*data*/) {} }); e3Layout.reopenClass({ diff --git a/addon/components/e3-layout/identity.js b/addon/components/e3-layout/identity.js index 5b0386b..e9aff51 100644 --- a/addon/components/e3-layout/identity.js +++ b/addon/components/e3-layout/identity.js @@ -1,10 +1,8 @@ -import Ember from 'ember'; import layout from '../e3-layout'; - /* This is more or less a utility layout that will take x & y scales and - create a layour for objects based on that layout. + create a layout for objects based on that layout. */ export default layout.extend({ name: 'identity', diff --git a/addon/helpers/e3-bind-layout.js b/addon/helpers/e3-bind-layout.js index c064d8e..b20eb28 100644 --- a/addon/helpers/e3-bind-layout.js +++ b/addon/helpers/e3-bind-layout.js @@ -15,7 +15,6 @@ export function e3BindLayout(params/*, hash*/) { if(layout) { return function(data) { let itemLayout = layout(data); - console.log(itemLayout); if(itemLayout) { return itemLayout[layoutProp]; } diff --git a/tests/unit/helpers/e3-bind-layout-test.js b/tests/unit/helpers/e3-bind-layout-test.js index f14d144..ae45ade 100644 --- a/tests/unit/helpers/e3-bind-layout-test.js +++ b/tests/unit/helpers/e3-bind-layout-test.js @@ -5,6 +5,12 @@ module('Unit | Helper | e3 bind layout'); // Replace this with your real tests. test('it works', function(assert) { - var result = e3BindLayout(42); + let lookup = {'1234': {x: 12}}; + let layout = function(data) { + return lookup[data.id]; + }; + + var result = e3BindLayout([layout, 'x']); assert.ok(result); + assert.equal(result({id: '1234'}), 12, 'the correct value is returned'); });