Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
10 changes: 5 additions & 5 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -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/
- [ ] Canvas High DPI: http://www.html5rocks.com/en/tutorials/canvas/hidpi/
72 changes: 72 additions & 0 deletions addon/components/e3-layout.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import Ember from 'ember';
const {guidFor} = Ember;

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;
28 changes: 28 additions & 0 deletions addon/components/e3-layout/identity.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import layout from '../e3-layout';

/*
This is more or less a utility layout that will take x & y scales and
create a layout 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)
};
}
});
25 changes: 25 additions & 0 deletions addon/helpers/e3-bind-layout.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
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);
if(itemLayout) {
return itemLayout[layoutProp];
}
};
}
}

export default Ember.Helper.helper(e3BindLayout);
4 changes: 2 additions & 2 deletions addon/utils/shadow/scales/ordinal.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -95,4 +95,4 @@ function calculateMissingPosition(lookedUpVal, domain, sort) {
}

return found;
}
}
1 change: 1 addition & 0 deletions app/components/e3-layout.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from 'ember-e3/components/e3-layout';
1 change: 1 addition & 0 deletions app/components/e3-layout/identity.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from 'ember-e3/components/e3-layout/identity';
1 change: 1 addition & 0 deletions app/helpers/e3-bind-layout.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default, e3BindLayout } from 'ember-e3/helpers/e3-bind-layout';
1 change: 1 addition & 0 deletions tests/dummy/app/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
1 change: 0 additions & 1 deletion tests/dummy/app/routes/bubble-1.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ export default Ember.Route.extend({
return g(10);
},
setupController(controller, model) {
window.c = this;
controller.set('model', model);
}
});
37 changes: 37 additions & 0 deletions tests/dummy/app/routes/force-direction.js
Original file line number Diff line number Diff line change
@@ -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() {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

not a huge fan of the function names o and g here...very non-descript

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);
}
});
28 changes: 28 additions & 0 deletions tests/dummy/app/templates/force-direction.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<h2 class="title">Force Direction (in progress)</h2>
<br><br>
{{#e3-container type='svg' height=400 width=800 as |ctx meta|}}
<metadata>
{{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')
}}
</metadata>

{{#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}}
26 changes: 26 additions & 0 deletions tests/integration/components/e3-layout-test.js
Original file line number Diff line number Diff line change
@@ -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');
});
26 changes: 26 additions & 0 deletions tests/integration/components/e3-layout/identity-test.js
Original file line number Diff line number Diff line change
@@ -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');
});
16 changes: 16 additions & 0 deletions tests/unit/helpers/e3-bind-layout-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
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) {
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');
});