+1 vote
asked by (1.7k points)

Using Sugarcube 2 in Twine 1.

I'm back with my drag-and-drop nightmares... hope you're all ready for some FUN times. Basically, everything works fine when my draggables & droppables are both in the body, but I've moved my droppables to the UI-bar (StoryCaption, to be specific), and now they don't seem to register their draggable counterparts. Might this have something to do with using 'postdisplay' to set up the drag-and-drop?

Posting all of my code would take ages, so here's some hopefully helpful snippets.

I don't think any of my CSS is relevant, except that the UI-bar is set automatically to a z-index of 50. In order to have the draggables drag over it, I set their z-index arbitrarily to 100. Is this what's causing my problem?

/*these are my draggables*/

.song, .song3 {
padding: 5px;
background-color: rgba(41,0,0,.7);
display: inline-block;
font-size: .9rem;
padding-left: 10px;
padding-right: 10px;
color: rgba(255,255,255,.8);
margin-top: 5px;
z-index: 100;
}

/*and the droppables*/

#firstSlot, #secondSlot, #thirdSlot, #fourthSlot, #fifthSlot, #sixthSlot, .emptySlot {
width: 100%;
border: 3px ridge brown;
border-radius: 5px;
background-color: rgba(255,255,255,.1);
height: 45px;
color: red;
font-size: 1.1rem;
text-align: center;
}

StoryCaption: depending on the passage, display no past choices, offer a current choice ('"#firstSlot") or display a past choice.

<<if tags().includes("none")>>
<div class="emptySlot"></div>
<div class="emptySlot"></div>
<div class="emptySlot"></div>
<<elseif tags().includes("pickone")>>
<div id="firstSlot"></div>
<div class="emptySlot"></div>
<div class="emptySlot"></div>
<<elseif tags().includes("one")>>
<div class="Slot"><<display oneChoice>></div>
<div class="emptySlot"></div>
<div class="emptySlot"></div>
<</if>>

Truncated version of the JQuery. Basically set $need to however many choices are being made in a specific passage, and when the choices hit that amount, reveal the buttons to move forward. Record each dragged object's ID for future reference.

postdisplay["setUp"] = function () {

    $('.btn1').hide();
	$('.btn2').hide();

	$( ".song" ).addClass("touch");

    $( ".song" ).draggable({
	revert: true,
	containment: "document",
	scope: "all"
	});

	$( "#firstSlot" ).droppable({
	drop: handleFirstDrop,
	scope: "all"
	});

	State.variables["songNum"] = 0;

};

function handleFirstDrop( event, ui ) {
	$(this).html("");
    ui.draggable.draggable( 'disable');
    $(this).droppable( 'disable' );
	ui.draggable.removeClass('touch');
	ui.draggable.addClass('done');
    ui.draggable.position( { of: $(this), my: 'left center', at: 'left+3 center' } );
    ui.draggable.draggable('option', 'revert', false);

    State.variables["songNum"]++;
	State.variables["choice1"] = ui.draggable.attr('id');

  if ( State.variables["songNum"] == State.variables["need"]) {
    $('.btn1').show();
	$('.btn2').show();
	$('.ui-draggable').removeClass('touch');
	$('.ui-draggable').draggable('disable');
    }
} 


$(document).on('click', '.btn2 button', function() {

    State.variables["songNum"] = 0;

    $('.btn1').hide();
	$('.btn2').hide();

    $('.ui-draggable') 
        .draggable('enable')
        .addClass('touch')
		.removeClass('done')
        .draggable( 'option', 'revert', true);
    $('.ui-droppable').droppable('enable');

    $('.song').removeAttr('style');

});

Actual passage offering the drag-and-drop choice:

<<set $need to 1>><div id="talk">Passage text goes here...

<div id="songChoice"><div class="song" id="RBFI">Royal Blood - Figure It Out</div> <div class="song" id="CCPB"></div></div>

<span class="btn1"><hr><<button "Yep, that's right.">><<goto "0c">><</button>> <<button "No, wait a second...">><<goto "0b">><</button>></span>
</div>

Any and all help is appreciated, as always.

1 Answer

0 votes
answered by (62.6k points)
selected by
 
Best answer

You cannot use any of the task objects to post-process elements rendered by the various special passages that add content to the UI bar as they all are processed before the special passages in question.  Your only good option here is to use the :passageend event, which was added in SugarCube v2.20.0.

For instance, replace your current postdisplay task:

postdisplay["setUp"] = function () {
	/* set up code goes here */
};

With something like the following:

$(document).on(':passageend', function (ev) {
	/* set up code goes here */
});

 

commented by (1.7k points)
Aha, one of my prime suspects was indeed the guilty culprit! Thanks, I'll fiddle with this.
commented by (1.7k points)
Well... we've gone slightly in the opposite direction. If I place all the jquery within the :passageend event, the draggable are no longer draggable, so I can't test whether the drop works. If I place the draggable within postdisplay and the droppable within :passageend, I can drag them but the slots don't accept the drop. Any thoughts?

I'm 99% sure I'm using version 2.2 of Sugarcube. This is a new computer, so I installed fairly recently, but I can uninstall and reinstall to be certain.
commented by (137k points)

using version 2.2 of Sugarcube

TME stated you need v2.20.0 or later of SugarCube for the :passageend event to exist, I'm unsure if you missed typed the version in your comment or not.

I tested your code by replacing your setUp postdisplay event code with an equivalent :passageend event handler, and dragging a song into a slot in the StoryCaption area worked.

eg. I copied your "Actual passage offering" example into a passage tagged with pickone, your StoryCaption example in to relevant special passage, your CSS example into the Story Stylesheet area, your handleFirstDrop() function into the Story Javascript area, and finally replaced your setUp postdisplay event code with the following :passageend event in the Story Javascript area.

$(document).on(':passageend', function (ev) {
	$('.btn1').hide();
	$('.btn2').hide();
	$( ".song" ).addClass("touch");

	$( ".song" ).draggable({
		revert: true,
		containment: "document",
		scope: "all"
	});

	$( "#firstSlot" ).droppable({
		drop: handleFirstDrop,
		scope: "all"
	});

	State.variables["songNum"] = 0;
});

 

commented by (62.6k points)
Check the version of the release you're using or simply download the latest release (as I write this: v2.21.0).
commented by (1.7k points)
Haha, yep, a typo. That'd be a real trick if I were using a version that outdated!

I reinstalled and everything seems to be doing fine, so I must not have been up to date. Thanks to both of you for your patience and assistance!
Welcome to Twine Q&A, where you can ask questions and receive answers from other members of the community.

You can also find hints and information on Twine on the official wiki and the old forums archive.

See a spam question? Flag it instead of downvoting. A question flagged enough times will automatically be hidden while moderators review it.
...