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!
jQuery

Avatar of undefined
Last Comment
Gary

8/22/2022 - Mon
Scott Fell

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

ASKER
rascal

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.
Scott Fell

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

Experts Exchange is like having an extremely knowledgeable team sitting and waiting for your call. Couldn't do my job half as well as I do without it!
James Murphy
ASKER
rascal

@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.
Gary

You're calling the fancybox function outside the document.ready but you are initing the fancybox setup in a document.ready.
ASKER
rascal

@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.
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.
Gary

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
Gary

Log in or sign up to see answer
Become an EE member today7-DAY FREE TRIAL
Members can start a 7-Day Free trial then enjoy unlimited access to the platform
Sign up - Free for 7 days
or
Learn why we charge membership fees
We get it - no one likes a content blocker. Take one extra minute and find out why we block content.
See how we're fighting big data
Not exactly the question you had in mind?
Sign up for an EE membership and get your own personalized solution. With an EE membership, you can ask unlimited troubleshooting, research, or opinion questions.
ask a question
ASKER
rascal

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

Gary

Wouldn't it just be easier to simulate the click rather than repeating code...?
Experts Exchange has (a) saved my job multiple times, (b) saved me hours, days, and even weeks of work, and often (c) makes me look like a superhero! This place is MAGIC!
Walt Forbes
Scott Fell

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.
ASKER
rascal

@Gary,
You can't use the .click() to emulate clicking on an <a> tag.
Gary

Yes you can.
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.
ASKER
rascal

Gary

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
ASKER
rascal

I stand corrected :)
All of life is about relationships, and EE has made a viirtual community a real community. It lifts everyone's boat
William Peck
ASKER
rascal

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.
ASKER
rascal

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?
ASKER
rascal

GaryC123 - this is what I meant when I said that you cannot invoke an <a> from the .click() handler: http://jsfiddle.net/9txPQ/4/
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.
Gary

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.