Adding a function to jQuery draggable revert "event"
Asked Answered
E

2

24

What I have:

I have a draggable div with a revert parameter set as "invalid".

What I need:

When the revert occurs I want to trigger a CSS change to another element.

The problem:

"revert" is parameter rather than an event so I'm experiencing great difficulty in triggering the required CSS change when the revert occurs.

My code:

$('#peg_icon').draggable({
    revert: 'invalid',
    scroll: false,
    stack: "#peg_icon",
    drag: function(event, ui) {
        $('#peg_icon').css('background-image','url(images/peg-icon-when-dragged.png)');
    }
});

What I've tried:

I've unsuccessfully attempted using "revert" as an event:

revert: function(event, ui) {
    $('#peg_icon').css('background-image','url(images/peg-icon-default.png)');
},

I've also unnsuccesfully tried to get the revert paramater to take this function:

function(socketObj)
  {
     //if false then no socket object drop occurred.
     if(socketObj === false)
     {
        //revert the peg by returning true
        $('#peg_icon').css('background-image','url(images/peg-icon-default.png)');
        return true;
     }
     else
     {
        //return false so that the peg does not revert
        return false;
     }
  }

Context:

I'm dragging a div that when dragged, the background-image changes and when the drag reverts, the background-image is restored to its original state.

My question:

How do I trigger a CSS change to another element when revert occurs on a drag?

Epinephrine answered 28/1, 2013 at 21:52 Comment(2)
Just wanted to say, very well thought out and communicated question!Strother
Acknowledgment appreciated.Epinephrine
S
26

It turns out that revert can accept a method. See this for a complete example: http://jsfiddle.net/mori57/Xpscw/

Specifically:

$(function() {
    $("#ducky").draggable({
        revert: function(is_valid_drop){
            console.log("is_valid_drop = " + is_valid_drop);
            // when you're done, you need to remove the "dragging" class
            // and yes, I'm sure this can be refactored better, but I'm 
            // out of time for today! :)
            if(!is_valid_drop){
               console.log("revert triggered");
                $(".pond").addClass("green");
                $(this).removeClass("inmotion");
               return true;
            } else {
                $(".pond").removeClass("green");
                $(this).removeClass("inmotion");
            }
        },
        drag: function(){
            // as you drag, add your "dragging" class, like so:
            $(this).addClass("inmotion");
        }
    });
    $("#boat").droppable({
      drop: function( event, ui ) {
        $(this)
          .addClass("ui-state-highlight");
      }
    });
  });

Hope this helps... I'm guessing that whatever you were trying to modify was the issue, not the attempt to use revert with a function call. Take a look again at what CSS you were trying to set, and see if maybe your issue was in there.

Strother answered 28/1, 2013 at 22:36 Comment(6)
Specifically, I would, instead of using the .css() method, use addClass() to add a class to your draggable... have the icon-change in the CSS, not in the Javascript, so that when you revert, all you have to do is call .removeCSS('drag-indicator-class') from your draggable, and the image will revert to its default automatically.Strother
Thank you for the comprehensive answer, code and working example. Minor note: I had no idea that that classes could be appended to ids in CSS i.e. #some_id.some_class. It's the first time I've seen that kind of selector. I was instead using !important to force the .inmotion class to override the default #peg_icon id.Epinephrine
Question: What is the advantage of using addClass/removeClass instead of the JavaScript method? Is it a case of using an on/off action instead of two separate actions? My original reason for using the JavaScript method was mainly based on the superstition that the default and "in motion" background images would not be preloaded via CSS and that somehow the JavaScript method "forces" a quicker switching between background images. Simply put, does either method (i.e. CSS vs JavaScript) preload or load background images quicker than the other?Epinephrine
The advantage is in flexibility, and separating the presentation from the logic. At some point, you may want to reuse the code, or change the images used. CSS is where that kind of information belongs, and changing it in the CSS is a lot less likely to inadvertently introduce bugs than having to make changes directly in your JS. I can't answer to the preload part of the question... that's something I'd have to research, but forcing that via JS also means introducing more HTTP requests (one for each time you switch images), which would also be inefficient, as opposed to the cached css.Strother
Understood, I'll stick with the add/remove class approach that you've advised.Epinephrine
Minor note: is_valid_drop is never true, instead it is the droppable element on a successful drop.Sydelle
M
1

You want to do something like this:

 $('#peg_icon').draggable({
        revert: function (socketObj) {
        if (socketObj === true) {
            // success
            return false;
        }
        else {
            // reverting
            return true;
        }
    },
        scroll: false,
        stack: "#peg_icon",
        drag: function(event, ui) {
            $('#peg_icon').css('background-image','url(images/peg-icon-when-dragged.png)');
        }
    });

DEMO: http://jsfiddle.net/yTMwu/35/

Hope this helps!

Mancuso answered 28/1, 2013 at 22:39 Comment(1)
Thanks for the code and Fiddle demo. For some reason, this code prevented me from dropping #peg_icon to a secondary drop area (i.e. a drop area other than the drop area being dragged from). I appreciate that my provision of a limited context in the above question, might be the cause of this problem. Side note: I've been somewhat traumatized by your scary Cage avatar.Epinephrine

© 2022 - 2024 — McMap. All rights reserved.