Howdy, Stranger!

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

Custom macros: A question about combining multiple macros together

edited March 2014 in Help! with 1.x
Okay, so I have a number of very similar macros that I'd like to combine if possible.  An example of one macro is this, which is based on code supplied here:
macros["append"] =
{
handler: function(place, macroName, params, parser)
{

// process the contents of the container macro
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 we successfully found an end tag for the macro
if (end !== -1)
{
parser.nextMatch = tagEnd;

// Macrocode
this.a = macroName;
this.b = parser.source.slice(start, end);

this.c = ('<div id="' + this.a + '">' + this.b + '</div>');

new Wikifier(place, this.c);
//endmacrocode
}
else
{
throwError(place, "<<" + macroName + ">>: cannot find a matching close tag");
}
},
};
macros["endappend"] = { handler: function () {} };
I have four macros which all use this code, however, where I have marked //macrocode and //endmacrocode shows where the macro differs each time.  The macro names are Append, Question, Answer and Choiceblock. 

I thought I'd try and be clever and combine this into one script using an if statement that would change the contents between //macrocode and //endmacrode based on the name of the macro, but what I've come up with just doesn't seem to work (in fact I just get a blank passage).  The combined macro looks like this:
(function () {
version.extensions['dialoguemacro'] = {
major: 1,
minor: 0,
revision: 0
};

macros['append'] = macros['answer'] = macros['question'] = macros['choiceblock'] =
{
handler: function(place, macroName, params, parser)
{

// process the contents of the container macro
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 we successfully found an end tag for the macro
if (end !== -1)
{

if (macroName = "append")
{
parser.nextMatch = tagEnd;
// append
this.a = macroName;
this.b = parser.source.slice(start, end);

this.c = ('<div id="' + this.a + '">' + this.b + '</div>');

new Wikifier(place, this.c);
}
else if (macroName = "answer")
{
parser.nextMatch = tagEnd;
// answer
this.a = macroName;
this.b = params[0];
this.c = parser.source.slice(start, end);

this.d = ('<div class="answer-' + this.b + '">' + this.c + '</div>');

new Wikifier(place, this.d);
}
else if (macroName = "question")
{
parser.nextMatch = tagEnd;
// question
this.a = macroName;
this.b = params[0];
this.c = parser.source.slice(start, end);

this.d = ('<a class="question" id="' + this.b + '">' + this.c + '</a>');

new Wikifier(place, this.d);

}
else if (macroName = "choiceblock")
{
parser.nextMatch = tagEnd;
// choiceblock
this.a = macroName;
this.b = params[0];
this.c = parser.source.slice(start, end);

this.d = ('<div class="inlinechoice-' + this.b + '" id="' + this.b + '">' + this.c + '</div>');

new Wikifier(place, this.d);
}
}
else
{
throwError(place, "<<" + macroName + ">>: cannot find a matching close tag");
}
},
};
macros["endappend"] = { handler: function () {} };
macros["endanswer"] = { handler: function () {} };
macros["endquestion"] = { handler: function () {} };
macros["endchoiceblock"] = { handler: function () {} };
}());

Have I misunderstood how you would combine a macro?  Is this even possible?  I've looked at some of Leon Arnott's macros and have seen that he often begins his macros with multiple macro names, so I think you can do this?  I'm pretty sure the if logic is correct, because if I put it into one of the standalone macros, I can execute the code based on the name of the macro, so I think it's to do with how I'm combining the macro names at the top/bottom of the code.

Demo with seperate macros: HTML Link  | TWS Link

Demo with combined macro: HTML Link  | TWS Link

Comments

  • Your main issue is that you're using the assignment operator (=) when you meant to use the equality operator (==) within the conditional component of your if statements.  Beyond that, you're repeating yourself unnecessarily and can simplify your code a good deal.

    As a suggestion:

    (function () {

    version.extensions["dialoguemacro"] =
    {
    major : 1
    , minor : 0
    , revision : 0
    };

    macros["append"] = macros["answer"] = macros["question"] = macros["choiceblock"] =
    {
    handler: function(place, macroName, params, parser)
    {
    // process the contents of the container macro
    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 we successfully found an end tag for the macro
    if (end !== -1)
    {
    parser.nextMatch = tagEnd;

    var wikitext = parser.source.slice(start, end);
    switch (macroName)
    {
    case "append":
    wikitext = '<div id="' + macroName + '">' + wikitext + '</div>';
    break;

    case "answer":
    wikitext = '<div class="answer-' + params[0] + '">' + wikitext + '</div>';
    break;

    case "question":
    wikitext = '<div class="question" id="' + params[0] + '">' + wikitext + '</div>';
    break;

    case "choiceblock":
    wikitext = '<div class="inlinechoice-' + params[0] + '" id="' + params[0] + '">' + wikitext + '</div>';
    break;
    }

    new Wikifier(place, wikitext);
    }
    else
    {
    throwError(place, "<<" + macroName + ">>: cannot find a matching close tag");
    }
    }
    };
    macros["endappend"] = macros["endanswer"] = macros["endquestion"] = macros["endchoiceblock"] = { handler: function () {} };

    }());
  • Of course, I should have spotted that given there are plenty of examples in your part of the code!  I'm too used to VBA/SQL syntax I think!  I definitely knew that I was repeating myself, so your suggested modifications are appreciated.  For some reason though, when using your code my .css styling doesn't seem to apply to the appropriate lines, so I'll need to check that out.  I think the idea was to get it working and then to tidy it up  ;D  This has certainly been somewhat of a learning process!
  • The code isn't applying IDs and classes uniformly, so that's likely the issue.
  • If I adjust my original code to == instead of = in the if statement, the css styling works.  Obviously there's a lot of repeated code in there though, but I cut it down using your guide (although it's not exactly the same) and the css styling still works.  However, the example you provided works, but the css styling doesn't seem to work?  It's no big deal, but I'll post my code later anyway.  Once again, thanks for your help though, it's much appreciated.
  • The choiceblock section of your above example produces broken markup.  Maybe that's part of it.  I can't see enough of the picture to say.  /shrug

    The TWS you posted also seems to be missing some external JS (fakechoice1.js), so there's that too.
Sign In or Register to comment.