0

I'm trying to make a mock-up application for prototyping apps, using backbone & jQuery. It's pretty minimal at this point. http://jsfiddle.net/IgnorantUser/u7JkX/

I just have 2 models Canvas and ButtonWidget. There are also 3 Views: the CanvasView for the Canvas, ButtonInCanvas view for the ButtonWidget and a dummy view called ButtonInToolbar which is not backed by the ButtonWidget model, instead it gets it's default values from a .button css class and is used for dragging & dropping into the canvas, populating it with buttons.

Since there are gonna be other widgets (labels, textboxes, imageholders etc...) I've taken the approach of passing the drop event handling triggered by "CanvasView" in the context of "ButtonInToolbar" view, by using the following code:

    passDrop: function (e, ui){
        if ($(ui.draggable).parent().is('#toolbar')){
            ui.draggable.trigger('drop'); //sets the drop in the context of the dragged view (ButtonInToolbar)
        }

The issue I'm facing is that I wanna be able to pass the ui.position.left and ui.position.top values into the ButtonInToolbar view, so that when I call the dropHandler method to append a new ButtonInCanvas view, I can pass the position of the drop and render the Button where it actually dropped. How do I do that?

    dropHandler: function () {
        $('.canvas').append(new ButtonInCanvas({model: new ButtonWidget}).render().el);
    }

I've tried passing (event, ui) within the above function so that i can have the ui.position.left value but I get "Uncaught TypeError: Cannot read property 'position' of undefined". How could I work around this issue?

Also, in the above code, I'm using a selector for the canvas instead of the CanvasView instance. Having in mind that in the future there would be more than one CanvasView, how could I associate the specific CanvasView instance so that the Widgets append only into it and not in all DOM elements that have a class of canvas?

More importantly, since this is my first attempt with Backbone, and it doesn't have that much in common with "ToDo" apps, can you point out any fatal errors in my implementation? Things I'm doing wrong, or I could have done in a better/more efficient way

IgnorantUser
  • 197
  • 1
  • 12

2 Answers2

0

From the jQuery .trigger() docs:

.trigger( eventType [, extraParameters ] )

eventType Type: String A string containing a JavaScript event type, such as click or submit. extraParameters Type: Array, PlainObject Additional parameters to pass along to the event handler.

So, you can pass any additional parameters you want in the .trigger() function:

passDrop: function (e, ui) {
    if ($(ui.draggable).parent().is('#toolbar')) {
        var offset = this.$el.offset(),
            top = ui.offset.top - offset.top,
            left = ui.offset.left - offset.left;
        ui.draggable.trigger('drop', [top, left]);
    }
}

And handle the extra parameters in the callback:

dropHandler: function (event, top, left) {
    var el = new ButtonInCanvas({model: new ButtonWidget}).render().el;
    $(el).css({position: "absolute", top: top, left: left});
    $('.canvas').append(el);
}

Also, add the following to your CSS:

.canvas {
    position: relative;
}

See updated fiddle.

Lukas
  • 9,765
  • 2
  • 37
  • 45
  • Thanx! Any idea how could I pass these values when i do $('.canvas').append(new ButtonInCanvas({model: new ButtonWidget(}).render().el); Tried various things but didn't work – IgnorantUser Jan 10 '13 at 14:58
  • Great, although I would like to pass the ui.position or ui.offset in my model attributes positionx and positiony, or if this is not possible, pass the ui.position/ui.offses to the ButtonInCanvas view and from there to the model – IgnorantUser Jan 10 '13 at 15:52
0

Lukas I can't thank you enough for the help you gave me! :) In the end I managed to use your bits of code for passing the offset into the view constructor

$('.canvas').append(new ButtonInCanvas({
    model: new ButtonWidget,
    xpos:left,
    ypos:top
  }).render().el);

Then I used model.options in the initialization of ButtonInCanvas to set the drop position values into the model itself:

initialize: function (){
_.bindAll(this, 'render', 'setCssStyle', 'setPosition'); 
this.model.set({
    'positionx': this.options.xpos,
    'positiony': this.options.ypos
})

And finally I made a method setPosition that sets the css top/width by getting the position x/y from the model. I call this method inside the render function

setPosition: function () {
    this.$el.css({
    left: this.model.get('positionx') + 'px',
    top : this.model.get('positiony') + 'px',
    position: "absolute"
     });
},

Also, I've updated the jsfiddle http://jsfiddle.net/IgnorantUser/u7JkX/

Now I need to get my head around the whole append in the specific instance of canvas instead of $(.canvas). I guess cid will do the trick! Excited!

IgnorantUser
  • 197
  • 1
  • 12
  • Somehow, I missed the part in your question where you talked about `$(".canvas")` vs. the specific canvas you're dealing with. I've updated the fiddle with a fix for that too: http://jsfiddle.net/u7JkX/34/ – Lukas Jan 11 '13 at 15:58
  • Basically, you instantiate the `CanvasView`, and pass its `$el` to each `ButtonInToolbar` view you create. – Lukas Jan 11 '13 at 15:59
  • I was thinking of passing the Canvas model cid into the canvasview as an id attribute, so I could then use the setDrop to also pass the cid inside the dropHanlder and use it as the jquery selector to render the button in that specific canvasview. Unfortunately this.options doesn't work before init :/ (or i was doing something wrong) Could you comment the jsfiddle just to help me understand what you do? Thank you once more! – IgnorantUser Jan 11 '13 at 16:24
  • Thanx, I added a few things in the jsfiddle (a + button that appends a canvasview) but it just appends one canvasview :/ http://jsfiddle.net/IgnorantUser/u7JkX/38/ Can't seemt to understand why it does so, maybe it has something to do with the canvasView variable? – IgnorantUser Jan 11 '13 at 18:59
  • Ahh, I see what you're trying to do now. I've made some changes for you: http://jsfiddle.net/u7JkX/41/ – Lukas Jan 11 '13 at 19:25
  • Now, in addition to passing top and left to the drop handler, it also passes the target canvas view's top-level element. – Lukas Jan 11 '13 at 19:26