Beginners Javascript question here.
I am trying to create a function that finds all the links in a given div and sets up an onclick event for each one. I can get the link hrefs correctly, but when I try using them in the onclick function, Javascript seems to only use the last value found:
I.E
I have these links
#purpose
#future
#faq
When I use the onclick function, every link is reported as the #faq link.
Here's the code:
function prepareLinks () {
var nav = document.getElementById('navigation');
var links = nav.getElementsByTagName ('a');
for (var i = 0; i<links.length; i++) {
var linkRef = links[i].getAttribute('href').split("#")[1];
links[i].onclick = function () {
var popUp = "You clicked the " +linkRef +" link";
alert (popUp);
}
}
}
Here you have a closure creation. External variable linkRef becomes saved in inner onclick function. Try this way:
clickFunction() {
var popUp = "You clicked the " + this.href.split("#")[1] +" link";
// this should mean current clicked element
alert (popUp);
}
for (var i = 0; i<links.length; i++) {
links[i].onclick = clickFunction;
}
This is a scoping problem. The expression "You clicked the " +linkRef +" link" is evaluated when the onclick event fires, but what is the value of linkRef at this point?
You're trying to attach a separate onClick handler to each link, but you're accidentally attaching the same one.
You could generate a new function each time by using the new Function() constructor as
links[i].onclick = new Function("","alert('You clicked the '"+linkRef+"' link');");
See http://tadhg.com/wp/2006/12/12/using-new-function-in-javascript/ for more details.
But it's generally better to see if you can have a single handler. It's interesting that when you get to an event handler, the "this" keyword refers to the generator of the event. So you could have your original code refer to this.getAttribute("href"). Too many handlers will make your javascript event processing slow.
Related
I am trying to write a simple game using two.js. I have a function which is called either from button click event and from game loop:
function endGame(gameLoop){
showStartGame();
gameLoop.pause();
$("#gameSquare svg:first").remove();
$("#startGame").show();
}
The line $("#startGame").show() executes correctly only when called from the event, the rest works perfectly fine in both cases.
Click event handler:
$("#abandonGame").click(function(){
endGame(two);
gameLoopPaused = true;
gameStarted = false;
});
The call that doesn't work properly(this.update() is called inside game loop):
this.update = function(){
var computedVector = new Two.Vector(0,0);
screens.forEach(function(screen){
screen.update(speed);
screen.getRectangles().forEach(function(item){
computedVector.x = item.rect.translation.x;
computedVector.y = item.rect.translation.y + screen.getPosition().y;
if(computedVector.distanceTo(new Two.Vector(ship.getX(), ship.getY())) < latura + 20)
endGameEvent();
});
try wrapping it in document.ready
$(document).ready(function() {
$("#startGame").show();
});
You can't call show() on an object before it exists
The problem was with the parent of $("#startGame"), it was hidden as well. It worked with event because by the time I was hitting the $("#abandonGame") button It was displayed on the screen.
I'm adding a click event to all links that match a particular selector as part of a JS module I'm creating. It looks something like this.
var Lightbox = (function () {
var showLightbox = function () {
// this does stuff
};
var init = function () {
var links = document.querySelectorAll(options.selector);
for(var i = 0; i < links.length; i++) {
links[i].addEventListener('click', function() {
showLightbox();
}, false);
}
};
return {
init: init
};
})();
Lightbox.init();
On first load the any links on the page that match the selector work. There is also a closeLightbox() method that works fine. However when clicking the links for a second time nothing happens. I get no console errors – nuffin.
Is there something I'm doing wrong when adding the event listener?
EDIT: I've updated the code to remove some redundant methods and have pasted the full code here: http://pastebin.com/mC8pSAV2
You are reassigning innerHTML of the whole document:
document.body.innerHTML += response;
on the link click. That wipes out all existing DOM elements with their events and creates new DOM structure with no clicks assigned.
I have a clickable image that when you click a modal popup appears. I want to make sure you can only click it once and while the popup is showing, the clickable image is unclickable. I've tried several methods but no solution works as I want it to.
Here is the code:
init: function () {
var myButton = document.getElementById("kaffePic");
var clickable = true;
console.log(clickable);
myButton.onclick = function(e) {
e.preventDefault();
console.log(clickable);
if(clickable)
{
clickable = false;
popup(myButton, clickable);
}
else
{
return false;
}
};
}
And here is a part of the popup window (removed some code that has nothing to do with the issue).
function popup(theButton, returnClick) {
var myDiv = document.createElement("div");
myDiv.className = "popupWindow";
var newButton = document.createElement('a');
var image = document.createElement('img');
image.src = 'img/theclosebutton.png';
image.className = "popupImage";
newButton.appendChild(image);
myDiv.appendChild(newButton);
newButton.onclick = function () {
document.body.removeChild(myDiv);
returnClick = true;
};
}
Right now I can click it once, and then never again.
Any suggestions?
it's called only once because clickable is set to false after the first click. i suspect you are trying to set it to true in your popup-method by calling returnClick = true; but all that does is setting your argument-value, not the actual clickable-variable itself.
right now, clickable is a variable in the scope of init, so popup can't access it. you could, for example, make clickable a var in the scope of init's parent object. then in popup, you'd access clickable by parentObject.clickable.
//illustration of my example
parentObject {
var clickable,
function init()
}
function popup() {
...
parentObject.clickable = true;
}
Check .one() event handler attachment of jquery and this the .one() of jquery is used to Attach a handler to an event for the elements. The handler is executed at most once per element per event type. second one is link to an stack overflow questions about resetting the .one().Hope this helps
My goal is to store the total amount of clicks on links in a certain page into a variable and recall that variable when the user exits the page. Would this be a correct way of doing it?
window.onunload = function(){
alert("Total Links Clicked:" + clicks(););
}
var clicks = function(){
var clickArray = [];
var getLinks = document.getElementsByTagName(A);
var clickValue = getLinks.onclick = function() {
clickArray.push("1");
}
var totalClicks = clickArray.length;
return totalClicks;
}
Your code won't work for several reasons:
You bind the click handler in clicks() function and don't call clicks() until the page is unloaded, at which point it is too late to handle any clicks. You need to bind the click handler when the page loads.
You can't set .onclick on a list of elements, which is what your getLinks variable is given it was set to the result of getElementsByTagName() (get elements not get element).
You pass an undeclared variable A to getElementsByTagName(); you should pass the string "a".
You have a semicolon inside the alert()'s closing ), which is a syntax error.
You could try something like this:
window.onload = function() {
var clicks = 0;
window.onunload = function(){
alert("Total Links Clicked:" + clicks);
}
function clicked() {
clicks++;
}
var getLinks = document.getElementsByTagName("a");
for (var i = 0; i < getLinks.length; i++)
getLinks[i].onclick = clicked;
};
Note that the browser may block an alert() during an unload event, but if you use console.log() instead you can see that clicks had the right value.
Note also that of course a click on a link to another page will cause an unload, so the click count will only be more than 1 if you have links within the current page.
Demo: http://jsfiddle.net/A3bkT/1/
You can use sessionStorage or localStorage for that.
if(typeof(Storage)!=="undefined")
{
// store the clicks here
sessionStorage.numClicks = value;
}
and read more on these two here : http://www.w3schools.com/html/html5_webstorage.asp
Bind a global event listener and just store the count with sessionStorage:
var clicks = 0;
document.addEventListener('click', function(event) {
if (event.target.nodeName == 'A') {
window.sessionStorage.setItem('clicks', ++clicks);
}
}, false);
I'm having trouble adding eventListener to through javascript. Ok, I have a function that creates 4 anchor elements. I want to add an event to them onmouseover that calls a function to change their backkground color. Here's the code (look at the next to last line of createAnchor() to find the relevant code line.
function createAanchor(index) {
var a = document.createElement("a");
var text = getText(index);
var a = document.createElement("a");
var t = document.createTextNode(text);
a.href = getHref(index);
a.appendChild(t);
a.style.textAlign = "center";
a.style.fontSize = "1.2em";
a.style.color = "white";
a.style.fontFamily = "arial";
a.style.fontWeight = "bold";
a.style.textDecoration = "none";
a.style.lineHeight = "238px";
a.style.width = "238px";
a.style.margin = "5px";
a.style.background = eightColors(index);
a.style.position = "absolute";
a.addEventListener("onmouseover", changeColor());
return a;
}
function changeColor() {
alert("EVENT WORKING");
}
Ok here's the problem. When the function gets to a.addEventListener("onmouseover", changeColor()); the function changeColors() executes, but it does not execute later on onmouseover Why is this?
There is no such event onmouseover, the event is called mouseover.
You have to pass a function reference to addEventlistener. () calls the function, as you already noticed, so... don't call it.
This is how it should be:
a.addEventListener("mouseover", changeColor);
I recommend to read the excellent articles about event handling on quirksmode.org.
It's because you wrote changeColors() instead of just changeColors. The () tell JavaScript to call the function.
In other words, changeColors by itself is a reference to the function, while changeColors() refers to the function and then calls it. The result of the function call (the return value from the function) is what's ultimately passed to addEventListener().
Ok I think we need to understand when to use the prefix "on" with the event type. In IE 8 or less then IE8 we use attachEvent and detachEvent which are equivalent to addEventListener and removeEventListener. There are some differences which are not required for this question.
While using attachEvent the event type is prefixed with "on" but in addEventListener no prefix is used.
hence,
elem.attachEvent("onclick",listener); // <= IE8
elem.addEventListener("click",listener,[,useCapture]); // other browsers
I've needed to do something like that too. I have an infoWindow in my map and I need to handle a click event on paragraph in that infoWindow. So I did it like this:
google.maps.event.addListener(infoWindow, 'domready', function()
{
paragraph = document.getElementById("idOfThatParagraph");
paragraph.addEventListener("click", function()
{
//actions that I need to do
});
});
It works for me. So I hope it will help someone :)