简而言之,我正在尝试使用ember.js和HTML5原生拖放来重现jquery-ui购物车演示的基本版本:http://jqueryui.com/demos/droppable/shopping-cart.html。
之前尝试使用ember + jquery-ui实现拖放并且难以使用此解决方案:http://jsfiddle.net/Wu2cu/2/,我看到了pangratz的HTML5解决方案:http://jsfiddle.net/pangratz666/DYnNH/并决定尝试一下。
我已经分叉了pangratz的jsfiddle,创建了一个productsController和一个addedToCartController,它根据isAdded属性过滤了productsController:http://jsfiddle.net/GU8N7/3/
这很好,但是当我尝试使用#each迭代器并将唯一的可拖动视图附加到迭代器中的每个对象时,我就会陷入困境。我希望能够拖动每个“产品”对象,当它被放入“购物车”区域时,将该对象的isAdded属性设置为true,从而将其显示在“购物车”中。
任何帮助将不胜感激!!
(同样作为奖励,我想让购物车中的物品可以分类,但在第一座桥越过之前,这可能太多了。)
答案 0 :(得分:47)
请查看下面的代码以获得解决方案(附加一些内容)。包括对购物车项目的排序(请参阅JS末尾的cartController
)。
这是一个工作小提琴:http://jsfiddle.net/ud3323/5uX9H/。
更新:添加了拖动图片示例。
的车把强> 的
<script type="text/x-handlebars" >
<b>Available Products</b>
<br /><br />
{{#each App.productsController}}
{{#view App.ProductView contentBinding="this"}}
{{content.name}}
{{/view}}<br />
{{/each}}
<hr />
{{#view App.ProductDropTarget
dragContextBinding="App.productsController.currentDragItem"}}
Shopping Cart
<div style="height: 20px">{{helpText}}</div>
{{/view}}
<br />
{{#each App.cartController}}
{{#view App.ProductView contentBinding="this"}}
{{content.name}}
{{/view}}<br />
{{/each}}
</script>
的 JavaScript的:强> 的
App = Ember.Application.create({});
DragNDrop = Ember.Namespace.create();
DragNDrop.cancel = function(event) {
event.preventDefault();
return false;
};
DragNDrop.Draggable = Ember.Mixin.create({
attributeBindings: 'draggable',
draggable: 'true',
dragStart: function(event) {
var dataTransfer = event.originalEvent.dataTransfer;
dataTransfer.setData('Text', this.get('elementId'));
}
});
DragNDrop.Droppable = Ember.Mixin.create({
dragEnter: DragNDrop.cancel,
dragOver: DragNDrop.cancel,
drop: function(event) {
event.preventDefault();
return false;
}
});
App.Product = Ember.Object.extend({
name: null,
isAdded: null
});
App.ProductView = Ember.View.extend(DragNDrop.Draggable, {
tagName: 'span',
// .setDragImage (in #dragStart) requires an HTML element as the first argument
// so you must tell Ember to create the view and it's element and then get the
// HTML representation of that element.
dragIconElement: Ember.View.create({
attributeBindings: ['src'],
tagName: 'img',
src: 'http://twitter.com/api/users/profile_image/twitter'
}).createElement().get('element'),
dragStart: function(event) {
this._super(event);
// Let the controller know this view is dragging
this.setPath('content.isDragging', true);
// Set the drag image and location relative to the mouse/touch event
var dataTransfer = event.originalEvent.dataTransfer;
dataTransfer.setDragImage(this.get('dragIconElement'), 24, 24);
},
dragEnd: function(event) {
// Let the controller know this view is done dragging
this.setPath('content.isDragging', false);
}
});
App.ProductDropTarget = Ember.View.extend(DragNDrop.Droppable, {
tagName: 'div',
classNames: ['dropTarget'],
classNameBindings: ['cartAction'],
helpText: null,
// This will determine which class (if any) you should add to
// the view when you are in the process of dragging an item.
cartAction: Ember.computed(function(key, value) {
if(Ember.empty(this.get('dragContext'))) {
this.set('helpText','(Drop Zone)');
return null;
}
if(!this.getPath('dragContext.isAdded')) {
this.set('helpText', '(Drop to Add)');
return 'cart-add';
} else if(this.getPath('dragContext.isAdded')) {
this.set('helpText', '(Drop to Remove)');
return 'cart-remove';
} else {
this.set('helpText', '(Drop Zone)');
return null;
}
}).property('dragContext').cacheable(),
drop: function(event) {
var viewId = event.originalEvent.dataTransfer.getData('Text'),
view = Ember.View.views[viewId];
// Set view properties
// Must be within `Ember.run.next` to always work
Ember.run.next(this, function() {
view.setPath('content.isAdded', !view.getPath('content.isAdded'));
});
return this._super(event);
}
});
App.productsController = Ember.ArrayController.create({
content: [
App.Product.create({ name: "MacBook Pro", isAdded: false }),
App.Product.create({ name: "iPhone", isAdded: false }),
App.Product.create({ name: "iPad", isAdded: true }),
App.Product.create({ name: "iTV", isAdded: false })
],
currentDragItem: Ember.computed(function(key, value) {
return this.findProperty('isDragging', true);
}).property('@each.isDragging').cacheable(),
productsInCart: Ember.computed(function(key, value) {
return this.filterProperty('isAdded', true);
}).property('@each.isAdded').cacheable()
});
App.cartController = Ember.ArrayController.create({
content: Ember.computed(function(key, value) {
var cartItems = this.get('cartItems');
if(!Ember.empty(cartItems)) {
// Sort desc by name
return cartItems.sort(function(a,b){
if((a.get('name').toLowerCase()) < (b.get('name').toLowerCase()))
return -1;
else return 1;
});
}
}).property('cartItems').cacheable(),
cartItemsBinding: 'App.productsController.productsInCart'
});
答案 1 :(得分:2)
我正在寻找一个拖拽例子并找到你的,我将代码稍微更新到1.0.0-rc5并添加双击项目能力以获得乐趣......
http://jsfiddle.net/kadactivity/hhBrM/1/
<强>车把强>
<script type="text/x-handlebars" >
<b>Available Products</b>
<br /><br />
{{#each product in model}}
{{#view App.ProductView contentBinding="product"}}
{{view.content.name}}
{{/view}}<br />
{{/each}}
<hr />
{{#view App.ProductDropTarget
dragContextBinding="currentDragItem"}}
Shopping Cart
<div style="height: 20px">{{helpText}}</div>
{{/view}}
<br />
{{#each cart in productsInCart}}
{{#view App.ProductView contentBinding="cart"}}
{{view.content.name}}
{{/view}}<br />
{{/each}}
</script>
<强>的Javascript 强>
App = Ember.Application.create();
App.Router.map(function() {
// put your routes here
});
App.ApplicationRoute = Ember.Route.extend({
model: function() {
return [
App.Product.create({ name: "MacBook Pro", isAdded: false }),
App.Product.create({ name: "iPhone", isAdded: false }),
App.Product.create({ name: "iPad", isAdded: true }),
App.Product.create({ name: "iTV", isAdded: false })
];
}
});
DragNDrop = Ember.Namespace.create();
DragNDrop.cancel = function(event) {
event.preventDefault();
return false;
};
DragNDrop.Draggable = Ember.Mixin.create({
attributeBindings: "draggable",
draggable: "true",
dragStart: function(event) {
var dataTransfer = event.originalEvent.dataTransfer;
dataTransfer.setData("Text", this.get("elementId"));
}
});
DragNDrop.Droppable = Ember.Mixin.create({
dragEnter: DragNDrop.cancel,
dragOver: DragNDrop.cancel,
drop: function(event) {
event.preventDefault();
return false;
}
});
App.Product = Ember.Object.extend({
name: null,
isAdded: null
});
App.ProductView = Ember.View.extend(DragNDrop.Draggable, {
tagName: "span",
// .setDragImage (in #dragStart) requires an HTML element as the first argument
// so you must tell Ember to create the view and it"s element and then get the
// HTML representation of that element.
dragIconElement: Ember.View.create({
attributeBindings: ["src"],
tagName: "img",
src: "http://twitter.com/api/users/profile_image/twitter"
}).createElement().get("element"),
dragStart: function(event) {
this._super(event);
// Let the controller know this view is dragging
this.set("content.isDragging", true);
// Set the drag image and location relative to the mouse/touch event
var dataTransfer = event.originalEvent.dataTransfer;
dataTransfer.setDragImage(this.get("dragIconElement"), 24, 24);
},
dragEnd: function(event) {
// Let the controller know this view is done dragging
this.set("content.isDragging", false);
},
doubleClick: function(event) {
this.set("content.isAdded", !this.get("content.isAdded"));
}
});
App.ProductDropTarget = Ember.View.extend(DragNDrop.Droppable, {
tagName: "div",
classNames: ["dropTarget"],
classNameBindings: ["cartAction"],
helpText: null,
// This will determine which class (if any) you should add to
// the view when you are in the process of dragging an item.
cartAction: function() {
if(Ember.isEmpty(this.get("dragContext"))) {
this.set("helpText","(Drop Zone)");
return null;
}
if(!this.get("dragContext.isAdded")) {
this.set("helpText", "(Drop to Add)");
return "cart-add";
} else if(this.get("dragContext.isAdded")) {
this.set("helpText", "(Drop to Remove)");
return "cart-remove";
} else {
this.set("helpText", "(Drop Zone)");
return null;
}
}.property("dragContext"),
drop: function(event) {
var viewId = event.originalEvent.dataTransfer.getData("Text"),
view = Ember.View.views[viewId];
// Set view properties
// Must be within `Ember.run.next` to always work
Ember.run.next(this, function() {
view.set("content.isAdded", !view.get("content.isAdded"));
});
return this._super(event);
}
});
App.ApplicationController = Ember.ArrayController.extend({
currentDragItem: function() {
return this.findProperty("isDragging", true);
}.property("@each.isDragging"),
productsInCart: function() {
var cartItems = this.filterProperty("isAdded", true);
console.log(cartItems);
if(!Ember.isEmpty(cartItems)) {
// Sort desc by name
return cartItems.sort(function(a,b){
if((a.get("name").toLowerCase()) < (b.get("name").toLowerCase()))
return -1;
else return 1;
});
}
}.property("@each.isAdded")
});