I'm currently developing an Ember App for combining magnetic ornaments ( pls. see screenshot link ).
http://s7.postimg.org/9k2nq75yj/question_edit.png
On the left the user selects a category and then has the ability to chose main parts ( the long necklaces you see in the subcategory "Unsere Halsketten" & "Unsere Armbänder" ) or smaller parts, called elements ("Unsere Elemente") which then can be dropped into the "Drop Area".
In this early stage of development the drop area is simply a ember component which displays the content of an array (template: each item in array) . When a user drops an item to the drop area it's id is transfered through dataTransfer and a controller action (called from the component )fetches the item from the store and pushes it to the array.
As the necklaces have 2 open connections to add another item ( the items have magnetic connections) the goal now is to have a dynamic drop zone.
I'll explain:
The user drops a necklace (e.g. "ART_HALS_1") to the drop area. As it is a part with 2 open connectors and it is a necklace (it is big) i now want it to appear in drop center. Now that there's 2 open connections i need the drop center to have 2 additional drop areas added ( drop-left & drop-right) on top of it so there can be another item attached to it (like elements "Unsere Elemente").
As this is my first ember project I'm not really sure how i should continue from here.
I started reading into containerView and collectionView but i cannot figure out a good concept.
If anybody could help me giving a path in which direction i should go, i would be very thankful for that!
Following the most important code parts. The App is written with the help of ember-app-kit, coffescript (translated javascript version below) and for the template emblem (compiles to handlebars). The items come from a simple rails api.
item Model
App.Item = DS.Model.extend
itemName: DS.attr('string')
#with the help of collection, typ and subtyp i know exactly what kind of item i got (necklace, element, armbrace...)
collection: DS.attr('string'),defaultValue: 'art_nou'
typ: DS.attr('string'),defaultValue: 'element'
subtyp: DS.attr('string'),defaultValue: 'misc'
#number of connections
noc: DS.attr('string')
price: DS.attr('string')
img: DS.attr('string'),defaultValue: '/assets/'
bigUrl:( ->
url=@get('img')
lastPart = url.split('/').pop()
return '/assets/'+'LARGE_' + lastPart
).property('url')
App.Item.reopenClass
COLLECTIONS: ['art_nou', 'cleopatra', 'balance', 'pendant','rio_de_oro','simplicity', 'styx', 'misc']
TYPES: ['mag','plug','tie']
SUBTYPES:['d1','d1_2','plug_1','plug_2','plug_3','armband','halskette','element', 'ohrring']
valid: (fields) ->
fields.itemName
tool template( this is the app, theres no routes )
section#tool
// Kategorien
#cat
h1 Kollektionen
ul
li
span.kategorie.alle click="showAll" []Alle
li
category-control action="showCollection" kategorie="art_nou" name="Art Nouveau"
li
category-control action="showCollection" kategorie="cleopatra" name="Cleopatra"
li
category-control action="showCollection" kategorie="balance" name="Balance"
li
category-control action="showCollection" kategorie="pendant" name="Pendant"
li
category-control action="showCollection" kategorie="rio_de_oro" name="Rio de Oro"
li
category-control action="showCollection" kategorie="simplicity" name="Simpliticy"
li
category-control action="showCollection" kategorie="styx" name="Styx"
//Katalog
a class="runter chevron" click="scrollDown"
img src="assets/down.png"
a class="rauf chevron" click="scrollUp"
img src="assets/up.png"
div class={showCatalogue:kat:kat showCatalogue::kat-invisible }
.container
h2
|Unsere
=kollektionActive
| Kollektion
// muss variabel werden
span.kat-text Unsere Cleopatra Kollection zeichnet sich durch den individuellen Magnetverschluss aus.
span.hr
//will be components later
if halsketten
h3 Unsere Halsketten
div.row
each item in halsketten
draggable-item item=item
div.product
div.img
img src=item.img
div.itemName
item.itemName
div.clearfix
if armbaender
h3 Unsere Armbänder
div.row
each item in armbaender
draggable-item item=item
div.product
div.img
img src=item.img
div.itemName
item.itemName
div.clearfix
if ohrringe
h3 Unsere Ohrringe
div.row
each item in ohrringe
draggable-item item=item
div.product
div.img
img src=item.img
div.itemName
item.itemName
div.clearfix
if elemente
h3 Unsere Elemente
div.row
each item in elemente
draggable-item item=item
div.product
div.img
img src=item.img
div.itemName
item.itemName
div.clearfix
.ws
bigUrl
#drop
draggable-dropzone action="addItem"
each item in speicher
img src=item.bigUrl
= outlet
footer
tool controller
App.ToolController = Ember.ArrayController.extend
# im drop bereich befindliche elemente
speicher: Em.A([])
# Katalog
showDialog: false
showCatalogue: false
isActive: false
kollektionActive: ''
halsketten: Ember.computed.filterBy('controller','subtyp','halskette')
armbaender: Ember.computed.filterBy('controller','subtyp','armband')
ohrringe: Ember.computed.filterBy('controller','subtyp','ohrring')
elemente: Ember.computed.filterBy('controller','subtyp','element')
containerTop:"0"
upVisible: (->
containerTop=@get('containerTop')
if containerTop>=0
jQuery("a.rauf").delay(200).animate {opacity: "0"},500,'swing'
return true
else if containerTop<0
jQuery("a.rauf").delay(200).animate {opacity: "1"},500,'swing'
return false
else
# alert("hmm")
).observes("containerTop")
actions:
addItem: (itemId) ->
speicher = @get('speicher')
# gedragtes item anhand von itemId im store finden
item=@store.find "item", itemId
speicher.pushObject item
# console.log(speicher)
resetTool: ->
@set 'speicher', []
showAll: ->
kollektion=@get('model')
@set 'controller', kollektion
@set 'kollektionActive', 'gesamte'
@set 'showCatalogue', true
showCollection: (collectionId,name) ->
@set 'kollektionActive', name
kollektion=@get('model')
filter=kollektion.filterBy('collection', collectionId)
@set 'controller', filter
@set 'showCatalogue', true
draggable-item Component
App.DraggableItemComponent = Ember.Component.extend
classNames : [ 'draggable-item' ]
attributeBindings : [ 'draggable' ]
draggable : 'true'
dragStart: (event) ->
event.dataTransfer.setData 'text/data', @get('item.id')
draggable-dropzone Component
App.DraggableDropzoneComponent = Ember.Component.extend
classNames : [ 'draggable-dropzone' ]
classNameBindings : [ 'dragClass' ]
dragClass : 'deactivated'
dragLeave: (event) ->
event.preventDefault()
@set 'dragClass', 'deactivated'
dragOver: (event) ->
event.preventDefault()
@set 'dragClass', 'activated'
drop: (event) ->
@set 'dragClass', 'deactivated'
itemId = event.dataTransfer.getData('text/data')
@sendAction "action" , itemId
category-control
App.CategoryControlComponent = Ember.Component.extend
# tagname:'span'
classNames : [ 'category' ]
classNameBindings: ['active']
active: false
click: (event) ->
@sendAction 'action', @get('kategorie'), @get('name')
return
JAVASCRIPT VERSION TRANSLATED BY WEBSERVICE js2.coffee
item model
App.Item = DS.Model.extend({
itemName: DS.attr('string'),
collection: DS.attr('string'),
#with the help of collection, typ and subtyp i know exactly what kind of item i got (necklace, element, armbrace...)
defaultValue: 'art_nou',
typ: DS.attr('string'),
defaultValue: 'element',
subtyp: DS.attr('string'),
defaultValue: 'misc',
#number of connections
noc: DS.attr('string'),
price: DS.attr('string'),
img: DS.attr('string'),
defaultValue: '/assets/',
bigUrl: (function() {
var lastPart, url;
url = this.get('img');
lastPart = url.split('/').pop();
return '/assets/' + 'LARGE_' + lastPart;
}).property('url')
});
App.Item.reopenClass({
COLLECTIONS: ['art_nou', 'cleopatra', 'balance', 'pendant', 'rio_de_oro', 'simplicity', 'styx', 'misc'],
TYPES: ['mag', 'plug', 'tie'],
SUBTYPES: ['d1', 'd1_2', 'plug_1', 'plug_2', 'plug_3', 'armband', 'halskette', 'element', 'ohrring'],
valid: function(fields) {
return fields.itemName;
}
});
tool controller
App.ToolController = Ember.ArrayController.extend({
speicher: Em.A([]),
showDialog: false,
showCatalogue: false,
isActive: false,
kollektionActive: '',
halsketten: Ember.computed.filterBy('controller', 'subtyp', 'halskette'),
armbaender: Ember.computed.filterBy('controller', 'subtyp', 'armband'),
ohrringe: Ember.computed.filterBy('controller', 'subtyp', 'ohrring'),
elemente: Ember.computed.filterBy('controller', 'subtyp', 'element'),
containerTop: "0",
upVisible: (function() {
var containerTop;
containerTop = this.get('containerTop');
if (containerTop >= 0) {
jQuery("a.rauf").delay(200).animate({
opacity: "0"
}, 500, 'swing');
return true;
} else if (containerTop < 0) {
jQuery("a.rauf").delay(200).animate({
opacity: "1"
}, 500, 'swing');
return false;
} else {
}
}).observes("containerTop"),
actions: {
addItem: function(itemId) {
var item, speicher;
speicher = this.get('speicher');
item = this.store.find("item", itemId);
return speicher.pushObject(item);
},
resetTool: function() {
return this.set('speicher', []);
},
showAll: function() {
var kollektion;
kollektion = this.get('model');
this.set('controller', kollektion);
this.set('kollektionActive', 'gesamte');
return this.set('showCatalogue', true);
},
showCollection: function(collectionId, name) {
var filter, kollektion;
this.set('kollektionActive', name);
kollektion = this.get('model');
filter = kollektion.filterBy('collection', collectionId);
this.set('controller', filter);
return this.set('showCatalogue', true);
}
}
});
draggable-item component
App.DraggableItemComponent = Ember.Component.extend({
classNames: ['draggable-item'],
attributeBindings: ['draggable'],
draggable: 'true',
dragStart: function(event) {
return event.dataTransfer.setData('text/data', this.get('item.id'));
}
});
draggable-dropzone component
App.DraggableDropzoneComponent = Ember.Component.extend({
classNames: ['draggable-dropzone'],
classNameBindings: ['dragClass'],
dragClass: 'deactivated',
dragLeave: function(event) {
event.preventDefault();
return this.set('dragClass', 'deactivated');
},
dragOver: function(event) {
event.preventDefault();
return this.set('dragClass', 'activated');
},
drop: function(event) {
var itemId;
this.set('dragClass', 'deactivated');
itemId = event.dataTransfer.getData('text/data');
return this.sendAction("action", itemId);
}
});
category-control component
App.CategoryControlComponent = Ember.Component.extend({
classNames: ['category'],
classNameBindings: ['active'],
active: false,
click: function(event) {
this.sendAction('action', this.get('kategorie'), this.get('name'));
}
});