0 votes
by (220 points)

Hello, I'm trying to add a tabbed form template from CodePen but keep getting a javascript-error with the form displaying down instead of tabbed.

Also encountering the err on a direct copy-paste on a new twine project.

Using Twine 2.2.1 & Sugarcube 2.28.2 on Twine Local editor & Google Chrome

I have limited Javascript experience could someone please point me to where i'm going wrong?

Javascript from Form Wizard:

$(document).ready(function () {
    //Initialize tooltips
    $('.nav-tabs > li a[title]').tooltip();
    
    //Wizard
    $('a[data-toggle="tab"]').on('show.bs.tab', function (e) {

        var $target = $(e.target);
    
        if ($target.parent().hasClass('disabled')) {
            return false;
        }
    });

    $(".next-step").click(function (e) {

        var $active = $('.wizard .nav-tabs li.active');
        $active.next().removeClass('disabled');
        nextTab($active);

    });
    $(".prev-step").click(function (e) {

        var $active = $('.wizard .nav-tabs li.active');
        prevTab($active);

    });
});

function nextTab(elem) {
    $(elem).next().find('a[data-toggle="tab"]').click();
}
function prevTab(elem) {
    $(elem).prev().find('a[data-toggle="tab"]').click();
}

 

Screenshot of error on Twine:

CodePen Form Wizzard:

1 Answer

+1 vote
by (159k points)

NOTE: The CodePen example you linked to assumes that the Bootstrap v3.3.5 library and a specific font are available, I will assume that you have correctly added both of these things to your project.

The event associated with the $(document).ready() function can't be used within a Twine project, because the story format JavaScript engine that is embedded within the generated Story HTML file is using that event to start up that engine.

SugarCube has it's own set of events which you can use instead, in this specific use-case I suggest using the :passagerender event.

note: You didn't state if the Form Wizard code will be used in all or a limited set of Passages, and knowing this fact can influence where and how you would use the :passagerender event. For the following explanation I will assume you want it in all Passages.

The following copy of your example has been changed to use the specified event, it has also been changed to define the nextTab() and prevTab() functions on the special setup object which makes them available throughout SugarCube code.
This JavaScript code should be placed within your project's Story Javascript area, or within a script tagged passage if you as using a TWEE compiler.

setup.nextTab = function (elem) {
    $(elem).next().find('a[data-toggle="tab"]').click();
};
setup.prevTab = function (elem) {
    $(elem).prev().find('a[data-toggle="tab"]').click();
};

$(document).on(':passagerender', function (ev) {

	const $content = $(ev.content);

	//Initialize tooltips
	$content
		.find('.nav-tabs > li a[title]')
		.tooltip();

    //Wizard
	$content
		.find('a[data-toggle="tab"]')
		.on('show.bs.tab', function (e) {
			var $target = $(e.target);
			if ($target.parent().hasClass('disabled')) {
				return false;
			}
		});

	$content
		.find(".next-step")
		.click(function (e) {
			var $active = $('.wizard .nav-tabs li.active');
			$active.next().removeClass('disabled');
			setup.nextTab($active);
		});

	$content
		.find(".prev-step")
		.click(function (e) {
			var $active = $('.wizard .nav-tabs li.active');
			setup.prevTab($active);
		});
});

Now if you add the HTML from the CodePen example into a Passage and then view it while viewing the story you should see a working approximation of the original.

If you only want the Form Wizard to work in a limited set of passages then you could assign them a known Passage Tag (like form-wizard) and change the above :passagerender handler to the following

$(document).on(':passagerender', function (ev) {

	if (tags().includes('form-wizard')) {

		const $content = $(ev.content);

		//Initialize tooltips
		$content
			.find('.nav-tabs > li a[title]')
			.tooltip();

		//Wizard
		$content
			.find('a[data-toggle="tab"]')
			.on('show.bs.tab', function (e) {
				var $target = $(e.target);
				if ($target.parent().hasClass('disabled')) {
					return false;
				}
			});

		$content
			.find(".next-step")
			.click(function (e) {
				var $active = $('.wizard .nav-tabs li.active');
				$active.next().removeClass('disabled');
				setup.nextTab($active);
			});

		$content
			.find(".prev-step")
			.click(function (e) {
				var $active = $('.wizard .nav-tabs li.active');
				setup.prevTab($active);
			});
	}
});

 

by (220 points)
Oh wow...

Stongly noted,

Thank you @GreyElf!
...