Howdy, Stranger!

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

[SC 2.6.2] Need help with addclass macro. (possible CSS-dumbness)

edited July 2016 in Help! with 2.0
For a visual feedback system, I want to highlight <td>s in a table to show the player their development:
<<set $path to [1,2,1,2,2,3,1,2,1,2]>>
<table id="eval">
<tbody>
<tr>
<td>&nbsp;</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
<td>10</td>
<td>sum</td>
</tr>
<tr>
<td>Level 5</td>
<td id="4x1">&nbsp;</td>
<td id="4x2">&nbsp;</td>
<td id="4x3">&nbsp;</td>
<td id="4x4">&nbsp;</td>
<td id="4x5">&nbsp;</td>
<td id="4x6">&nbsp;</td>
<td id="4x7">&nbsp;</td>
<td id="4x8">&nbsp;</td>
<td id="4x9">&nbsp;</td>
<td id="4x10">&nbsp;</td>
<td><<print $path.count(4)>></td>
</tr>
<tr>
<td>Level 4</td>
<td id="3x1">&nbsp;</td>
<td id="3x2">&nbsp;</td>
<td id="3x3">&nbsp;</td>
<td id="3x4">&nbsp;</td>
<td id="3x5">&nbsp;</td>
<td id="3x6">&nbsp;</td>
<td id="3x7">&nbsp;</td>
<td id="3x8">&nbsp;</td>
<td id="3x9">&nbsp;</td>
<td id="3x10">&nbsp;</td>
<td><<print $path.count(3)>></td>
</tr>
<tr>
<td>Level 3</td>
<td id="2x1">&nbsp;</td>
<td id="2x2">&nbsp;</td>
<td id="2x3">&nbsp;</td>
<td id="2x4">&nbsp;</td>
<td id="2x5">&nbsp;</td>
<td id="2x6">&nbsp;</td>
<td id="2x7">&nbsp;</td>
<td id="2x8">&nbsp;</td>
<td id="2x9">&nbsp;</td>
<td id="2x10">&nbsp;</td>
<td><<print $path.count(2)>></td>
</tr>
<tr>
<td>Level 2</td>
<td id="#1x1">&nbsp;</td>
<td id="1x2">&nbsp;</td>
<td id="1x3">&nbsp;</td>
<td id="1x4">&nbsp;</td>
<td id="1x5">&nbsp;</td>
<td id="1x6">&nbsp;</td>
<td id="1x7">&nbsp;</td>
<td id="1x8">&nbsp;</td>
<td id="1x9">&nbsp;</td>
<td id="1x10">&nbsp;</td>
<td><<print $path.count(1)>></td>
</tr>
<tr>
<td>Level 1</td>
<td id="0x1">&nbsp;</td>
<td id="0x2">&nbsp;</td>
<td id="0x3">&nbsp;</td>
<td id="0x4">&nbsp;</td>
<td id="0x5">&nbsp;</td>
<td id="0x6">&nbsp;</td>
<td id="0x7">&nbsp;</td>
<td id="0x8">&nbsp;</td>
<td id="0x9">&nbsp;</td>
<td id="0x10">&nbsp;</td>
<td><<print $path.count(0)>></td>
</tr>
</tbody>
</table>

<<for $i to 0; $i lt $path.length; $i++>>\
	<<set $index to $i+1>>\
	<<set $id to "#" + $path[$i] + "x" + $index>>\	
	<<addclass $id "green">>\
	<</for>>\

I get the error
Error: <<addclass>>: no elements matched the selector "#2x4"
for each combination. I was wondering if the "#"-sign was the issue or am I addressing the <td>s incorrectly?

Comments

  • Because the ID'ed HTML TD elements don't exist until they are added to the DOM and rendered, you can't directly reference them within the same passage. So the error message is correct, not element matched the selector, because it does not exist yet.

    You need to use some method to delay the running of your for loop, one of these methods is to use a Task Object like postdisplay.
  • edited July 2016
    greyelf has already explained why what you're trying to do isn't working, so I'll skip to some examples of how to do it. In both examples, I create an aggregate selector and add the class to all of the elements at once—in general, the less you poke the DOM the better. You'll note that I also check the passage name to ensure that the code is only executed on the appropriate passage—without that, it would be executed on all passages.


    Using the PassageDone special passage:
    <<if passage() === "YOUR_TABLE_PASSAGE_NAME">>
    	<<set
    		_selector to $path
    			.map(function (v, i) {
    				return "#" + v + "x" + (i + 1);
    			})
    			.join(",")
    	>>
    	<<addclass _selector "green">>
    <</if>>
    
    I used a temporary variable here to keep the variable store clean.


    Using a postrender task: (goes in Story JavaScript)
    postrender['path-highlighting'] = function (content, taskName) {
    	if (passage() === 'YOUR_TABLE_PASSAGE_NAME') {
    		var selector = State.variables.path
    			.map(function (v, i) {
    				return '#' + v + 'x' + (i + 1);
    			})
    			.join(',');
    		$(content).find(selector).addClass('green');
    	}
    };
    
  • Thank you both for the explanation and the solution. I went for the PassageDone solution and it works perfectly.
    Can I bother you with another thing? I have another array $answerLog that stores, whether the questions have been answered correctly or incorrecty.
    [true, true, false, true, false, false]
    
    The indexes match those of $path.
    Could you help me <<addclass>> two different classes, let's say "red" and "green", depending on the contents of $answerLog?
  • edited July 2016
    Sure, though you're going to have to provide more details than that.

    You say that the indices are the same. Will the selectors be the same as well (e.g. "#2x4") or is this for something else?
  • Oh, great, thank you so much in advance.
    So my $path-array holds the levels at which questions were answered.
    $answerLog has the same size and contains 'true' or 'false' at the same index, reflecting if the questions were answered correctly or not.
    The respective index+1 could be read as the round (1 through 10), thus corresponding to the last digit of the <td>-ids in the above table.
    e.g.:
    $path =[2,2,1,1,2,3,3,2,2,3]
    $answerLog=[false, false, true, true, true, false, true, true, false, false]
    
    would mean that:
    • Question one (index +1) was answered incorrectly at level 2. Class "red" should be added.
    • Question two (index+2) was answered incorrectly at level 2. Class "red" should be added.
    • Question three (index +3) was answered correctly at level 1. Class "green" should be added.
      etc.

    So the selectors will be the same, $answerLog determines, which class should be added.
    (red for false, green for true).
    Thank you!


  • So, it's simply an extension of the previous.

    Try:
    <<if passage() === "YOUR_TABLE_PASSAGE_NAME">>
    	<<set
    		_correct   to [],
    		_incorrect to [];
    
    		$path.forEach(function (v, i) {
    			var selector = "#" + v + "x" + (i + 1);
    
    			if ($answerLog[i]) {
    				_correct.push(selector);
    			} else {
    				_incorrect.push(selector);
    			}
    		});
    
    		_correct   to _correct.join(",");
    		_incorrect to _incorrect.join(",");
    	>>
    	<<addclass _correct "green">>
    	<<addclass _incorrect "red">>
    <</if>>
    
  • edited July 2016
    I've found that in general, <<addclass>> use should be in PassageDone as opposed to passage text where possible, otherwise bad things tend to happen as browsers don't like it when you try to alter the classes at the same time they're trying to display the text.

    Though if you really need it in a passage you can get away with a tiny break created with <<timedcontinue 0.1s>>.
Sign In or Register to comment.