I have this JavaScript which detects whether the browser supports touch events, and then sets a touch event with every element that has a click event:
function isTouchEnabled() {
if ('ontouchstart' in window) {
var all = document.querySelectorAll('[onclick]');
for (var i = 0; i < all.length; i++) {
all[i].setAttribute('ontouchstart', car);
var car = all[i].getAttribute('onclick');
}
}
}
This works up until this bit: all[i].setAttribute('ontouchstart', car);
With this bit, I aimed to carry the attribute value from the click event to the touch event, but this does not work, because the touch event attribute value ends up being undefined. Can anybody solve this ?
Try this:
function hitMe() {
alert('I am hit !');
}
function isTouchEnabled() {
if ('ontouchstart' in window) {
var all = document.querySelectorAll('[onclick]');
for (var i = 0; i < all.length; i++) {
var car = all[i].getAttribute('onclick');
all[i].setAttribute('ontouchstart', car);
}
}
}
isTouchEnabled();
<div onclick="hitMe()">Click Me!</div>
Related
hello I am struggling to use JS in order to make the buttons on my HTML page add a border to the button when it is clicked and to remove the border when it is clicked again. it works for the first 2 clicks but then no longer does anything after that. please excuse my js im extremely inexperienced.
JavaScript:
<script>
var flag = true;
var buttons = document.getElementsByClassName("btn");
function buttonFunction() {
if (flag) {
for (var i = 0; i < buttons.length; i++) {
document.getElementsByClassName("btn")[i].addEventListener("click", function() {
this.classList.add("buttonSelect");
flag = false
return
});
}
} else {
if (flag == false) {
for (var i = 0; i < buttons.length; i++) {
document.getElementsByClassName("btn")[i].addEventListener("click", function() {
this.classList.add("buttonUnselect");
flag = true
return
});
}
}
}
}
</script>
The real issue is you're adding both classes and never removing them. Get rid of the if else statement and just toggle the class on click. Don't need to wrap the loop in a function either. Just let the javascript execute the event listeners at runtime.
Also, make use of the buttons var you created instead of trying to query the DOM again for the same elements.
<script>
var buttons = document.getElementsByClassName("btn");
for (var i = 0; i < buttons.length; i++) {
buttons[i].addEventListener("click", function() {
this.classList.toggle("buttonSelect");
})
}
</script>
I have a slider input field that gives a numeric value when slid. I would like to clone an object X times based on the slider value, however when I try to accomplish this it creates an endless loop. Is there anyway to get the number of cloned elements to match the slider value when it changes? Here is the code I was using.
jQuery(document).ready(function($) {
$(window).load(function() {
$('input#fieldname3_1').change(function() {
var e = $('#student-icons.icon > span');
var n = $('#fieldname9_1').val();
$('#student-icons.icon').html(
for (var i = 0; i < n; i++) {
e.clone().insertAfter(e);
});
}).change()
});
});
Try the following setup:
HTML:
<input type="range" id='fieldname3_1' style='width: 200px'>
<div id='student-icons' class='icon'></div>
JavaScript:
$(document).ready(function($) {
$('input#fieldname3_1').change(function() {
var n = $(this).val();
// reset the element
$('#student-icons.icon').html('');
for (var i = 0; i < n; i++) {
// The html of what you want to clone goes here
$('#student-icons.icon').append("<div id='hello'>"+i+"</div>")
}
});
});
I also recommend using the oninput event if browser support is not an issue (IE 9 and up only):
$(document).ready(function($) {
$('input#fieldname3_1')[0].oninput = function() {
var n = $(this).val();
$('#student-icons.icon').html('');
for (var i = 0; i < n; i++) {
$('#student-icons.icon').append("<div id='hello'>"+i+"</div>")
}
};
});
This will allow the event to fire as soon as the input is changed rather than wait on the keydown.
JsFiddle
JsFiddle w/ onInput
I'm building a simple calculator app. I'm trying to accomplish three things:
Assign an event listener to the buttons.
When the button is clicked, fire an event.
Use the eventListener function to display the value of the clicked button.
for (i = 0; i < btn.length; i++) {
var btnVal = btn[i].value;
btn[i].addEventListener("click", function() { displayNumber(btnVal) }, false);
}
function displayNumber(param) {
displayedNum.innerHTML = param;
}
It seems btnVal is not accessible when passed to the event listener function.
The assignment won't work like that. Instead, use the target's value
for (i = 0; i < btn.length; i++) {
btn[i].addEventListener("click", function(e) {
displayNumber(e.target.value)
}, false);
}
Defining event listeners (or other asynchronous things) inside of a loop is tricky. You may think you're creating several different btnVal variables, one for each time through the loop, but you're not. That var btnVal gets hoisted to the top and reused, so your code ends up behaving like this:
var btnVal;
for (i = 0; i < btn.length; i++) {
btnVal = btn[i].value;
btn[i].addEventListener("click", function() { displayNumber(btnVal) }, false);
}
So all of your event listeners are interacting with the very same variable, and when they eventually get clicked, they'll only see the very last value that was assigned to btnVal, which should be btn[btn.length -1].value. All the values earlier in the array are lost.
There are a few ways you can address this:
1) Rather than depending on a closure variable, you could pull it from the element itself when the event goes off.
for (i = 0; i < btn.length; i++) {
btn[i].addEventListener("click", function (event) {
displayNumber(event.target.value);
});
}
2) Move the event listener creation into a function, and pass btnVal in. Since it's now a function parameter, it gets a new binding.
for (i = 0; i < btn.length; i++) {
createListener(btn[i], btn[i].value);
}
function createListener(element, val) {
element.addEventListener("click", function () { displayNumber(val) }, false);
}
3) you can do it inline using an IIFE.
for (i = 0; i < btn.length; i++) {
(function (button) {
button.addEventListener("click", function () { displayNumber(button.value) }, false);
})(btn[i]);
}
EDIT: added option 4
4) If you can use ES2015, use let. Let has block scope, and will get a new binding each time through the loop
for (i = 0; i < btn.length; i++) {
let btnVal = btn[i].value;
btn[i].addEventListener("click", function() { displayNumber(btnVal) }, false);
}
You cant use btnVal inside the event.
It should look like this
for (i = 0; i < btn.length; i++) {
btn[i].addEventListener("click", function(event) {
var clickedButton = event.target || event.srcElement;
console.log(clickedButton.value)
}, false);
}
I have many buttons that have class="clearSelect". I want these buttons the execute a function onclick. I am new to javascript and not quite sure why this is occurring but I think my functions are being executed instead of only executing onclick
The code below is what is calling all my other functions causing every button to be clicked.
code:
var buttons = document.getElementsByClassName("clearSelect"); // objects with class="clearSelect"
for (var i = 0; i < buttons.length; i++) {
var button = buttons[i];
// button.addEventListener("onclick", clearOrSelectAll(button.id));
button.onclick = clearOrSelectAll(button.id);
}
These are the functions being called:
function clearOrSelectAll(btn) {
var cleartab = clearButtonSet[btn];
var selecttab = selectButtonSet[btn];
// console.log("clicked!");
if (cleartab != null) {
getOSList(cleartab, false);
} else {
getOSList(selecttab, true);
}
}
function getOSList(tabVal, fate) {
var configTab = document.getElementById(tabVal);
var browserList = configTab.getElementsByClassName("browser_list");
// var idObjs = browserList.getElementsByTagName("li");
for (var h = 0; h < browserList.length; h++) {
var idObjs = browserList[h].getElementsByTagName("li");
// console.log(h);
// console.log(idObjs);
// select all
if (fate) {
for (var i = 0; i < idObjs.length; i++) {
if (configs[idObjs[i].id] == null) {
idObjs[i].className = "selected";
configs[idObjs[i].id] = config_dictionary[idObjs[i].id];
}
}
// clear all
} else {
for (var j = 0; j < idObjs.length; j++) {
if (configs[idObjs[j].id] == null) {
idObjs[j].className = "unselected";
delete configs[idObjs[j].id];
}
}
}
}
}
#Christopher was very close, but button.id should be this.id.
button.onclick = function() {
clearOrSelectAll(this.id);
}
The reason button.id doesn't work can be demonstrated with this code:
var buttons= document.getElementsByTagName('button');
for (var i = 0; i < buttons.length; i++) {
var button = buttons[i];
button.onclick = function() {
alert(button.id);
}
}
<button id="B1">Button 1</button>
<button id="B2">Button 2</button>
<button id="B3">Button 3</button>
Each button returns "B3," because that's the last object that the variable button is assigned to.
In your for loop when you attach the event to all of the buttons, you are calling the clearOrSelectAll function. You probably want to wrap it in an anonymous function to make sure it's only called when the event is fired.
// Non-ideal solution: see edit
button.onclick = function() {
clearOrSelectAll(button.id);
}
EDIT: It has been pointed out that the 'this' context variable will point to the element in question when an event handler is attached by means of the onclick property, or the addEventListener method. As such it would probably be cleaner (and easier to read) if you were to reference that instead of using 'button' as a closure and count on javascript engines to not optimize your loop too heavily (as that would mess with the value of 'button' at the time that the event is called.
button.onclick = function() {
clearOrSelectAll(this.id);
};
I am currently using the below to detect if an element with the id bar is clicked. I would like to change it so that this function would run whether bar is clicked or any a tag without duplicating the function.
document.getElementById("bar").onclick = function() {
//do things...
};
Just define the function separately and give it a name:
function MyFunction() {
// Your function here
}
document.getElementById("bar").onclick = MyFunction;
var links = document.getElementsByTagName("a");
for (var i=0; i < links.length; i++) {
links[i].onclick = MyFunction;
}
Depending on the browsers you can target, you could use
var nodes = document.querySelectorAll("#bar, a");
for (var i=0, ii=nodes.length; i < ii; i++) {
nodes[i].addEventListener('click', function multiElementClickHandler(event){ alert("clicked " + event.target); });
}
Otherwise, define it separately like #mayabelle said. :)