Changing and loading an iframe 'src' attribute with jQuery

Hi everyone,

I’m very new to jQuery and quite rusty with my web design in general. I have a page on my site with 5 buttons alongside an iframe which is embedded from Youtube showing a video. All I want is for each of the buttons to load a different video from Youtube into the iframe without simply reloading the whole page. I’ve searched and seen some examples of jQuery interaction with iframes, but all too complex for me to fully follow. Could someone please provide a simple example of what I need to do? I just need jQueary to change the src value and reload the iframe when the user clicks on one of the buttons.

Any help would be greatly appreciated.

Thanks.

You could use the target attribute on the link to target the iFrame.

If you have the embed links to the youtube videos, you can do something like this:


<p><a href="http://www.youtube.com/embed/Q5im0Ssyyus" target="someFrame">Charlie 1</a></p>
<p><a href="http://www.youtube.com/embed/QFCSXr6qnv4" target="someFrame">Charlie 2</a></p>
<p><a href="http://www.youtube.com/embed/eaCCkfjPm0o" target="someFrame">Charlie 3</a></p>

<iframe name="someFrame" id="someFrame" width="560" height="315"></iframe>

Live demo: [URL=“http://jsfiddle.net/GeekyJohn/GH5QG/”]http://jsfiddle.net/GeekyJohn/GH5QG/

Of course if for some reason you need to use JavaScript, then you could simply change the source of the iframe.

in jQuery parlance this would only be a few lines:


$(document).ready(function(){
    $("a").click(function(e) {
        e.preventDefault();
        
        $("#someFrame").attr("src", $(this).attr("href"));
    })
});

That’s exactly what I needed. Thank you very much. I thought of using jQuery because I’d also like to be able to add a class to the button as it’s clicked to enable the active link to be styled differently.

Any chance you could provide an example of this behaviour also?

Thanks.

I reckon that this would work:


$("a").click(function(e) {
  e.preventDefault();
  $("#someFrame").attr("src", $(this).attr("href"));
  $("a").removeClass("active");
  $(this).addClass("active");
})

First removing the “active” class from all links, then adding that class to the clicked link.

May I suggest that you give your links e.g. a class name to identify them:

<p><a href="http://www.youtube.com/embed/Q5im0Ssyyus" class="myButtons">Charlie 1</a></p>

And get them e.g. like this:

$("a.myButtons")

That gives you the freedom to add more <a> tags to the page without affecting them too.

That would be rather bad for performance, it would be better to reference only the already active links like so:


  $("a.active").removeClass("active");

Most certainly an excellent idea. The other option would be to have an ID or class on the parent of the links.


$("#theButtons a.active").removeClass("active");

 $("a.active").removeClass("active"); 

Good point :slight_smile:

BTW, do you think jQuery keeps a chached list over all a tags?
Or does it perhaps do the following when parsing “a.active”:

  1. First get all a tags on the page.
  2. Then look through them all to find those with the className attribute containing the string “active”.
  3. Then remove the “active” string from their className attribute.

If so, it may not improve performance …

It depends on how the selector is constructed :slight_smile:

You can always cache your jQuery results yourself by storing a result set in a variable. So for example if you would loop over something, you wouldn’t want to get jQuery to perform a lookup and instantiate a new instance of itself.
e.g.


//This is *bad*

for( var i = 0; i < aLongDataSet.length; i++ ) {
  $("a.someLink"); // ouch, jQuery needs to look this up *every* time.
  //do stuff
}

// This is *much* better

var i = 0;

// we're also caching the length of the data set so it doesn't have to be requested each time
// it's a micro optimization, but a good habit to get in to nonetheless.
var len = aLongDataSet.length; 

// I prefix my jQuery objects with a '$' so I instantly know that var contains a jQuery object
var $links = $("a.someLink"); 

for ( i = 0; i < len; i++ ) {
 //you can now do something with $links
}

Ok, back to how jQuery performs a selection on an item with a class.

The selector engine, called "Sizzle", will attempt to use the browser’s native methods that are fastest first: [I]document.getElementsByTagName()[/I], [I]document.getElementsByClassName()[/I],[I] document.getElementById()[/I], and [I]document.querySelectorAll()[/I] (and not necessarily in that order, if you want to see what selectors are fast/slow take a look at http://mootools.net/slickspeed/ of course results will vary depending on which browser you use).

To performance enhance our selectors, you can give them a context. You can do this in several ways.

You can put all your elements in a container <div> with an ID on it as that will be quite fast to select and will reduce the amount of data subqueries have to go through.
e.g.


<div id="myLinks">
  <h3>My links</h3>
  <a href="#" class="myClass">Link</a>
  <a href="#" class="myClass">Link</a>
  <a href="#" class="myClass">Link</a>
</div>

To then select them with jQuery we can do this in the following manners.


// use #myLinks before the class selector, jQuery will find "#myLinks" first 
// and search for the remaining selector in its contents
$("#myLinks a.myClass");

// use a context parameter, the jQuery selector can take a context (Selector, DOM node, Document or jQuery)
var domNode = document.getElementById("myLinks");
var $jqObj = $("#myLinks");

// select with Selector
$("a.myClass", "#myLinks");

// select with DOM node
$("a.myClass", domNode);

// select with jQuery Object
$("a.myClass", $jqObj);

It’s not always necessary to do this, it depends on how many items you have across the page and if you’re trying to narrow them down to a particular part of the page.

For example, let’s say you wanted to only select links with a class in the sidebar of your page, you would use $(“#sidebar a.someClass”) or $(“a.someClass”, document.getElementById(“sidebar”)) as it would be a lot faster to only search the DOM of the sidebar than it would to search the DOM of the entire page.

Read more about jQuery Context: [URL=“http://api.jquery.com/jQuery/”]http://api.jquery.com/jQuery/

Hope this helped :slight_smile:

Interesting. I never heard of document.querySelectorAll() before. Generally, I’m a bit hesitant to use an element’s id as in document.getElementById() because I imagine, that the browser has to run through ALL elements until it finds a match - but perhaps it keeps an index.

Anyway, I only ever get an element once and then I store a reference to that element in e.g. a property of an object for later use.

document.querySelector/querySelectorAll is still a bit on the new and shiny side, and unfortunately doesn’t work in some older browsers. (See caniuse.com/queryselector.) Of course a fallback “polyfill” method could be used that falls back to a selector engine like [URL=“http://dustindiaz.com/qwery”]qwery or [URL=“http://sizzlejs.com/”]sizzle (or if you’re doing a lot of selecting, it might be worth just using one of these selector engines :))

document.getElementById() is usually the better and faster method for selecting a single element as browser vendors have heavily optimized it.
(Check out this jsperf test that compares querySelector, querySelectorAll, getElementById, getElementsByClassName, and getElementsByTagName)

That’s a good practice to stick with :). While often it’s a bit of a micro-optimization, it can lead to massive performance gains, especially if you’re looping through a particularly long data set.

This is what I was looking.
Is there any way to start on page load, with first link video within iframe?

You could do something like this:


links = document.getElementById("myLinks").getElementsByTagName("a");
if (links.length > 0) {
  firstAnchor = links[0];
}

document.getElementById("someFrame").src = firstAnchor.href;

If you’re using jQuery you could do it like this:


$("#someFrame").attr("src", $("#myLinks a:first").attr("href"));

You just put that at the bottom of the page (or below the iFrame and links in any case) and it will set the href of the first link as the src of the iFrame

Awesome!!! Perfect output. Thanks a lot!!!

I’m debugging another task, I really appreciate if you can share your inputs;
within Lightbox am using iframe to load external html file. However, some user has noticed that iframe is taking time to load static html file. I have two blocks in lightbox one is with youtube link and another with html page. Any suggestions to load faster iframe src file?

Thanks a lot!

If you want stuff to execute on pageload it is a good idea to use this method:


$(document).ready( function(){
  $("#someFrame").attr("src", $("#myLinks a:first").attr("href"));
});

Thus you don’t have to worry about putting the script tags at a specific place on the page. You can put it wherever you like - even in a separate js file.

* If you’re using jQuery :wink:

Depending on what the application is, I tend to often put some JavaScript that is absolutely required for my application to work in the header, and most everything else can go in the footer. This way any time you write non-jQuery code you won’t have to worry about sticking things in an onLoad handler.

This will ensure your markup and CSS load and execute quicker as they don’t have to wait for scripts to load & execute.

The user who created this thread specifically wrote above that he DOES use jQuery … :smiley:

Whoops yup!

Though this functionality can be written with just a few lines of regular JavaScript without requiring the jQuery overhead (:

Sorry for a very late reply.

Thank you again guys for the terrific help. I’ve taken in what you’ve recommended and have it working just as I wanted. Great performance advice too!

Much appreciated!

My situation is much the same as Duckie’s. I have a page with an iFrame and four links to native files that each will appear within the iFrame when summoned. I’ve done this with straight HTML. The problem is that when I land on the page I have an empty iFrame until I click one of the links.

Not only would it be nice to have the iFrame populated with the first link upon arrival, but it would be a real bonus if there was a way to arrive at this page with any other of the remaining links appearing, if in fact that’s the content someone came looking for. For example, if I place anchors for my four links on another page, it would be ideal if someone could select the second item and find it populating the iFrame upon arrival at my-iFrame-page.php.

I’m not opposed to using jQuery nor javascripting of any kind, but I’m afraid that for a newbie, there’s a lot that I don’t grasp when I try to sort through everything above. I’d be over the moon if someone could post a working example that achieves what I’m after. :slight_smile: