Jump to content
GreenSock

Search In
  • More options...
Find results that contain...
Find results in...
apo

Draggable trigger issue

Warning: Please note

This thread was started before GSAP 3 was released. Some information, especially the syntax, may be out of date for GSAP 3. Please see the GSAP 3 migration guide and release notes for more information about how to update the code to GSAP 3's syntax. 

Recommended Posts

Hi guys,

 

I am working on a drag and sort thing with draggable and i have an issue that i can't find a way around it. Actually it looks like a bug.

 

Items are in an unordered list so they are all identical in terms of child elements and class names.

 

Draggable seems to work find with a class selector. Here's a code pen with just a simple setup. There is no drag trigger.

 

See the Pen CEHBo by ap-o (@ap-o) on CodePen

 

But, once i pass a trigger selector everything goes wrong. Try to drag the little black box.

See the Pen qfKtm by ap-o (@ap-o) on CodePen

 

Thanks in advance for your time

*Apo

 

Share this post


Link to post
Share on other sites

That's not a bug - it's just that "trigger" is supposed to be an element (or a jQuery object that has one result), but you were passing in selector text that selected ALL of those ".play-button" elements. Instead, for each Draggable, you should specify which .play-button element you want to be the trigger (for that particular Draggable instance). So it should be as simple as using jQuery's each() method to loop through the results, and the find() method to get the appropriate ".play-button" each time through the loop. 

$(".track-item").each(function(i, element) {
  Draggable.create(this, {
    trigger: $(this).find(".play-button"),
    type:"y",
    edgeResistance:0.75,
    bounds:".playlist",
  });
});

Here's the revised codepen: 

http://codepen.io/GreenSock/pen/f39ea10e4ee4cd60b927994136351981/?editors=001

  • Like 2

Share this post


Link to post
Share on other sites

Hi and welcome to the GreenSock forums.

 

Thanks for providing the codepen, it was very useful.

 

This is only a selector issue. What's happening is that you set as trigger for each Draggable instance a jQuery collection of every element with a class "play-button", so when you drag one it triggers the Draggable instance of every li element in the collection.

 

One solution is loop through all the li elements, create a variable for each "play-button" and a Draggable instance for each li element Then set that particular li element's play-button as the trigger, something like this:

$.each($(".track-item"), function(i,e)
{
  //store this li element's play-button in a variable
  var triggerEl = $(e).find(".play-button");

  Draggable.create(e,
  {
    //apply that as this particular li element's Draggable instance trigger
    trigger: triggerEl,
    type:"y",
    edgeResistance:0.75,
    bounds:".playlist",
  });
});

That should make things work as you expect.

 

Rodrigo.

 

PS: well... what Jack just said 8-)

Share this post


Link to post
Share on other sites

Hi,

 

Thanks for the quick response.

 

i reached that solution too, just didn't feel so elegant. 

 

Just for the sake of conversation, i think that in such a case, where you pass a class selector or an array of elements to the draggable create, the trigger concept feels a bit flaky. Yet, i do understand your reasoning.

 

Again, thanks for your time.

Cheers

Share this post


Link to post
Share on other sites

Did you have any recommendations for making it less "flaky"? I can't think of any way that it could be expected or engineered to work as you expected in that situation. Even if we injected the code necessary to check for jQuery objects, loop through the results, etc., we couldn't know for sure that the trigger order would match the target order (or even that there'd be the same number of results for each).

 

If you've got ideas, I'm all ears.  

  • Like 1

Share this post


Link to post
Share on other sites

From my perspective the trigger is always going to be a child of the target. Or at least i can't really think of a functional scenario where the draggable target is a class or an array of elements and the trigger is a single element.

 

Given that you could do something like that

Draggable.create = function(targets, vars) {
    if (typeof(targets) === "string") {
        targets = TweenLite.selector(targets);
    }
    var a = _isArrayLike(targets) ? _flattenArray(targets) : [targets],
    i = a.length;
    while (--i > -1) {

        if(typeof(vars.trigger) === string){
            var trigger = a[1].getElementsByClassName(class);
            vars.trigger = trigger;
        }

        a[i] = new Draggable(a[i], vars);
    }
    return a;
};

Which is exactly what you suggested to do above, since TweenLite.selector is in fact window.$ or the native equivalent.

 

Again thats only my opinion, i just think the trigger will always be a child of the target.

 

Cheers

*A

Share this post


Link to post
Share on other sites

Hi,

 

You're right is hard to imagine one element having a trigger influence to another collection draggable instances. But the trigger not always will be a children of the Draggable target, imagine you have a series of elements in an horizontal disposition and you move them side to side by dragging in a sibling element below or above it or you could even move them by dragging on their parent element, kind of like the iPod records collection.

 

Like Jack said there are plenty of scenarios and accommodating the code to serve all of them properly would be quite a task and it could bloat the filesize which is something Jack is very careful with.

 

Rodrigo.

  • Like 2

Share this post


Link to post
Share on other sites

Yep, Rodrigo is right. Plus, I don't think that code that you suggested would work properly since it assumes the selector text is a class name. And couldn't getElementsByClassName() return multiple results? And what if it was an ID or some more complex selector text? This sounds like an edge case that's better dealt with by simply doing your own loop like I suggested above, wouldn't you agree?

  • Like 3

Share this post


Link to post
Share on other sites

Hi,

 

Jamie made a great example where the Draggable's instance trigger is the parent element:

 

See the Pen lykFn by jamiejefferson (@jamiejefferson) on CodePen

Share this post


Link to post
Share on other sites

It's even less connected than that. The Draggable target and the trigger are independent children of the body with no child/parent relationship, and the onDrag is used to update a third target. Draggable is pretty flexible =)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Warning: Please note

This thread was started before GSAP 3 was released. Some information, especially the syntax, may be out of date for GSAP 3. Please see the GSAP 3 migration guide and release notes for more information about how to update the code to GSAP 3's syntax. 


  • Recently Browsing   0 members

    No registered users viewing this page.

×