CSS Tabs not working with PassageDone

Please specify version and format if asking for help, or apply optional tags above:
Twine Version: 2.3.5
Story Format: Sugarcube

I have a village map in CSS tabs like so:

<div id="Manage Village" class="tab" style="display:none">
		<span id="village"><<include "Village Map">></span>
</div>

There’s javascript that changes the style so the div is displayed when you click on the tab, with the function called like this:

<button class="tablink" onclick="openTab(event,'Manage Village')">Manage Village</button>

And here’s the javascript for openTab:

window.openTab = function(evt, tabName) {
  var i, x, tablinks;
  x = document.getElementsByClassName("tab");
  for (i = 0; i < x.length; i++) {
    x[i].style.display = "none";
	}
  tablinks = document.getElementsByClassName("tablink");
  for (i = 0; i < tablinks.length; i++) {
    tablinks[i].className = tablinks[i].className.replace(" red", "");
  }
  document.getElementById(tabName).style.display = "block";
	evt.currentTarget.className += " red";
}

Finally, here’s the passage that is displayed in the tab when you click on it:

<<nobr>>

<<if $villagecenter is "built" and $castle is "built" and $barracks is "built">>
	<img usemap="#Village Map" src="https://i.imgur.com/TJf8HdD.png" alt="Village Map" />
	
<<elseif $villagecenter is "built" and $castle is "built" and $barracks is not "built">>
	<img usemap="#Village Map" src="https://i.imgur.com/d8NXZ1g.png" alt="Village Map" />
	
<<elseif $villagecenter is "built" and $castle is not "built" and $barracks is not "built">>
	<img usemap="#Village Map" src="https://i.imgur.com/rtbpb3g.png" alt="Village Map" />
	
<<elseif $villagecenter is "built" and $castle is not "built" and $barracks is "built">>
	<img usemap="#Village Map" src="https://i.imgur.com/BMNImiM.png" alt="Village Map" />
	
<<elseif $villagecenter is not "built" and $castle is "built">>
	<img usemap="#Village Map" src="https://i.imgur.com/E9YgDOX.png" alt="Village Map" />
	
<<else>>
	<img usemap="#Village Map" src="https://i.imgur.com/QcSlyBL.png" alt="Village Map" />
<</if>>

<map name="Village Map">
	<area alt="Village Center" title="Village Center" data-passage="Village Center" coords="582,159,579,109,561,106,657,21,764,110,736,110,736,160,764,171,789,217,777,280,666,336,537,303,509,255,529,192" shape="poly">

	<area alt="Castle" title="Castle" data-passage="Castle" coords="17,80,17,106,23,108,24,320,91,320,94,303,239,302,242,319,312,318,311,112,320,112,320,81,236,81,234,108,242,110,241,139,97,143,94,107,100,107,98,79" shape="poly">
	
    <area alt="Barracks" title="Barracks" data-passage="Barracks" coords="57,441,71,442,73,547,275,550,278,441,290,439,250,407,209,440,221,442,221,458,122,460,119,440,134,438,94,405" shape="poly">
</map>

<</nobr>>

Problem is, this map needs to use maphilight, which uses the following pasted into PassageDone

<<script>>

// Apply maphilight to all images that have a usemap attribute, e.g.
// all the maps that are in this twine. This sets the default styling
// for all the maps. These are all the possible styling options.
// Note: for picking colors, check out http://hslpicker.com/. You can
// copy the HEX value as long as you leave off the "#".
$("img[usemap]").maphilight({
  fill: true,             	// Fill the area?
  fillColor: 'dd319b',    	// HEX format without the starting "#"
  fillOpacity: 0.5,       	// Opacity of the filled area
  stroke: true,           	// Outline the area?
  strokeColor: 'ef9ace',
  strokeOpacity: 1,
  strokeWidth: 3,			// Outline width
  fade: true,             	// Animate when hovered with a fade?
  alwaysOn: false,        	// Always show the areas?
  neverOn: false,
  groupBy: false,
  wrapClass: true,
  shadow: false,
  shadowX: 0,
  shadowY: 0,
  shadowRadius: 6,
  shadowColor: '000000',
  shadowOpacity: 0.8,
  shadowPosition: 'outside',
  shadowFrom: false
});

<</script>>

I’ve also pasted verbatim the maphilight code into the javascript, which is available at https://github.com/mikewesthad/twine-resources/blob/master/demos/html-maps/jquery.maphilight-modified.min.js. It also works… except for one thing:

The first time the page loads, the map is not displayed, but that’s to be expected. The problem is once you click on the map tab, it displays the map, but PassageDone has already run. It doesn’t find the map, and so no areas highlight. Clicking an area of the map still works without the highlight, and I’ve set it up to refresh the map passage with the new info, after which the highlighting works. But for the first appearance of the map I can’t seem to <<include “PassageDone”>> or replace it, and of course refreshing the containing passage each time the tab comes into focus is an infinite loop. So I’m stumped. Sugarcube is behaving in a way I don’t understand.

I’m not entirely following what you’re trying to do, if I’m honest. However, if the issue is that your script might be firing at the wrong time when the page loads (like before the div is created) so the elements aren’t getting changed like you wanted, you might be able to solve it using the “document ready” trick. It goes like this:

$(document).ready(function() {
	// stuff you want done after the page has completely loaded
});

Just to be clear, document is not a placeholder name. The only thing in the example to replace is what I commented out.

Okay, sorry for being unclear. I’ve updated my question with more context. I’m not sure this document ready trick will work because it seems like the same thing PassageDone is supposed to do (run after everything is loaded). The maphilight needs to use the coordinates to put highlights on the map, but since the map is not displayed at first, it can’t do that.

Edit: Yeah, putting the maphilight function in this document ready function makes no difference.

Would it work if you were to turn your map highlight code into a function and then call it from both PassageDone and also the openTab function?

1 Like

That sounds like it could work, but I’m very unfamiliar with javascript. How would I format it into a function? (I kind of already thought it was a function…)

I’m not 100% certain, since I didn’t try it out, but I think you just need to move the script from the PassageDone passage into a :passagerender event handler instead. So get rid of that passage and put this into your JavaScript section instead:

$(document).on(":passagerender", function (event) {
	// Apply maphilight to all images that have a usemap attribute, e.g.
	// all the maps that are in this twine. This sets the default styling
	// for all the maps. These are all the possible styling options.
	// Note: for picking colors, check out http://hslpicker.com/. You can
	// copy the HEX value as long as you leave off the "#".
	$(event.content).find("img[usemap]").maphilight({
		fill: true,             	// Fill the area?
		fillColor: 'dd319b',    	// HEX format without the starting "#"
		fillOpacity: 0.5,       	// Opacity of the filled area
		stroke: true,           	// Outline the area?
		strokeColor: 'ef9ace',
		strokeOpacity: 1,
		strokeWidth: 3,			// Outline width
		fade: true,             	// Animate when hovered with a fade?
		alwaysOn: false,        	// Always show the areas?
		neverOn: false,
		groupBy: false,
		wrapClass: true,
		shadow: false,
		shadowX: 0,
		shadowY: 0,
		shadowRadius: 6,
		shadowColor: '000000',
		shadowOpacity: 0.8,
		shadowPosition: 'outside',
		shadowFrom: false
	});
});

Hopefully that does the trick! :slight_smile:

Sorry, doesn’t work.

This worked! Thanks!

1 Like