Link to home
Start Free TrialLog in
Avatar of rascal
rascalFlag for United States of America

asked on

Invoking Fancybox via Javascript fails, but ok with JQuery?

Hi Experts,
We created a page that shows videos using FancyBox via JQuery and it all works fine. We set an onclick handler on each video link. You can see the page working here: http://www.globalpartnerships.org/learn-more/videos/

However, we also wanted to be able to pass the YouTube video ID to the page via a querystring and have the page display that video, so we set up a Javascript function to invoke FancyBox. But this doesn't work and we can't figure out why! Here is the link to page using the querystring: http://www.globalpartnerships.org/learn-more/videos/?v=05zozOAqjBM

(Note that the v= parameter will only work if the video id passed is one already contained on the page. The one in the example above is the first video on the page).

We tried tracing with Firebug and it showed a message of "TypeError: loading is undefined" and it shows loading.hide as the function in error. I suppose that's FancyBox's "loading" animation but I have no idea how this error comes into effect or even why.

The function CustomPageInitContent() is where all our code is that relates to FancyBox.

Any ideas or help would be greatly appreciated!

Thanks experts!
Avatar of Scott Fell
Scott Fell
Flag of United States of America image

Why don't you either read the query string with php or in jquery you could grab it this way.  http://jquery-howto.blogspot.com/2009/09/get-url-parameters-values-with-jquery.html


// Read a page's GET URL variables and return them as an associative array.
function getUrlVars()
{
    var vars = [], hash;
    var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
    for(var i = 0; i < hashes.length; i++)
    {
        hash = hashes[i].split('=');
        vars.push(hash[0]);
        vars[hash[0]] = hash[1];
    }
    return vars;
}

var v = getUrlVars()["v"];
// from here run the videos as on your first link

Open in new window

Avatar of rascal

ASKER

Getting the parameter is no problem, the problem is that when I invoke the FancyBox manually via javascript, it fails with the error: "TypeError: loading is undefined"

further, once it fails with that error, the original code's Fancybox fails as well.
I don't think you need to completely rewrite your jquery based on a querystring or not.

Using what is working now and just adding an if statement checking for the querystring you could do below although I have not tested.  If it works correctly, I would also add some type of error trapping in case a querystring is used that does not match a video.
//***********************************
// ShowVideo
//***********************************
function ShowVideo(sHref,sTitle)
{
	$.fancybox({
		'type' : 'iframe',
		// hide the related video suggestions and autoplay the video
		'href' : sHref.replace(new RegExp('watch\\?v=', 'i'), 'embed/') + '?rel=0&autoplay=1',
		'overlayShow' : false,
		'centerOnScroll' : true,
		'speedIn' : 100,
		'speedOut' : 50,
		'width' : 640,
		'height' : 480,
		'titlePosition' : 'inside',    //  'float', 'outside', 'inside' or 'over'
		'title' : sTitle,
		'swf': {'allowfullscreen':'true', 'wmode':'transparent'}
	}); // $.fancybox
}

// Read a page's GET URL variables and return them as an associative array.
function getUrlVars()
{
    var vars = [], hash;
    var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
    for(var i = 0; i < hashes.length; i++)
    {
        hash = hashes[i].split('=');
        vars.push(hash[0]);
        vars[hash[0]] = hash[1];
    }
    return vars;
}

var v = getUrlVars()["v"];
if (v.length>0){
	ShowVideo(document.URL,'some title')
}



//***********************************
// CustomPageInitContent
//***********************************
function CustomPageInitContent()
{
	$('a.videogallery').on('click', function(event) {
		event.preventDefault();
		$.fancybox({
			'type' : 'iframe',
			// hide the related video suggestions and autoplay the video
			'href' : this.href.replace(new RegExp('watch\\?v=', 'i'), 'embed/') + '?rel=0&autoplay=1',
			'overlayShow' : false,
			'centerOnScroll' : true,
			'speedIn' : 100,
			'speedOut' : 50,
			'width' : 640,
			'height' : 480,
			'titlePosition' : 'inside',    //  'float', 'outside', 'inside' or 'over'
        	'title' : $(this).attr('rel'),
			'swf': {'allowfullscreen':'true', 'wmode':'transparent'}
		}); // $.fancybox
	}); // $('a.more')
	
	// auto invoke the video if passed in a querystring
	}

Open in new window

Avatar of rascal

ASKER

@padas - your code is essentially what my code does - it detects a querystring value and if found, invokes the ShowVideo() function. The problem is that it doesn't work. When there is no call to ShowVideo, then the original code works fine. But when I introduce a separate function (the ShowVideo() function) and try to call it manually, it fails with the error message and after that, not even the main fancybox calls work.
You're calling the fancybox function outside the document.ready but you are initing the fancybox setup in a document.ready.
Avatar of rascal

ASKER

@Gary - we are actually calling fancybox from within our document.ready:

document.ready calls CustomPageInitContent() which calls our fancybox.

(there is an attempt to find any anchor tags with class="fancybox" in the document.ready() function, but there are none on the page, so that is ignored.
sVideoID equals
http://www.youtube.com/embed/http://www.youtube.com/embed/05zozOAqjBM
(this is not a typo)
Caused by
if (sVideoID.toLowerCase().indexOf('05zozoaqjbm') > -1)
{
sVideoID = 'http://www.youtube.com/embed/' + sVideoID;
ShowVideo(sVideoID,sRel);
}


Maybe this is causing the burp
ASKER CERTIFIED SOLUTION
Avatar of Gary
Gary
Flag of Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of rascal

ASKER

I just stumbled on the solution: It's a timing thing. The manual call to ShowVideo() needs to take place after about 1 second to give time to <something> to initialize - whether it's giving time for fancybox to initialize, or giving time for the a.videogallery lick handler loop to complete (the code in the CustomPageInitContent() function).

See the code below - CustomPageInitContent() is called from my document.ready(). Note the setTimeout function at the bottom of CustomPageInitContent().

<script type="text/javascript">
//***********************************
// ShowVideo
//***********************************
function ShowVideo(sHref,sTitle)
{
	$.fancybox({
		'type' : 'iframe',
		// hide the related video suggestions and autoplay the video
		'href' : sHref.replace(new RegExp('watch\\?v=', 'i'), 'embed/') + '?rel=0&autoplay=1',
		'overlayShow' : false,
		'centerOnScroll' : true,
		'speedIn' : 100,
		'speedOut' : 50,
		'width' : 640,
		'height' : 480,
		'titlePosition' : 'inside',    //  'float', 'outside', 'inside' or 'over'
		'title' : sTitle,
		'swf': {'allowfullscreen':'true', 'wmode':'transparent'}
	}); // $.fancybox
}
//***********************************
// CheckQuerystring
//***********************************
function CheckQuerystring()
{
	// auto invoke the video if passed in a querystring
	<?php
	$sQSVideoID = strtolower(trim($_REQUEST['v']));
	if (strlen($sQSVideoID)>0) { 
	?>
			$('a.videogallery').each(function() {
				var sVideoID = $(this).attr('href');
				var sRel = $(this).attr('rel');
				
				if (sVideoID.toLowerCase().indexOf('<?php echo $sQSVideoID;?>') > -1)
				{
					ShowVideo(sVideoID,sRel);
					return false; // break out of the loop
				} // if (sVideoID.toLowerCase().indexOf('<?php echo $sQSVideoID;?>') > -1)
			}); // $('a.each')
	<?php
	} // if (strlen($sQSVideoID)>0)  
	?>

}
//***********************************
// CustomPageInitContent
//***********************************
function CustomPageInitContent()
{
	$('a.videogallery').on('click', function(event) {
		event.preventDefault();
		$.fancybox({
			'type' : 'iframe',
			// hide the related video suggestions and autoplay the video
			'href' : this.href.replace(new RegExp('watch\\?v=', 'i'), 'embed/') + '?rel=0&autoplay=1',
			'overlayShow' : false,
			'centerOnScroll' : true,
			'speedIn' : 100,
			'speedOut' : 50,
			'width' : 640,
			'height' : 480,
			'titlePosition' : 'inside',    //  'float', 'outside', 'inside' or 'over'
        	'title' : $(this).attr('rel'),
			'swf': {'allowfullscreen':'true', 'wmode':'transparent'}
		}); // $.fancybox
	}); // $('a.more')
	
	setTimeout('CheckQuerystring()',1000);
}
</script>

Open in new window

Wouldn't it just be easier to simulate the click rather than repeating code...?
I agree with GaryC123, that is what I was trying to get at. You shouldn't need to have to call it in multiple spots.
Avatar of rascal

ASKER

@Gary,
You can't use the .click() to emulate clicking on an <a> tag.
Yes you can.
Again 'Yes you can'.
What you cannot do is emulate someone clicking a link, that is as if someone really did click a link and for example the target being followed.

You can simulate a click and any event bound to it will be executed.
See this fiddle for an example
http://jsfiddle.net/9txPQ/2/
No user interaction but the anchor click function fires
Avatar of rascal

ASKER

I stand corrected :)
Avatar of rascal

ASKER

I've requested that this question be closed as follows:

Accepted answer: 0 points for rascal's comment #a39473857

for the following reason:

This is the solution to the problem - we had initially tried using the .click() but it failed with the error message listed in my original question posting.

What the problem was - was we called the .click() handler too soon (even though we called it from our document.read() function). Perhaps fancybox needed more time to initialize? At any rate, we deferred our code for 1 second by setting a setTimeout() of 1000 milliseconds to invoke our function, then it all worked fine.
Avatar of rascal

ASKER

Sorry, didn't mean to close this on my comment - I meant to close it on GaryC123's comment that we use the .click() handler and award points to GaryC123.

How can we adjust?
Avatar of rascal

ASKER

GaryC123 - this is what I meant when I said that you cannot invoke an <a> from the .click() handler: http://jsfiddle.net/9txPQ/4/
Yes that's I thought you were thinking and why I thought I had clarified it in my comment.
Your click event in your jsfiddle is working and firing but there is nothing to do with the click, the href will not be followed because you cannot emulate a real click.
Click Request Attention under your initial question.