+1 vote
by (210 points)
edited by

Hello, I have the following code and CSS for a drag and drop item. My question is how to make it go to the passage [[entrance]] upon the drop. Ideally I want it to make a noise and then go to the next passage. I am using SugarCube 2.19

Code:

<script>
function allowDrop(ev) {
    ev.preventDefault();
}

function drag(ev) {
    ev.dataTransfer.setData("text", ev.target.id);
}

function drop(ev) {
    ev.preventDefault();
    var data = ev.dataTransfer.getData("text");
    ev.target.appendChild(document.getElementById(data));
}
</script>
Please [[open the door|entrance]] to begin
<div id="div1" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<span id="drag1" draggable="true" ondragstart="drag(event)">Open the door </span>

 

CSS

#div1 {
    width: 350px;
    height: 70px;
    padding: 10px;
    border: 1px solid #aaaaaa;
}


 

1 Answer

+2 votes
by (159k points)
selected by
 
Best answer

The Engine API contains a method named Engine.play() which can be used within your drop function to transition the story to the entrance passage.

by (210 points)

Thank you for your reply greyelf. When I add the line Engine.play("entrance"); I get the following error:

ReferenceError: Engine is not defined.

I do not fully understand the API, is there a special thing I need to do to include them?

by (68.6k points)

In general, you should not be using <script> elements within SugarCube, as they will be evaluated outside of SugarCube's scope—meaning not having access to its APIs.  Try using the <<script>> macro instead.

by (210 points)

Thank you for explaining TheMadExile. So I originally tried using <<script>>, but a funny thing happens. I get the error below. For some reason my function definitions disappear or lose scope outside of the <<script>>?

Error: Uncaught ReferenceError: drag is not defined.

Stack Trace:
ReferenceError: drag is not defined at HTMLSpanElement.ondragstart(chrome-extension....)

 

by (68.6k points)

Sorry.  I wasn't paying enough attention there.  Yes, that's the issue.

If you want to define things that will be globally accessible—which you need since you're using the on… event attributes—then you should:

  1. Place your code in a script section (Twine 2: Story JavaScript; Twine 1: script-tagged passage).
  2. Attach them directly to window or, for the purposes of namespacing, to an object you've attached to window.

For example—attaching them directly to window:

window.allowDrop = function (ev) {
	ev.preventDefault();
};

window.drag = function (ev) {
	ev.dataTransfer.setData("text", ev.target.id);
};

window.drop = function (ev) {
	ev.preventDefault();
	var data = ev.dataTransfer.getData("text");
	ev.target.appendChild(document.getElementById(data));
	
	Engine.play("entrance");
};

NOTE: You do not have to alter how you're calling them in your markup, since properties of window are treated as globals.

by (210 points)
Thank you so much! I've been struggling with this for hours.
...