Slider based Ranking Mobile Setup (#9)
mobile-phone
Slider Ranking Mobile

For this question, a float question will be implemented and the below code will be placed into it. In case it is ranking question, the “_order” question should also be implemented.

  <radio 
   label="ketoolSliderRankingMobileGrid"
   fir="off"
   surveyDisplay="desktop">
    <title>How would you rate these banks?</title>
    <row label="r1">ICICI Bank{@imageURL::bank_1.png||largeImageURL::bank_1_L.png||width::130px||height::170px@}</row>
    <row label="r2">HDFC Bank{@imageURL::bank_2.png||largeImageURL::bank_2_L.png||width::130px||height::170px@}</row>
    <row label="r3">Bank of Baroda{@imageURL::bank_3.png||largeImageURL::bank_3_L.png||width::130px||height::170px@}</row>
    <row label="r4">State Bank of India{@imageURL::bank_4.png||largeImageURL::bank_4_L.png||width::130px||height::170px@}</row>
    <row label="r5">Axis Bank{@imageURL::bank_5.png||largeImageURL::bank_5_L.png||width::130px||height::170px@}</row>
    <row label="r7" open="1" randomize="0">Other{@width::130px||height::170px@}</row>
    <col label="c0" value="0">0</col>
    <col label="c1" value="1">1</col>
    <col label="c2" value="2">2</col>
    <col label="c3" value="3">3</col>
    <col label="c4" value="4">4</col>
    <col label="c5" value="5">5</col>
    <col label="c6" value="6">6</col>
    <col label="c7" value="7">7</col>
    <col label="c8" value="8">8</col>
    <col label="c9" value="9">9</col>
    <col label="c10" value="10">10</col>
    <col label="c99" value="99">Don't know{@exclusive::true@}</col>
    <style name="page.head"><![CDATA[
<style>
  .answers{display:none;}
  #btn_continue {
    visibility: hidden;
  }
</style>
]]></style>
    <style name="question.after"><![CDATA[
<div class="ketool-stage" id= "ketool-stage-${this.label}" style="margin-top: -30px;"></div>

    <script type="text/javascript" crossorigin="anonymous" src="${KEDomain}/framework.min.js"></script>

    <script type="text/javascript">
      if (!ketool.qDefs)
        ketool.qDefs = {};
      if (!ketool.toolLoader) {
        ketool.toolLoader = new ketool.Loader({
            "baseFileURL": "${KEDomain}/",
            "scriptDeps": [
                "fancyboxlib.js",
                "Slider_libs.js",                
              "Carousel_libs.js",
              "Carousel.js"
            ],
            "cssDeps": [
                "ionicons.min.css",
                "libs_fancybox.css",
                "Slider_libs.css",
              
                "style_framework.css",  
                "Carousel_libs.css",              
                "Carousel.css",
                "keBrown.css"
            ],
            "coreFile": "core_app.js",
            "messages": null,
            "platformInterface": { js: "platform_app.js", css: "platform_style.css" }
                                        });      
      }
      ketool.qDefs["${this.label}"] = ${jsexport()};
      var isTest = "${gv.isUser() and not gv.debug.respview}" === "True";


     //SETTINGS AND STUFF GOES HERE
      var toolSettings = {
      //standard tool params
      "toolJs": "slider_rank_mob.js",
      "toolName": "SliderBasedRankingMobileApp",      
      "jsToLoad": [],
      "cssToLoad": ["slider_rank_mob.css"],
      "baseToolPath": "${KEDomain}/",      
      "container": "#ketool-stage-" + getFormName(1),
      "toolCssNames": [],
      "qid": getFormName(1),
      "time_qid": "${this.label}_Time",
      "order_qid": "${this.label}_Order",    
      //"overall_exclusive_qid": "${this.label}_Dk",
      "imageBaseURL": "${KEDomain}/",
      "minRequired": null,
      "maxAllowed": 999,
      "numDecimalsTimeData": 2,
      //end standard tool params      
      "orientation": "horizontal",
      "leftContent": "Not at all important",
      "midContent": "Fairly Important",
      "rightContent": "Very important",      
      "snapping": false,
      "rtlMode": false,
      "scalePrefix": "",
      "scaleSuffix": "",
      "numDecimals": 0,
      "decimalSign": ".",
      "showGrabberValue": true,
      "stickyGrabberValue": false,
      "showTicks": true,
      "showTickNumbers": true,
      "showTickLabels": true,
      "showMidTicks": true,
      "disabled": false,
      "initialPosition": "50%",      
      "respectDistance": true, // If set to true, the distance between scales will be relative to the difference between the scale values. Otherwise, distance will just be equal.             
      "nonGridSetting": {},      
      "carouselSettings": {
        "showCounter": true,
        "countAnswered": false,            
        "numCardsCarousel": 1,
        "animationSpeed": 300,
        "itemMargin": 30
      },
      "answerItemConfig": { // in px
        "width": 130,
        "height": 120,        
      },     
      "noUiSliderParams": {},
      "autoNextItem": false,
      "navigation": "completed", // can be: answered, oneAnswered, always, never, completed 
      "showOverview": true,
      "overviewLabels": {        
        rank: "Rank",
        item: "Item",
        value: "Value"
      },
      "oneByOne": false,
      "showRank": true,      
      "isRanking": true,
      "duplicateError": "Please make sure you don't have any duplicate rating.",
      "exclusiveAnimation": true,          
      "exclusiveSettings": {
        width: "120px",
        height: "40px"        
      },
      "overallExclusiveSettings": {        
        width: "170px",
        height: "50px"        
      },
      "otherMinChar": 1,
      "customValidation": function (q) {
        console.log("customValidation()", q);
        return true;
      }      
    };      

      ketool.toolLoader.registerSettings(toolSettings, function (info) {
          console.log("Questions loaded");
          console.log(info.bridge.exportQuestions());
          console.log(info);

          info.instance.setToolValidation(toolSettings.customValidation);

          info.bridge.setPageValidation(function(){
              console.log("setPageValidation");
              return true;
          });

          info.instance.on("tool_loaded", function(e){
            //console.log("tool_loaded", e);
            if(isTest){
                ${initKEToggleData()}
            }
          });
      });
      //END USER EDITABLE CODE
      
      $ (document).ready(function(){       
        ketool.toolLoader.initLoad();

 
    });
    </script>

    <style>
      /* --- Override default Decipher styles --- */

      .ketool-container .openbox-container textarea {
        min-width: auto !important;
      }

      /* --- End Override default Decipher styles --- */
    </style>
]]></style>
  </radio>

  <float 
   label="ketoolSliderRankingMobileGrid_Time"
   fir="off"
   translateable="0">
    <title>Data node for time data. ketoolSliderRankingMobileGrid_Time.</title>
    <row label="r1">ICICI Bank{@imageURL::bank_1.png||largeImageURL::bank_1_L.png||width::130px||height::170px@}</row>
    <row label="r2">HDFC Bank{@imageURL::bank_2.png||largeImageURL::bank_2_L.png||width::130px||height::170px@}</row>
    <row label="r3">Bank of Baroda{@imageURL::bank_3.png||largeImageURL::bank_3_L.png||width::130px||height::170px@}</row>
    <row label="r4">State Bank of India{@imageURL::bank_4.png||largeImageURL::bank_4_L.png||width::130px||height::170px@}</row>
    <row label="r5">Axis Bank{@imageURL::bank_5.png||largeImageURL::bank_5_L.png||width::130px||height::170px@}</row>
    <row label="r7">Other</row>
    <style cond="not (gv.isUser() and not gv.debug.respview)" name="page.head"><![CDATA[
<style>
    #question_${this.label} { display: none; }
  </style>
]]></style>
    <style name="question.after"><![CDATA[
<script>
        if (!ketool.qDefs)
            ketool.qDefs = {};

        ketool.qDefs["${this.label}"] = ${jsexport()};        
    </script>
]]></style>
  </float>

  <text 
   label="ketoolSliderRankingMobileGrid_Order"
   fir="off"
   translateable="0">
    <title>Data node for order data. ketoolSliderRankingMobileGrid_Order.</title>
    <row label="r1">ICICI Bank{@imageURL::bank_1.png||largeImageURL::bank_1_L.png||width::130px||height::170px@}</row>
    <row label="r2">HDFC Bank{@imageURL::bank_2.png||largeImageURL::bank_2_L.png||width::130px||height::170px@}</row>
    <row label="r3">Bank of Baroda{@imageURL::bank_3.png||largeImageURL::bank_3_L.png||width::130px||height::170px@}</row>
    <row label="r4">State Bank of India{@imageURL::bank_4.png||largeImageURL::bank_4_L.png||width::130px||height::170px@}</row>
    <row label="r5">Axis Bank{@imageURL::bank_5.png||largeImageURL::bank_5_L.png||width::130px||height::170px@}</row>
    <row label="r7">Other</row>
    <style cond="not (gv.isUser() and not gv.debug.respview)" name="page.head"><![CDATA[
<style>
    #question_${this.label} { display: none; }
  </style>
]]></style>
    <style name="question.after"><![CDATA[
<script>
        if (!ketool.qDefs)
            ketool.qDefs = {};

        ketool.qDefs["${this.label}"] = ${jsexport()};
    </script>
]]></style>
  </text>
General Instructions for all ketool setups

For all ketool setup, please implement the below block at the start of the survey XML

<exec when="init">
KEDomain = "https://au.focusvision.com/survey/selfserve/560/221003"
project_id = gv.survey.path

def initKEToggleData():
  returntext = "\n var dataToggler = jQuery('<div>For testing only - click here to expand data capturing nodes to verify the data capture during test mode.</div>');\n"
  returntext += "dataToggler.addClass('dataToggle');\n"
  returntext += "dataToggler.css({'text-decoration': 'underline','font-size': 'small','color': 'blue','cursor': 'pointer','margin-top': '20px'});\n"
  returntext += "jQuery('.ketool-stage').last().after(dataToggler);\n"
  returntext += "dataToggler.click(info.bridge.toggleDataNodes());\n"
  return returntext

def initkelegacyDataToggle():
  if gv.isUser() and not gv.debug.respview:
    output = "<script>\n"
    output += "var dataToggler = jQuery('<div>Please click here to see the data nodes for this tool.</div>');\n"
    output += "dataToggler.addClass('dataToggle');\n"
    output += "dataToggler.css({'text-decoration': 'underline','font-size': 'small','color': 'blue','cursor': 'pointer','margin-top': '20px'});\n"
    output += "dataToggler.click(kelegacyDataToggle);\n"
    output += "function kelegacyDataToggle(){ if(jQuery('.survey-page').hasClass('showkelegacyData')) jQuery('.survey-page').removeClass('showkelegacyData'); else jQuery('.survey-page').addClass('showkelegacyData');  }\n"
    output += "jQuery(function(){jQuery ('.survey-buttons').before(dataToggler); })\n"
    output += "</script>\n"
    output += "<style>.showkelegacyData .answers,.showkelegacyData .question{display: block !important;visibility: visible !important;}</style>\n"
    return output
  else:
    return ""
</exec>

We also have few general options in all ketool setups with function “initKEToggleData” is being called, which should not be changed, these are:


These options are optional and should only be implemented if needed:
For any follow-up question (including “_time”, “_order” questions) should include the below code:
<exec when="init">
<style name="question.after"><![CDATA[
<script type='text/javascript'>if (ketool.qDefs) ketool.qDefs["${this.label}"] = ${jsexport()};</script>
]]></style>
We can also use below row/column/group options (wherever applicable) in each row in format “{@rowOption1::rowOption1Value|| rowOption2::rowOption2Value @}” wherever required, all the possible options in a question are mentioned below.

Slider based Ranking Mobile Setup (#9)

Below are the tool settings, row and scale options to be used for slider based ranking mobile setup:

Tool Settings Use Value Type / Syntax Default Value / Possible Values
overall_exclusive_qid Multi response question for holding the overall exclusive data. The question itself can have multiple rows - for multiple overall exclusive options string
orientation Whether the sliders should be displayed in vertical or horizontal mode. fixed string Default value: horizontal
Possible values: ["horizontal","vertical"]
minRequired The number of items that must be answered for the user to proceed. Setting this to null means that all items must be answered. Number > 0 or blank/null null/blank
maxAllowed The maximum number of items that can be answered. Number > 0 999
numDecimalsTimeData The number of decimal places that the time data should be rounded to. E.g. set to 2 for two decimal places - 2.73. Number > 0 0
snapping Whether the slider grabbers snap to scale tick marks, or can be dragged anywhere on the slider. Snapping will always be true for grid sliders. boolean true
rtlMode Whether the tool should be displayed in right-to-left mode (for arabic surveys). boolean true
scalePrefix Text to insert before all scale labels. string
scaleSuffix Text to insert after all scale labels. string
numDecimals The number of decimal places that will be shown for the slider grabber values. Number > 0
decimalSign The delimiter used to indicate a decimal place - e.g. "," or "." . string .
showGrabberValue Whether the handle/grabber value will be shown in the content box above the handle/grabber. boolean true
stickyGrabberValue If this is set to true and showGrabberValue is also set to true, the grabber values are always shown. boolean false
showTicks Whether scale ticks should be shown on the slider. boolean true
showTickNumbers Whether scale ticks numbers should be shown on the slider. boolean true
showTickLabels Whether the scale tick labels should be shown. boolean true
showMidTicks Whether the shorter "mid" ticks should be shown. boolean true
initialPosition Where the slider grabbers are placed on the slider initially. Can be in percentage or actual slider value. String (required) 50%
respectDistance If set to true, the distance between scales will be relative to the difference between the scale values. Otherwise, distance will just be equal. boolean true
nonGridSetting min The minimum value. number 0
max The maximum value. number
increment The step / increment. This can also be an answer row property. number 1
scaleMask Used to mask slider scales.
Values present here are the only ones that'll be shown in the slider scale.
This is useful when you want to show a limited number of scales.
array e.g. “scaleMask : [0,10,20,30,40,50,60,70,80,90,100]
scaleLabelMask Used to mask slider scale labels.
Values present here are the only ones that'll be shown in the slider scale.
This is useful when you still want to show the ticks without its label.
array e.g. “scaleLabelMask : [“0”,””,””,””,””,50,”“,”“,””,””,”100”]
exclusives precode The exclusive precode. number
content The exclusive text. string
carouselSettings showCounter Whether to show the progress (i.e., number of answered items). boolean false
countAnswered Whether to count the # of answered items. boolean true
numCardsCarousel Number of cards shown at once in the carousel. If 'oneByOne' is set to true, it effectively ignores any value here and sets a value of 1 for this param. If this param is not specified then the tool will attempt to show as many cards as possible based off the card size. number 1
animationSpeed Transition speed between cards in carousel. number 300
itemMargin The space between the carousel items. number 30
answerItemConfig width Answer option width (px) String (for width in px) 300
height Answer option height (px). String (for width in px) 100
noUiSliderParams noUiSlider settings that can be used to override default tool behavior.
This should be the last resort in case any of the tool settings doesn't meet the requirements.
Reference here.
string Reset
showZoom Zoom-in buttons appear if true. boolean false
zoomButtonImage Image URL to use for the 'zoom' button that appears on answer cards. string Path already specified; no change needed here
zoomPosition Position of the zoom button. fixed string Default value: bottom-right
Possible values: ["bottom-right","top-right","bottom-left","top-left"]
disabled If set to true, disables the tool (except the reset button). boolean true
otherType Other specify input type. fixed string Default value: textarea
Possible values: ["text","textarea"]
otherMinChar Minimum character required for the other specify box. Setting this to 0 would make the Other spec not required. number 1
isRanking Whether or not a duplicate rank is allowed. boolean false
showRank Whether to show the item rank. boolean true
duplicateError The error message to show when there's a duplicate rating. If this is set to an empty string, we don't show any error messages. string Please make sure you don't have any duplicate rating.
navigation Navigation type for the carousel - when the next/prev buttons are enabled:
'answered' - you are allowed to navigate back to the already answered items
'completed' - navigation is enabled once you answer for all items
'oneAnswered' - navigation for all items is enabled once you answer at least one item
'always' - navigation is always enabled - you can jump to any item
'never' - navigation is never enabled - you cannot change your answers
fixed string Default value: answered
Possible values: ["answered", "oneAnswered", "always", "never", "completed"]
autoNextItem Whether the tool should automatically proceed to the next statement when the current one is answered.
Note that the navigation parameter affects this - set the navigation parameter to 'answered'to prevent auto next.
boolean false
showOverview Whether to show the overview or not. boolean true
overviewLabels rank Label for the rank. string Rank
item Label for the item. string Item Name
value Label for the value. string Value
oneByOne Whether to show the items one at a time. boolean false
exclusiveAnimation Whether the slider grabbers are animated back to their original position when an exclusive option is selected. boolean true
exclusiveSettings width Button width (px) String (for width in px) 110px
height Button height (px). String (for width in px) 50px
softDisable Whether disabled elements can still be interacted or not when this exclusive option is selected. boolean true
overallExclusiveSettings width Button width (px) String (for width in px) 110px
height Button height (px). String (for width in px) 50px
compOrder The position of any of the core parts (e.g., carousel, slider, exclusive, overview) of the tool from top to bottom. array ["carousel","slider","exclusive","overview"]
compGroupOrder The position of the component groups (e.g., core and global / overall exclusive). array ["core","globalExclusive"]
overviewHeader Overview header text.

Row Options Use Value Type / Syntax Possible Values
leftContent Text to show for a row on left side string
midContent Text to show for a row on mid side string
rightContent Text to show for a row on right side string
disabled Whether this item should be disabled or not. boolean
increment Increment in case of a row number 1
imageURL Image used for the card (optional) string Image file URL
largeImageURL Image used for the large card image string Image file URL
width Custom width to apply to this answer option. Number > 0
height Custom height to apply to this answer option. Number > 0
optional Whether the item can be left without an answer. Please disable required/validation for this item. boolean
otherType Other specify input type. fixed string Default value: textarea
Possible values: ["text","textarea"]
otherMinChar Minimum character required for the other specify box. Setting this to 0 would make the Other spec not required. number 1
Scale/column Options Use Value Type / Syntax Possible Values
customValue Custom value to use in case slider label and value should be different. Note that this is only applicable to grid sliders. number
exclusive Specifies if the scale should be exclusive. boolean