1

No matter where I put this, it won't work. Meaning, it won't work inside the html file, in script-tags, not above the hideShow function not below it. I have one JS file and a html file. There are two functions in that JS file, the first one works fine, but when I try to call the second one, it just won't work, wheras when I try to execute the same piece of code directly inside the onclick="" property of the img it works. Here is said JS file:

function hideShow(x,y) {
    var hide = document.getElementById(x);
    var show = document.getElementById(y);
    if (!hide.classList.contains("height-zero") && show.classList.contains("height-zero")) {
        hide.classList.add("height-zero");
        show.classList.remove("height-zero");
    } else {
        hide.classList.remove("height-zero");
        show.classList.add("height-zero");
    }
 }

function changeSource(x) {
    this.src = x;
}

And this is how I put it in the img-tag

<img src="img/label.png" onClick="changeSource('img/label2.png')">

Note I have more than one image

1
  • Because you're not passing the this as context. Function#call (thisCtx, args) or Function#apply (thisCtx, argCollectionObj) allows to do that -> changeSource.call(this, "img/label2.png") Commented Nov 18, 2016 at 10:30

3 Answers 3

3

You need to pass this to your function:

<img src="img/label.png" onClick="changeSource(this, 'img/label2.png')">

function changeSource(el, x) {
    el.src = x;
}
Sign up to request clarification or add additional context in comments.

6 Comments

Thank you very much. I thought the function would know that 'this' refered to the object it was called from, but yeah, it works now. Will accept this as answer in 5 mins.
@J.H. It does not, because function can be called from other function, than this would link to two different things and that is wrong.
@mplungjan Can you provide source about that?
Just search "inline javascript practice" - it is quite established to separate view and controller. If you have inline handlers they may interfere with other scripts. For example I stopped using <body onload in 1998 or so in favour of window.onload and later added event listeners if necessary.
@mplungjan But lots of event listeners will slow down your site. Having onClick provides less footprint...
|
1

And an alternative of @Justinas answer is to pass this context to this function call, just like my comment said:

changeSource.call(this, "img/label2.png")

Comments

0

Alternative to other answer, if you move the event assignment from inline to the script tag, you can use this - right now your this is window.

If you have more than one image you can give them a class and do

window.onload=function() {
  var imgs = document.querySelectorAll(".labelImage");
  for (var i=0, n=imgs.length;i<n;i++) {
    imgs[i].onclick=function() {
      this.src = this.getAttribute("data-src2"); 
      // or possibly this.src = this.src.replace(/label\./,"label2.")
    }
  }
}

using

<img class="labelImage" src="img/label1.png" data-src2="img/label1x.png" />
<img class="labelImage" src="img/label2.png" data-src2="img/label2x.png" />
<img class="labelImage" src="img/label3.png" data-src2="img/label2x.png" />

Inline, this also works, I however recommend you do not use inline functions:

<img src="img/label.png" onclick="this.src='img/label2.png'" />

4 Comments

Well, well, this solution is much more elegant. Thanks. EDIT: On a second thought, it doesn't work the way I want to use it though, I have a lot of images that I need to use that function on.
Your solution require unique ID for each image, so it's not re-usable and when you have 10 images, than you will be needing 10 onClick function declarations.
@J.H. The multiple images was not part of the original description. Please see the update for multiple images. If the clicked image has a post or prefix, then the data-src2 can be removed and the replace version used
@Justinas feel free to remove your downvote which was rather harsh given the lack of information from OP

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.