I am developing an app that stays in the website itself, and I want every link to call a function. I have tried this:
HTML
link<br>
link 2
Javascript
var a = document.getElementsByTagName("a");
for (var i = 0; i < a.length; i++) {
a[i].onclick = function () {
return false
}
}
What is wrong? It doesn't work.
Since it's not jQuery, you should use the preventDefault function.
var a = document.getElementsByTagName("a");
for (var i = 0; i < a.length; i++) {
a[i].onclick = function (e) {
e.preventDefault();
doSomething();
}
}
edit for pure javascript solution
document.addEventListener("click", function(e){
if (e.nodeName==="A"){
e.preventDefault();
return false;
}
}, false);
This will only add one single event to the document and prevent all clicks on anchor elements only.
I removed the old solution because of the comment, that this wasn't a jquery question
Don't use return false, it does more than you really need. Instead try event.preventDefault()
var a = document.getElementsByTagName("a").forEach(function (e) {
e.onclick = function (a) {
doSomething(a);
return false;
}
}
}
Related
I'm making a javascript quiz using a single HTML page. For some reason, my code will only display one question and upon clicking the element, it does not go to the next question. And it doesn't start the quiz with the first question.
I used a for loop inside a for loop. The first loop renders the question and then the other renders its corresponding choices. The questions and choices are held in an array containing the objects.
I've only been coding with Javascript and jQuery for a few weeks, so you'll have to tell me in beginner terms. I will have to refactor it. I apologize for it being somewhat messy.
I tried taking out the return commands. Same with preventDefault, no changes.
function renderQuiz(i) {
$heading.text("");
$mainDiv.text("");
$heading.text(quizQuestions[i].question);
for (var j = 0; j < quizQuestions[i].choices.length; j++) {
//console.log(quizQuestions[0].choices.length);
var li = document.createElement("li");
li.innerText = JSON.stringify(quizQuestions[i].choices[j]);
$mainDiv.append(li);
};
$('li').on("click", function() {
if (event.target.matches('li')) {
event.preventDefault();
var guess = event.target.innerText;
var answer = (JSON.stringify(quizQuestions[i].answer[0]));
if (guess === answer) {
timeLeft += 10;
console.log(timeLeft + "it works");
} else {
timeLeft -= 10;
console.log(timeLeft)
};
}
});
return;
};
mainPage();
$button.on("click", function(click) {
event.preventDefault();
for (var i = 0; i < quizQuestions.length; i++) {
renderQuiz(i);;
}
});
The $button click event is iterating through all of the questions, that is why the last question is the one displayed.
You need to define the variable i outside of the $button click function, then increment i on each click of the button.
var i = -1;
function renderQuiz(i) {
...
};
mainPage();
$button.on("click", function(click) {
event.preventDefault();
renderQuiz(++i);
});
There is an error in the $button onclick handler (in your console you should have "Uncaught ReferenceError: event is not defined").
If the function takes click as parameter then you should apply the method preventDefault() to that same parameter. In other words instead of
$button.on("click", function(click) {
event.preventDefault();
you should have
$button.on("click", function(event) {
event.preventDefault();
By the way there is the same error here
$('li').on("click", function() {
you should have
$('li').on("click", function(event) {
I hope this help.
I'm trying to do this, but the loop ends after the first trigger. Any ideas to help me out?
$(document).on('click', '#configurator .myalbumimgs .autofill', function(e) {
e.preventDefault();
var nb_of_images = $('#grid div.configimg').length;
for (i = 0; i < nb_of_images; i++) {
alert(i);
$('.imgpicker .photo .add').eq(i).trigger('click');
}
});
Edit 1: Everything works fine if I remove $('.imgpicker .photo .add').eq(i).trigger('click'); and just let the loop run.
If I put a number in, like eq(3) selects the right one, but only that one. Then it stops as before.
No errors in console :S
Edit 2: Found out the correct solution, my mistake with .eq on the wrong element. Thanks for all suggestions! Correct code:
$(document).on('click', '#configurator .myalbumimgs .autofill', function(e) {
e.preventDefault();
if ($(this).not('.done')) {
var multiselector_nbimages = $('#grid').attr('data-nbimages');
var nb_images_selected = parseInt($('#grid div.configimg').not('.temp').length);
var max_nb_images = parseInt(multiselector_nbimages);
if (nb_images_selected < max_nb_images) {
var album_images = $(this).parent().parent().children('.imgpicker').children('.photo');
var nb_of_grid_images = $('#grid div.configimg.temp').length;
for (i = 0; i < nb_of_grid_images; i++) {
album_images.eq(i).children('.add').not('.selected').trigger('click');;
}
$(this).addClass('done');
} else {
alert(lang_valid_max_nb_of_photos);
}
}
});
jquery has built in each method .
$('#configurator .albumbtn.autofill').on('click', function(e) {
e.preventDefault();
//Iterate through every configimg
$('#grid div.configimg').each(function(el) {
// $(this) is current element in the list
if($(this).hasClass('someclass')) { $(this).trigger('click') }
})
});
function () {
var i = 0;
$('.class').click(i=i+1)
if(i=3) {
$('.class2').css('display','block');
}
}
This code does not work, Please help me.
Should be :
$(function() { //ready function
var i = 0;
$('.class').click(function(){ //Attach click event to '.class'
i=i+1; //Or i++;
if(i===3) { //Use triple equal '===' for comparaison
$('.class2').css('display','block');
}
})
})
Hope this helps.
You should bind your click event outside the function, and then track the 3rd click. You should also use a comparison operator instead of assignment. Of course, all of this should be wrapped in document ready.
var i = 0;
$('.class').on('click', function() {
i = i + 1;
if(i === 3) {
$('.class2').css('display','block');
}
});
Here is a Fiddle Demo.
I have 3 divs with class: wpEdit and onClick: alertName()
<div class="wpEdit" onClick="alertName()">Bruce Lee</div>
<div class="wpEdit" onClick="alertName()">Jackie Chan</div>
<div class="wpEdit" onClick="alertName()">Jet li</div>
When clicked i want to know the Index of class wpEdit of the clicked Div:
function alertName(){
//Something like this
var classIndex = this.className.index; // This obviously dosnt work
alert(classIndex);
}
when clicked on Bruce Lee it should alert : 0
when clicked on Jackie Chan it should alert : 1
when clicked on Jet Li it should alert : 2
I need to know which instance of class="wpEdit" is clicked on
Try this
function clickedClassHandler(name,callback) {
// apply click handler to all elements with matching className
var allElements = document.body.getElementsByTagName("*");
for(var x = 0, len = allElements.length; x < len; x++) {
if(allElements[x].className == name) {
allElements[x].onclick = handleClick;
}
}
function handleClick() {
var elmParent = this.parentNode;
var parentChilds = elmParent.childNodes;
var index = 0;
for(var x = 0; x < parentChilds.length; x++) {
if(parentChilds[x] == this) {
break;
}
if(parentChilds[x].className == name) {
index++;
}
}
callback.call(this,index);
}
}
Usage:
clickedClassHandler("wpEdit",function(index){
// do something with the index
alert(index);
// 'this' refers to the element
// so you could do something with the element itself
this.style.backgroundColor = 'orange';
});
The first thing you might want to address in your code is the inline HTML binding.
You could use document.addEventListener on each element, or rely on event delegation.
The widely most used implementation of event delegation comes with jQuery. If you're already using jQuery, this is the way to go!
Alternatively I've also my own little delegate utility.
const delegate = (fn, selector) => {
return function handler(event) {
const matchingEl = matches(event.target, selector, this);
if(matchingEl != null){
fn.call(matchingEl, event);
}
};
};
const matches = (target, selector, boundElement) => {
if (target === boundElement){
return null;
}
if (target.matches(selector)){
return target;
}
if (target.parentNode){
return matches(target.parentNode, selector, boundElement);
}
return null;
};
This is how you would register the event listener.
document.getElementById('#parent')
.addEventListener('click', delegate(handler, '.wpEdit'));
And this is how you could get the index of the element that generated the event.
const handler = (event) => {
console.log(Array.prototype.indexOf.call(event.currentTarget.children, event.target));
}
Live demo:
const delegate = (fn, selector) => {
return function handler(event) {
const matchingEl = matches(event.target, selector, this);
if (matchingEl != null) {
fn.call(matchingEl, event);
}
};
};
const matches = (target, selector, boundElement) => {
if (target === boundElement) {
return null;
}
if (target.matches(selector)) {
return target;
}
if (target.parentNode) {
return matches(target.parentNode, selector, boundElement);
}
return null;
};
const handler = (event) => {
console.log(Array.prototype.indexOf.call(event.currentTarget.children, event.target));
}
document.getElementById('parent')
.addEventListener('click', delegate(handler, '.wpEdit'));
<div id="parent">
<div class="wpEdit">Bruce Lee</div>
<div class="wpEdit">Jackie Chan</div>
<div class="wpEdit">Jet li</div>
</div>
If you want the index of the div's based on your class wpEdit you can do like this:
HTML:
<div class="wpEdit">Bruce Lee</div>
<div class="wpEdit">Jackie Chan</div>
<div class="other">Other</div>
<div class="wpEdit">Jet li</div>
JS:
$(".wpEdit").bind("click", function(){
var divs = $(".wpEdit");
var curIdx = divs.index($(this));
alert(curIdx);
});
Live example : http://jsfiddle.net/pJwzc/
More information on the index function of jQuery : http://api.jquery.com/index/
Using vanilla javascript, this one works for me:
var wpEdits = document.querySelectorAll(".wpEdit");
for (let i = 0; i < wpEdits.length; i++)
wpEdits[i].addEventListener("click", showID);
function showID(evt) {
for (let i = 0; i < wpEdits.length; i++)
if(wpEdits[i] == evt.target)
alert(i);
}
May not be the best solution though as I am still new to js.
Since I am very new to JS, take the following explanation with a grain of salt:
(Line-1)
This is similar to var wpEdits = document.getElementsByClassName("wpEdit");. It will assign all instances of class="wpEdit" from the html file to the wpEdits variable.
(Line-3 and Line-4)
This two lines will cause any click on the class="wpEdit" to call function showID() defined below.
(Line-6 and Line-10)
When a click event happens, the browser will pass the unique properties of the item being clicked to the evt variable. This then is used in the for loop to compare against all available instances incrementally. The evt.target is used to get to the actual target. Once a match is found, it will alert the user.
To avoid wasting CPU time, running a break; is recommended to exit the loop soon after the match is found.
I could not understand, why people add new functions in previous answers, so...
const wpEdit = document.getElementsByClassName('wpEdit');
for(let i = 0; i < wpEdit.length; i++){
wpEdit[i].addEventListener('click',function(){
alert(i);
});
}
I just added 'click' event, using the loop. And [i] already is the current clicked class index...
FIDDLE
I have a jquery function that shows/hides spans that look like "tips" when I click an input field on a form.
The function works great on FirfFox,Chrome,IE(!) :) , etc. But not at all on webkit based browsers aka Safari and Android (tested)
$(function(prepareInputsForHints) {
var inputs = document.getElementsByTagName("input");
for (var i=0; i<inputs.length; i++){
(function(i) {
// Let the code cleane
var span = inputs[i].nextElementSibling;
if(span instanceof HTMLSpanElement) {
if(span.className == "hint") {
span.onmouseover = function() { this.isOver = true; }
span.onmouseout = function() { this.isOver = false; if(!inputs[i].isFocus) inputs[i].onblur(); }
// the span exists! on focus, show the hint
inputs[i].onfocus = function () {
this.isFocus = true;
span.style.display = "inline";
}
// when the cursor moves away from the field, hide the hint
inputs[i].onblur = function () {
this.isFocus = false;
if(!span.isOver) span.style.display = "none";
}
}
}
})(i);
}
});
Also, for your convenience i provide you with http://jsfiddle.net/eZnYY/1/
Try to replace you code line:
if(span instanceof HTMLSpanElement) {
with next:
if(span && span.tagName.toUpperCase()==="SPAN") {
http://jsfiddle.net/eZnYY/3/ Checked on desktop Safary and Android browser (emulator)
You should use the jQuery methods to ensure cross browser compatibility (your question has the jQuery Tag).
This is pure javascript. Convert your code to jQuery, use the jQuery events and set the css.
For example:
your code
var inputs = document.getElementsByTagName("input");
for (var i=0; i<inputs.length; i++){ .. }
jQuery
$("input").each(function() { ... });
What I don't understand is, if you're using jquery, why are you not leveraging it in your function? I assure you that if you were to use jquery to attach the events, they will work in webkit and all other browsers.