I'm trying to clean the URLs of elements and every thing is working, but the onclick event fired directly on the page load but not when I click. How can I fix this?
HTML:
<a class="button" href="http://192.168.1.99:8888/propertyturkey/admin/clients/index/today_calls/?status=3&sales=70&tagged=1&clientName=turkey&nextCall=turkey&clientEmail=sdfgsdfg">Today call list</a>
<input type="reset" class="reset" id="reset" value="Reset">
JS:
var buttons = document.querySelectorAll('.button');
var reset = document.querySelector('.reset');
function forEach(array, action) {
for (var i = 0; i < array.length; i++) {
action(array[i])
};
}
function clear_url_parameters(element) {
if (!element)
return false;
var element_url = element.getAttribute('href');
var split_url = element_url.split("?");
var queries = split_url[1].split("&");
var new_queries = [];
for (var i = 0; i < queries.length; i++) {
query = queries[i].split("=");
new_queries.push(query[0] + "=");
}
cleared_url = split_url[0] + new_queries.join('');
element.setAttribute('href', cleared_url);
}
reset.addEventListener('click', forEach(buttons, clear_url_parameters));
Demo on jsfiddle
You are passing the result of executing the function forEach to your event listener.
Try this:
reset.addEventListener('click', function () { forEach(buttons, clear_url_parameters); } );
change
reset.addEventListener('click', forEach(buttons, clear_url_parameters));
to
reset.addEventListener('click', function(){
forEach(buttons, clear_url_parameters)
});
Because the parameter you passed to addEventListener has already been called.
Related
I've been testing around to see if you can prevent having duplicate event listeners
The code below loops through all the buttons with a certain attribute.
the problem is it only works with ONE button
let LOGIC;
let removeListener = undefined;
let test = document.getElementById("test")
let allButtons = document.querySelectorAll("input[btn]")
function GameLogic(btn, test) {
test.innerHTML = eval(`${test.textContent} + 1`)
btn.value += "1"
}
let Apply = function() {
for (let i = 0; i < allButtons.length; i++) {
if (removeListener == true){
allButtons[i].removeEventListener("click", LOGIC)
}
LOGIC = GameLogic.bind(null, allButtons[i], test)
allButtons[i].addEventListener("click", LOGIC);
removeListener = true
}
}
document.getElementById("redo").addEventListener("click", Apply)
Here is the HTML:
<input type = "button" id = "DIE" btn value = "Click Me">
<input type = "button" id = "DIE" btn value = "Click Me">
<input type = "button" id = "DIE" btn value = "Click Me">
<input type = "button" id = "DIE" btn value = "Click Me">
<button id = "redo"> Redo Function </button>
<p id = "test">0</p>
I've tried so many different solutions and nothing really worked.
The logic seemed to add up the in the aforementioned code.
First of all, in your function Accept, the statement removeListener = true seems to be in the wrong place.
let Apply = function () {
for (let i = 0; i < allButtons.length; i++) {
if (removeListener == true) {
allButtons[i].removeEventListener("click", LOGIC)
}
LOGIC = GameLogic.bind(null, allButtons[i], test)
allButtons[i].addEventListener("click", LOGIC);
removeListener = true //Set as true for the first button
}
}
Instead of :
let Apply = function () {
for (let i = 0; i < allButtons.length; i++) {
if (removeListener == true) {
allButtons[i].removeEventListener("click", LOGIC)
}
LOGIC = GameLogic.bind(null, allButtons[i], test)
allButtons[i].addEventListener("click", LOGIC);
}
removeListener = true //Set as true after the first loop has run
}
Second issue is your variable LOGIC. As it is changed in every steps of the loop, when you click on Redo, you have the value for the last button instead of the first.
A solution could be to use an array like this :
let LOGICS = []; //Now is an array
let removeListener = undefined;
let test = document.getElementById("test")
let allButtons = document.querySelectorAll("input[btn]")
function GameLogic(btn, test) {
test.innerHTML = eval(`${test.textContent} + 1`)
btn.value += "1"
}
let Apply = function () {
for (let i = 0; i < allButtons.length; i++) {
if (removeListener == true) {
allButtons[i].removeEventListener("click", LOGICS[i])//So when your remove the event listener, it is the function you have used to add it who is passed
}
LOGICS[i] = GameLogic.bind(null, allButtons[i], test)
allButtons[i].addEventListener("click", LOGICS[i]);
}
removeListener = true
}
document.getElementById("redo").addEventListener("click", Apply)
The id attribute needs to be unique. You have multiple buttons with the same id ("DIE"). That's not allowed and makes the html invalid
I'm doing some exercises and come across where I can't pass the value from the input box to a function inside a script, I don't really know what I have done wrong, I tried different things but didn't really work out. How can I make it work? I want to able to enter a number then press a button so that it prints pyramid according to given number, here is my code :
window.onload = function() {
let aantalLijnen = parseInt(document.getElementById('number').value);
document.getElementById("button").onclick = stars();
function stars() {
for (var i = 1; i <= aantalLijnen; i++) {
var row = '';
for (var j = 1; j <= i; j++) {
row += '*';
}
console.log(row);
}
}
};
<p>Give a number betweeen 2 and 10
<input type="number" id='number'>
<button id="button">Click</button></p>
You're calling stars() and assigning the result to the onclick handler.
You need to pass the function itself...
document.getElementById("button").onclick = stars;
Or just create an anonymous function directly...
document.getElementById("button").onclick = function() {
...
}
As pointed out by #j08691, you are setting the value of aantalLijnen on the page load.
Instead you want to get the value at the time the function runs, so you need to move it into the function itself...
window.onload = function() {
document.getElementById("button").onclick = function () {
let aantalLijnen = parseInt(document.getElementById('number').value);
for (var i = 1; i <= aantalLijnen; i++) {
var row = '';
for (var j = 1; j <= i; j++) {
row += '*';
}
console.log(row);
}
}
};
<p>Give a number betweeen 2 and 10
<input type="number" id='number'>
<button id="button">Click</button></p>
you have to get the value from input every time you click on the button
window.onload = function () {
const numberElem = document.getElementById('number');
document.getElementById("button").addEventListener('click', stars);
function stars() {
let aantalLijnen = parseInt(numberElem.value);
for (var i = 1; i <= aantalLijnen; i++) {
var row = '';
for (var j = 1; j <= i; j++) {
row += '*';
}
console.log(row);
}
}
};
Besides what already said by others
Don't use onclick handlers. Stick to cumulative listeners with addEventListener
You could use String.prototype.repeat();
Defer your script or place it right before the closing </body> tag
Learn the difference between let and const
function stars() {
const num = parseInt(document.getElementById('number').value, 10);
if (num < 2 || num > 10) return console.log("Use from 2 to 10 inclusive");
const row = '*'.repeat(num);
console.log(row)
}
document.getElementById("button").addEventListener('click', stars);
Give a number betweeen 2 and 10
<input type="number" id='number'>
<button id="button">Click</button>
What am I essentially trying to do is to produce container with buttons, which have the same handler but get different arguments like this:
<div id="container">
<button onclick="onclick_handler(1)">1</button>
<button onclick="onclick_handler(2)">2</button>
<button onclick="onclick_handler(3)">3</button>
</div>
Using this:
function onload_handler() {
var container = document.getElementById("container");
var i;
for (i = 0; i < 3; i++) {
var button = document.createElement('button');
button.innerHTML = i;
button.addEventListener('click', function() {
onclick_handler(i);
});
container.appendChild(button);
}
}
function onclik_handler(val) {
console.log(val);
}
And when I click buttons I get 4 in my console. What am I doing wrong?
Could it also be done without usage of anonymous functions?
Try to resolve the problem created by closure, by creating a scope per iteration,
function(i){
button.addEventListener('click', function() {
onclick_handler(i);
});
})(i);
And your full code would be,
function onload_handler() {
var container = document.getElementById("container");
var i;
for (i = 0; i < 3; i++) {
var button = document.createElement('button');
button.innerHTML = i;
(function(i){
button.addEventListener('click', function() {
onclick_handler(i);
});
})(i)
container.appendChild(button);
}
}
function onclik_handler(val) {
console.log(val);
}
I have such script in js file wich I'm calling from jsp, and I need to add listener instead of "onload".
What important for me:
1) It must be pure js without jQuery or anything
2) Input tags would be created dynamically(Maybe this is important)
3) It must be external js file(<script src="<c:url value="/js/focus.js" />"></script>), but not the tag <script>function.....</script> inside jsp page
onload = function () {
var allInput = document.getElementsByTagName("input");
for (i = 0; i < allInput.length; i++) {
allInput[i].onfocus = showHint
}
};
function showHint() {
var hint = document.getElementById("hint");
hint.innerHTML = this.name + " " + this.value;
hint.style.display = "block";
};
The page can get focus before is't loaded. And if the page is not loaded your inputs don't exist so window.onfocus can't set allInput[i].onfocus. When the page is refreshed with the focus on the devtools the page gets a chance to create inputs before window.onfocus call.
Put your window.onfocus inside window.onload so that it is always called after the page is loaded. If you don't want to override window.onload use addEventListener instead:
addEventListener('load', function () {
addEventListener('focus', function() {
var allInput = document.getElementsByTagName("input")
for (i = 0; i < allInput.length; i++) {
allInput[i].addEventListener('focus', showHint)
}
}
})
function showHint() {
var hint = document.getElementById("hint")
hint.innerHTML = this.name + " " + this.value
hint.style.display = "block"
}
replace onload with onfocus
onfocus = function () {
var allInput = document.getElementsByTagName("input");
for (i = 0; i < allInput.length; i++) {
allInput[i].onfocus = showHint
}
};
That works for me
window.addEventListener('load', function () {
var allInput = document.getElementsByTagName("input");
for (i = 0; i < allInput.length; i++) {
allInput[i].onfocus = showHint
}
});
function showHint() {
var hint = document.getElementById("hint");
hint.innerHTML = this.name + " " + this.value;
hint.style.display = "block";
};
So I have this piece of code:
window.onload = function () {make_buttons ('calc'); }
function make_buttons (id) {
console.log (id);
var input = document.createElement("INPUT");
document.getElementById(id).appendChild(input);
for (var i = 0;i < 10; i++){
var btn = document.createElement ("BUTTON");
var t = document.createTextNode (i);
btn.appendChild(t);
document.getElementById(id).appendChild(btn).onclick=document.getElementsByTagName("INPUT").value=i;
}
};
Now when I have created the button with the for loop, it should also have the onclick event attached to it which writes the current value of i into my input form.
Code I have written produces no errors but when the button is clicked, it simply does not do anything. Why is that?
New version:
window.onload = function () {make_buttons ('calc'); }
function make_buttons (id) {
var input = document.createElement("input");
input.type = 'text';
input.id = 'inp';
document.getElementById(id).appendChild(input);
for (var i = 0;i < 10; i++){
var btn = document.createElement ("button");
btn.id = i;
var txt = document.createTextNode (i);
btn.appendChild(txt);
var make_btn = document.getElementById(id).appendChild(btn);
make_btn.onclick = button_pressed (i);
}
};
function button_pressed (id) {
document.getElementById("inp").value += id;
};
Method document.getElementsByTagName() returns a NodeList collection that you should iterate through.
You need to go in loop through retrieved elements and assign the value attribute to each of them.
So that you can change
document.getElementById(id).appendChild(btn).onclick=document.getElementsByTagName("INPUT").value=i;
to something like this:
var id = 'my-form',
btn = document.createElement('input');
btn.type = 'button';
btn.value = 'Click me!';
btn.onclick = function() {
var inputs = document.getElementsByTagName('input');
// NodeList to Array if needed:
// var inputsArray = Array.prototype.slice.call(inputs);
for(var i = 0, l = inputs.length; i < l; i++) {
inputs[i].value = i;
}
return false;
};
document.getElementById(id).appendChild(btn);
DEMO #1
Update:
About your second question, yes it won't work in this way since at the time when your onclick event handler is called it's using the last value assigned to i variable. To avoid this you can just use closures.
For example,
HTML:
<form action="" id="my-form">
<input type="text" id="inp" />
</form>
JavaScript:
var btn,
input,
form,
createHandler;
input = document.getElementById('inp');
form = document.getElementById('my-form');
createHandler = function(i) {
return function() {
input.value += i;
};
};
for(var i = 0; i < 5; i++) {
btn = document.createElement('input');
btn.type = 'button';
btn.value = 'Append ' + i;
form.appendChild(btn);
btn.onclick = createHandler(i);
}
DEMO #2
Also you can use just immediately invoked anonymous function to create that closure in the body of your loop:
for(var i = 0; i < 5; i++) {
// ...
btn.onclick = (function(theNumberToAppend) {
return function() {
input.value += theNumberToAppend;
};
})(i);
}
DEMO #3