Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Can Links Run Javascript?

Hello all. Inventory system is finished. My page layouts are working. So thanks up front to everyone who helped me with those when I ran into issues. Got a different type of question now. Image for reference.

undefined

So I've got this nifty little equipment div with links for player.head, player.accessory and so on. I've also got the player's location on the bottom right which loads state.history[1].title.passage. So since I don't want to mess with that, does Twine's linking syntax allow you to run a macro or perform an operation without changing the passage? I know you can manipulate variables with it like
[[Give me a cookie!|Passage2][$player.inventory.push("Cookie")]]
Anyway to use Twine link styles to do something else? Like only run a macro? I could do some neat fly-in equipment window stuff if I can figure this out.

Comments

  • I have no idea, but you're game is going to be way cooler than mine ever will!

    So awesome!
  • Thanks for the compliment! You can give me a run for my money I bet, though. :D Speaking of, if anybody sees anything here and asks, "How did you do that?" I'd be more than happy to share the code.
  • I sure wouldn't mind a PM to learn. :)
  • I don't believe any header allows you to use the wiki link syntax and not forward to a passage or an external URL.

    If you were using SugarCube, you could simply use the <<click>> macro, but you aren't.  Let me see if I can convert a really old version of <<click>> to the old-style macro API that the vanilla headers use.

    This should work I believe:



    <<click link_text [passage_name]>><<endclick>>
    Binds its contents to a link, which silently executes/wikifies them when clicked, optionally forwarding the user to another passage.

    Arguments:
    • link_text: The text of the link.
    • passage_name: The, optional, name of the passage to forward the user to.
    Usage:

    <<click "Give me a cookie!">><<set $player.inventory.push("Cookie")>><<endclick>>
    Vanilla <<click>> minified:

    /*! <<click>> macro for the Twine 1.4+ vanilla headers */
    (function(){version.extensions.clickMacro={major:1,minor:1,revision:0};macros.click={handler:function(g,d,b,c){if(0===b.length)throwError(g,"<<"+d+">>: no link text specified");else{for(var a="end"+d,m=c.source.indexOf(">>",c.matchStart)+2,n=-1,h=m,e=m,p=1;-1!==(h=c.source.indexOf("<<",e))&amp;&amp;-1!==(e=c.source.indexOf(">>",h));){var k=c.source.slice(h+2,e),q=k.search(/\s/);-1!==q&amp;&amp;(k=k.slice(0,q));e+=2;switch(k){case a:p--;break;case d:p++}if(0===p){n=h;break}}if(-1!==n){c.nextMatch=e;try{for(a=0;a<
    b.length;a++)b[a]=eval(Wikifier.parse(b[a]))}catch(r){throwError(g,"<<"+d+">>: bad argument: "+b[a],c.fullMatch());return}var f=document.createElement("a"),a=b[0],l=1<b.length?b[1]:void 0;void 0!==l&amp;&amp;f.classList.add(tale.has(l)?"internalLink":"brokenLink");f.classList.add(d+"Link");f.innerHTML=a;f.addEventListener("click",function(){var a=c.source.slice(m,n);return function(){""!==a&amp;&amp;new Wikifier(document.createElement("div"),a);void 0!==l&amp;&amp;state.display(l,f)}}(),!1);g.appendChild(f)}else throwError(g,
    "<<"+d+">>: cannot find a matching close tag")}}};macros.endclick={handler:function(){}}})();
    Vanilla <<click>> unminified: (Hmm.  No [spoiler] tag?  /sigh)

    /*! <<click>> macro for the Twine 1.4+ vanilla headers */
    (function () {
    "use strict";

    version.extensions["clickMacro"] = { major: 1, minor: 1, revision: 0 };
    macros["click"] =
    {
    handler: function (place, macroName, params, parser)
    {
    if (params.length === 0)
    {
    throwError(place, "<<" + macroName + ">>: no link text specified");
    return;
    }

    var openTag = macroName
    , closeTag = "end" + macroName
    , start = parser.source.indexOf(">>", parser.matchStart) + 2
    , end = -1
    , tagBegin = start
    , tagEnd = start
    , opened = 1;

    while ((tagBegin = parser.source.indexOf("<<", tagEnd)) !== -1
    &amp;&amp; (tagEnd = parser.source.indexOf(">>", tagBegin)) !== -1)
    {
    var tagName = parser.source.slice(tagBegin + 2, tagEnd)
    , tagDelim = tagName.search(/\s/);
    if (tagDelim !== -1)
    {
    tagName = tagName.slice(0, tagDelim);
    }

    tagEnd += 2;
    switch (tagName)
    {
    case closeTag:
    opened--;
    break;
    case openTag:
    opened++;
    break;
    }
    if (opened === 0)
    {
    end = tagBegin;
    break;
    }
    }

    if (end !== -1)
    {
    parser.nextMatch = tagEnd;

    try
    {
    // try to process $variable arguments
    for (var i = 0; i < params.length; i++)
    {
    params[i] = eval(Wikifier.parse(params[i]));
    }
    }
    catch (e)
    {
    throwError(place, "<<" + macroName + ">>: bad argument: " + params[i], parser.fullMatch());
    return;
    }

    var linkEl = document.createElement("a")
    , linkText = params[0]
    , passage = params.length > 1 ? params[1] : undefined;

    if (passage !== undefined)
    {
    linkEl.classList.add(tale.has(passage) ? "internalLink" : "brokenLink");
    }
    linkEl.classList.add(macroName + "Link");
    linkEl.innerHTML = linkText;
    linkEl.addEventListener("click", (function ()
    {
    var clickBody = parser.source.slice(start, end);
    return function ()
    {
    // execute the contents and discard the output (if any)
    if (clickBody !== "")
    {
    new Wikifier(document.createElement("div"), clickBody);
    }

    // go to the specified passage (if any)
    if (passage !== undefined)
    {
    state.display(passage, linkEl);
    }
    };
    }()), false);
    place.appendChild(linkEl);
    }
    else
    {
    throwError(place, "<<" + macroName + ">>: cannot find a matching close tag");
    }
    }
    };
    macros["endclick"] = { handler: function () {} };

    }());
    UPDATE: Updated to add $variable substitution.
  • This works! And it's awesome! Thank you so much.

    I don't mean to look a gift horse in the mouth, but is there a way to get the macro to index variables? This code is... beyond me.

    Right now if I can't do <<click $player.accessory>> for example. If it's too much of a hassle, this is still excellent. Thank you again.

    EDIT: Tried making linkText = ("<<" + params[0] + ">>") and that didn't work. Dang!
  • Gah, sorry.  I forgot the vanilla headers make macros perform $variable substitution on their arguments themselves.  One sec, let me fix that.

    UPDATE: Okay!  I've fixed the <<click>> macro above (both the minified and unminified versions) to perform $variable substitution on all arguments.  Things like <<click $player.accessory>> should work now.
  • oh my GOODNESS
  • For those interested, <<click>> without a passage link is functionally identical to a <<replace>> containing a <<silently>>* (but of course significantly briefer and, to its credit, with a slightly more informative name).

    *Which you could substitute for a <<nobr>> if you're only going to put <<set>> inside it, which I wager you will.
  • L wrote:

    For those interested, <<click>> without a passage link is functionally identical to a <<replace>> containing a <<silently>>* (but of course significantly briefer and, to its credit, with a slightly more informative name).

    *Which you could substitute for a <<nobr>> if you're only going to put <<set>> inside it, which I wager you will.


    Is <<click>> part of 1.4?  Or is it stashed away on your blog somewhere?  I've never heard of it before, but it sounds amazing.

    Also, is <<nobr>> working now?  I thought it was buggy...
  • Liyamu wrote:
    Is <<click>> part of 1.4?  Or is it stashed away on your blog somewhere?  I've never heard of it before, but it sounds amazing.

    It's in this very thread (well, the vanilla header version anyway).  Look up thread for it.
  • TheMadExile wrote:

    Liyamu wrote:
    Is <<click>> part of 1.4?  Or is it stashed away on your blog somewhere?  I've never heard of it before, but it sounds amazing.

    It's in this very thread (well, the vanilla header version anyway).  Look up thread for it.


    :o 

    Now don't I feel stupid...  :-[

    Anyway, thanks for this!
Sign In or Register to comment.