2012-04-12 69 views
3

我有一个指向图像的链接列表,以及一个需要URL(图像)并将该图像放在页面上的js函数当函数被调用时。JavaScript - 遍历所有标签,为每个标签添加一个onklick

我最初为每个a添加了一个内联onlick =“showPic(this.getAttribute('href'))”,但我想分离出内联js。这是我添加一个onclick每个当标签页面加载FUNC:

function prepareLinks(){ 
var links = document.getElementsByTagName('a'); 
for(var i=0; i<links.length; i++){ 
    var thisLink = links[i]; 
    var source = thisLink.getAttribute('href'); 
    if(thisLink.getAttribute('class') == 'imgLink'){ 
     thisLink.onclick = function(){ 
      showPic(source); 
      return false; 
     } 
    } 
} 
} 

function showPic(source){ 
var placeholder = document.getElementById('placeholder'); 
placeholder.setAttribute('src',source); 
} 

window.onload = prepareLinks(); 

...但每showPic被调用时,源变种是最后一个图像的href。我怎样才能让每个链接都有正确的onclick?

+1

不想使用jQuery,使这个名副其实的单行? – 2012-04-12 23:24:40

+4

你的'window.onload'是错误的。这会将'prepareLinks()'的返回赋值给'window'的'load'事件。 – alex 2012-04-12 23:36:01

+0

@alex:很好的捕获,甚至没有看到 – 2012-04-12 23:37:16

回答

0

感谢您的回复。原来我错误地诊断了这个问题,对不起。实际上使用一个新的变种和annon。函数添加onclick每个循环迭代工作(传递的href是正确的)。这不起作用,因为当我删除内联的onclick处理程序时(我现在用一个父母身份获得它们),我通过从HTML中移除的“imgLink”类获得了a-tags。另外我需要使用“return!showPic(this.href);”单击时通常会停止链接。

工作代码:

function showPic(source){ 
var placeholder = document.getElementById('placeholder'); 
placeholder.setAttribute('src',source); 
return true; 
} 

function prepareLinks() { 
if(!document.getElementById('imgLinks')){ return false; }; 
var galLinks = document.getElementById('imgLinks'); 
var links = galLinks.getElementsByTagName('a'); 
for(var i=0; i<links.length; i++) { 
    var thisLink = links[i]; 
    thisLink.onclick = function() { 
     return !showPic(this.href); 
    }; 
} 
} 

window.onload = function(){ 
prepareLinks(); 
} 
4

JavaScript没有块范围,所以关闭的变量最后被分配给它。您可以通过在另一封包装就解决这个问题:

function prepareLinks() { 
    var links = document.getElementsByTagName('a'); 
    for(var i = 0; i < links.length; i++) { 
     var thisLink = links[i]; 
     var source = thisLink.getAttribute('href'); 
     if(thisLink.getAttribute('class') == 'imgLink') { 
      thisLink.onclick = (function(source) { 
       return function() { 
        showPic(source); 
        return false; 
       }; 
      })(source); 
     } 
    } 
} 

当然,你可以让这个简单,使用this

function prepareLinks() { 
    var links = document.getElementsByTagName('a'); 

    for(var i = 0; i < links.length; i++) { 
     var thisLink = links[i]; 

     if(thisLink.getAttribute('class') == 'imgLink') { 
      thisLink.onclick = function() { 
       showPic(this.href); 
       return false; 
      }; 
     } 
    } 
} 

我相信,随着IE5或IE6这个无论是休息的兼容性,但希望你不关心这些=)

+0

块范围不会解决这个问题。另外,如果您只是从处理程序中获取源代码,则不需要创建所有这些额外的范围 – 2012-04-12 23:27:26

+1

@JuanMendes:实际上,块范围将真正解决此问题。至于从处理程序得到它 - 已经添加;) – Ryan 2012-04-12 23:29:14

+0

我仍然不同意,我不认为块范围将修复它,'源'在所有处理程序在相同的块定义 – 2012-04-12 23:34:05

0

这是在访问外部变量的循环内的事件处理程序的古老问题。

您的source变量在click事件发生时从作用域链上拉下,然后由于迭代过程已被设置为最后的href属性。

您需要通过执行以下两件事之一来打破关闭。

许多浏览器最简单但不支持的是使用let,它允许您使用块范围。

let source = thisLink.getAttribute('href'); 

jsFiddle。它在Firefox中工作,但不是Chrome。

2038年,当我们处理year 2038 problem和所有浏览器都实现了ES6时,这将以修复这个问题的标准方式解决。

更困难的理解和执行方法是与所有浏览器兼容是打破封闭与诸如图案...

thisLink.onclick = (function(src) { 
    return function(){ 
      showPic(src); 
      return false; 
     } 
})(source); 

jsFiddle

+0

我在SO每一天看到这个问题...... – 2012-04-12 23:32:33

+1

'let'不是EcmaScript(还),它是Mozilla的JavaScript,希望它能够很快进入EcmaScript – 2012-04-12 23:48:12

+0

@JuanMendes [It's在途中](http://wiki.ecmascript.org/doku.php?id=harmony:let)。 – alex 2012-04-12 23:50:41

2

MiniTech移动的答案应该解决您的问题,这就是source变量是由所有的onclick处理

你做它的方式共享是非常浪费的,就没有必要设置一个单独的处理程序,每一个环节。另外,如果有任何链接是动态添加的,它将不起作用。事件代表团是要走的路。

function interceptLinks() { 
    // Bad way to set onclick (use a library) 
    document.onclick = function() { 
    if (this.tagName.toUpperCase() != 'A') { 
     return; 
    } 
    // Bad way to check if it contains a class (use a library) 
    if (this.getAttribute('class') == 'imgLink') { 
     showPic(this.getAttribute('href')); 
     return false; 
    } 
    } 
} 
+1

+1用于建议事件委派。 – alex 2012-04-12 23:35:18

相关问题