Forum Discussion

StevenChippe932's avatar
StevenChippe932
Community Member
4 years ago

Sort variables from highest to lowest

Hi,

Does anyone have a Javascript for taking a series of number variables, corresponding text variables of their labels, sorting them, then populating, say "varTop3_1_Label", "varTop3_1_Score", "varTop3_2_Label", "varTop3_2_Score", "varTop3_3_Label", and "varTop3_3_Score"?

I have been asked to create a "Top 3" from values selected on 18 sliders, displaying the top 3 Slider's "name"s and the Slider value.

I have tackled this before on a timed quiz using triggers, where each quiz question has a countdown timer and the user gets fewer points the longer it takes to answer if they answer correctly. Then their score is placed on a leaderboard. This was a mammoth task, and something I'm struggling to recreate with this sliders activity.

I'm guessing this can be accomplished more efficiently using Javascript. It doesn't need to be dynamic - what I'm aiming for is a "click this button to view your top 3" button.

I have little-to-no knowledge of Javascript, but this kind of request comes in from time-to-time, so I would like to have a working script that can be adapted whenever these self-evaluation type requests come in.

I'm guessing it would need to comprise of

  1. player.GetVars for variables of the slider names and their values,
  2. a JS var that creates a string from the values
  3. a .sort() function to reorder them
  4. the reordered string to be written to JS vars
  5. Those JS values be player.Setvar'd to the SL variables "varTop3_1_Label", "varTop3_1_Score", "varTop3_2_Label" etc.

I just don't know how to construct it, especially ensuring that the values are linked to their label.

I have tried adapting some found JS from elsewhere on ELH, but I think it was designed to operate differently to what I'm trying to accomplish:

var player = GetPlayer();
var Slider1 = player.GetVar("Slider1");
var Slider2 = player.GetVar("Slider2");
var Slider3 = player.GetVar("Slider3");
var Slider4 = player.GetVar("Slider4");
var Slider5 = player.GetVar("Slider5");
var Slider6 = player.GetVar("Slider6");
var Slider7 = player.GetVar("Slider7");
var Slider8 = player.GetVar("Slider8");
var Slider9 = player.GetVar("Slider9");
var Slider10 = player.GetVar("Slider10");
var Slider11 = player.GetVar("Slider11");
var Slider12 = player.GetVar("Slider12");
var Slider13 = player.GetVar("Slider13");
var Slider14 = player.GetVar("Slider14");
var Slider15 = player.GetVar("Slider15");
var Slider16 = player.GetVar("Slider16");
var Slider17 = player.GetVar("Slider17");
var Slider18 = player.GetVar("Slider18");

var Points = [Slider1, Slider2, Slider3, Slider4, Slider5. Slider6, Slider7, Slider8, Slider9, Slider10, Slider11, Slider12, Slider13, Slider14, Slider15, Slider16, Slider17, Slider18];

Points.sort(function(a , b){return b-a});
for ( i=O;i <Points.length;i++)
document. write(Points[i] + "<br >" ) ;
player.Setvar ("Points",Points) ;

  • I have managed to get this to work.

    For the benefit of anyone else wanting to sort variables into order, here is the Javascript  I used:

    var player = GetPlayer();
    var Slider1 = player.GetVar("Slider1");
    var Slider2 = player.GetVar("Slider2");
    var Slider3 = player.GetVar("Slider3");
    var Slider4 = player.GetVar("Slider4");
    var Slider5 = player.GetVar("Slider5");
    var Slider6 = player.GetVar("Slider6");
    var Slider7 = player.GetVar("Slider7");
    var Slider8 = player.GetVar("Slider8");
    var Slider9 = player.GetVar("Slider9");
    var Slider10 = player.GetVar("Slider10");
    var Slider11 = player.GetVar("Slider11");
    var Slider12 = player.GetVar("Slider12");
    var Slider13 = player.GetVar("Slider13");
    var Slider14 = player.GetVar("Slider14");
    var Slider15 = player.GetVar("Slider15");
    var Slider16 = player.GetVar("Slider16");
    var Slider17 = player.GetVar("Slider17");
    var Slider18 = player.GetVar("Slider18");
    var SliderName1 = player.GetVar("SliderName_1");
    var SliderName2 = player.GetVar("SliderName_2");
    var SliderName3 = player.GetVar("SliderName_3");
    var SliderName4 = player.GetVar("SliderName_4");
    var SliderName5 = player.GetVar("SliderName_5");
    var SliderName6 = player.GetVar("SliderName_6");
    var SliderName7 = player.GetVar("SliderName_7");
    var SliderName8 = player.GetVar("SliderName_8");
    var SliderName9 = player.GetVar("SliderName_9");
    var SliderName10 = player.GetVar("SliderName_10");
    var SliderName11 = player.GetVar("SliderName_11");
    var SliderName12 = player.GetVar("SliderName_12");
    var SliderName13 = player.GetVar("SliderName_13");
    var SliderName14 = player.GetVar("SliderName_14");
    var SliderName15 = player.GetVar("SliderName_15");
    var SliderName16 = player.GetVar("SliderName_16");
    var SliderName17 = player.GetVar("SliderName_17");
    var SliderName18 = player.GetVar("SliderName_18");

    var myarray = [
    { key: SliderName1, val: Slider1 },
    { key: SliderName2, val: Slider2 },
    { key: SliderName3, val: Slider3 },
    { key: SliderName4, val: Slider4 },
    { key: SliderName5, val: Slider5 },
    { key: SliderName6, val: Slider6 },
    { key: SliderName7, val: Slider7 },
    { key: SliderName8, val: Slider8 },
    { key: SliderName9, val: Slider9 },
    { key: SliderName10, val: Slider10 },
    { key: SliderName11, val: Slider11 },
    { key: SliderName12, val: Slider12 },
    { key: SliderName13, val: Slider13 },
    { key: SliderName14, val: Slider14 },
    { key: SliderName15, val: Slider15 },
    { key: SliderName16, val: Slider16 },
    { key: SliderName17, val: Slider17 },
    { key: SliderName18, val: Slider18 }
    ]

    myarray.sort(function(a, b){
    return b.val - a.val;
    });

    var Top1Object = myarray[0];
    var Top2Object = myarray[1];
    var Top3Object = myarray[2];

    var Top1DestructuredLabel = Top1Object.key
    var Top2DestructuredLabel = Top2Object.key
    var Top3DestructuredLabel = Top3Object.key

    var Top1DestructuredValue = Top1Object.val
    var Top2DestructuredValue = Top2Object.val
    var Top3DestructuredValue = Top3Object.val

    Top1LabelForStoryline = Top1DestructuredLabel.toString();
    Top2LabelForStoryline = Top2DestructuredLabel.toString();
    Top3LabelForStoryline = Top3DestructuredLabel.toString();

    Top1ValueForStoryline = Top1DestructuredValue.toString();
    Top2ValueForStoryline = Top2DestructuredValue.toString();
    Top3ValueForStoryline = Top3DestructuredValue.toString();

    player.SetVar ("Top3_1_Label",Top1LabelForStoryline);
    player.SetVar ("Top3_2_Label",Top2LabelForStoryline);
    player.SetVar ("Top3_3_Label",Top3LabelForStoryline);
    player.SetVar ("Top3_1_Value",Top1ValueForStoryline);
    player.SetVar ("Top3_2_Value",Top2ValueForStoryline);
    player.SetVar ("Top3_3_Value",Top3ValueForStoryline);


    To reuse this, you just need to change the 'Slider1' etc. and 'SliderName_1' etc. in quotes to the names of your Storyline variables for the labels and values to rank, If you need more or less than 18 like I have, you need to add or delete rows - remember that the second paragraph ends with a ].

    If you want to have a Top 5, Top 10 or whatever, you'll need to add additional lines to the last 6 paragraphs, mirroring the syntax. 

    Then create these text variables in Storyline: called:
    Top3_1_Label
    Top3_2_Label
    Top3_3_Label
    Top3_1_Value
    Top3_2_Value
    Top3_3_Value
    .. and insert them as references in the text box or table you want them displayed in.

    If you're interested in how this works, the first paragraph brings in the labels and values from Storyline, the second organises them into an array ready for sorting, the third little paragraph sorts in reverse numerical order like a league table or scoreboard ( if you need to be in numerical order from least to most, substitute that part with
    myarray.sort(function(a, b){
    return a.val - b.val;
    });
    The fourth paragraph extracts the first, second and third from the sorted array (in Javascript, 0=First, 1=Second etc.)
    The Fifth and Sixth pull apart the joined-up "Label-Value" into separate Label and Value variables
    The Seventh and Eighth convert those variables into strings to make sure Storyline can understand them
    The final paragraph updates the Storyline variables Top_3_1_Label etc. with the new variables.

    I’ve been told, by people knowledgeable and helpful enough to advise me, that this could be done more efficiently by using dot notation in the fourth paragraph, eradicating the need for the 5th and 6th paragraphs (the erroneously named ‘destructured’ vars), but they were oddly reluctant to actually explain how, and I’m not a JavaScript developer, so it is what it is.

  • I have done some research, and I think I'm getting nearer to solving this, although it doesn't yet produce outputs into the variables (I get [object Object] for each. Maybe my syntax is out.

    var player = GetPlayer();
    var Slider1 = player.GetVar("Slider1");
    var Slider2 = player.GetVar("Slider2");
    var Slider3 = player.GetVar("Slider3");
    var Slider4 = player.GetVar("Slider4");
    var Slider5 = player.GetVar("Slider5");
    var Slider6 = player.GetVar("Slider6");
    var Slider7 = player.GetVar("Slider7");
    var Slider8 = player.GetVar("Slider8");
    var Slider9 = player.GetVar("Slider9");
    var Slider10 = player.GetVar("Slider10");
    var Slider11 = player.GetVar("Slider11");
    var Slider12 = player.GetVar("Slider12");
    var Slider13 = player.GetVar("Slider13");
    var Slider14 = player.GetVar("Slider14");
    var Slider15 = player.GetVar("Slider15");
    var Slider16 = player.GetVar("Slider16");
    var Slider17 = player.GetVar("Slider17");
    var Slider18 = player.GetVar("Slider18");
    var SliderName1 = player.GetVar("SliderName_1");
    var SliderName2 = player.GetVar("SliderName_2");
    var SliderName3 = player.GetVar("SliderName_3");
    var SliderName4 = player.GetVar("SliderName_4");
    var SliderName5 = player.GetVar("SliderName_5");
    var SliderName6 = player.GetVar("SliderName_6");
    var SliderName7 = player.GetVar("SliderName_7");
    var SliderName8 = player.GetVar("SliderName_8");
    var SliderName9 = player.GetVar("SliderName_9");
    var SliderName10 = player.GetVar("SliderName_10");
    var SliderName11 = player.GetVar("SliderName_11");
    var SliderName12 = player.GetVar("SliderName_12");
    var SliderName13 = player.GetVar("SliderName_13");
    var SliderName14 = player.GetVar("SliderName_14");
    var SliderName15 = player.GetVar("SliderName_15");
    var SliderName16 = player.GetVar("SliderName_16");
    var SliderName17 = player.GetVar("SliderName_17");
    var SliderName18 = player.GetVar("SliderName_18");

    var myarray = [{ key: SliderName1, val: Slider1 }, { key: SliderName2, val: Slider2 }, { key: SliderName3, val: Slider3 }, { key: SliderName4, val: Slider4 }, { key: SliderName5, val: Slider5 }, { key: SliderName6, val: Slider6 }, { key: SliderName7, val: Slider7 }, { key: SliderName8, val: Slider8 }, { key: SliderName9, val: Slider9 }, { key: SliderName10, val: Slider10 }, { key: SliderName11, val: Slider11 }, { key: SliderName12, val: Slider12 }, { key: SliderName13, val: Slider13 }, { key: SliderName14, val: Slider14 }, { key: SliderName15, val: Slider15 }, { key: SliderName16, val: Slider16 }, { key: SliderName17, val: Slider17 }, { key: SliderName18, val: Slider18}];

    myarray.sort(function(a, b){return b.val - a.val});

    var [var1, var2, var3, var4, var5, var6, var7, var8, var9, var10, var11, var12, var13, var14, var15, var16, var17, var18] = myarray;

    Top31 = var1.toString();
    Top32 = var2.toString();
    Top33 = var3.toString();
    Top3All = myarray.toString();

    player.SetVar ("Top3_1" ,Top31);
    player.SetVar ("Top3_2" ,Top32);
    player.SetVar ("Top3_3" ,Top33);
    player.SetVar ("Top3_All", Top3All);

  • Hi Steven!

    I just wanted to say your script works great! Very easy to replicate and adapt, and your explanations for how it works were perfect!

    Thanks again!

  • Hello,

    I hope anybody can help. I want to rank (13) scores (variables) that are determined through an assessment. The scores then need to be ranked (descending order) and then match to variables RankOne, RankTwo, etc.

    This is how far I got:

    Yes, I checked the article. It was not that much helpful so we decided to make a custom code for it.

    here's the latest code:
    var player = GetPlayer();
    var Analytical_Score = player.GetVar("Analytical_Score");
    var Collaborative_Score = player.GetVar("Collaborative_Score");
    var Adaptable_Score = player.GetVar("Adaptable_Score");



    var data = [Analytical_Score, Collaborative_Score, Adaptable_Score];


    var count = 0;
    var values = [] ;

    for (var i = 0; i < data.length; i++) {

    count = count+1
    }

    var data1 = new Array();

    // $.each( data, function( key, value ) {

    for (var i = 0; i < data.length; i++) {

    data1[i] = data[i].value;

    }


    // these code are important for reading the score. need to call these variables after sorting is done
    // var RankOne = data[0];
    // var RankTwo = data[1];
    // var RankThree = data[2];

    document.write(data[i] + "<br >" ) ;

    // for descending order
    data1.reverse(data1.sort());
    // for ascending order
    data1.sort();
    player.SetVar("OrderScore",data);

  • Hi Steven! This post is several years old now, but I wanted to say thanks for posting your finished solution. I built a Jeopardy-style quiz game and wanted to rank the winners on the final slide. This was my first ever experience using JavaScript in Storyline, and you made it super easy and straightforward! Thanks for sharing your hard work so the rest of us can benefit.

  • Hi Steven

    I agree with Katherine above.  I have no Javascript knowledge and ironically, I have 18 groupings of data that I am trying to generate the top 3 of.  This script couldn't be more perfect.  I only wish I knew what I was doing wrong.

    I have a feeling that I am missing something really simple.  For that, I apologize. :)

    As instructed, I changed all the "Slider1" and "SliderName_1" to the Variables I set in mine. 

    Mine are:

    1. "A_Counter" (to "R_Counter").  These count every time that a particular group option is chosen throughout the course. 

    2. "A_name" (to "R_Name") which converts the letter to its complete name. (Example A_Name = Arts and Sciences, B_Name = Science and Technology, etc.)

    I have created 3 more variables: "1st", "2nd", and "3rd" for the top 3 ranked letters (which when placed, show the complete name instead of the letter).

    What other variables do I need to have for this Javascript to work?

    In the attachment - for the sake of ease, I put a random number in each Counter variable to bypass the very long survey that is required to count up the totals.

    Slide 1 - is the current manual effort that the Javascript would replace.  Currently, the user has to look at the results and manually enter the top three highest scores into text entry boxes.

    Slide 2 - Converts the 3 manually entered top letters to their full name.  On this slide the learner can Learn more about each group they are most interested in.

    In a perfect world we would let the javascript calculate the top three results that are revealed on the 2nd slide. so that we wouldn't need to show the first slide.

    What am I missing?  I may be missing variables or storyline triggers.  I have no idea.

    Here is the modified Javascript that Steven provided above with my variables in place.  Below is my test story file.

    var player = GetPlayer();
    var A_Counter = player.GetVar("A_Counter");
    var B_Counter = player.GetVar("B_Counter");
    var C_Counter = player.GetVar("C_Counter");
    var D_Counter = player.GetVar("D_Counter");
    var E_Counter = player.GetVar("E_Counter");
    var F_Counter = player.GetVar("F_Counter");
    var G_Counter = player.GetVar("G_Counter");
    var H_Counter = player.GetVar("H_Counter");
    var I_Counter = player.GetVar("I_Counter");
    var J_Counter = player.GetVar("J_Counter");
    var K_Counter = player.GetVar("K_Counter");
    var L_Counter = player.GetVar("L_Counter");
    var M_Counter = player.GetVar("M_Counter");
    var N_Counter = player.GetVar("N_Counter");
    var O_Counter = player.GetVar("O_Counter");
    var P_Counter = player.GetVar("P_Counter");
    var Q_Counter = player.GetVar("Q_Counter");
    var R_Counter = player.GetVar("R_Counter");
    var A_name = player.GetVar("A_name");
    var B_name = player.GetVar("B_name");
    var C_name = player.GetVar("C_name");
    var D_name = player.GetVar("D_name");
    var E_name = player.GetVar("E_name");
    var F_name = player.GetVar("F_name");
    var G_name = player.GetVar("G_name");
    var H_name = player.GetVar("H_name");
    var I_name = player.GetVar("I_name");
    var J_name = player.GetVar("J_name");
    var K_name = player.GetVar("K_name");
    var L_name = player.GetVar("L_name");
    var M_name = player.GetVar("M_name");
    var N_name = player.GetVar("N_name");
    var O_name = player.GetVar("O_name");
    var P_name = player.GetVar("P_name");
    var Q_name = player.GetVar("Q_name");
    var R_name = player.GetVar("R_name");

    var myarray = [
    { key: A_name, val: A_Counter },
    { key: B_name, val: B_Counter },
    { key: C_name, val: C_Counter },
    { key: D_name, val: D_Counter },
    { key: E_name, val: E_Counter },
    { key: F_name, val: F_Counter },
    { key: G_name, val: G_Counter },
    { key: H_name, val: H_Counter },
    { key: I_name, val: I_Counter },
    { key: J_name, val: J_Counter },
    { key: K_name, val: K_Counter },
    { key: L_name, val: L_Counter },
    { key: N_name, val: M_Counter },
    { key: N_name, val: N_Counter },
    { key: O_name, val: O_Counter },
    { key: P_name, val: P_Counter },
    { key: Q_name, val: Q_Counter },
    { key: R_name, val: R_Counter }
    ]

    myarray.sort(function(a, b){
    return b.val - a.val;
    });

    var Top1Object = myarray[0];
    var Top2Object = myarray[1];
    var Top3Object = myarray[2];

    var Top1DestructuredLabel = Top1Object.key
    var Top2DestructuredLabel = Top2Object.key
    var Top3DestructuredLabel = Top3Object.key

    var Top1DestructuredValue = Top1Object.val
    var Top2DestructuredValue = Top2Object.val
    var Top3DestructuredValue = Top3Object.val

    Top1LabelForStoryline = Top1DestructuredLabel.toString();
    Top2LabelForStoryline = Top2DestructuredLabel.toString();
    Top3LabelForStoryline = Top3DestructuredLabel.toString();

    Top1ValueForStoryline = Top1DestructuredValue.toString();
    Top2ValueForStoryline = Top2DestructuredValue.toString();
    Top3ValueForStoryline = Top3DestructuredValue.toString();

    player.SetVar ("Top3_1_Label",Top1LabelForStoryline);
    player.SetVar ("Top3_2_Label",Top2LabelForStoryline);
    player.SetVar ("Top3_3_Label",Top3LabelForStoryline);
    player.SetVar ("Top3_1_Value",Top1ValueForStoryline);
    player.SetVar ("Top3_2_Value",Top2ValueForStoryline);
    player.SetVar ("Top3_3_Value",Top3ValueForStoryline);

    Any help anyone can provide would be tremendous.  Thank you in advance.

    Cathy

  • your problem are the six variables - not created in Storyline

    player.SetVar ("Top3_1_Label",Top1LabelForStoryline);
    player.SetVar ("Top3_2_Label",Top2LabelForStoryline);
    player.SetVar ("Top3_3_Label",Top3LabelForStoryline);
    player.SetVar ("Top3_1_Value",Top1ValueForStoryline);
    player.SetVar ("Top3_2_Value",Top2ValueForStoryline);
    player.SetVar ("Top3_3_Value",Top3ValueForStoryline);

    1st, 2nd, 3rd and 1st_Counter, 2nd_Counter, 3rd_Counter should be correct

    here is a modernized JavaScript version of your script

    let player = GetPlayer();

    // used Storyline variables
    // 'A_Counter' ... 'R_Counter'
    // 'A_name'    ... 'R_name' 
        
    let myArray = []
    for( let i='A'.charCodeAt(0); i<='R'.charCodeAt(0); i++) {
        let char = String.fromCharCode(i)
        
        myArray.push({
          counter: player.GetVar(char + "_Counter"),
          name:    player.GetVar(char + "_name")     
        })
    }

    console.log( "myArray unsorted: ", [...myArray] )

    myArray.sort( (a, b) => b.counter - a.counter); // sort descending

    console.log( "myArray sorted: ", [...myArray] )

    player.SetVar("1st", myArray[0].name);
    player.SetVar("2nd", myArray[1].name);
    player.SetVar("3rd", myArray[2].name);

    player.SetVar("1st_Counter", myArray[0].counter);
    player.SetVar("2nd_Counter", myArray[1].counter);
    player.SetVar("3rd_Counter", myArray[2].counter);

    in the browser console (-> F12) you can see the debug info

     

  • Thank you, Thank you, Thank you.  I have no idea what it means, LOL, but it works!! 

    I have decided that I am going to take some fundamental JS courses.  What you are able to do is amazing!

    Cathy