Ember.js + HTML5拖放购物车演示 [英] Ember.js + HTML5 drag and drop shopping cart demo

查看:84
本文介绍了Ember.js + HTML5拖放购物车演示的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

简而言之,我正在尝试重现jquery-ui购物车演示的基本版本: http:// jqueryui.com/demos/droppable/shopping-cart.html 与ember.js和HTML5本机拖放n。



之前尝试实现拖动和使用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,从而将其显示在购物车中。



任何帮助将不胜感激!



(也作为奖励,我想让购物车中的物品可以排序,但这可能太多了,直到第一座桥被越过。 )

解决方案

查看下面的代码以获得解决方案(附有几个附加功能)。包括购物车项目的排序(请参阅JS结尾的 cartController )。



这里有一个工作小提琴: http://jsfiddle.net/ud3323/ 5uX9H /



更新:添加了拖动图片示例。



Handlebars

 < script type =text / x-handlebars> 
< b>可用产品< / b>
< br />< br />
{{#each App.productsController}}
{{#viewview.ProductView contentBinding =this}}
{{content.name}}
{{/ view }}< br />
{{/ each}}
< hr />

{{#view App.ProductDropTarget
dragContextBinding =App.productsController.currentDragItem}}
购物车
< div style =height:20px > {{HELPTEXT}}< / DIV>
{{/ view}}
< br />
{{#each App.cartController}}
{{#viewview.ProductView contentBinding =this}}
{{content.name}}
{{/ view }}< br />
{{/ each}}
< / script>

em> JavaScript:

  App = Ember.Application.create({}) ; 

DragNDrop = Ember.Namespace.create();

DragNDrop.cancel = function(event){
event.preventDefault();
返回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)需要一个HTML元素作为第一个参数
//,所以你必须告诉Ember创建视图,它是元素,然后获取该元素的
// HTML表示。
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);
//让控制器知道这个视图是拖动
this.setPath('content.isDragging',true);

//设置相对于鼠标/触摸事件的拖动图像和位置
var dataTransfer = event.originalEvent.dataTransfer;
dataTransfer.setDragImage(this.get('dragIconElement '),24,24);
},

dragEnd:function(event){
//让控制器知道这个视图完成拖动
这个。 setPath('content.isDragging',false);
}
});

App.ProductDropTarget = Ember.View.extend(DragNDrop.Droppable,{
tagName:'div',
classNames:['dropTarget'],
classNameBindings :['cartAction'],
helpText:null,

//这将确定你应该添加到
//该视图中的类(如果有的话),当你在拖动项目的过程
cartAction:Ember.computed(function(key,value){
if(Ember.empty(this.get('dragContext'))){
this .set('helpText','(Drop Zone)');
返回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帮助文件, '(Drop Zone)');
return null;
}

})property('dragContext')。cacheable(),

drop:function(event){
var viewId = event.originalEvent.dataTransfer.getData('Text'),
view = Ember.View.views [viewId];

//设置视图属性
//必须在Ember.run.next中才能始终工作
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)){
//按名称排序desc
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'
});



In short, I am trying to reproduce a basic version of jquery-ui's shopping cart demo: http://jqueryui.com/demos/droppable/shopping-cart.html with ember.js and HTML5 native drag n drop.

After previously trying to implement drag and drop with ember + jquery-ui and having difficulty using this solution: http://jsfiddle.net/Wu2cu/2/, I saw pangratz's HTML5 solution: http://jsfiddle.net/pangratz666/DYnNH/ and decided to give it a shot.

I have forked pangratz's jsfiddle, created a productsController and an addedToCartController that filters the productsController based on an isAdded property: http://jsfiddle.net/GU8N7/3/

That works fine, but then I get stuck when I try to use an #each iterator and append unique draggable views to each object in the iterator. I want to be able to drag each "product" object, and when it is dropped into the "shopping cart" area, set that object's isAdded property to true, thus having it show up in the "shopping cart."

Any help would be greatly appreciated!!

(also as a bonus, I'd like to make the items in the shopping cart sortable, but that's probably too much to ask for until the first bridge is crossed.)

解决方案

Take a look at the code below for a solution (with a few extras). Sorting of the cart items is included (see cartController at the end of the JS).

And a working fiddle here: http://jsfiddle.net/ud3323/5uX9H/.

UPDATE: Added a drag image example.

Handlebars

<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'
});

​ ​

这篇关于Ember.js + HTML5拖放购物车演示的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆