javascript - basic onclick event question - javascript

I have a dynamic table populated from an array.
When building the table I have the following inside of a loop:
var tdRecord = trRecord.insertCell(trRow.cells.length);
var tdRecordId = dataArray[j][0];
tdRecord.onclick = function() { alert(tdRecordId); }
The problem is that alert will only alert the last set tdRecordId in the array. If I click on any of the other td rows they all alert the same number.
Anyone know how I can fix this?

This should work:
(function( id ) {
tdRecord.onclick = function() {
alert( id );
};
}( tdRecordID ));
You seem to be running your code inside a loop. In that case, all click handlers will point to the same tdRecordId value. If you want to capture the value of the current iteration, you have to use a function wrapper which will do that for you.

tdRecord.onclick = function () { alert('123'); };

You could use jQuery's data feature: http://jsfiddle.net/zRXS6/.
$(function(){
var number = 1;
var div1 = $('<div>a</div>');
div1.data('number', number);
div1.click(function() {window.alert($(this).data('number'))});
number = 2;
var div2 = $('<div>b</div>');
div2.data('number', number);
div2.click(function() {window.alert($(this).data('number'))});
$('body').append(div1).append(div2);
});

tdRecord.onclick = "alert(" + tdRecordId + ")";
Set it as a literal, rather then a dynamic. :)
In what you're doing, it will always refer to the variable, rather then the current value.
So as the variable changes, what the function alerts will change.
In this, it actually inserts the value, rather then the variable itself, so it will stay the same instead of changing.

Related

Function is not behaving as intended. Why?

Sorry for not being more precise on the title.
https://jsfiddle.net/ptxsha6m/1/
<script>
var theID = document.getElementById('result1');
function change(){
var checkboxes = document.getElementsByClassName('checkbox');
var chekboxInputs = Array.from(checkboxes).map(a => a.querySelector('input'));
var allAreUnselected = chekboxInputs.every(function(elem){
return !elem.checked;
});
if(allAreUnselected){
chekboxInputs.forEach(function(input){
Array.from(document.querySelectorAll("." + input.getAttribute("rel"))).forEach(function(theID){
theID.style.background = 'blue';
});
});
}
else {
chekboxInputs.forEach(function(input){
Array.from(document.querySelectorAll("." + input.getAttribute("rel"))).forEach(function(theID){
theID.style.background = input.checked ? 'red' : 'gray';
});
});
}
}
change();
</script>
Basically, as I wrote, it should change the div#id with the background yellow to red once a checkbox is selected. But for some reason it insists in targeting the div with class only.
I know there must be something wrong with the logic, there's a few things that I can tell but others I don't understand. For example, at "if(allAreUnselected)" shouldn't it set the background of the yellow box to blue? Since they are all unselected?
All I'm trying to achieve is be able to manipulate the div# inside the function. Any help?
Thanks
Early in your script you capture the DOM element you're talking about in a variable named theID:
var theID = document.getElementById('result1');
Later on, where you're changing the color of the elements, you're using an anonymous function in a forEach, which has a parameter also named theID:
(/* lots of code */).forEach(function(theID){
theID.style.background = 'blue'
});
That parameter name masks the variable defined earlier, so when you use theID inside that function it refers to each of the forEach elements instead of the #result1 element -- and you wind up never attempting to change the color of #result1.
If you want to change the color of that container, either use a different parameter name, so the variable isn't masked by it:
(/* lots of code */).forEach(function(foo){
foo.style.background = 'blue'
theID.style.background = // your logic here for deciding what color #result1 should be
});
...or do it outside the anonymous function:
if(allAreUnselected){
theID.style.background = 'blue';
chekboxInputs.forEach(function(input){
(/* lots of code */).forEach(function(theID){ // (I'd still change that parameter name, though, because masked variables are confusing)
In line 41 what you think is the theID variable is wrong. In this case the variable theID will be shadowed from the variable that the forEach function passes as argument to the callback function(theID){..}.
forEach passes each item in the array as argument to the function you declare on each iteration. Try to change the name of this variable, ex. ...forEach(function(chekboxInput) { chekboxInput.style.background = 'blue';} nothing will change.
From here the theID is not anymore the div with id=result1 but one of the elements in the chekboxInputs that you are iterating on.
See also the answer from Daniel Beck.

Javascript on click event not reading else statement or variables

I'm trying to make a click handler that calls a function; and that function gets a string and basically slices the last character and adds it to the front, and each time you click again it should add the last letter to the front.
It seem so easy at first that I thought I could just do it using array methods.
function scrollString() {
var defaultString = "Learning to Code Javascript Rocks!";
var clickCount = 0;
if (clickCount === 0) {
var stringArray = defaultString.split("");
var lastChar = stringArray.pop();
stringArray.unshift(lastChar);
var newString = stringArray.join('');
clickCount++;
} else {
var newArray = newString.split("");
var newLastChar = newArray.pop();
newArray.unshift(newLastChar);
var newerString = newArray.join("");
clickCount++;
}
document.getElementById('Result').innerHTML = (clickCount === 1) ? newString : newerString;
}
$('#button').on('click', scrollString);
Right now it only works the first time I click, and developer tools says newArray is undefined; also the clickCount stops incrementing. I do not know if it's an issue of scope, or should I take a whole different approach to the problem?
Every time you click you are actually reseting the string. Check the scope!
var str = "Learning to Code Javascript Rocks!";
var button = document.getElementById("button");
var output = document.getElementById("output");
output.innerHTML = str;
button.addEventListener("click", function(e){
str = str.charAt(str.length - 1) + str.substring(0, str.length - 1);
output.innerHTML = str;
});
button{
display: block;
margin: 25px 0;
}
<button id="button">Click Me!</button>
<label id="output"></label>
It is, in fact, a scoping issue. Your counter in inside the function, so each time the function is called, it gets set to 0. If you want a counter that is outside of the scope, and actually keeps a proper count, you will need to abstract it from the function.
If you want to keep it simple, even just moving clickCount above the function should work.
I do not know if it's an issue of scope
Yes, it is an issue of scope, more than one actually.
How?
As pointed out by #thesublimeobject, the counter is inside the function and hence gets reinitialized every time a click event occurs.
Even if you put the counter outside the function, you will still face another scope issue. In the else part of the function, you are manipulation a variable (newString) you initialized inside the if snippet. Since, the if snippet didn't run this time, it will throw the error undefined. (again a scope issue)
A fine approach would be:
take the counter and the defaultString outside the function. If the defaultString gets a value dynamically rather than what you showed in your code, extract its value on page load or any other event like change, etc. rather than passing it inside the function.
Do not assign a new string the result of your manipulation. Instead, assign it to defaultString. This way you probably won't need an if-else loop and a newLastChar to take care of newer results.
Manipulate the assignment to the element accordingly.
You can use Javascript closure functionality.
var scrollString = (function() {
var defaultString = "Learning to Code Javascript Rocks!";
return function() {
// convert the string into array, so that you can use the splice method
defaultString = defaultString.split('');
// get last element
var lastElm = defaultString.splice(defaultString.length - 1, defaultString.length)[0];
// insert last element at start
defaultString.splice(0, 0, lastElm);
// again join the string to make it string
defaultString = defaultString.join('');
document.getElementById('Result').innerHTML = defaultString;
return defaultString;
}
})();
Using this you don't need to declare any variable globally, or any counter element.
To understand Javascript Closures, please refer this:
http://www.w3schools.com/js/js_function_closures.asp

How to increment div id name and localStorage content name using for loop?

I'm trying to run a for loop and increment a number of things here but can't get my head around it
jQuery code
var counter1 = localStorage.getItem('counter1item');
if (counter1 == null){
$("#i1").html('Zero');
} else {
$("#i1").html(counter1);
}
$("#i1").on("click", function(){
counter1++;
$("#i1").html(counter1);
localStorage.setItem('counter1item', $("#i1").html());
});
When I'm use for loop and try to increment everything then it doesn't work:
var i = 0;
for(i=0;i<100;i++){
var counter+"i" = localStorage.getItem('counter+"i"+item');
if (counter+"i" == null){
$("#i"+i).html('Zero');
} else {
$("#i"+i).html(counter+"i");
}
$("#i"+i).on("click", function(){
counter+"i"++;
$("#i"+i).html(counter1);
localStorage.setItem('counter+"i"+item', $("#i"+i).html());
});
}
What am I doing wrong? Any help would appreciated, Thanks.
The problem of your variable definitions has been already explained.
Another problem - When setting click event inside loop, the counter and i variables are overridden each iteration, so that each button will return variable which was set at the end of the loop.
F.ex:
If the loop is: i=0; i<100; i++ , then at the end of the loop i for each button will be always equal to 100. And counter will be always equal to the last set counter +1, because these variables loses their uniqueness outside the loop.
You have to store the i variable somewhere, so that it won't get updated while loop lasts, and is always unique for each button.
I'd store the i in a data-id attribute of the button and set click event on class selector, outside for loop.
Also, since the data is a simple string, you can use .text() instead of .html().
HTML:
<button class="counter" id="i0"></button>
<button class="counter" id="i1"></button>
...
Script:
// no need for this:
//var i = 0;
for(/* i is defined here: */ var i=0; i<10; i++){
var c = localStorage.getItem('counter'+ i +'item');
// add data-id to the element:
$("#i"+i).text(c == null ? 'Zero' : c).data('id',i);
}
// listen for click event on 'counter' class:
$(document).on("click",".counter", function(){
// parse number from text of the button:
var c = $(this).text(parseInt($(this).text())+1 || 1).text();
// grab the id from data-id attribute:
localStorage.setItem('counter'+ $(this).data('id') +'item', c);
});
DEMO
Remove all quotes around the use of variables. Putting them in quotes makes them a string, not your variable (multiple instances of this problem)...
Like this:
'counter+"i"+item'
Literally translates to this string:
counteriitem
Say i = 2, you would write it like so:
'counter'+i+'item'
to result in this string:
counter2item
Also, I don't see the variable counter defined in the second snippet correctly.

If Statement and Function (Basic) keep track on divs innerHTML?

Ok so I have a function set up already and it gets added in the div as numbers and letters
"var elCamLocation = $( "TEST" )"
Right!
Now I want to use a function to keep track on what is in the innerHTML of the "TEST" div and if the contents of the div changes to "0.00x2.00z0.00" then I want it to do something for example lets just say change url to keep it simple.
Here is what I have..
var Numbs = getElementById("TEST").innerHTML;
function TE()
{
if(Numbs = "0.00x2.00z0.00")
{
window.location.assign("http://google.com")
}
};
But it isn't working the window.location.assign("http://google.com")isn't triggering at all
any idea's?
= is for assignment. You should test for equality using the === operator.
if(Numbs === "0.00x2.00z0.00")
{
//etc.
}

even.data is not change

here is my own practice demo, it works well as i expect. but when i use line 8 ( comment on my demo code ) instead of line 7 ,the input text values all change to 0 which is different than the result of demo i giving out.
i look at the jquery website it only gives me this
Description: An optional object of data passed to an event method when the current executing handler is bound.
i think the result of using line 8 or line 7 should be the same because of i is assigned to count object, but it is not. Could someone explain me about this question. by the way, if someone could refactor my code will be even more nicer THANKS!!
here is my code
var i = 0;
$("#aa").on("click", {
count : i
},
function(event) {
var div = $('<div/>');
var input = $('<input />').attr("value", event.data.count);
event.data.count++;
//i++;
var bt = $('<input />').attr({
type : "button",
value : "remove",
});
div.append(input);
div.append(bt);
var index = $("div").length;
if (index == 0) {
$("#aa").after(div);
} else {
$("div").last().after(div);
}
bt.on('click', function(event) {
$(this).parent().remove();
});
});
when the current executing handler is bound.
this is important thing in the section. So, the object will be created only once, during the time of binding the function with the click event. So, changing i will not change the value of event.data.
When you do
event.data.count++;
you are actually mutating the object and the state of the object will be retained. That is why it works.

Categories

Resources