Skip to content

Commit

Permalink
Initial cut
Browse files Browse the repository at this point in the history
  • Loading branch information
Christopher Garrett committed Aug 31, 2016
1 parent 70de7ad commit bbed5b5
Show file tree
Hide file tree
Showing 32 changed files with 512 additions and 477 deletions.
15 changes: 14 additions & 1 deletion addon/components/liquid-append.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,22 @@
import Ember from 'ember';

export default Ember.Component.extend({
willInsertElement() {
const wormhole = this.get('wormhole');

if (wormhole.willAppendNodes) {
wormhole.willAppendNodes(this.element);
}
},

didInsertElement() {
const nodes = this.get('nodes');
const wormhole = this.get('wormhole');
const nodes = this.get('wormhole.nodes');

this.$().append(nodes);

if (wormhole.didAppendNodes) {
wormhole.didAppendNodes(this.element);
}
}
});
14 changes: 0 additions & 14 deletions addon/components/liquid-target-container.js

This file was deleted.

92 changes: 67 additions & 25 deletions addon/components/liquid-target.js
Original file line number Diff line number Diff line change
@@ -1,50 +1,92 @@
import Ember from 'ember';
import HashMap from 'perf-primitives/hash-map';
import layout from '../templates/components/liquid-target';

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

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

firstTime: true,

name: 'default',
liquidTargetService: service('liquidTarget'),

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

this.stackMap = new HashMap();
this.stackQueue = A();
this.set('stacks', A());

const name = this.get('name');

this.get('liquidTargetService').registerTarget(name, this);
},

appendWormhole(wormhole) {
const stackName = wormhole.get('stack');
let stack = this.stackMap.get(stackName);

if (stack === undefined) {
const cssClass = A([
wormhole.get('class'),
wormhole.get('stack'),
wormhole._containerClass
]).compact().join(' ');

stack = A([{ stackName, class: cssClass, empty: true }]);

this.stackMap.set(stackName, stack);

//
this.stackQueue.pushObject(stack);

currentItem: computed('items.lastObject', function() {
return this.get('items.lastObject') || { emptyTarget: true };
}),
Ember.run.scheduleOnce('afterRender', this, this.flushStackQueue);
}

Ember.run.next(() => {
stack.pushObject(wormhole);
});
},

removeWormhole(wormhole) {
const stackName = wormhole.get('stack');
const stack = this.stackMap.get(stackName);

Ember.run.next(() => {
stack.removeObject(wormhole);
});
},

flushStackQueue() {
this.get('stacks').pushObjects(this.stackQueue);
this.stackQueue.clear();
},

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

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

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

afterTransition() {
if (!this.firstTime && !this.isDestroyed) {
const contextClass = this.get('currentItem.targetClass');
this.set('contextClass', contextClass);
}
afterTransition([{ value }]) {
if (value.empty) {
if (value.hasAnimated) {
const stacks = this.get('stacks')
const stack = this.stackMap.get(value.stackName);

this.firstTime = false;
this.set('target.isAnimating', false);
this.get('liquidTargetService').didAnimate();
stacks.removeObject(stack);
this.stackMap.delete(value.stackName);
} else {
value.hasAnimated = true;
}
}
}
}
});
44 changes: 10 additions & 34 deletions addon/components/liquid-wormhole.js
Original file line number Diff line number Diff line change
@@ -1,54 +1,30 @@
import Ember from 'ember';

const { A, computed, inject, observer, run } = Ember;
const { A, computed, inject, generateGuid } = Ember;

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

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

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

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

childWormholes: computed(() => A()),
willInsertElement() {
const nodes = this.$().children();
this.set('nodes', nodes);

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

didInsertElement() {
const parentWormhole = this.nearestOfType(LiquidWormhole);
const childWormholes = this.get('childWormholes');
const liquidTargetService = this.get('liquidTargetService');

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

if (parentWormhole && parentWormhole._state !== 'inDOM') {
parentWormhole.get('childWormholes').unshiftObject(this);
parentWormhole.get('childWormholes').unshiftObjects(childWormholes);
} else {
liquidTargetService.appendItem(this._target, this);

childWormholes.forEach((wormhole) => liquidTargetService.appendItem(wormhole._target, wormhole));
}
this.get('liquidTargetService').appendWormhole(this, this.get('liquidTarget'));

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

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

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

export default LiquidWormhole;
6 changes: 3 additions & 3 deletions addon/index.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import Constraint from 'liquid-fire/constraint';

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

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

export function onCloseWormhole() {
return new Constraint('newValue', ({ emptyTarget }) => emptyTarget);
return new Constraint('newValue', ({ empty }) => empty);
}
16 changes: 0 additions & 16 deletions addon/instance-initializers/browser/liquid-target-container.js

This file was deleted.

87 changes: 31 additions & 56 deletions addon/services/liquid-target.js
Original file line number Diff line number Diff line change
@@ -1,77 +1,52 @@
import Ember from 'ember';

const { computed } = Ember;
const { computed, A, generateGuid, getOwner } = Ember;
const { reads } = computed;

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

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

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);
this.targets = Ember.Object.create();
},

appendToQueue(target, method, item) {
this.get('queue').pushObject({ target, method, item });
appendWormhole(wormhole, targetName = 'default') {
let target = this.targets.get(targetName);

if (!this.get('targets').isAny('isAnimating')) {
this.flushQueue();
if (target === undefined) {
if (targetName === 'default') {
target = this.addDefaultTarget();
} else {
throw new Error('Liquid Wormhole target does not exist');
}
}

target.appendWormhole(wormhole);
},

flushQueue() {
const queue = this.get('queue');
removeWormhole(wormhole, targetName = 'default') {
const target = this.targets.get(targetName);

queue.forEach(({ target, method, item }) => {
target.items[method](item);
});
if (target === undefined) {
throw new Error('Liquid Wormhole target does not exist');
}

queue.clear();
target.removeWormhole(wormhole);
},

didAnimate() {
if (this.get('queue.length')) {
this.flushQueue();
} else {
this.cleanTargets();
}
registerTarget(targetName, wormholes) {
this.targets.set(targetName, wormholes);
},

cleanTargets() {
const targets = this.get('targets');
addDefaultTarget() {
const instance = getOwner(this);
const target = instance.lookup('component:liquid-target');
target.set('classNames', ['liquid-target', 'default-liquid-target']);
target.appendTo(instance.rootElement);

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);
}
return target;
}
});
14 changes: 5 additions & 9 deletions addon/styles/addon.css
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
.liquid-target-container {
.default-liquid-target {
position: absolute;
top: 0;
left: 0;
right: 0;
width: 100%;
z-index: 9999;
}

.liquid-target {
position: relative;
.default-liquid-target .liquid-child {
overflow: visible;
width: 100%;
}

.liquid-wormhole-container {
display: none;
}

.liquid-target > .liquid-child {
overflow: visible;
}
Loading

0 comments on commit bbed5b5

Please sign in to comment.