Add-ons / Click to Proceed

This set of macros/functions aims to provide an easy way to set up content that is revealed bit-by-bit via user interaction.

Author Cyrus Firheir
Website https://github.com/cyrusfirheir/cycy-wrote-custom-macros/tree/master/click-to-proceed
Story format SugarCube 2
Last checked Wed Feb 24 2021
License Unlicense
Download ctp.zip

Index

Overview

This set of macros/functions aims to provide an easy way to set up content that is revealed bit-by-bit via user interaction.

Using nested <<linkreplace>> and <<linkappend>> works, but gets tedious and is often prone to errors. The CTP (Click To Proceed: original-est name ever) macros make it a bit easier by turning them into blocks instead of nests.

Installation

If using the Twine desktop/web app, copy contents of click-to-proceed.js to Story JavaScript, and contents of click-to-proceed.css to Story Stylesheet.

If using a compiler like Tweego, drop click-to-proceed.js and click-to-proceed.css to your source folder.

click-to-proceed.twee-config.yaml can also be added to the workspace if using the Twee 3 Language Tools VSCode extension, for macro definitions.

Example usage

See more examples.

<<ctp "testID">>
  This is the first string.
<<ctpNext clear>>
  Second! It cleared the first one out!
<<ctpNext nobr>>
  Third, but with nobr...
<<ctpNext 2s>>
  The fourth shows up 2 seconds late.
<<ctpNext t8n>>
  And the final one. With a transition!
<</ctp>>

<<link "Next">>
  <<ctpAdvance "testID">>
<</link>>

<<link "Back">>
  <<ctpBack "testID">>
<</link>>

Macros

<<ctp>>

<<ctp>>

The main CTP macro inside which all content is written.

Usage:

<<ctp id [keywords]>>
  …
<</ctp>>

READ: Documentation

<<ctpNext>>

<<ctpNext>>

To be used inside <<ctp>> to separate the content into blocks.

Usage:

<<ctpNext [keywords]>>

READ: Documentation

<<ctpHead>>

<<ctpHead>>

To be used inside <<ctp>> as a block prepended to the chain which is re-evaluated at every <<ctpAdvance>> and <<ctpBack>>. As long as it is inside <<ctp>>, the position does not matter.

Usage:

<<ctpHead [keywords]>>

READ: Documentation

<<ctpTail>>

<<ctpTail>>

To be used inside <<ctp>> as a block appended to the chain which is re-evaluated at every <<ctpAdvance>> and <<ctpBack>>. As long as it is inside <<ctp>>, the position does not matter.

Usage:

<<ctpTail [keywords]>>

READ: Documentation

<<ctpAdvance>>

<<ctpAdvance>>

The 'proceed' part of Click To Proceed... Used to move the train forward and show the next blocks.

Usage:

<<ctpAdvance id>>

READ: Documentation

<<ctpBack>>

<<ctpBack>>

Turns back time and goes back one block.

Usage:

<<ctpBack id>>

READ: Documentation

Macro keywords

Keywords for controlling behavior:

Additional keywords for individual blocks (<<ctpNext>>, <<ctpHead>>, <<ctpTail>>) in a chain (these are used to break out of behavior set by the <<ctp>> macro):

JavaScript usage

The CTP object

The CTP custom object is set up as follows:

Example:

var ctpTest = new CTP({
  id: "ctpTest",
  selector: "#ctp-test-id"
});

The content object

Each entry in the stack of content (plus the head and tail) is stored in an object structured as follows:

var content = {
  index: 0, // whole number [string for "head" and "tail"]
  clear: false, // boolean
  nobr: false, // boolean
  transition: false, // boolean
  delay: 0, // time in milliseconds
  content: "Actual content to be put out to DOM" // string
}

JavaScript API

CTP.getCTP

CTP.getCTP

Syntax: CTP.getCTP(id [, clone])

Returns a CTP object created with the <<ctp>> macro.

Example:

CTP.getCTP("testID");

<CTP Object>.add()

<CTP Object>.add()

Syntax: <CTP Object>.add(content [, keywords])

Adds content to the end of the stack and returns the CTP object for chaining.

Example:

ctpTest
  .add("This is the first string.")
  .add("Second! It cleared the first one out!", "clear")
  .add("Third, but with nobr...", "nobr")
  .add("And the final one. With a transition!", "t8n");

<CTP Object>.advance()

<CTP Object>.advance()

Syntax: <CTP Object>.advance()

Does the same as <<ctpAdvance>>, moving to the next block. Returns a promise if advanced successfully, undefined otherwise.

Example:

ctpTest.advance();

<CTP Object>.back()

<CTP Object>.back()

Syntax: <CTP Object>.back()

Does the same as <<ctpBack>>, reverting to the previous blocks. Returns the CTP object for chaining.

Example:

ctpTest.back();

<CTP Object>.go()

<CTP Object>.go()

Syntax: <CTP Object>.go(diff)

Jumps to a specific block by the specified number of blocks.

Example:

// advance() twice
ctpTest.go(2);

// go back() twice
ctpText.go(-2);

<CTP Object>.goTo()

<CTP Object>.goTo()

Syntax: <CTP Object>.goTo(index)

Jumps to a specific block to the specified index of block.

Example:

// go to the 5th block
ctpTest.goTo(4);

<CTP Object>.entry()

<CTP Object>.entry()

Syntax: <CTP Object>.entry(index [, noT8n])

Returns the HTML output for a single block at the index passed into it.

Example:

ctpTest.entry(2);

// Assuming ctpTest is the same as in the previous examples, this returns:
// <span class="macro-ctp-entry macro-ctp-entry-index-2">Third, but with nobr...</span>

<CTP Object>.out()

<CTP Object>.out()

Syntax: <CTP Object>.out()

Returns the HTML string output for setting up the chain with the structure and the first block.

NOTE: This does NOT return the contents of the head and tail. That needs to be done manually (see second example.)

Example:

ctpTest.out();

/* Returns:
*
* <span class="macro-ctp-wrapper">
*  <span class="ctp-head"></span>
*  <span class="ctp-body">
*    <span class="macro-ctp-entry macro-ctp-entry-index-0">
*      Content
*    </span>
*  </span>
*  <span class="ctp-tail"></span>
* </span>
*/
$("#test-ctp-element")
  .wiki(ctpTest.out())
  .find(".macro-ctp-wrapper .ctp-head").wiki(CTP.item(ctpTest.head))
  .siblings(".ctp-tail").wiki(CTP.item(ctpTest.tail));

/* Returns:
*
* <span class="macro-ctp-wrapper">
*  <span class="ctp-head">
* 		Head content
* </span>
*  <span class="ctp-body">
*    <span class="macro-ctp-entry macro-ctp-entry-index-0">
*      Content
*    </span>
*  </span>
*  <span class="ctp-tail">
* 		Tail content
* 	</span>
* </span>
*/

Examples

Chain where the Back and Next buttons hide when not needed

<<ctp "testID">>
  <<set _ctp to CTP.getCTP("testID")>>
  This is the first string.
<<ctpHead>>
  <<if _ctp.log.index gt 0>>
    <<button "Back">>
      <<ctpBack "testID">>
    <</button>>
  <</if>>
<<ctpNext clear>>
  Second! It cleared the first one out!
<<ctpNext nobr>>
  Third, but with nobr..
<<ctpNext 500ms>>
  The fourth shows up half a second late.
<<ctpNext t8n>>
  And the final one. With a transition!
<<ctpTail>>
  <<if _ctp.log.index lt _ctp.stack.length - 1>>
    <<button "Next">>
      <<ctpAdvance "testID">>
    <</button>>
  <</if>>
<</ctp>>

Complete usage

State.variables.ctpTest = new CTP({
  id: "ctpTest",
  selector: "#ctp-test-id"
});

State.variables.ctpTest
  .add("This is the first string.")
  .add("Second! It cleared the first one out!", "clear")
  .add("Third, but with nobr...", "nobr")
  .add("And the final one. With a transition!", "t8n");

In Passage:

<div id="#ctp-test-id">
  <<= $ctpTest.out()>>
</div>

<<link "Advance">>
  <<run $ctpTest.advance()>>
  <!-- Because $ctpTest was created manually, using the <<ctpAdvance>>
    macro won't work. To be able to use <<ctpAdvance>>, the CTP object
    needs to be set as a property of State.variables["#macro-ctp-dump"]
    as that is what is used internally to store CTP objects created via
    the macros. -->
<</link>>

Live demo

Demo Twee code:

:: Start
<<ctp "testID">>
  Click next to show a new line of text.
<<ctpNext>>
  Click again to reveal the next line... after 2 seconds.
<<ctpNext 2s>>
  Now click again to reveal more text in this line.
<<ctpNext nobr>>
  The next one will clear the text.
<<ctpNext clear>>
  That is all.
<</ctp>>
<<link "Next">>
  <<ctpAdvance "testID">>
<</link>>
<<link "Back">>
  <<ctpBack "testID">>
<</link>>