简体   繁体   中英

Why can't I use javascript variable inside of FancyBox?

// Post Div
<div id="post-1"><img src="art/image01.jpg" /></div>
<div id="post-2"><img src="art/image02.jpg" /></div>
<div id="post-3"><img src="art/image03.jpg" /></div>

// MYSQL Json Encode Generated Information
var allPosts = [{"type":"tumblr", "link":"www.blah.com"},
    {"type":"instagram", "link":"blah.com"},
    {"type":"tumblr", "link":"www.blah.com"}]

var postTotals = 3;

// Generates FancyBox Links for Clickable Post Div
function generateFancyBox(){
    for(i=1;i<=postTotals;i++){
        $("#post-"+i).click(function(){
            alert(allPosts[i].link); // This alerts "www.blah.com" just fine.
            $.fancybox({
            "type" : "iframe",
            "href" : allPosts[i].link // This Variable is always "Undefined".
            });
        });
    }
}

I don't understand why href : allPosts[i].link - always becomes undefined .

This code is a shorthand version of a larger project I'm working on. I have html DIVs that I need FancyBox to create clickable links.

I can not seem to get the allPosts[i].link to print the URL . However, right above it, when I alert(allPosts[i].link); it prints the URL just fine.

What am I doing wrong?

Replace the $.fancybox call with an immediately executing function, which creates a additional closure.

(function () {
        alert(i);
        $.fancybox({
            "type": "iframe",
            "href": allPosts[i].link // This Variable is always "Undefined".
        });
    })();

2 problems:

1) In the click event handler, wrap the click handler assignment in an Immediately Invoked Function Expression (IIFE).

JSFiddle it.

function generateFancyBox(){
    for(i=1;i<=postTotals;i++){
        (function (ii) {
            $("#post-"+ii).click(function(){
                console.log(allPosts[ii-1].link);                
                //$.fancybox({ "type" : "iframe", "href" : allPosts[ii-1].link });
            });
        }(i))
    }
}

By the time the click handler (and fancybox) does it's job, i is not what it was when it was passed, as a reference, to fancybox. Passing i in as a parameter to the IIFE you're creating a new scope with a new variable ii that gets locked in to the current value of the for loop i when it was passed to the click handler.

2) There's also a problem with the loop and DIV indexes not sync'ing with the image/link array. So I changed:

allPosts[ii] to allPosts[ii-1]

Your loop and image DIVs start with "1" as in for(i=1; and post-1 but your image/link array is zero-based, which means it starts with "0" as in allPosts[0] . So when grabbing the image/link element, decrement counter by one.

The real problem is that you are creating closures inside a loop . See this for further information.

What you have to do is to create the closure outside of the loop and call it as the handler (or callback ) of your click event , passing i as argument , so

the closure :

function launchFancybox(i) {
    return function () {
        $.fancybox({
            type: "iframe",
            href: allPosts[i].link
        });
    }
}

Then bind the click events to each div inside your generateFancyBox() function like :

function generateFancyBox() {
    for (var i = 0; i < allPosts.length; i++) {        
        $("#post-"+(i+1)).click( launchFancybox(i) );
    }
}

NOTES :

  • we need to initialize i declaring it with var (in strict mode, it will return an undeclared variable error if you don't)
  • notice that i should always start with 0 , otherwise you will never have access to the first element of the allPosts array . You need to use (i+1) to refer to each div's ID though.
  • you don't actually need var postTotals = 3; since you can always refer to the length of your allPosts array

See JSFIDDLE

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM