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!
LVL 1
rascalAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Scott Fell, EE MVEDeveloper & EE ModeratorCommented:
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

0
rascalAuthor Commented:
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.
0
Scott Fell, EE MVEDeveloper & EE ModeratorCommented:
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

0
Build an E-Commerce Site with Angular 5

Learn how to build an E-Commerce site with Angular 5, a JavaScript framework used by developers to build web, desktop, and mobile applications.

rascalAuthor Commented:
@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.
0
GaryCommented:
You're calling the fancybox function outside the document.ready but you are initing the fancybox setup in a document.ready.
0
rascalAuthor Commented:
@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.
0
GaryCommented:
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
0
GaryCommented:
I think you're problem is coming from trying to initiate the fancybox twice.
Why not after you do your normal initialization do something like

$("a[href='http://www.youtube.com/embed/05zozOAqjBM']").click();

The element already has fancybox bound to it so you are just simulating a click.
Obviously you would still build the url as you are doing at the moment.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
rascalAuthor Commented:
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

0
GaryCommented:
Wouldn't it just be easier to simulate the click rather than repeating code...?
0
Scott Fell, EE MVEDeveloper & EE ModeratorCommented:
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.
0
rascalAuthor Commented:
@Gary,
You can't use the .click() to emulate clicking on an <a> tag.
0
GaryCommented:
Yes you can.
0
GaryCommented:
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
0
rascalAuthor Commented:
I stand corrected :)
0
rascalAuthor Commented:
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.
0
rascalAuthor Commented:
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?
0
rascalAuthor Commented:
GaryC123 - this is what I meant when I said that you cannot invoke an <a> from the .click() handler: http://jsfiddle.net/9txPQ/4/
0
GaryCommented:
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.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
jQuery

From novice to tech pro — start learning today.