Подтвердить что ты не робот

Ember.js + HTML5 перетащить корзину для покупок

Короче говоря, я пытаюсь воспроизвести базовую версию демоверсии jquery-ui для покупок: http://jqueryui.com/demos/droppable/shopping-cart.html с ember.js и встроенным drag5 drop от HTML5.

После предварительной попытки перетащить с помощью ember + jquery-ui и с трудностями использовать это решение: http://jsfiddle.net/Wu2cu/2/, я увидел решение pangratz HTML5: http://jsfiddle.net/pangratz666/DYnNH/ и решил сделать снимок.

У меня есть forked pangratz jsfiddle, созданный productController и добавленныйToCartController, который фильтрует productsController на основе свойства isAdded: http://jsfiddle.net/GU8N7/3/

Это хорошо работает, но затем я застреваю, когда пытаюсь использовать итератор #each и добавляю уникальные перетаскиваемые представления каждому объекту в итераторе. Я хочу, чтобы иметь возможность перетаскивать каждый объект "продукт", а когда он попадает в область "корзина", установите для этого объекта свойствоAdded значение true, и, таким образом, он появится в "корзине покупок".

Любая помощь будет принята с благодарностью!!

(также как бонус, я хотел бы сделать элементы в корзине сортировки сортированными, но это, вероятно, слишком много, чтобы просить, пока не пересечет первый мост.)

4b9b3361

Ответ 1

Взгляните на приведенный ниже код для решения (с несколькими дополнительными функциями). Включается сортировка элементов корзины (см. cartController в конце JS).

И рабочая скрипка здесь: 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 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'
});

Ответ 2

Я искал перетаскивание n drop и нашел ваш, я немного обновил код до 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")
});