i made a new macro for twine!
first, you can check out a small demo that uses it.
this is for twine 1.4, and is a macro that adds some slightly more advanced form controls, with inline displays. this adds three new macros:
a
a
(if you want text to be refreshed based on multiple toggle groups, you can nest
an example of use:
would display two sets of three selections, with a "$var is ..." blurb beneath each one that's automatically updated every time you change a value.
here's the code:
here's some example css:
and you should just be able to drop those into 'script' and 'stylesheet'-tagged passages, respectively, for the macro to work.
(the one thing missing from that css wrt the demo is the demo also has a
first, you can check out a small demo that uses it.
this is for twine 1.4, and is a macro that adds some slightly more advanced form controls, with inline displays. this adds three new macros:
<<toggle>>, <<block>>, and <<endblock>>.a
<<toggle>> is in the form <<toggle $varname groupname value display>>, and it generates some clickable text ("display"), which, when clicked, will set $varname to value. if there are multiple toggles with the same groupname, clicking one will deselect any others.a
<<block>> is in the form <<block groupname>>...<<endblock>>. when a toggle is selected, it will also inline refresh the text inside any blocks with matching groupnames.(if you want text to be refreshed based on multiple toggle groups, you can nest
<<block>>s with no issue.)an example of use:
<<toggle $foo foo foo_a "foo a">>
<<toggle $foo foo foo_b "foo b">>
<<toggle $foo foo foo_c "foo c">>
<<block foo>>\
$foo is <<print $foo>>
<<endblock>>
<<toggle $bar bar 1 one>>
<<toggle $bar bar 2 two>>
<<toggle $bar bar 3 three>>
<<block bar>>\
$bar is <<print $bar>>
<<endblock>>would display two sets of three selections, with a "$var is ..." blurb beneath each one that's automatically updated every time you change a value.
here's the code:
::block macro [script]
function innercontent(tag, parser) {
var
i,
textbegin = parser.source.indexOf(">>",parser.matchStart)+2,
textend = -1,
text = parser.source.slice(textbegin),
depth = 0;
for (i = 0; i < text.length; i++) {
if (text.substr(i,tag.length + 5) === ("<<end" + tag)) {
if(depth===0){
textend=textbegin+i;
break;
}else{
depth--;
}
} else if (text.substr(i,tag.length + 2) === ("<<" + tag)) {
depth++;
}
}
if (textend === -1) {
throwError(place,"can't find matching end"+tag,parser.fullMatch());
return;
}
return [textbegin, textend];
}
function parseArg (str) { return (str[0] == "$"? eval(Wikifier.parse(str)) : str); }
function varArg (str) { return (str[0] == "$"? str.substr(1) : str); }
macros.block = {
handler: function (place, macroName, params, parser) {
var class_ = params[0][0] == "$"
? eval(Wikifier.parse(params[0]))
: params[0];
var block = insertElement (null, "span", null, "blockSpan " + class_.replace(" ", "_"));
var inner_index = innercontent ("block", parser);
block.tweecode = parser.source.slice(inner_index[0], inner_index[1]);
parser.nextMatch=inner_index[1];
place.insertBefore(block,null);
new Wikifier(block, block.tweecode);
}
};
macros.endblock = { handler: function () {}}
macros.toggle = {
handler: function (place, macroName, params, parser) {
var varName = params[0] !== undefined ? varArg(params[0]) : null;
var group = params[1] !== undefined ? parseArg(params[1]) : null;
var value = params[2] !== undefined ? parseArg(params[2]) : null;
var display = params[3] !== undefined ? parseArg(params[3]) : null;
var c = insertElement (null, "span", null, "toggleContainer", null);
var toggleInput = insertElement (c, "input", "toggle_" + value, "toggleInput toggleGroup_" + group, null);
var toggleLabel = insertElement (c, "label", null, "toggleLabel", display);
toggleInput.type = "radio";
toggleInput.name = group;
toggleInput.value = value;
toggleLabel.htmlFor = "toggle_" + value;
var changeList = [group];
toggleInput.addEventListener ('change', function () {
console.log (params[0] + " set to \"" + toggleInput.value + "\"");
state.history[0].variables[varName] = toggleInput.value;
changeList.map (function (f) { console.log (f); reshow (f); });
});
place.insertBefore(c, null);
}
};
window.reshow = function (name) {
var
rall=document.querySelectorAll(".passage .blockSpan." + name.replace(" ", "_")),
ret=false;
for(var i=0;i<rall.length;i++){
ret=reshowOne(rall[i]);
}
return ret;
}
function reshowOne (target) {
target.innerHTML="";
new Wikifier(target,target.tweecode);
target.classList.add("blockSpanIn");
if(target.timeout){
clearTimeout(target.timeout);
}
target.timeout=setTimeout(
function(){
target.classList.remove("blockSpanIn");
},
1);
}here's some example css:
::toggle style [stylesheet]
input[type="radio"].toggleInput { display: none; }
input.toggleInput + label { padding: 2px; cursor: pointer; font-weight: bold; transition: 0.5s; }
input.toggleInput + label { background: transparent; color: #f09; }
input.toggleInput + label:hover { background: #400020; color: #f9c; }
input.toggleInput:checked + label { background: #f09; color: #000; }and you should just be able to drop those into 'script' and 'stylesheet'-tagged passages, respectively, for the macro to work.
(the one thing missing from that css wrt the demo is the demo also has a
table label { display: block; } style rule, to make all the labels the same width inside the table they're laid out in.)