Skip to content

Commit

Permalink
Adds liquid-wormhole
Browse files Browse the repository at this point in the history
  • Loading branch information
Christopher Garrett committed Mar 16, 2016
1 parent 8045533 commit 7510007
Show file tree
Hide file tree
Showing 26 changed files with 400 additions and 5 deletions.
Empty file removed addon/.gitkeep
Empty file.
9 changes: 9 additions & 0 deletions addon/components/liquid-append.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import Ember from 'ember';

export default Ember.Component.extend({
didInsertElement() {
const nodes = this.get('nodes');

this.$().append(nodes);
}
});
14 changes: 14 additions & 0 deletions addon/components/liquid-target-container.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import Ember from 'ember';
import layout from '../templates/components/liquid-target-container';

const { inject, computed } = Ember;
const { service } = inject;

export default Ember.Component.extend({
layout: layout,
classNames: ['liquid-target-container'],
classNameBindings: ['hasTargets'],

hasTargets: computed.bool('liquidTargetService.targets.length'),
liquidTargetService: service('liquid-target')
});
50 changes: 50 additions & 0 deletions addon/components/liquid-target.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import Ember from 'ember';
import layout from '../templates/components/liquid-target';

const { computed, inject } = Ember;
const { htmlSafe } = Ember.String;
const { service } = inject;

export default Ember.Component.extend({
layout: layout,
classNames: ['liquid-target'],
classNameBindings: ['contextClass'],
attributeBindings: ['style'],

firstTime: true,

liquidTargetService: service('liquidTarget'),

style: computed('index', function() {
return htmlSafe(`z-index: ${1000000 + this.get('index')}`);
}),

currentItem: computed('items.lastObject', function() {
return this.get('items.lastObject') || { emptyTether: true };
}),

actions: {
willTransition() {
this.set('target.isAnimating', true);
},

afterChildInsertion() {
const currentItem = this.get('currentItem');

if (currentItem.didAppendNodes) {
this.get('currentItem').didAppendNodes();
}
},

afterTransition() {
if (!this.firstTime && !this.isDestroyed) {
const contextClass = this.get('currentItem.targetClass');
this.set('contextClass', contextClass);
}

this.firstTime = false;
this.set('target.isAnimating', false);
this.get('liquidTargetService').didAnimate();
}
}
});
39 changes: 39 additions & 0 deletions addon/components/liquid-wormhole.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import Ember from 'ember';

const { computed, inject, observer } = Ember;

const { service } = inject;
const { alias } = computed;

export default Ember.Component.extend({
to: null,
classNames: ['liquid-wormhole-container'],

liquidTarget: alias('to'),
liquidTargetService: service('liquid-target'),

nodes: computed(function() {
if (this.element) {
return this.$().children();
}
}),

liquidTargetDidChange: observer('liquidTarget', function() {
this.get('liquidTargetService').removeItem(this._target, this);
this.get('liquidTargetService').appendItem(this._target, this);
}),

didInsertElement() {
this._target = this.get('liquidTarget');

this.get('liquidTargetService').appendItem(this._target, this);

this._super.apply(this, arguments);
},

willDestroyElement() {
this.get('liquidTargetService').removeItem(this._target, this);

this._super.apply(this, arguments);
}
});
13 changes: 13 additions & 0 deletions addon/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import Constraint from 'liquid-fire/constraint';

export function target(name) {
return new Constraint('parentElementClass', `${name}-liquid-target`);
}

export function onOpenWormhole() {
return new Constraint('newValue', ({ emptyTarget }) => !emptyTarget);
}

export function onCloseWormhole() {
return new Constraint('newValue', ({ emptyTarget }) => emptyTarget);
}
16 changes: 16 additions & 0 deletions addon/instance-initializers/liquid-target-container.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export function initialize(instance) {
let liquidTargetContainer;

if (instance.lookup) {
liquidTargetContainer = instance.lookup('component:liquid-target-container');
} else {
liquidTargetContainer = instance.container.lookup('component:liquid-target-container');
}

liquidTargetContainer.appendTo(instance.rootElement);
}

export default {
name: 'liquid-target-container',
initialize: initialize
};
77 changes: 77 additions & 0 deletions addon/services/liquid-target.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import Ember from 'ember';

const { computed } = Ember;

export default Ember.Service.extend({
targets: computed(() => Ember.A()),
queue: computed(() => Ember.A()),

appendItem(targetName, item) {
const targets = this.get('targets');
let target;

if (!(target = targets.findBy('name', targetName))) {
Ember.run(function() {
target = {
name: targetName,
items: Ember.A(),
class: `${targetName}-liquid-target`,
contextClass: item.get('targetClass'),
firstTime: true
};

targets.pushObject(target);
});
}

this.appendToQueue(target, 'pushObject', item);
},

removeItem(targetName, item) {
const targets = this.get('targets');
const target = targets.findBy('name', targetName);

this.appendToQueue(target, 'removeObject', item);
},

appendToQueue(target, method, item) {
this.get('queue').pushObject({ target, method, item });

if (!this.get('isAnimating')) {
this.flushQueue();
}
},

flushQueue() {
const queue = this.get('queue');

queue.forEach(({ target, method, item }) => {
target.items[method](item);
});

queue.clear();
},

didAnimate() {
if (this.get('queue.length')) {
this.flushQueue();
} else {
this.cleanTargets();
}
},

cleanTargets() {
const targets = this.get('targets');

if (targets) {
const targetsToRemove = targets.filter((target) => {
const firstTime = target.firstTime;
target.firstTime = false;

return !firstTime && !target.isAnimating && target.items.get('length') === 0;
});

targets.removeObjects(targetsToRemove);
}
}
});
15 changes: 15 additions & 0 deletions addon/styles/addon.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
.liquid-target-container {
position: absolute;
top: 0;
left: 0;
right: 0;
z-index: 9999;
}

.liquid-target {
position: relative;
}

.liquid-wormhole-container {
display: none;
}
15 changes: 15 additions & 0 deletions addon/templates/components/liquid-target-container.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{{#each liquidTargetService.targets as |target index|}}
{{#liquid-target
target=target
name=target.name
items=target.items
class=target.class
index=index
contextClass=target.contextClass

as |target|}}
{{#liquid-versions value=target.currentItem notify=target renderWhenFalse=true as |currentItem|}}
{{liquid-append nodes=currentItem.nodes}}
{{/liquid-versions}}
{{/liquid-target}}
{{/each}}
1 change: 1 addition & 0 deletions addon/templates/components/liquid-target.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{{yield this}}
Empty file removed app/.gitkeep
Empty file.
1 change: 1 addition & 0 deletions app/components/liquid-append.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from 'liquid-wormhole/components/liquid-append';
1 change: 1 addition & 0 deletions app/components/liquid-target-container.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from 'liquid-wormhole/components/liquid-target-container';
1 change: 1 addition & 0 deletions app/components/liquid-target.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from 'liquid-wormhole/components/liquid-target';
1 change: 1 addition & 0 deletions app/components/liquid-wormhole.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from 'liquid-wormhole/components/liquid-wormhole';
1 change: 1 addition & 0 deletions app/instance-initializers/liquid-target-container.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default, initialize } from 'liquid-wormhole/instance-initializers/liquid-target-container';
1 change: 1 addition & 0 deletions app/services/liquid-target.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from 'liquid-wormhole/services/liquid-target';
47 changes: 47 additions & 0 deletions app/transitions/fade-direction.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { isAnimating, finish, timeSpent, animate, stop } from 'liquid-fire';

export default function fade(dimension, direction, opts, offset=20) {
const oldParams = { opacity: 0 },
newParams = { opacity: [(opts.maxOpacity || 1), 0] },
fadingElement = findFadingElement(this);

let outOpts = opts,
firstStep;

if (dimension.toLowerCase() === 'x') {
oldParams.translateX = `${(direction * offset)}px`;
newParams.translateX = ['0px', `${(direction * offset)}px`];
} else {
oldParams.translateY = `${(direction * offset)}px`;
newParams.translateY = ['0px', `${(direction * offset)}px`];
}

if (fadingElement) {
// We still have some older version that is in the process of
// fading out, so out first step is waiting for it to finish.
firstStep = finish(fadingElement, 'fade-out');
} else {
if (isAnimating(this.oldElement, 'fade-in')) {
// if the previous view is partially faded in, scale its
// fade-out duration appropriately.
outOpts = { duration: timeSpent(this.oldElement, 'fade-in') };
}
stop(this.oldElement);
firstStep = animate(this.oldElement, oldParams, outOpts, 'fade-out');
}
return firstStep.then(() => {
return animate(this.newElement, newParams, opts, 'fade-in');
});
}

function findFadingElement(context) {
for (var i = 0; i < context.older.length; i++) {
var entry = context.older[i];
if (isAnimating(entry.element, 'fade-out')) {
return entry.element;
}
}
if (isAnimating(context.oldElement, 'fade-out')) {
return context.oldElement;
}
}
4 changes: 4 additions & 0 deletions app/transitions/fade-down.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import fadeDirection from './fade-direction';
export default function(opts={}) {
return fadeDirection.call(this, 'y', -1, opts, opts.offset);
}
4 changes: 4 additions & 0 deletions app/transitions/fade-left.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import fadeDirection from './fade-direction';
export default function(opts={}) {
return fadeDirection.call(this, 'x', -1, opts, opts.offset);
}
4 changes: 4 additions & 0 deletions app/transitions/fade-right.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import fadeDirection from './fade-direction';
export default function(opts={}) {
return fadeDirection.call(this, 'x', 1, opts, opts.offset);
}
4 changes: 4 additions & 0 deletions app/transitions/fade-up.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import fadeDirection from './fade-direction';
export default function(opts={}) {
return fadeDirection.call(this, 'y', 1, opts, opts.offset);
}
Loading

0 comments on commit 7510007

Please sign in to comment.