Ember.js + HTML5 drag and drop shopping cart demo

前端 未结 2 534
予麋鹿
予麋鹿 2020-12-07 19:17

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

相关标签:
2条回答
  • 2020-12-07 19:46

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

    ​ ​

    0 讨论(0)
  • 2020-12-07 20:00

    i was looking for a drag n drop exemple and find yours, i updated the code slightly to 1.0.0-rc5 and add a double click on item ability for fun ...

    http://jsfiddle.net/kadactivity/hhBrM/1/

    Handlebars

    <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")
    });
    
    0 讨论(0)
提交回复
热议问题