0 votes
by (130 points)

(Using SugarCube v2.12.1, working on a team IF project)

The stock Settings API dialog couldn't handle the amount of content settings we needed without it turning into an ugly beast. We instead built a nice, user-friendly menu with CSS in a story passage named Settings. This works great, with one exception: navigation.

We want to use the UIBar API to handle the Settings button, but we don't want the Settings API to manage the menu. Instead, when the user clicks the Settings button, we just want it to go to the passage exactly like a regular story link would, keeping the 'return' functionality intact.

After toying with things, we figured out how to turn the settings button on without having Settings API objects, by bypassing the check:

false?jQuery("#menu-item-settings").remove():Dialog.addClickHandler("#menu-item-settings a",null,UI.buildSettings).text(L10n.get("settingsTitle"))

However, actually putting in the detour is beyond our team's expertise. Can anyone suggest an approach?

2 Answers

+1 vote
by (63.1k points)

Something like: 

$('#menu-item-settings a').off('click').on('click', function (e) {
    Engine.play('some passage');
});

Will probably work, and won't require you to destroy and recreate the element. 

by (130 points)
Works like a champ. Thank you very much!
by (68.6k points)
edited by

Unfortunately, using .on('click' harms accessibility.  The following would be better:

$('#menu-item-settings a').off().ariaClick(function (ev) {
	ev.preventDefault();
	Engine.play('passage name');
});

That said, unless you've defined settings using the API, the menu item gets removed and doing so just to keep the menu item is silly.  There's also the problem of where you're executing this code (if you place it where you should be, then it won't work as-is, so if it seems to be working you're probably doing something less than ideal; I'm referring to both versions, Chapel's and mine).

All in all, you're probably better off either adding your own entry to the core menu or simply using the StoryMenu special passage.

by (130 points)
Thanks for the heads up on the accessibility issue.

Since the source already builds and then disables the settings button, we simply deactivated the check (for Settings API content) that removes it. With the small change in the OP, the button appears without the need to create any settings using the Settings API, or define a new menu choice.

Since both versions of code are functional when placed after this disabled check, we will use the more accessible version. Thank you both for your help!
+1 vote
by (68.6k points)

For the reasons outlined in my comment on Chapel's answer, I'd suggest something like the following if you want the menu item within the core menu: (goes in your Story JavaScript)

$(document).one(':passageinit', function (ev) {
	var $link = jQuery(document.createElement('a'));
	$link
		.attr('tabindex', 0)
		.text(L10n.get('settingsTitle'))
		.ariaClick(function (ev) {
			ev.preventDefault();
			Engine.play('PASSAGE NAME');
		});
	jQuery(document.createElement('li'))
		.attr('id', 'menu-item-settings')
		.append($link)
		.insertBefore('#menu-item-restart');
});

NOTES:

  1. Replace PASSAGE NAME with the name of your settings passage.
  2. Do not use the Setting API or you'll end up with two conflicting menu items.
...