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?

Dominor Novus
  • 2,248
  • 5
  • 29
  • 35

2 Answers2

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.

Jason M. Batchelor
  • 2,951
  • 16
  • 25
  • 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. – Jason M. Batchelor Jan 28 '13 at 22:54
  • 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. – Dominor Novus Jan 29 '13 at 09:52
  • **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? – Dominor Novus Jan 29 '13 at 09:53
  • 2
    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. – Jason M. Batchelor Jan 29 '13 at 15:48
  • Understood, I'll stick with the add/remove class approach that you've advised. – Dominor Novus Jan 31 '13 at 01:03
  • 3
    **Minor note:** ```is_valid_drop``` is never true, instead it is the droppable element on a successful drop. – Marcel Burkhard Dec 05 '14 at 13:32
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!

Dom
  • 38,906
  • 12
  • 52
  • 81
  • 3
    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._ – Dominor Novus Jan 29 '13 at 09:59