Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.javascript > #21711 > unrolled thread
| Started by | "Tony Johansson" <johansson.andersson@telia.com> |
|---|---|
| First post | 2013-10-24 01:47 +0200 |
| Last post | 2013-10-26 00:38 +0200 |
| Articles | 6 — 4 participants |
Back to article view | Back to comp.lang.javascript
I don't want to have if for each index in the loop "Tony Johansson" <johansson.andersson@telia.com> - 2013-10-24 01:47 +0200
Re: I don't want to have if for each index in the loop Ben Bacarisse <ben.usenet@bsb.me.uk> - 2013-10-24 02:44 +0100
Re: I don't want to have if for each index in the loop "Tony Johansson" <johansson.andersson@telia.com> - 2013-10-24 09:16 +0200
Re: I don't want to have if for each index in the loop Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2013-10-24 12:17 +0200
Re: I don't want to have if for each index in the loop dhtml <dhtmlkitchen@gmail.com> - 2013-10-25 14:52 -0700
Re: I don't want to have if for each index in the loop Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2013-10-26 00:38 +0200
| From | "Tony Johansson" <johansson.andersson@telia.com> |
|---|---|
| Date | 2013-10-24 01:47 +0200 |
| Subject | I don't want to have if for each index in the loop |
| Message-ID | <l49n7g$u0a$1@dont-email.me> |
I have two functions InitThumbnails and ShowBigImage shown below. I want to
create event handlers for each element when I loop through the thumbnailsArr
by using only one statement like this
element.addEventListener("click", function () {
ShowBigImage(thumbnailsArr[i]); }, false);
In the present code in function InitThumbnails I have this solution
if (i == 0)
element.addEventListener("click", function () {
ShowBigImage(thumbnailsArr[0]); }, false);
else if(i==1)
element.addEventListener("click", function () {
ShowBigImage(thumbnailsArr[1]); }, false);
else if(i==2)
element.addEventListener("click", function () {
ShowBigImage(thumbnailsArr[2]); }, false);
else if(i==3)
element.addEventListener("click", function () {
ShowBigImage(thumbnailsArr[3]); }, false);
else if(i==4)
element.addEventListener("click", function () {
ShowBigImage(thumbnailsArr[4]); }, false);
it works but it's not a nice code and I want to have only one statement like
I said earlier in this way
element.addEventListener("click", function () {
ShowBigImage(thumbnailsArr[i]); }, false);
The problem is that when I test this and use this statement
element.addEventListener("click", function () {
ShowBigImage(thumbnailsArr[i]); }, false);
and put a breakpoint on function ShowBigImage the passed parameter image is
undefined.
I think I need to use something called closure but I don't know how to write
?
function InitThumbnails(thumbnailsArr)
{
for (var i = 0; i < thumbnailsArr.length; i++)
{
var element = document.getElementById("fig" + i);
element.setAttribute("src", "img/" + thumbnailsArr[i]);
element.setAttribute("alt", thumbnailsArr[i].split(".")[0]);
document.getElementById("desc" + i).innerHTML =
thumbnailsArr[i].split(".")[0];
if (i == 0)
element.addEventListener("click", function () {
ShowBigImage(thumbnailsArr[0]); }, false);
else if(i==1)
element.addEventListener("click", function () {
ShowBigImage(thumbnailsArr[1]); }, false);
else if(i==2)
element.addEventListener("click", function () {
ShowBigImage(thumbnailsArr[2]); }, false);
else if(i==3)
element.addEventListener("click", function () {
ShowBigImage(thumbnailsArr[3]); }, false);
else if(i==4)
element.addEventListener("click", function () {
ShowBigImage(thumbnailsArr[4]); }, false);
}
}
function ShowBigImage(image)
{
var element = document.getElementById("bigimage");
element.setAttribute("src", "img/" + image);
element.setAttribute("alt", image.split(".")[0]);
}
//Tony
[toc] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2013-10-24 02:44 +0100 |
| Message-ID | <0.2881687aedec8c956bad.20131024024418BST.87li1jbfyl.fsf@bsb.me.uk> |
| In reply to | #21711 |
"Tony Johansson" <johansson.andersson@telia.com> writes:
> I have two functions InitThumbnails and ShowBigImage shown below. I
> want to create event handlers for each element when I loop through the
> thumbnailsArr by using only one statement like this
> element.addEventListener("click", function () {
> ShowBigImage(thumbnailsArr[i]); }, false);
<snip>
> I think I need to use something called closure but I don't know how to
> write ?
>
> function InitThumbnails(thumbnailsArr)
> {
> for (var i = 0; i < thumbnailsArr.length; i++)
> {
> var element = document.getElementById("fig" + i);
> element.setAttribute("src", "img/" + thumbnailsArr[i]);
> element.setAttribute("alt", thumbnailsArr[i].split(".")[0]);
> document.getElementById("desc" + i).innerHTML =
> thumbnailsArr[i].split(".")[0];
element.addEventListener("click",
(function (idx) {
return function () { ShowBigImage(thumbnailsArr[idx]); }
})(i),
false);
> }
> }
The gist of it (and I am twisting the terminology a lot here) is that in
you previous attempt, all the functions created in the loop capture the
same thing 'i' -- so they share it. You need a function whose
environment has a binding for a copy of the value of 'i'. One way to do
that is to call a function that returns the function you need, passing
it the value you want to bind to a new identifier. Each of the many
event handlers end up with an environment with its own 'idx', each one
with a different value.
By the way, what you wrote before was also a closure -- it simply did
not have the right bindings in its environment.
<snip>
--
Ben.
[toc] | [prev] | [next] | [standalone]
| From | "Tony Johansson" <johansson.andersson@telia.com> |
|---|---|
| Date | 2013-10-24 09:16 +0200 |
| Message-ID | <l4ahg3$7ba$1@dont-email.me> |
| In reply to | #21712 |
Many thanks nice solution and it was exactly this that I was looking for.
//Tony
"Ben Bacarisse" <ben.usenet@bsb.me.uk> skrev i meddelandet
news:0.2881687aedec8c956bad.20131024024418BST.87li1jbfyl.fsf@bsb.me.uk...
> "Tony Johansson" <johansson.andersson@telia.com> writes:
>
>> I have two functions InitThumbnails and ShowBigImage shown below. I
>> want to create event handlers for each element when I loop through the
>> thumbnailsArr by using only one statement like this
>> element.addEventListener("click", function () {
>> ShowBigImage(thumbnailsArr[i]); }, false);
> <snip>
>> I think I need to use something called closure but I don't know how to
>> write ?
>>
>> function InitThumbnails(thumbnailsArr)
>> {
>> for (var i = 0; i < thumbnailsArr.length; i++)
>> {
>> var element = document.getElementById("fig" + i);
>> element.setAttribute("src", "img/" + thumbnailsArr[i]);
>> element.setAttribute("alt", thumbnailsArr[i].split(".")[0]);
>> document.getElementById("desc" + i).innerHTML =
>> thumbnailsArr[i].split(".")[0];
>
> element.addEventListener("click",
> (function (idx) {
> return function () { ShowBigImage(thumbnailsArr[idx]); }
> })(i),
> false);
>
>> }
>> }
>
> The gist of it (and I am twisting the terminology a lot here) is that in
> you previous attempt, all the functions created in the loop capture the
> same thing 'i' -- so they share it. You need a function whose
> environment has a binding for a copy of the value of 'i'. One way to do
> that is to call a function that returns the function you need, passing
> it the value you want to bind to a new identifier. Each of the many
> event handlers end up with an environment with its own 'idx', each one
> with a different value.
>
> By the way, what you wrote before was also a closure -- it simply did
> not have the right bindings in its environment.
>
> <snip>
> --
> Ben.
[toc] | [prev] | [next] | [standalone]
| From | Thomas 'PointedEars' Lahn <PointedEars@web.de> |
|---|---|
| Date | 2013-10-24 12:17 +0200 |
| Message-ID | <3044571.oA5CmXAGKN@PointedEars.de> |
| In reply to | #21713 |
Tony Johansson wrote: > Many thanks nice solution and it was exactly this that I was looking for. > > [Top post] What you are looking for is - to read on attribute properties in order to get rid of setAttribute(); - to read on event bubbling in order to get rid of multiple event listeners; - to learn to quote in order to get read again. <http://PointedEars.de/faq> -- PointedEars Twitter: @PointedEars2 Please do not Cc: me. / Bitte keine Kopien per E-Mail.
[toc] | [prev] | [next] | [standalone]
| From | dhtml <dhtmlkitchen@gmail.com> |
|---|---|
| Date | 2013-10-25 14:52 -0700 |
| Message-ID | <6ca9a5c5-bfaa-48ca-947e-be5fc60fb3b3@googlegroups.com> |
| In reply to | #21714 |
On Thursday, October 24, 2013 3:17:34 AM UTC-7, Thomas 'PointedEars' Lahn wrote:
> Tony Johansson wrote:
>
>
>
> > Many thanks nice solution and it was exactly this that I was looking for.
>
> >
>
> > [Top post]
>
>
>
> What you are looking for is
>
>
>
> - to read on attribute properties in order to get rid of setAttribute();
>
> - to read on event bubbling in order to get rid of multiple event listeners;
>
Yes!
Valuable advice here.
The information on closures is useful to learn, and should be considered here for the OP. And in this particular case, OP, bubbling is more elegant, so look into that.
Here is a general example, though there must be better examples online.
var imgThumbExp = /-thumb$/;
var imgContainer = document.body; // Replace with closer ancestor
imgContainer.onclick = imgContainerClicked;
function imgContainerClicked(ev) {
var target = ev.target;
if(target && imgThumbExp.test(target.id)) {
showBigImage(target.id.replace(imgThumbExp , "");
}
}
<img id="pretzel-thumb" src="pretzel-thumb.jpg">
<img id="pretzel" src="pretzel.jpg">
> - to learn to quote in order to get read again.
>
>
>
> <http://PointedEars.de/faq>
>
>
>
> --
>
> PointedEars
>
>
>
> Twitter: @PointedEars2
>
> Please do not Cc: me. / Bitte keine Kopien per E-Mail.
[toc] | [prev] | [next] | [standalone]
| From | Thomas 'PointedEars' Lahn <PointedEars@web.de> |
|---|---|
| Date | 2013-10-26 00:38 +0200 |
| Message-ID | <4429325.cM6MFbt01H@PointedEars.de> |
| In reply to | #21732 |
dhtml wrote:
> Thomas 'PointedEars' Lahn wrote:
>> Tony Johansson wrote:
>> > Many thanks nice solution and it was exactly this that I was looking
>> > for.
>> >
>> > [Top post]
>>
>> What you are looking for is
>>
>> - to read on attribute properties in order to get rid of setAttribute();
>> - to read on event bubbling in order to get rid of multiple event
>> listeners;
>
> Yes!
>
> Valuable advice here.
>
> The information on closures is useful to learn, and should be considered
> here for the OP. And in this particular case, OP, bubbling is more
> elegant, so look into that.
>
> Here is a general example, though there must be better examples online.
Plenty.
> var imgThumbExp = /-thumb$/;
> var imgContainer = document.body; // Replace with closer ancestor
The comment should be a multi-line pre-comment to tell it apart of
deactivating single-line comments.
The comment content is very important here. The same as a short scope chain
increases efficiency, so does a short event bubbling route.
> imgContainer.onclick = imgContainerClicked;
>
> function imgContainerClicked(ev) {
> var target = ev.target;
A wrapper is required to support non-W3C DOM implementations, in particular
the MSHTML DOM before version 9, or version 9 in Browser Compatibility Mode.
<http://msdn.microsoft.com/en-us/library/ie/ff974946(v=vs.85).aspx>
> if(target && imgThumbExp.test(target.id)) {
> showBigImage(target.id.replace(imgThumbExp , "");
Passing ID strings *instead of* DOM object references to functions is not a
good idea.
> }
> }
>
> <img id="pretzel-thumb" src="pretzel-thumb.jpg">
> <img id="pretzel" src="pretzel.jpg">
It is a lot easier (and more efficient) to use the suffix for the *target*
element of the feature instead of the source element. And I would filter
for a class name, if necessary the element type before that:
/* Replace with closer ancestor */
var imgContainer = document.body;
imgContainer.onclick = jsx.dom.createEventListener(imgContainerClicked);
function imgContainerClicked (ev)
{
var target = ev.target;
/* A wrapper is required to support non-HTML5 DOM implementations */
if (target.classList.contains("thumb"))
{
showBigImage(document.getElementById(target.id + "-large"));
}
}
<img id="pretzel" src="pretzel-thumb.jpg" class="thumb">
<img id="pretzel-large" src="pretzel.jpg">
See also:
<http://www.w3.org/TR/2012/WD-dom-20121206/#dom-element-classlist>
<http://PointedEars.de/wsvn/JSX/trunk/dom.js>
<http://PointedEars.de/wsvn/JSX/trunk/dom/events.js>
Please trim your quotes, and avoid using the borken Google Groups if
possible.
<http://PointedEars.de/faq/notes/posting/>
--
PointedEars
Twitter: @PointedEars2
Please do not Cc: me. / Bitte keine Kopien per E-Mail.
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.javascript
csiph-web