Is there a way to trigger a macro through mouseover and mouse-off? (Twine 2, Sugarcube 2)

+1 vote
asked Aug 6 by puppetz87 (250 points)
Hello all,

What I'm trying to accomplish is to reveal some items stats (by replacing a div with a <<replace>> macro) within my story everytime the player mouseovers an image (something like how RPGs "reveal" the detailed stats of a piece of equipment everytime the player's mouse hovers over the item slot), and hide those stats as soon as the player's mouse leaves the bounds of the image.

Is there a simple way to accomplish that using CSS? Or do I have to dabble into javascript to achieve that?

2 Answers

0 votes
answered Aug 7 by TheMadExile (14,870 points)

There are various ways to use mouse hover and CSS to reveal hidden information.  What you're, specifically, looking to do—execute macros on mouse hover—however, is something that you'd need JavaScript to accomplish.  So, the question becomes, which do you really need.  Depending on where the item stats/descriptions are coming from and how you're displaying them—mostly the latter, actually—will determine what you can use.  For now, I'll assume you'll need to use <<replace>>, and thus event handlers in JavaScript.

What does the markup of your item images look like?  I ask because a) they need to be targetable and b) the system will need to know which item's stats to show when the player is hovering over its image—I'm assuming here that you aren't going to have separate and unique passages for each item, so distinguishing between them is necessary.

0 votes
answered Aug 7 by Akjosch (3,950 points)

You probably need a bit of JavaScript. Specifically, mark your item images with some data which allows you to identify the item in code (I use a `data-item` attribute for this in the example below), then attach a "mouseover" event handler which clears the description div and replaces it with the item's description.

Example follows. To make it more modular, I created two widgets - "ItemBox" would in your case display the item's image surrounded by the div element, "DescribeItem" describes the item it gets and can get as complicated and intricate as you wish. For the example, I go with ...

<<widget "ItemBox">>
	<<= "<div style='margin: 2px 10px; border: 1px solid white; padding: 2px 10px;' data-item='" + $args[0] + "'>" + $args[1][$args[0]].name + "</div>">>
<</widget>>

<<widget "DescribeItem">>
	<b>$args[0].name</b>
	<hr>
	$args[0].desc
<</widget>>

This can then be used as follows (the first part is simply some dummy variable initialisation).

<<set $items = {
	bsword: {
		name: "Boredsword",
		desc: "This sword looks rather bored. It even yawns when it thinks you're not looking."},
	heal_stone: {
		name: "Healing Potstone",
		desc: "A potent healing agent. Assuming you can eat rocks."},
	cap: {
		name: "Bottlecap",
		desc: "It's essentially trash, but you're still holding onto it in the hope it might once become valuable."},
	}>>
<<set $inv = ["bsword", "cap", "heal_stone", "cap"]>>

<div style="display: flex;">
	<div id="itemlist" style="flex-grow: 1; flex-shrink: 0; width: 33%;">
		<<for _i = 0; _i < $inv.length; ++ _i>><<ItemBox $inv[_i] $items>><</for>>
	</div>
	<div id="itemdesc" style="flex-grow: 2; flex-shrink: 0; width: 66%;">
	</div>
	<<script>>
	jQuery(function() {
		const displayArea = jQuery(itemdesc);
		jQuery("div[data-item]").each(function(idx, div) {
			const itemId = jQuery(div).attr("data-item");
			jQuery(div).mouseover(function() {
				displayArea.empty().wiki("<<DescribeItem `$items['" + itemId + "']`>>");
			});
		});
	});
	<</script>>
</div>

That's it. Those two passages, the first one marked as a widget passage, already show you all the functionality you typically need in such a situation. Try them out!

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.
...