3 different drag elements for 1 drop field?

Hi there,
is it generally possible to generate a drop field for three different drag elements? That the drag elements are swapped and returned to their starting point as soon as a new drag lands in the drop field. And this only with JavaScript, without timeline animations.

Thanks a lot

With JavaScript anything is possible :slight_smile:

As drop targets aren't a built-in feature of Hype, are you currently using any specific drop code?

This is post probably has the most canonical way and easiest setup:

The general flow is:

  1. Add the HypeDragAndDropEnabler.js file to your project, and turn off the "Include in document <head>" checkbox
  2. Add these script tags to your head html via the document inspector:
    <script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=IntersectionObserver"></script>
    <script src="https://cdn.jsdelivr.net/gh/worldoptimizer/HypeMutationObserver@1.1/HypeMutationObserver.min.js"></script>
    <script type="text/javascript" src="${resourcesFolderName}/HypeDragAndDropEnabler.js? toEnsureLoidingLatestBuilt"></script>
    
  3. Add a Class Name to the drop element (in the Identity Inspector)
  4. Add at least these two Additional HTML Attributes to the drag elements (also in the Identity Inspector):
    • data-drag as true
    • data-drop as the class name specified in step 3

In this flow, it is the drag element that specifies where it can be dropped, so it is possible for a single target to take multiple elements.

SimpleDragAndDrop.hype.zip (23.3 KB)

There's more configurability and options that are shown in the original post about it.

3 Likes

dragAndMultipleBack.hype.zip (20.6 KB)

it’ll need timelines and custombehavior for backSwap though …

//////

in fact you could use those custombehavior-events to swap back by listeners … just search the forum for attempts on this feature …

I currently use this drop script:

DragAndDrop.hype.zip (31.5 KB)

But I’m not sure if a combination would work with this script, because I currently have two drop fields for one drag element and I would like to have one dropfield for 3 elements only accepting one at the time returning the other based on the coordinates it has been on its startposition.

you can extend both scripts, but mixing does not make sense …

DragAndDropExtended.hype.zip (23.0 KB)

This solution is on top of the draganddropenabler-script.
To make it work the script needed a small change to make the solved puzzle-pieces avaiable in hypeDocument.customData.solvedPuzzlePieses ...

read the comments in the script to see how it works.

Hope it'll work :slight_smile: (for sure improveable :wink: )

 function collectDragInitPositions(hypeDocument, element, event) {
  		//Object to hold the initial positions of the draggable elements
  		hypeDocument.customData.dragElsOrigPositions = {};
  		//array holding the draggable elements
      const dragEls = [... element.querySelectorAll("[data-drag]")];
      //fill the above mentioned array with top/left positions
      dragEls.forEach(function(el){
      const leftPos = hypeDocument.getElementProperty(el, 'left');
      const topPos = hypeDocument.getElementProperty(el, 'top');
      hypeDocument.customData.dragElsOrigPositions[el.id] = {};
      hypeDocument.customData.dragElsOrigPositions[el.id].left  = leftPos;
      hypeDocument.customData.dragElsOrigPositions[el.id].top  = topPos;
      })

  }


  function extendDragDropJustOneDropAtATime(hypeDocument, element, event) {
 //is it our custombehaviour that triggerd this event?
   if(event.customBehaviorName === "checkApple"){
   //get arr from the set resolved by the extension ...
   const droppedIds = [... hypeDocument.customData.solvedPuzzlePieses];
//set the price. the draggable element holds it as a data-attribute
hypeDocument.getElementById('price').innerHTML = hypeDocument.getElementById(droppedIds[droppedIds.length-1]).dataset.price;
//is there a second apple in the shoppingbag, then put it out
  if(droppedIds.length > 1){
  //the first entry is the outdated one
const identyfier = droppedIds[0];
//get the element
const el = hypeDocument.getElementById(identyfier);
//reset its position
hypeDocument.setElementProperty(el, 'left', hypeDocument.customData.dragElsOrigPositions[identyfier].left, 0.3, 'easeinout');
hypeDocument.setElementProperty(el, 'top', hypeDocument.customData.dragElsOrigPositions[identyfier].top, 0.3, 'easeinout');
//delete id from the set
hypeDocument.customData.solvedPuzzlePieses.delete(identyfier);
  };

   
   }
    return true;
  }

  if("HYPE_eventListeners" in window === false) {
    window.HYPE_eventListeners = Array();
  }
  window.HYPE_eventListeners.push({"type":"HypeTriggerCustomBehavior", "callback":extendDragDropJustOneDropAtATime});
  window.HYPE_eventListeners.push({"type":"HypeScenePrepareForDisplay", "callback":collectDragInitPositions});
4 Likes

Many thanks :slight_smile:

Is it also possible to do a second drag and drop function in the same hype? These separate from each other. So if id 4.apple meets the shopping bag 2, that it has no influence on the upper drag and drop function. Thanks a lot!!!

DragAndDropExtended-2.hype.zip (39.7 KB)

1 Like

yes, everything (well a lot :wink: ) is possible :slight_smile:

the key-functionalities here are

  1. the hypeDocument.customData.solvedPuzzlePieses
    This set serves the ids of all dropped draggable elements.

  2. the usage of custombehaviors to run javascript functions to analyse and act on the above set-data

so it just depends on some logic to set up here …
But this highly depends on basic js-knowledge AND the implementation that Hype does here.

Helping out here would only trigger the next question. So best help here seems to get you help yourself:)

the first answer of mine includes enough info to solve this …

/////
javascript.info may be a good starting point on js
and hypes documentation on js of course:
https://tumult.com/hype/documentation/#javascript

this may seem a long way, but’ll get you really further!

2 Likes

Yesterday I worked on this hype (DragAndDropExtended) all day long… And of course I read all the Javascript articles. Now the Javascript HypeDragAndDropEnabler makes me insecure. Does this also have to be edited like the script in the hype head? Would be very grateful for this tip.

I would place a feature request for that @jonathan @Daniel ! Drag and drop is gaining in popularity and use cases are growing. Especially designers with no js coding experience would be thankful to have a visual implementation of this great engaging feature built-in in hype for designing educational drag-n-drop online games.

1 Like

to clarify:

  • the script enables drag and drop functionality without the need to script.
  • it’s got even some non-coding-logic-possibility using the data-onpuzzlesolved which checks if all draggable elements have been placed …
  • the executed custumbehaviours offer the possibility to add responses <- here is also set up for your own scripting logic for more advanced use cases

your case seems to need this scripted addition. in fact i’m not 100% sure what you’re trying to achieve and that’s why i advised to learn js … for you to be independend!

///////
in detail:
If you like to use the HypeDragAndDropEnabler, then the way to go will be to rely on its functionality. This means working with custombehaviours and the set hypeDocument.customData.solvedPuzzlePieses (uhh, i really wrote pieses instead of pieces in the script). Hypes messaging system dispatches the custombehaviour-events. (a nice overview -> https://github.com/worldoptimizer/HypeCookBook/wiki/Hype-Events). The common way to act on those events is to write the code to the documents head. (implementation is also described in Hypes documentation)

So let’s say you’ve added the data-attribute data-dropcustombehavior to a dropfield. Than hype will forward a custombehaviour-event whose event.customBehaviorName will be the value of the attribute.
Now the script in the head can check this and act … you know the element that triggered the event and the above mentioned set holds the ids of the elements that have been dropped. That should be enough info for a logical decision to get it go …

///////////////////////////

this won’t be an very easy task and you probably won’t know enough about js in one day …

////////////////////////

any other solution will be possible, but’ll always rely on custom scripting …

1 Like

@Ed_Sager you’re right, but please consider that a pure drag and drop functionality won’t solve the issues coming up to implement logical decisions on those drag and drops … there are so many custom use cases. you can not cover them all …

1 Like

Yes - we’d definitely like to “off the shelf” have ways to detect dropping and collisions, but ultimately there will need to be logic to decide what to do with it.

@Ed_Sager Yes this would be fantastic. I am a designer student and have litle experience with JavaScript. This would make things a lot easier for me. Of course it always depends on the application, but it would be a great help for all designers.

Ps: I still try to solve the riddle from this post so I can go on in my project but I feel miles away …

1 Like

As drop targets aren’t a built-in feature of Hype, are you currently using any specific drop code?

This could be one possibility without the need of custom scripting … https://www.youtube.com/watch?v=bJYgCNTwt0Q&feature=youtu.be

indeed there are several other approaches just search the forum … :slight_smile:

I am stuck and have to admit in the end that I am “only” a desiger. What I tried to program was for nothing. Now I ask if someone could make me an offer to solve this little problem (for a programmer)? I am very thankful for every offer, because I would like to have this great function in my project.

Hi there,
I have 3 different drag elements for 1 drop field but I have even 4 sets of elements. Look the following image:


At the moment when I drag for example the head1 element on its drop it's rejecting the other elements just dragged and that's because I have a "checkApple" custombehavior for everything.

Can you suggest me the way to change the initial script to allow every set can stay in its place eventually with 3 custombehaviors? Thanks in advance.

DD_replace.zip (52.4 KB)

I guess I don't quite understand the behavior you want - if you do not want the pieces to get rejected out, just remove the "checkApple" behavior/listener code, since this is what is only allowing a single piece at a time.

Can you maybe give a few steps as explicit actions on what you want to happen and for which dropzone?