Jump to content

[SOLVED] JavaScript in PHP loop -- not doing what I need


Recommended Posts

Hi All,

 

I am really newbie at JavaScript, so I'm not surprised that I'm not getting the result I am expecting. Basically, I dynamically create a few different sets of drop down boxes. I want to have a link that is triggered by each option value of the selected drop down. So I'm using JS to make that link go to the corresponding option value. When I view my source my JS function and the id of my select boxes appear to be incrementing correctly. But no matter what option value I choose it will default to the option value URL that is in the last drop down box. I am hoping someone might be able to take a look and see what I've done wrong:

 


<h3>Featured Series</h3>
<hr />
<ul>
  <?php
  $qs = db_query("SELECT n.title, n.nid FROM {node} n LEFT JOIN {content_type_series} cs ON (n.nid = cs.nid) WHERE cs.field_bbs_feature_value = %d ORDER BY n.title", '1');
  $counter=1;
    while($data = db_fetch_object($qs)){ 
    
    // We loop the javascript so that we can have each select box go to the right value
    ?>

<script type="text/javascript">
function goTo() {
var sE = null, url;
if(document.getElementById) {
sE = document.getElementById('urlList<?php echo $counter;?>');
} else if(document.all) {
sE = document.all['urlList<?php echo $counter;?>'];
}
if(sE && (url = sE.options[sE.selectedIndex].value)) {
location.href = url;
}
}
</script>

      <a href="<?=base_path();?>"><img src="http://dev.retn.org/sites/all/themes/zen/retn/images/thumbnail.jpg" alt="" class="thumbnail" /></a>
  
       <form>
       <li>
       <?php print check_plain($data->title); ?><br>
       <select STYLE='width: 300px' id='urlList<?=$counter;?>'>
<?php $programs = db_query("SELECT nid FROM {content_type_program} WHERE field_series_nid = '%d' ORDER BY field_pdate_value", $data->nid);
      while($program = db_fetch_object($programs)){
        $node = node_load($program->nid); ?>

        <option value="<?php echo check_url(base_path().$node->path) ;?>"><?php echo check_plain($node->title);?></option>

<?php

     } ?>
     </select>
     <a href="#" class="button webcast" onClick="goTo();">WATCH VIDEO</a>
     </li>
     </form>
     <hr />
<?php 
  $counter++;
}

?>
</ul>

 

Thanks so much in advance!

Well, your main problem is that your PHP loop is causing you to overwrite your JavaScript function every time it iterates, which is why it only brings you to the last option.  Regardless, there's a far easier way to go about this.

 

The easiest way to accomplish what you want is to wait for the PHP to write out the HTML, then let the script act on it.  That way, you save yourself from the headache of trying to mix and match PHP, HTML, and JavaScript at the same time.  I've written a small test file that should illustrate how to go about this.  I'll explain it in detail below.

 

Test page code:

<html>
<head>
   <script type="text/javascript">
      window.onload = function()
      {
         var selects = document.getElementsByTagName("select");
         var trigger = document.getElementById("trigger");

         trigger.onclick = function()
         {
            for(var i = 0; i < selects.length; i++)
            {
               var mySelect = selects[i];
               var selectValue = mySelect[mySelect.selectedIndex].value;

               if(selectValue != "#")
               {
                  location.href = selectValue;
                  return false;
               }
            }
         }
      }
   </script>
</head>

<body>

<select>
   <option value="#">Please select a search engine</option>
   <option value="http://www.google.com/">Google</option>
   <option value="http://www.yahoo.com/">Yahoo</option>
   <option value="http://www.msn.com/">MSN</option>
</select>

<select>
   <option value="#">Please select a news site</option>
   <option value="http://www.cnn.com/">CNN</option>
   <option value="http://www.msnbc.com/">MSNBC</option>
   <option value="http://www.abcnews.com/">ABC News</option>
</select>

<br /><br />

<a href="#" id="trigger">GO!</a>

</body>
</html>

 

1. window.onload tells the script to wait until the document (the HTML) is fully loaded before acting.

2. We get references to both selects (getElementsByTagName returns an array with all elements matching the tag name) and the link we're using as a trigger for the location change.

3. We create an onclick event handler for the trigger.  This does a couple of things:

  a. It executes a for-loop.

  b. Inside of this loop, we create a local, temporary variable named mySelect which refers to the current <select> in the loop.  This helps us get the selectedIndex value.

  c. We also create a local, temporary variable named selectValue which holds the selectedIndex value for the current <select> in the loop.  This is mainly done to save on typing, because I'm lazy.

  d. We then check if the value in the current <select> is a url.  If so, we go there, if not, we keep looping.

 

And that's all there is to it.

 

Something to note: This method of navigation will only send the user to the first valid option selected by the user.  In my example, if the user selects both Google and MSNBC, they'll be taken to Google every time.  Also, this example assumes you have only one button/link controlling the entire thing.  You can have one button per submit, which wouldn't be much more difficult to implement.

hi Nightslyr,

 

thanks for responding, I figured I was creating a lot of redundancy in my script. this helps a lot! one thing -- i do need one button for each select box. can I just reuse

 

<a href="#" id="trigger">GO!</a>

 

or do i need separate ids for each link? thanks again for your help!

hi Nightslyr,

 

thanks for responding, I figured I was creating a lot of redundancy in my script. this helps a lot! one thing -- i do need one button for each select box. can I just reuse

 

<a href="#" id="trigger">GO!</a>

 

or do i need separate ids for each link? thanks again for your help!

 

Yup, you'll need a separate id for each link.  Remember: id = unique value.  By definition, there shouldn't be an id used for more than one element.

 

Another way to do it is to use another element that will only be used as a trigger for navigation for each <select> list.  I like using <button>'s.  You could do something like:

var selects = document.getElementsByTagName("select");
var triggers = document.getElementsByTagName("button");

for(var i = 0; i < triggers.length; i++) //could just as easily have the test "i < selects.length" as selects.length and triggers.length should be the same
{
   (function()
   {
      triggers[i].onclick = function()
      {
         var currentSelect = selects[i];
         var selectValue = currentSelect[currentSelect.selectedIndex].value;

         if(selectValue != "#")
         {
            location.href = selectValue;
            return false;
         }
      }
   })(); //use a self-executing anonymous function just to make sure scope isn't screwed up
}

 

With this, your <button>'s wouldn't even need id's, as each <button> would be tied with each <select>.

thanks again for the help (and so fast too!). i am starting to understand this all better, but i still can't get it to work quite right. now nothing happens when i click the link. i actually can't use buttons because i need to style them and can't have browsers interfere with the styling (yes, it's all the designers fault that this is so hard!). so i changed the trigger to go on 'a' tag since this page only has a hrefs that are applicable to the select boxes. this seems like it should work fine, and the code ends up printing out results like the following (just to give you an example)

<ul>  
<li>Brownell Library Lecture Series<br>
<select STYLE='width: 300px'>
<option value='#'>--Select Program----</option>
<option value="/programs/celebrating-europes-winter-festivals">Celebrating Europe&#039;s Winter Festivals</option>
<option value="/programs/antarctica">Antarctica</option>
<option value="/programs/ghana-my-homeland">Ghana, My Homeland</option>
</select>
<a href="#" class="button webcast" id="trigger1">WATCH VIDEO</a>
</li><hr />

  
<li>Champlain College Lecture Series<br>
<select STYLE='width: 300px'>
<option value='#'>--Select Program----</option>
<option value="/programs/cssu-titles">CSSU Titles</option>
<option value="/programs/zora-neale-hurston">Zora Neale Hurston</option>
<option value="/programs/abraham-lincoln-the-first-modern-president">Abraham Lincoln - The First Modern President</option>
</select>
<a href="#" class="button webcast" id="trigger2">WATCH VIDEO</a>
</li><hr />

<li>Vermont 3.0 - Academic Series<br>
<select STYLE='width: 300px'>
<option value='#'>--Select Program----</option>
<option value="/programs/ways-web-the">Ways of the Web, The</option>
<option value="/programs/connecting-physical-and-virtual-worlds">Connecting the Physical and Virtual Worlds</option>
<option value="/programs/state-game-the">State of the Game, The</option>
</select>
<a href="#" class="button webcast" id="trigger3">WATCH VIDEO</a>
</li><hr />
</ul>

etc, etc.

 

Here is the code I am using:

 

<script type="text/javascript">
var selects = document.getElementsByTagName("select");
var triggers = document.getElementsByTagName("a");

for(var i = 1; i < triggers.length; i++) //could just as easily have the test "i < selects.length" as selects.length and triggers.length should be the same
{
   (function()
   {
      triggers[i].onclick = function()
      {
         var currentSelect = selects[i];
         var selectValue = currentSelect[currentSelect.selectedIndex].value;

         if(selectValue != "#")
         {
            location.href = selectValue;
            return false;
         }
      }
   })(); //use a self-executing anonymous function just to make sure scope isn't screwed up
}
</script>

<h3>Featured Series</h3>
<hr />
<ul>
<?php
$qs = db_query("SELECT n.title, n.nid FROM {node} n LEFT JOIN {content_type_series} cs ON (n.nid = cs.nid) WHERE cs.field_bbs_feature_value = %d ORDER BY n.title", '1');
$counter=1;
while($data = db_fetch_object($qs)){ ?>

<?php // This prints the name of each TV series?>  
<li><?php print check_plain($data->title);?><br>
<select STYLE='width: 300px'>
<option value='#'>--Select Program----</option>
<?php
  $programs = db_query("SELECT nid FROM {content_type_program} WHERE field_series_nid = '%d' ORDER BY field_pdate_value", $data->nid);
  while($program = db_fetch_object($programs)){
    $node = node_load($program->nid);
?>
<?php // This prints the name of each individual episode of the current series into a select box ?>  
<option value="<?php echo check_url(base_path().$node->path) ;?>"><?php echo check_plain($node->title);?></option>

<?php
  } ?>
  <?php // For each TV series, next to its select box is a a href that goes to a program if it gets selected. This can't be a button because I need to style it and don't want the browser to interfere ?>  
  </select><a href="#" class="button webcast" id="trigger<?php echo $counter;?>">WATCH VIDEO</a></li><hr />
<?php 
$counter++;
}

?>
</ul>

 

I thought this would do the trick but nada. can you give me any further guidance on what I've missed? thanks so much.

Ah, there were a couple of problems with the code I gave you.  Scope can be tricky in JavaScript.  I actually tested the code I'm about to give you, and it works in both IE and Firefox:

<html>
<head>
   <script type="text/javascript">
      window.onload = function()
      {
         var selects = document.getElementsByTagName("select");
         var triggers = document.getElementsByTagName("a");

         for(var i = 0; i < triggers.length; i++)
         {
            (function()
            {
               var trigger = triggers[i];
               var currentSelect = selects[i];

               trigger.onclick = function()
               {
                  var selectValue = currentSelect[currentSelect.selectedIndex].value;

                  if(selectValue != "#")
                  {
                     location.href = selectValue;
                     return false;
                  }
               }
            })();
         }
      }
   </script>
</head>

 

Be sure to keep the window.onload part.  That ensures the code won't fire until everything else is loaded.

 

And, in general, you should write your applications like this:

 

PHP processing (handle user/form requests, get database info, put output into variables that can be echoed/printed)

|

|

V

HTML rendering/JavaScript insertion (write the JavaScript & HTML)

 

All your commands/form data should be handled first.  Then, you build your page structures from that backend processing.  You can include() generic page data (like a footer you use on every page), and store unique/dynamic output in variables.  This keeps everything separate and tidy, and reduces on errors by decoupling each type of code from one another.  Done this way, the PHP loop to create your <select>'s is completely separate from the JavaScript loop to create the onclick event handlers.

  • 3 months later...

Well, i know i haven't posted on this in 3 months and that i said it was solved, but i actually went back to this page today and noticed that it's not actually working like it should. i rechecked my code and everything appears to be along the same lines of what's written here, but it's still not working.

 

you can see the actual page and source of the page here: http://dev.retn.org/video-on-demand/browse-by-series

 

i also have another question about it...if i use the a tag for the javascript function, then will every link on this page eventually trigger the function?

 

any suggestions you can give would be great.

thanks so much!

Well, i know i haven't posted on this in 3 months and that i said it was solved, but i actually went back to this page today and noticed that it's not actually working like it should. i rechecked my code and everything appears to be along the same lines of what's written here, but it's still not working.

 

you can see the actual page and source of the page here: http://dev.retn.org/video-on-demand/browse-by-series

 

i also have another question about it...if i use the a tag for the javascript function, then will every link on this page eventually trigger the function?

 

any suggestions you can give would be great.

thanks so much!

 

Hi, it's been a while, huh?

 

There are a couple of things going on, from what I can see.

 

1. The biggest problem is that none of your options have any values.  You need to populate all of your select elements' options with the correct video file name for the user to be directed to them.  That said, simply doing that will either deliver the user to a blank page where the video plays, or will prompt them to download the file.  This may not be what you want.  Let me know what your design intentions (i.e., how/where you want the vids to play) are.

 

2. You're right in that using the typical <a href....> tags isn't a good idea in this case, given the other links on the page.  You can create generic HTML buttons to act as triggers, which is a better idea.  The JavaScript will be virtually the same, aside for one line of code.  A rough idea of it is:

 

JavaScript:

<html>
<head>
   <script type="text/javascript">
      window.onload = function()
      {
         var selects = document.getElementsByTagName("select");
         var triggers = document.getElementsByTagName("button"); //<--- note the different line here

         for(var i = 0; i < triggers.length; i++)
         {
            (function()
            {
               var trigger = triggers[i];
               var currentSelect = selects[i];

               trigger.onclick = function()
               {
                  var selectValue = currentSelect[currentSelect.selectedIndex].value;

                  if(selectValue != "#")
                  {
                     location.href = selectValue;
                     return false;
                  }
               }
            })();
         }
      }
   </script>
</head>

 

HTML:

<button name="button1" id="trigger1" type="button">WATCH VIDEO</button>

 

The most important attribute for the button tag is its type.  Giving it a type of 'button' makes it a simple push button.  Giving it a type of 'submit' makes it into a form submit button.  Similarly, giving it a type of 'reset' makes it a form reset button.

 

For your needs, simply replace the generic hyperlinks associated with the videos with a generic button element with a type of 'button'.  That should ensure that everything is synchronized correctly and that other links on your site don't launch videos.

  • 8 months later...

Nightslyr, thank you again. and again.

 

i want to apologize in the long delay...i was actually in africa for about 5 months and returned june 30. so i am only getting back to this now. you have offered me the perfect solution.

 

and as for the video issue, the button text is just misleading...it takes you to a description page of the video where you can then watch it. i am glad you mentioned this as it has caused me to change the button text as well. THANKS!

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.