Pass contextual variable to onclick event handler as argument - javascript

*This is happening inside a larger block of code, in a for loop. See end of post for entire loop.
I've read all of the posts that seem to be about this subject, but I'm still lost.
I'm trying to assign an onclick event to a checkbox. The function being assigned to the onclick event needs to have access to a variable that is available in the scope where the checkbox is defined (idvariable).
var idvariable = parentChildList[i].children[j]["subjectid"];
var input = document.createElement("input");
input.type = "checkbox";
input.value = "";
input.onclick = function () {
return clicked(idvariable);
};
function clicked(id) {
alert(id);
};
I've tried every variation of inline and named functions, but I can't figure out how to give the clicked function access to idvariable. In this example above, the value of that variable is undefined.
Or, if I try it with this way:
var input = document.createElement("input");
input.type = "checkbox";
input.value = "";
var idvariable = parentChildList[i].children[j]["subjectid"];
input.onclick = function (idvariable) {
return clicked(idvariable);
};
function clicked(id) {
alert(id);
};
I get an alert that says [object MouseEvent]. Same with the following where I removed the () from the method name I'm assigning to the onclick event:
var idvariable = parentChildList[i].children[j]["subjectid"];
input.onclick = function () {
return clicked;
}(idvariable);
function clicked(id) {
return alert(id);
};
*entire loop:
for (var i = 0; i < parentChildList.length; i++) {
var row = table1.insertRow(-1);
var cell = row.insertCell(0);
cell.innerHTML =
"<h4 class=\"panel-title\"><a data-toggle=\"collapse\" data-parent=\"#accordion\" href=\"#collapse" + i + "\">" + parentChildList[i]["title"] + "</a></h4>";
if (parentChildList[i].children.length > 0) {
var row2 = table1.insertRow(-1);
var cell2 = row2.insertCell(0);
var table2 = document.createElement("table");
table2.className = "collapse";
table2.id = "collapse" + i;
cell2.appendChild(table2);
for (var j = 0; j < parentChildList[i].children.length; j++) {
var row3 = table2.insertRow(-1);
var cell3 = row3.insertCell(0);
var div = document.createElement("div");
div.className = "checkbox";
var label = document.createElement("label");
label.innerText = parentChildList[i].children[j]["title"];
var input = document.createElement("input");
input.type = "checkbox";
input.value = "";
input.setAttribute('subj', idvariable);
var idvariable = parentChildList[i].children[j]["subjectid"];
alert(idvariable);
input.onclick = function () {
return clicked(this.getAttribute('subj'));
};
function clicked(id) {
return alert(id);
};
cell3.style.padding = "0px 0px 0px 10px";
cell3.style.fontsize = "x-small";
cell3.appendChild(div);
div.appendChild(label);
label.insertBefore(input, label.childNodes[0]);
}
}
}

onclick handler receives Event object. If a handler attached as elem.onclick=handler then the element is available inside the handler as this. So this is workaround.
var idvariable = parentChildList[i].children[j]["subjectid"];
var input = document.createElement("input");
input.type = "checkbox";
input.value = "";
input.setAttribute('data-subj', idvariable);
input.onclick = function () {
return clicked(this.getAttribute('data-subj'));
};
function clicked(id) {
alert(id);
};

You will have to append the checkbox to some existing element first, using the following code.
var element = document.getElementById("one").appendChild(input);
Then you can get the parent by using something like the following...
var x = document.getElementById("someId").parentElement;
where x will contain the parent element.
This link https://stackoverflow.com/a/9418326/886393 is about custom data in an event (custom event). Hope that helps.
Thanks
Paras

Related

Dynamic checkbox to hide dynamic inputbox

I'm rendering a dynamic input and checkbox from an array object which is fine, however I'm not quite sure how to hide the input when I click on the checkbox relative to the input.
function dynamicStuff () {
var objs = ['Id', 'Name', 'Age'];
for (var i = 0; i < objs.length; i++) {
objs[i];
var cElement = document.createElement("input");
cElement.type = "checkbox";
cElement.name = objs[i];
cElement.id = objs[i];
var cElementInput = document.createElement("input");
cElementInput.type = "text";
cElementInput.name = objs[i];
cElementInput.id = objs[i];
cElementInput.placeholder = objs[i]
document.getElementById('chkBox').appendChild(cElement);
document.getElementById('chkBox').appendChild(cElementInput);
}
}
Live example.
Saving on localStroage:
function chkboxCookie() {
var indexOfItem = checkAllFields.indexOf(this.id);
if (indexOfItem >= 0) {
checkAllFields.splice(indexOfItem, 1);
} else {
checkAllFields.push(this.id);
}
/* it saves paramater name in the localStorage*/
localStorage.setItem("checkedUsers", JSON.stringify(checkAllFields));
}
How do I hide the input that I ticked and potentially save that input name/Id in the localStorage?
You'd add an event handler that does something to the input when the checkbox is checked
function dynamicStuff() {
var objs = ['Id', 'Name', 'Age'];
for (var j = 0; j < objs.length; j++) {
(function(i) {
objs[i];
var cElementInput = document.createElement("input");
cElementInput.type = "text";
cElementInput.name = objs[i];
cElementInput.id = objs[i];
cElementInput.placeholder = objs[i];
var cElement = document.createElement("input");
cElement.type = "checkbox";
cElement.name = objs[i];
cElement.id = objs[i];
cElement.addEventListener('change', function() {
cElementInput.style.display = this.checked ? 'none' : 'inline';
localStorage.setItem(objs[i], this.value);
});
var br = document.createElement('br');
document.getElementById('chkBox').appendChild(cElement);
document.getElementById('chkBox').appendChild(cElementInput);
document.getElementById('chkBox').appendChild(br);
document.getElementById('chkBox').appendChild(br.cloneNode());
})(j);
}
}
dynamicStuff()
<div id="chkBox"></div>
Working fiddle.
The id attribute should be unique in the same page so try to change the id of the input for example :
cElementInput.id = objs[i]+'_input';
And attach change event to the checkbox's where you'll show/hide related inputs:
cElement.addEventListener("change", toggleInput, false);
Then define your toggleInput() function :
function toggleInput(){
var input_id = this.id+'_input';
document.getElementById(input_id).style.display = this.checked ? 'inline' : 'none';
localStorage.setItem(this.id, this.value);
}
To check/uncheck the checkboxe's based on localStorage, get the data first :
var localStorageData = JSON.parse(localStorage.getItem("checkedUsers"));
var data = localStorageData==null?[]:localStorageData;
Then check for the the values presented in the array and check/uncheck checkboxe's :
if(data.indexOf(objs[i]) >= 0)
cElement.checked = true;
else
cElement.checked = false;
Hope this helps.

Javascript: How to implement the "enter/return key" to save a value?

Sorry, I am not really good with JS.
The code is essentially the user double clicks on the text, textbox appears, changes text, and saves a new value. However, I want the user to be able to also click enter to save the new value.
In addition, if possible, to have a dedicated "Save" button to save the new value and "discard" to keep the old value.
Also, if I double click many times, the text appears as "(input type="text")". Is there a way to remove that?
Please help if you can.
The HTML + JS code
<html>
<head>
<script type="text/javascript">
window.onload = function() {
var elements = getElementsByClassName('text-edit', '*', document);
for(var i = 0; i < elements.length; i++) {
elements[i].ondblclick = function() {
this.setAttribute('oldText', this.innerHTML); // not actually required. I use this just in case you want to cancel and set the original text back.
var textBox = document.createElement('INPUT');
textBox.setAttribute('type', 'text');
textBox.value = this.innerHTML;
textBox.onblur = function() {
var newValue = this.value;
this.parentNode.innerHTML = newValue;
}
this.innerHTML = '';
this.appendChild(textBox);
}
}(i);
}
function getElementsByClassName(className, tag, elm) {
var testClass = new RegExp("(^|\\s)" + className + "(\\s|$)");
var tag = tag || "*";
var elm = elm || document;
var elements = (tag == "*" && elm.all) ? elm.all : elm.getElementsByTagName(tag);
var returnElements = [];
var current;
var length = elements.length;
for(var i = 0; i < length; i++) {
current = elements[i];
if(testClass.test(current.className)) {
returnElements.push(current);
}
}
return returnElements;
}
</script>
</head>
<div><span class="text-edit">Some text</span></div>
</html>
The snippet below allows you to modify the value of a textbox using save button or enter key and discarding any changes using cancel button.
<!-- HTML -->
<h1 id="editable">Lorem Ipsum</h1>
// JavaScript
window.onload = function(){
var h1 = document.getElementById('editable');
h1.onclick = function(){
var old = this;
var input = document.createElement("INPUT");
input.type = "text";
input.value = this.innerHTML;
input.onkeyup = function(e){
var code = (e.keyCode ? e.keyCode : e.which);
if(code == 13) {
old.innerHTML = input.value;
input.parentNode.replaceChild(old, input);
save.parentNode.removeChild(save);
cancel.parentNode.removeChild(cancel);
}
};
this.parentNode.replaceChild(input, this);
var save = document.createElement("INPUT");
save.type = "button";
save.value = "Save";
(function(old, input){
save.onclick = function(){
old.innerHTML = input.value;
input.parentNode.replaceChild(old, input);
this.parentNode.removeChild(this);
cancel.parentNode.removeChild(cancel);
};
})(old, input);
input.parentNode.insertBefore(save, input.nextSibling);
var cancel = document.createElement("INPUT");
cancel.type = "button";
cancel.value = "Cancel";
(function(old, input){
cancel.onclick = function(){
input.parentNode.replaceChild(old, input);
this.parentNode.removeChild(this);
save.parentNode.removeChild(save);
};
})(old, input);
input.parentNode.insertBefore(cancel, input.nextSibling);
};
};
Working jsBin

Passing One's Self to OnClick Event JavaScript

The on click event that I add to an input in javascript isn't working in the proper manner.
My code so far looks like so:
function order(option) {
if(option.checked) {
document.getElementId("col_order").value = document.getElementById("col_order").value + " " + option.value;
}
}
...//somewhere further down
for(var i = 0; i < options.length; i++) {
var check = document.createElement("input");
var label = document.createElement("label");
var description = document.createTextNode(options[i]);
check.type = "checkbox";
check.name = "order_list[]";
check.value = options[i];
check.onclick = "order(check)"; //Problem here
label.appendChild(check);
label.appendChild(description);
element.appendChild(label);
}
I have also tried:
check.onclick = (function() { var option = check; return function() {order(option);}})();
The problem that I am having is the check.onlick line of code. When I add this with normal HTML:
<input type = "checkbox" name = "order_list[]" onclick = "order(this)" value = "randVal">randVal</input>
I don't have any problem whatsoever; the method executes with the intended results. Any thoughts?
Let me clarify: I make it to the order function just fine, but I never get into the if statement, even though the checkbox was just clicked
Use addEventListener instead, and even if it looks like it should work, you're overwriting the same variables on each iteration as there is no closure in for loops, so I would probably add a closure to avoid issues.
For a checkbox you would listen for the change event, not click
for(var j = 0; j < options.length; j++) {
(function(i) {
var check = document.createElement("input");
var label = document.createElement("label");
var description = document.createTextNode(options[i]);
check.type = "checkbox";
check.name = "order_list[]";
check.value = options[i];
check.addEventListener('change', function() {
if (this.checked) {
var col_order = document.getElementById("col_order");
col_order.value = col_order.value + " " + this.value;
}
}, false);
label.appendChild(check);
label.appendChild(description);
element.appendChild(label);
})(j);
}
FIDDLE
check.onclick = "order(check)"; assigns a String as an on-click handler. That doesn't work; the browser expects a function there:
check.onclick = function() {
order(check);
}

Javascript - onclick event is not working

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

JavaScript: Getting the right UI element in a list of them

I am building a UI in JavaScript that involves adding a column of checkBoxes:
for (var key in ProcessAndPortList.list)
{
if (ProcessAndPortList.list.hasOwnProperty(key))
{
var dataRow = myTable.insertRow(-1);
var dataCell = dataRow.insertCell(-1);
dataCell.textContent = key;
dataCell = dataRow.insertCell(-1);
dataCell.textContent = ProcessAndPortList.list[key].port;
var terminationCheckbox = document.createElement('input');
terminationCheckbox.type = "checkbox";
terminationCheckbox.id = key;
terminationCheckbox.checked = ProcessAndPortList.list[key].markedForTermination;
terminationCheckbox.onchange = function() {
var isChecked = terminationCheckbox.checked;
markForTermination(key, isChecked);
};
var terminateCell = dataRow.insertCell(-1);
terminateCell.appendChild(terminationCheckbox);
}
}
The problem comes in associating the correct ID to the callback for when the checkbox for each entry is checked. I can't seem to get that checkbox's ID to the function. I only ever get the last checkBox's ID. How can I get the correct ID?
Changing this should work:
terminationCheckbox.onchange = function() {
markForTermination(this.id, this.checked);
};
It seems that you capture the variable key with that closure. But key changes on each iteration of the for loop. Capture some variable that is declared inside the loop instead.
for (var key in ProcessAndPortList.list)
{
if (ProcessAndPortList.list.hasOwnProperty(key))
{
var local_scope_key = key
var dataRow = myTable.insertRow(-1);
var dataCell = dataRow.insertCell(-1);
dataCell.textContent = key;
dataCell = dataRow.insertCell(-1);
dataCell.textContent = ProcessAndPortList.list[key].port;
var terminationCheckbox = document.createElement('input');
terminationCheckbox.type = "checkbox";
terminationCheckbox.id = key;
terminationCheckbox.checked = ProcessAndPortList.list[key].markedForTermination;
terminationCheckbox.onchange = function() {
var isChecked = terminationCheckbox.checked;
markForTermination(local_scope_key, isChecked);
};
var terminateCell = dataRow.insertCell(-1);
terminateCell.appendChild(terminationCheckbox);
}
}

Categories

Resources