我目前正在开发一个用于组合磁性饰品的 Ember 应用程序(请参见屏幕截图链接)。
http://s7.postimg.org/9k2nq75yj/question_edit.png
在左侧,用户选择一个类别,然后可以选择主要部分(您在子类别“Unsere Halsketten”和“Unsere Armbänder”中看到的长项链)或更小的部分,称为元素(“Unsere Elemente”),然后可以放入“放置区”。
在这个开发的早期阶段,放置区域只是一个显示数组内容的 ember 组件(模板:数组中的每个项目)。当用户将一个项目放置到放置区域时,它的 id 通过 dataTransfer 传输,并且控制器操作(从组件调用)从存储中获取项目并将其推送到数组。
由于项链有 2 个打开的连接以添加另一个项目(这些项目具有磁性连接),因此现在的目标是拥有一个动态放置区。
我会解释:
用户将项链(例如“ART_HALS_1”)放置到放置区域。因为它是带有 2 个开放式连接器的部件,而且它是一条项链(它很大),我现在希望它出现在下降中心。现在有 2 个打开的连接,我需要放置中心在其顶部添加 2 个额外的放置区域(drop-left 和 drop-right),以便可以附加另一个项目(如元素“Unsere Elemente”)。
由于这是我的第一个 ember 项目,我不确定我应该如何从这里继续。
我开始阅读 containerView 和 collectionView 但我想不出一个好的概念。
如果有人可以帮助我指明我应该走的方向,我将非常感谢!
遵循最重要的代码部分。该应用程序是在 ember-app-kit、coffescript(下面是翻译的 javascript 版本)和模板标志(编译到车把)的帮助下编写的。这些项目来自一个简单的 rails api。
项目型号
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
工具模板(这是应用程序,没有路线)
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
工具控制器
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
可拖动项组件
App.DraggableItemComponent = Ember.Component.extend
classNames : [ 'draggable-item' ]
attributeBindings : [ 'draggable' ]
draggable : 'true'
dragStart: (event) ->
event.dataTransfer.setData 'text/data', @get('item.id')
可拖放区域组件
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
类别控制
App.CategoryControlComponent = Ember.Component.extend
# tagname:'span'
classNames : [ 'category' ]
classNameBindings: ['active']
active: false
click: (event) ->
@sendAction 'action', @get('kategorie'), @get('name')
return
WEBSERVICE js2.coffee 翻译的 JAVASCRIPT 版本
项目模型
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;
}
});
工具控制器
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);
}
}
});
可拖动项组件
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'));
}
});
可拖放区域组件
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);
}
});
类别控制组件
App.CategoryControlComponent = Ember.Component.extend({
classNames: ['category'],
classNameBindings: ['active'],
active: false,
click: function(event) {
this.sendAction('action', this.get('kategorie'), this.get('name'));
}
});