Changing the width of columns in an array

More
1 month 2 weeks ago #215576 by MatthieuBRANTHOME
In fact, this is what I would ideally like to achieve:

1) A list of programming skills
2) A check-box, checked by default, that mean that people don't use this skill, in this case the slider is disabled
3) If the chek-box is unchecked, the slider became enable and people can assess the level of difficulty they encounter using the current skill (it would be nice if the slider value label did not appear)
4) (in a dreamed world) If someone re-check the checkbox, the slider returns to the middle en become disabled

Is this implementation totaly utopian, or is it feasible? (assuming my admin cancels the XSS filter)

Thanks in advance for your precious help,

MatthieuB

 

Please Log in to join the conversation.

More
1 month 2 weeks ago #215581 by tpartner
Yes, it is possible with extensive coding. Search the forum for "bootstrapSlider".

Cheers,
Tony Partner

Solutions, code and workarounds presented in these forums are given without any warranty, implied or otherwise.
The following user(s) said Thank You: DenisChenu

Please Log in to join the conversation.

More
1 month 2 weeks ago #215583 by Joffm
Hi,
I should say: Yes it is possible.
I found two old examples in the forum for version 2.50/2.73.
One to insert sliders in a matrix(text) one to have a checkbox,  and adapted it a bit.
 

Here is the javascript script
<script type="text/javascript" charset="utf-8">
    $(document).ready(function(){    
 
        // Identify this question
        var thisQuestion = $('#question{QID}');
 
        // Assign column-specific classes
        $('table.subquestion-list tr', thisQuestion).each(function(i) {
 
            $('> *:gt(0)', this).each(function(i){
                $(this).addClass('column-'+(i+1));
                $(this).attr('data-column', i+1);
            });
        });
      
          // Insert the sliders
        $('.answer-item.column-1 input[type="text"]', thisQuestion).each(function(i) {
            $(this).closest('td').addClass('with-slider');
            var thisValue = $(this).val();
 
            $(this).bootstrapSlider({
                'min': 0,
                'max': 10,
                'step': 0.1,
                'range': false,
                'value': Number(thisValue),
                'tooltip': 'always'
            });
 
            // Initialization stuff
            if(thisValue == '') {
                $(this).val('');
                $(this).closest('td').find('.tooltip').hide();
            }
            else {
                updateCallOut($(this).closest('td'));
            }
        });
 
        // A function to update the slider callout
        function updateCallOut(el) {
            var thisTooltip = $(el).find('.tooltip');
            //$('.tooltip-inner', thisTooltip).text(callOutText);
            thisTooltip.show().css('margin-left', '-'+(thisTooltip.width()/2)+'px');
        }
 
        // Listener on sliders
        $('td.with-slider .slider').on('mousedown', function(event, ui) {
            updateCallOut($(this).closest('td'));
        });            
        $('td.with-slider input[type="text"]', thisQuestion).on('slide slideStop', function(event, ui) {
            updateCallOut($(this).closest('td'));
            checkconditions($(this).val(), $(this).attr('name'), 'text');
        });
 
        // Listener on resizing (override the bootstrap callout behaviour)
        $(window).resize(function() {
            $('td.with-slider', thisQuestion).each(function(i) {
                if($('input[type="text"]', this).val() != '') {
                    updateCallOut(this);
                }
            });
        });
        
        // Define the slider left/right labels
        var sliderLeftLabels = ['no', 'no','no','no','no'];
        var sliderRightLabels = ['great', 'great', 'great', 'great', '10'];
        
        // Insert slider left/right labels
        $('td.with-slider', thisQuestion).append('<div class="left-text"></div><div class="right-text"></div>');
        $('.left-text', thisQuestion).each(function(i) {
            $(this).text(sliderLeftLabels[i]);
        });
        $('.right-text', thisQuestion).each(function(i) {
            $(this).text(sliderRightLabels[i]);
        });
 
        // Some clean-up styles for the sliders (could be placed in template.css)
        $('thead th, .answer-item.column-1', thisQuestion).css({
            'text-align': 'center'
        });
        $('.slider.slider-horizontal', thisQuestion).css({
            'margin': '1.7em auto 1em'
        });
        $('.slider-selection', thisQuestion).css({
            'background': 'transparent none',
            'box-shadow': 'none'
        });
        $('.slider-handle', thisQuestion).css({
            'top': '-4px'
        });
        $('.left-text, .right-text', thisQuestion).css({
            'margin-top': '-0.5em',
            'font-size': '90%'
        });
        $('.left-text', thisQuestion).css({
            'float': 'left'
        });
        $('.right-text', thisQuestion).css({
            'float': 'right'
        });
    });
  </script>
<script type="text/javascript" charset="utf-8">
    $(document).ready(function(){    
 
        // Identify this question
        var qID = {QID};
        var thisQuestion = $('#question'+qID);
 
        // Add some classes
        $(thisQuestion).addClass('with-exclusive-items');
        $('td.answer-item', thisQuestion).addClass('non-exclusive-item');
 
        // Loop through the last-column cells
        $('td.answer-item:last-child', thisQuestion).each(function(i) {
            varThisID = $('input[type="text"]', this).attr('id');
 
            // Add a class
            $(this).removeClass('non-exclusive-item').addClass('exclusive-item');
 
            // Hide the text input
            $('td.answer-item:last-child input[type="text"]', thisQuestion).hide();
 
            // Insert checkboxes
            $(this).append('<div class="checkbox">\
                                <input class="checkbox" name="" id="'+varThisID+'_cbox" value="N/A" type="checkbox">\
                                <label for="'+varThisID+'_cbox" class="answertext inserted-label"></label>\
                            </div>'); 
        });
 
        // Listener on the checkboxes
        $('.exclusive-item input[type="checkbox"]', thisQuestion).on('change', function(e) {
            var thisRow = $(this).closest('tr.subquestion-list');
            var thisCell = $(this).closest('td.answer-item');
            if($(this).is(':checked')) {
                $('input[type="text"]', thisCell).val('1');
                $('.non-exclusive-item input[type="text"]', thisRow).val('');
            }
            else {
                $('input[type="text"]', thisCell).val('');
            }
 
            // Fire Expression Manager
            $('input[type="text"]', thisRow).each(function(i) {
                $(this).trigger('keyup');
            });
        });
 
        // Listener on the text inputs
        $('.non-exclusive-item input[type="text"]', thisQuestion).on('keyup change', function(e) {
            var thisRow = $(this).closest('tr.subquestion-list');
            if($.trim($(this).val()) != '') {
                $('.exclusive-item input[type="checkbox"]', thisRow).prop('checked',false);
                $('.exclusive-item input[type="text"]', thisRow).val('');
            }
 
            // Fire Expression Manager
            $('.exclusive-item input[type="text"]', thisRow).trigger('keyup');
        });
 
        // Insert some styles (these could be in template.css)
        // For the LS 2.67 default template
        var newStyles = '.with-exclusive-items thead th.answertext {\
                            text-align: center;\
                        }\
                        .with-exclusive-items .exclusive-item {\
                            text-align: center;\
                            vertical-align: middle;\
                            cursor: pointer;\
                        }\
                        .with-exclusive-items .checkbox {\
                            padding-left: 0;\
                        }\
                        .with-exclusive-items .inserted-label {\
                            width: 24px;\
                            min-height: 24px;\
                            padding: 0;\
                        }\
                        .with-exclusive-items .inserted-label::before {\
                            margin: 4px 0 0 4px;\
                        }\
                        .with-exclusive-items .inserted-label::after {\
                            margin: 4px 0 0 4px;\
                        }';    
        $('head').append('<style type="text/css">'+newStyles+'</style>');    
    });    
</script>

Please, do not ask me anything about this.
I am not at all familiar with javascript.
What I do is a bit "trial and error".

You have to add some validation to avoid a setting of the slider and checking the box.
And as you know it is a bit difficult to set the column width, as this version is not based on bootstrap, but on a table with a colgroup.

But:
If there are "not used" elements, you should better ask in a previous question "Which do you use?" and then you display the slider only for "used" elements

Joffm


Volunteers are not paid.
Not because they are worthless, but because they are priceless
Attachments:

Please Log in to join the conversation.

More
1 month 2 weeks ago #215624 by MatthieuBRANTHOME
Wow, thank you  Joffm  for these pieces of code! This is almost what I am trying to do.
I need now to:
1)  delete the slider label
2)  link the checkbox and slider behaviour

Still waiting for code rights in questions in order to test this...

If there are "not used" elements, you should better ask in a previous question "Which do you use?" and then you display the slider only for "used" elements

The problem is that the list of skills is very long, and I don't want respondents to give up if they have too much reading (reading the list twice)






 

Please Log in to join the conversation.

More
1 month 2 weeks ago #215636 by Joffm
As I said: Don't ask me anything about the javascript.
I only showed a way to display it.
To be honest: This example doesn't work.

And:

The problem is that the list of skills is very long, and I don't want respondents to give up if they have too much reading (reading the list twice)

But they do not have to.

You have to guide them, you have to encourage them by explanation texts like.
Don't just fire questions.

"Now we show you a list of skills. Please, ...."

"Thank you for selecting your used skills.
In this question we now ask you to rate the difficulty of these."

And only the used skills are displayed. This will shorten the second list by a lot.
And in a multiple question you may display the items in more than one column.

Here something to read; mainly the first part "people friendly"
 

File Attachment:

File Name: surveyfriendly1.zip
File Size:977 KB


Joffm


Volunteers are not paid.
Not because they are worthless, but because they are priceless
Attachments:

Please Log in to join the conversation.

More
1 month 2 weeks ago - 1 month 2 weeks ago #215787 by MatthieuBRANTHOME
My admin just disabled the XSS filter! So I can try anything I want!

First of all, Tpartner's solution for changing the cell padding works, so worst case scenario, I'll stick with that.

I can now try to introduce sliders in the table :)
Last edit: 1 month 2 weeks ago by MatthieuBRANTHOME.

Please Log in to join the conversation.

More
1 month 1 week ago - 1 month 1 week ago #215870 by MatthieuBRANTHOME
Hi!
I am trying to change the way the sliders work so that the button turns red when the chosen value is -1.
Here is my code:

<script type="text/javascript" charset="utf-8">
 
$(document).ready(function(){
  var thisQuestion = $('#question{QID}');
  $('div.question-item',thisQuestion).each(function(i) {
            var subQuestionID =  $(this).attr('id');
            var sliderHandle = $('div.min-slider-handle',this);
              var sliderValue = $(sliderHandle).attr('aria-valuenow');
            console.log("MBR-sliderHandleValueNow");
              console.log(sliderValue);
  });
})
</script>


I can't access the handle in the code, it's as if it doesn't exist when calling the ready() function.
I specify that I am in a classic use of sliders: a multiple numerical input question with slider option enable

Does anyone have an idea to help me?

Thank you in advance!

MatthieuB
Last edit: 1 month 1 week ago by MatthieuBRANTHOME.

Please Log in to join the conversation.

More
1 month 1 week ago - 1 month 1 week ago #215897 by MatthieuBRANTHOME
I almost succeeded in doing what I wanted:

[img][url=https://ibb.co/0MCjkVm][img]https://i.ibb.co/85rDJ4N/surveyV3.png[/img][/url][/img]
<style type="text/css">.slider.slider-horizontal .slider-handle {
    margin-top: -5px;
}
.tooltip-main{
    visibility: hidden;
}
.slider-container {
    margin-top: 2em;
    margin-bottom: 1em;
}
.control-label{
      font-weight: bold;
}
.withslider {
    margin-bottom: 0px;
}
.form-group {
    margin-bottom: 0px;
}
.not-used-label{
    color:#e74c3c;
}
.not-used-handle{
    background-image: linear-gradient(to bottom, #e74c3c 0%, #e74c3c 100%);
}
.active-handle{
    background-image: linear-gradient(to bottom, #149bdf 0%, #0480be 100%);
}
.odd-line{
    background-color: #f9f9f9;
}
.even-line{
    background-color: #ecf0f1;
}
</style>
<script type="text/javascript" charset="utf-8">
$(document).on('ready pjax:scriptcomplete',function(){
    //Get the current question
      var thisQuestion = $('#question{QID}');
      // for each question item
      $('div.question-item',thisQuestion).each(function(i) {
        // Set line background alternately
        if(i%2 == 0){
          $(this).addClass("odd-line");
        }
          else{
          $(this).addClass("even-line");
        }
          var questionItemID =  $(this).attr('id');
        // Add not used label
        var questionLabel =$(".control-label",this);
      $(questionLabel).append("  <span id=NU"+questionItemID+" class='not-used-label'>Not used</span>" );
      // Set slider handle to not used
      var sliderHandle = $('.min-slider-handle',this);
      $(sliderHandle).addClass("not-used-handle");
      // Add mouse up handler
      $(sliderHandle).mouseup(function(){
          // Get question item ID
        var questionItem = $(this).closest('div.question-item');
        var questionItemID =  $(questionItem).attr('id');
        console.log(questionItemID);
        // if slider value is -1
        if($(this).attr('aria-valuenow')==-1){
            // Set slider handle to not used
              if(!$(this).hasClass("not-used-handle")){
                $(this).addClass("not-used-handle");
                $(this).removeClass("active-handle");
            }
              // show not used label
            $("#NU"+questionItemID).show();
        }
        // if slider value is different from -1
        else{
          // Set slider handle to active
          if(!$(this).hasClass("active-handle")){
                $(this).addClass("active-handle");
                $(this).removeClass("not-used-handle");                  }
          // hide not used label
            $("#NU"+questionItemID).hide();
        }
      });
  });
})
</script>

However, there is still a problem:
I rely on "mouseup" to update the display, but the problem is that the cursor is usually released without the mouse being in direct contact with it. So the display is not updated each time. What event should I watch for instead?

Thank you for your help,

MatthieuB
 
Last edit: 1 month 1 week ago by MatthieuBRANTHOME.

Please Log in to join the conversation.

More
1 month 1 week ago #215914 by MatthieuBRANTHOME
Finally, I did my graphic updates on the 'change' event of the slider text input, and it works perfectly!

Please Log in to join the conversation.

Start now!

Just create your account and start using Limesurvey today.

Register now