Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 7 of 7
  1. #1
    New Coder
    Join Date
    Feb 2011
    Posts
    12
    Thanks
    4
    Thanked 0 Times in 0 Posts

    Help with dynamically changing label font color when radio button is clicked

    I am building an online survey using a survey creation tool which allows me to incorporate javascript for additional functionality. However, I am new to javascript so would appreciate any help that you could provide me with.

    I have question types like agreement scales, where the respondent sees a list of statements and has to rate each one by clicking on a radio button. The source code of the matrix table looks like this:

    Code:
    <thead><tr class="Answers">
    
    			<th class='c1 BorderColor' width="25%" class='c1'> &nbsp; </th>
    		<th class='c2 BorderColor' class='c2 yAxisBorder' > &nbsp; </th>
    		<th class='c3 BorderColor' class='c3 yAxisBorder' > &nbsp; </th>
    	
    	
    										
    		<th width="25%" class='Selection BorderColor c4   ' id='header~QID19~1~4' >
    
    			<label>Disagree</label>
    		</th>
    										
    		<th width="25%" class='Selection BorderColor c5   ' id='header~QID19~2~5' >
    			<label>Neither agree nor disagree</label>
    		</th>
    										
    		<th width="25%" class='Selection BorderColor c6 last  ' id='header~QID19~3~6' >
    			<label>Agree</label>
    
    		</th>
    	
    	
    </tr></thead><tr class='ChoiceRow   '><th class='c1' id='header~QID19~1'><span class='LabelWrapper'><label for='QR~QID19~1'>Statement 1</label></span> </th><td class='c2 BorderColor' class='c2 yAxisBorder' headers='header~QID19~1' > &nbsp; </td><td class='c3 BorderColor' class='c3 yAxisBorder' headers='header~QID19~1' > &nbsp; </td><td class='c4   ' headers='header~QID19~1~4 header~QID19~1'><input type='radio' name='QR~QID19~1' value='QR~QID19~1~1'  ></td><td class='c5   ' headers='header~QID19~2~5 header~QID19~1'><input type='radio' name='QR~QID19~1' value='QR~QID19~1~2'  ></td><td class='c6 last  ' headers='header~QID19~3~6 header~QID19~1'><input type='radio' name='QR~QID19~1' value='QR~QID19~1~3'  ></td></tr><tr class='ChoiceRow ReadableAlt  '><th class='c1' id='header~QID19~2'><span class='LabelWrapper'><label for='QR~QID19~2'>Statement 2</label></span> </th><td class='c2 BorderColor' class='c2 yAxisBorder' headers='header~QID19~2' > &nbsp; </td><td class='c3 BorderColor' class='c3 yAxisBorder' headers='header~QID19~2' > &nbsp; </td><td class='c4   ' headers='header~QID19~1~4 header~QID19~2'><input type='radio' name='QR~QID19~2' value='QR~QID19~2~1'  ></td><td class='c5   ' headers='header~QID19~2~5 header~QID19~2'><input type='radio' name='QR~QID19~2' value='QR~QID19~2~2'  ></td><td class='c6 last  ' headers='header~QID19~3~6 header~QID19~2'><input type='radio' name='QR~QID19~2' value='QR~QID19~2~3'  ></td></tr><tr class='ChoiceRow  bottom '><th class='c1' id='header~QID19~3'><span class='LabelWrapper'><label for='QR~QID19~3'>Statement 3</label></span> </th><td class='c2 BorderColor' class='c2 yAxisBorder' headers='header~QID19~3' > &nbsp; </td><td class='c3 BorderColor' class='c3 yAxisBorder' headers='header~QID19~3' > &nbsp; </td><td class='c4   ' headers='header~QID19~1~4 header~QID19~3'><input type='radio' name='QR~QID19~3' value='QR~QID19~3~1'  ></td><td class='c5   ' headers='header~QID19~2~5 header~QID19~3'><input type='radio' name='QR~QID19~3' value='QR~QID19~3~2'  ></td><td class='c6 last  ' headers='header~QID19~3~6 header~QID19~3'><input type='radio' name='QR~QID19~3' value='QR~QID19~3~3'  ></td></tr><input type=hidden name='Transformation~QID19~1' value='YToxOntzOjEwOiJRUn5RSUQxOX4xIjtzOjE2OiJ7dmFsdWV9PVNlbGVjdGVkIjt9' id=''><input type=hidden name='Transformation~QID19~2' value='YToxOntzOjEwOiJRUn5RSUQxOX4yIjtzOjE2OiJ7dmFsdWV9PVNlbGVjdGVkIjt9' id=''><input type=hidden name='Transformation~QID19~3' value='YToxOntzOjEwOiJRUn5RSUQxOX4zIjtzOjE2OiJ7dmFsdWV9PVNlbGVjdGVkIjt9' id=''></table></div>
    I don't have any control over the HTML as this is generated by the survey tool. However, the survey tool has a "JavaScript Editor" for each question, where I can put in javascript functions, and it executes them when the page loads.

    What I want to do is to have the label for each row (i.e for each statement) to change color when a corresponding radio button has been selected. This way, it is easier for respondents to see which rows they have answered.

    I used the following JS code:

    Code:
    var radioname = [];
    var radiolist = [];
    var labelspans = [];
    var labels = [];
    var radios = [];
    var count;
    var spans = document.getElementsByTagName('span');
    
    function getLabels()
      {
        for (x=0; x<spans.length; x++)
      {
        if (spans[x].className == "LabelWrapper")
        {
          labelspans.push(spans[x]);
        }
      }
        for (y=0; y<labelspans.length; y++)
      {
       labels.push(labelspans[y].firstChild);
       radioname.push(labelspans[y].firstChild.htmlFor);
      }
    }
      
    function getRadios()
    {   
      //will put all radio groups into the "radiolist" array
      for (z=0; z<radioname.length; z++)
       {
         radiolist.push(document.getElementsByName(radioname[z]));
         //will add Event Listener to each radio button, and add each one to the "radios" array
         for (i=0; i<radiolist[z].length; i++)
           {
            chkradio = radiolist[z][i];
            chkradio.setAttribute("count",Number(z));
            chkradio.addEventListener("click", function(){changeLabel()}, false);
            radios.push(chkradio);
           }
      }
    }
    
    function changeLabel()
    //loops through all the radios to check if they are selected, and changes label color accordingly          
       {
        for (w=0; w<radios.length; w++)   
          {
           if (radios[w].checked)
               {
                a = radios[w].getAttribute("count");
                labels[a].innerHTML = labels[a].innerHTML.fontcolor("green");
               }
           }
        }
    getLabels();  
    getRadios();
    This code works as intended; however, as you can see, it loops through all the radio buttons when one is clicked. Is there a way to accomplish this without looping through all the radios, and thus make the script run faster?

    Also, I have read that the addEventListener function does not work for older versions of IE. Is there a simpler alternative?
    Last edited by np1986; 02-06-2011 at 04:37 PM.

  • #2
    GŁtkodierer
    Join Date
    Apr 2009
    Posts
    2,127
    Thanks
    1
    Thanked 426 Times in 424 Posts
    Regarding your second question: That's not really about *older* versions of IE, this is about *all* versions of IE (except IE9 that is, but that's still beta).

    You have to change
    PHP Code:
    chkradio.addEventListener("click", function(){changeLabel()}, false); 
    to

    PHP Code:
    if (chkradio.addEventListener){
      
    chkradio.addEventListener('click'changeLabelfalse); 
    } else if (
    chkradio.attachEvent){
      
    chkradio.attachEvent('onclick'changeLabel);

    Notice how I also got rid of the closure you had that changeLabel() call wrapped into. You don't need that, a plain reference to the function is just fine.

    As for your first question: Inside changeLabel, this will refer to the clicked radio (if you got rid of the closure I was just talking about; otherwise it will be the window object), so there's no need to loop.

  • Users who have thanked venegal for this post:

    np1986 (02-06-2011)

  • #3
    New Coder
    Join Date
    Feb 2011
    Posts
    12
    Thanks
    4
    Thanked 0 Times in 0 Posts
    Thank you, venegal!

    I simplified the changeLabel function based on your advice:

    PHP Code:
    function changeLabel()       
      {
       
    this.getAttribute("count");
       
    labels[a].innerHTML labels[a].innerHTML.fontcolor("Green");
      } 
    I also edited the getRadios function as follows;

    PHP Code:
    function getRadios()
    {   
      for (
    z=0z<radioname.lengthz++)
       {
         
    radiolist.push(document.getElementsByName(radioname[z]));
         for (
    i=0i<radiolist[z].lengthi++)
           {
            
    chkradio radiolist[z][i];
            
    chkradio.setAttribute("count",Number(z));
            if (
    chkradio.addEventListener)
             {
    chkradio.addEventListener('click'changeLabelfalse);}
            else if (
    chkradio.attachEvent)
             {
    chkradio.attachEvent('onclick'changeLabel);}  
           }
      }

    This all works beautifully in FireFox.

    I hadn't tested this before in Internet Explorer, so I did. Unfortunately, it doesn't seem to work and I am getting the following error:
    Line: 133
    Char: 4
    Error: Object doesn't support this property or method
    When I look at the source code, it seems to be the getLabels function that is throwing IE off:

    PHP Code:

    function getLabels()
      {
        for (
    x=0x<spans.lengthx++)
      {
        if (
    spans[x].className == "LabelWrapper")
        {
          
    labelspans.push(spans[x]);
        }
      }
        for (
    y=0y<labelspans.lengthy++)
      {
       
    labels.push(labelspans[y].firstChild);
       
    radioname.push(labelspans[y].firstChild.htmlFor); //Line 133
      
    }

    Do you have an idea why IE is having a problem with this?
    I tried rewriting it as radioname[radioname.length]=labelspans[y].firstChild.htmlFor but I am getting the same error.

  • #4
    GŁtkodierer
    Join Date
    Apr 2009
    Posts
    2,127
    Thanks
    1
    Thanked 426 Times in 424 Posts
    firstChild is not really reliable, because there could very well be an invisible text node that's returned instead of the label. So, you're probably better off doing something like
    PHP Code:
    radioname.push(labelspans[y].getElementsByTagName('label')[0].htmlFor); //Line 133 
    But it's hard to say if that's really the problem without being able to go in there with a debugger. If this doesn't help you, could you show your site live? Then it would probably be very easy to figure out what's going on.

  • #5
    New Coder
    Join Date
    Feb 2011
    Posts
    12
    Thanks
    4
    Thanked 0 Times in 0 Posts
    I made a mistake - it seems it wasn't the getLabels function that has the error. I used the source view in FireFox to get the line number, but it seems the line numbers are different in IE. I downloaded Microsoft Script Debugger, and it's the changeLabels function which IE is having trouble with.

    After a quick search on google, it appears that IE assigns the value of this to the window. So I think I would have a separate function for IE similar to the one I had originally (i.e. looping through all the elements) unless someone has any ideas on how to get around this issue.

  • #6
    GŁtkodierer
    Join Date
    Apr 2009
    Posts
    2,127
    Thanks
    1
    Thanked 426 Times in 424 Posts
    Ah right, I've been so spoilt by jQuery over those last few years that I sometimes forget some cross browser issues.

    Changing the changeLabels function just to accomodate IE would be bad design. The real difference between the browsers is how event assignment works, so that's where you have to make the change.

    This will most probably work for you; it extracts the event target from the event object and calls changeLabel in its context (so it will be this inside the function):

    PHP Code:
        if (chkradio.addEventListener) {
            
    chkradio.addEventListener('click'changeLabelfalse);  
        }
        else if (
    chkradio.attachEvent) {
            
    chkradio.attachEvent('onclick', function (event) {changeLabel.call(event.srcElement);});
        } 

  • Users who have thanked venegal for this post:

    np1986 (02-06-2011)

  • #7
    New Coder
    Join Date
    Feb 2011
    Posts
    12
    Thanks
    4
    Thanked 0 Times in 0 Posts
    Thank you! It's working in IE now. I guess I'll have to do some reading on event handling, but thank you for pointing me in the right direction.


  •  

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •