Javascript reference element created from appendchild? - javascript

I am creating tables with the appendchild method. They contain checkboxes. I would like to be able to have the user to click a checkbox and have it run a function. I need the function to access the other checkbox and see if its checked or not. Currently I can' seem to reference the table or checkboxes at all.
My code for creating the table is:
function makeTable() {
var ItemA = Item.ItemName.options[Item.ItemName.options.selectedIndex].text;
var myParagraph=document.getElementById("myLine");
myForm = document.createElement("FORM");
mytable = document.createElement("TABLE");
mytablebody = document.createElement("TBODY");
var CB_Format = document.createElement('input');
CB_Format.type = 'checkbox';
CB_Format.name= "CB_Test";
CB_Format.value= 1;
CB_Format.setAttribute("name", "CBTest2");
CB_Format.onclick = changeColor;
theCell.appendChild(CB_Format);
var CB_Delete = document.createElement('input');
CB_Delete.type = "checkbox";
CB_Delete.name = "CB_Test";
CB_Delete.setAttribute("name", "CBTest2");
CB_Delete.value = 2;
CB_Delete.onclick = answer;
theCell.appendChild(CB_Delete);
My understanding is that my solution should be as simple as alert(document.form.checkbox.checked) but no matter what combination of possible names I try I get the error that it is null or not an object in both ie8 and firefox.
Thank you for your help

> function makeTable() {
> var ItemA = Item.ItemName.options[Item.ItemName.options.selectedIndex].text;
> var myParagraph=document.getElementById("myLine");
> myForm = document.createElement("FORM");
> mytable = document.createElement("TABLE");
> mytablebody = document.createElement("TBODY");
If you don't declare variables with var, they become global variables when first evaluated. Always declare variables.
> var CB_Format = document.createElement('input');
> CB_Format.type = 'checkbox';
> CB_Format.name= "CB_Test";
> CB_Format.value= 1;
> CB_Format.setAttribute("name", "CBTest2");
The above line changes the name property from the value assigned a couple of lines earlier, why do both? Just assign the correct value to the name property once:
CB_Format.name = "CBTest2";
The same goes for the use of setAttribute later. Note that setting the value of a property doesn't always change the associated attribute in some browsers, so always use properties unless there is a specific reason to use setAttribute,
[...]
My understanding is that my solution should be as simple as
alert(document.form.checkbox.checked) but no matter what combination
of possible names I try I get the error that it is null or not an
object in both ie8 and firefox. Thank you for your help
Form controls are made available as named properties of the form element. If there is more than one control with the same name, they are in a collecion. Assigning different values to the name property and attribute is asking for trouble. It should be that the second assignment overwrites the first, but no doubt there is a browser somewhere that will keep both values (one for the attribute and the other for the property).
The simple solution is to always use properties and only assign one value. If you want the name to be CBTest2 (since that is the second one assigned), then when the input is added to the form and the form to the document it will be available as:
document.forms['formName'].elements['CBTest2']
If the names are valid identifiers, then shorthand dot notation can be used:
document.formName.CBTest2
Since you have two elements with that name, the returned value will be a collection (a little like an array), so to get the first one, use:
document.formName.CBTest2[0]

You could use some code similar to...
var checkboxes = document.querySelectorAll('#some-form input[type="checkbox"]');
Array.forEach(checkboxes, function(checkbox) {
checkbox.addEventListener(function() {
var hasOtherCheckedCheckbox = Array.every(checkboxes, function(checkbox) {
return checkbox.checked;
});
});
});
Of course, for complete browser support, you'll need to modify this code a bit.

Related

Get selected checkbox(dynamically created) value in javascript

I'm using the following code snippet for create a dynamic checkbox.
This code snippet is inside of the for loop.based on the for loop the check boxes will create.The main function is called in the html onload.
This functionality is working fine.But if I choose the check box I need to get the value of the check box.I use the addEventListener its not working fine.
var checkbox = document.createElement('input');
checkbox.type = "checkbox";
checkbox.name = "name";
checkbox.value = teamIds;
checkbox.id = i;
checkbox.addEventListener("click",setTeamIdsinTextBox(teamNamesToShow),false);
body.appendChild(checkbox);
Now I need, if I select the two checkboxes and I want to pass the both values to the setTeamIdsinTextBox function with comma separate string.
How can I do this? I need to achieve this with the javascript alone.
so I need to frame the selected checkbox values like
var teamNamesToShow ="firstselectedcheckboxvalue,secondselectedcheckboxvalue"
Thanks in Advance.
The click listener needs to iterate over the checkboxes and collect the ids of those that are checked. You can use a selector to get just the checked ones, or filter the checked ones later which allows for a less complex selector.
The following uses the more complex selector but simpler map callback:
window.onload = function(){
var form = document.forms['form0'];
for (var i=0; i<10; i++) {
var checkbox = document.createElement('input');
checkbox.type = 'checkbox';
checkbox.name = 'name' + i;
checkbox.value = 'value' + i;
checkbox.id = 'cb' + i;
checkbox.addEventListener("click",
setTeamIdsinTextBox,
false);
form.appendChild(checkbox); // add checkboxes to form, not body
}
}
function setTeamIdsinTextBox() {
var form = this.form;
var cbs = Array.from(form.querySelectorAll('input[type="checkbox"]:checked'));
var ids = cbs.map(function(cb) {return cb.id});
form.ta0.value = ids.join(', ');
}
<form id="form0">
<textarea id="ta0" name="ta0"></textarea>
</form>
The body of the function could be:
this.form.ta0.value = Array.from(this.form.querySelectorAll('input[type="checkbox"]:checked')).map(function(cb) {return cb.id}).join(', ');
but I think splitting it over a couple of lines is more sensible.
Edit
Array.from was introduced in ECMAScript 2015 so may not be available in all implementations in use. There's a polyfill at MDN that can be included to provide support where lacking. Also, it can be replaced with Array.prototype.slice, which has ubiquitous support.
Instead of:
Array.from(form.querySelectorAll('input[type="checkbox"]:checked'));
use:
[].slice.call(form.querySelectorAll('input[type="checkbox"]:checked'));
however that may fail in IE 8 as (from memory) it doesn't allow calling built–in methods with a host object as this. In that case, go directly to map and provide a polyfill for IE 8:
[].map.call(form.querySelectorAll('input[type="checkbox"]:checked'), function(cb) {return cb.id});
That will work in IE 8 as the polyfill for map means that it's a native function, not built–in so using a NodeList as this is OK. Versions of IE with map are OK with the host object thing.
In the for loop which you are iterating maintain an int variable which gives you the exact no. of checkboxes which you are going to create.And then using that again iterate through a for loop for that int variable and check for each checkbox whether it is checked or not.
int countCheckBox=0;
var listOfCheckBoxVal='';
function setTeamIdsinTextBox(){
for(int i =1; i<=countCheckBox;i++){
if(document.getElementById(i).checked==true){
listOfCheckBoxVal += document.getElementById(i).value+",";
}
}
Now this listOfCheckBoxVal variable will have the list of values of checked checkboxes seperated by a comma.

contenteditable not working on dynamically generated elements

I am dynamically creating an unordered list and adding items to it on a click of a button. I append this to a section that has contenteditable attribute set true. However, I do not see it working. I did set the contenteditable attribute to true even for the list but I guess it is supposed to inherit that from the section it is appended to. Here is the code of what I am doing.
// create text input
var categoryInput = document.createElement('input')
// create button to add the text entered to a list
var btnAddToList = document.createElement('input');
btnAddToList.type ="button";
//create a section to add a list to
var section = document.createElement('section');
var ul=document.createElement('ul');
section.appendChild(ul);
section.contenteditable = "true";
ul.contenteditable = "true";
//create an event handler to add to the list
if (btnAddToList.addEventListener) { btnAddToList.addEventListener('click', function () { addToList(ul, categoryInput.value);});
} else if (btnAddToList.attachEvent) {
btnAddToList.addEvent('click', function () { addToList(ul, categoryInput.value);});
Here is the function I call
function addToList(unorderedlist, inputText) {
if(inputText.length == 0) {
alert("Add Text");
return;
}
var listitem = document.createElement('li');
var listvalue = document.createTextNode(inputText);
listitem.appendChild(listvalue);
unorderedlist.appendChild(listitem);
}
What am I doing wrong or not doing? Any help appreciated. Thanks
The property is contentEditable (note upper-case 'E'), not contenteditable.
section.contentEditable = "true";
You need to set the attribute, not the property:
section.setAttribute('contenteditable', 'true');
Instead of
section.contenteditable = "true";
Some more info here and here (in the context of jQuery, but covers the topic splendidly nonetheless).
My current understanding of the difference is that attributes are the things you can set through markup (id, class, contenteditable, etc.), whereas properties are the properties of the actual javascript objects representing the DOM nodes. As the linked article mentions, the two are often kept in sync by the browser, but not always.
Edit:
As Tim Down states in his answer, while the above works (setting the attribute), the actual problem is that the name of the property is cased wrong. It should be
section.contentEditable = "true"; //Note the upper case 'E'
The reason setting the attribute works, is that attributes are case-insensitive.

Is it possible to link container to other one?

I have an array of data. I have put this data on my site in different places over different attributes, how innerHTML value placeholder etc.
Is it possible to link this values with the array from where I can take data? So that when I change the data in array, it going automatic changed on the site?
Also I try to show how I did it mean:
var test = Array();
test['place1'] = 'NY';
var myspan = document.createElement('span');
myspan.innerHTML = test['place1'];
On some event the value of test['place1'] is changed to 'LA', and at the same moment the value of myspan.innerHTML must be changed too.
Native JS only please.
This needs to be manually managed. A simple solution would be something like this:
function Place(container, initVal) {
this.container = container ? container : {};
this.set(initVal);
}
Place.prototype.place = "";
Place.prototype.get = function() {
return this.place;
}
Place.prototype.set = function(val) {
this.place = val;
this.container.innerHTML = val;
}
var test = {}; // object
test['place1'] = new Place(document.createElement('span'), "NY")
test['place1'].set('New Value');
This is not a full-feature solution, but gives you an idea of the coordination that needs to take place.
If you're only supporting modern browsers, then the syntax can be cleaned up a bit by using getters/setters.
In the future, you'll be able to use Proxy, which will make it even easier and cleaner.
There is no native way to bind an attribute of an HTML element to the values of an array, but you aren't actually using an array; you're using an object, and it is a simple matter to define special features on an object. For example:
First, define your object:
function boundArray(){
this._bindings = {};
this.setBinding = function(key,element){
this._bindings[key] = element;
};
this.setValue = function(key,value){
this[key] = value;
if(this._bindings[key]){
this._bindings[key].innerHTML = value;
}
}
}
Then use it in your code:
// create a new instance of the boundArray
var test = new boundArray();
// create the HTML element to use, and add it to the DOM
var myspan = document.createElement('span');
document.body.appendChild(myspan);
// bind the HTML element to the required key in the boundArray
test.setBinding('place1',myspan);
// Now every time you set that key on the boundArray (using setValue), it will also change the innerHTML field on the element
test.setValue('place1','NY');
// You can access your information from the boundArray in the usual ways:
var somevar = test.place1;
var anothervar = test['place1'];
What you are talking about is an MVVM solution. Most MVVM JavaScript solutions uses some object that represents an observable, which is a field within the object. When the value in the object changes, the observable lets the framework know to update the DOM. It also listens to the DOM for change events, and updates the object in reverse. For arrays, it's a similar process: it listens for adds or removes of the array, and updates the UI accordingly.
As #MCL points out in the comments on this post below, there is a way to watch changes to an object, and it isn't overly difficult to generically attach to an element on the DOM. However, There are a lot of good frameworks out there that make this REALLY easy, so that may be something to consider.

Why doesn't this javascript work assign .cells[] properly?

Why doesn't this work?
var row = document.getElementById(currentRow);
var otherRow = document.getElementById(targetRow);
row.cells[0] = otherRow.cells[0];
This works with
row.cells[0].innerHTML = otherRow.cells[0].innerHTML;
However, there are attributes attached to the cell which I also want to move over without having to manually recreate them.
Solution (Note: more is being done in my actual implementation, but this is the framework):
for (var i = 0; i < 4; i++) {
var copyTo = row.cells[i];
var copyFrom = otherRow.cells[i].cloneNode(true);
copyTo.parentNode.replaceChild(copyFrom, copyTo);
}
You should be able to use cloneNode() to actually clone the node and its attributes.
Each entry in cells refers to a DOMElement. When you typed row.cells[0] = otherRow.cells[0], you are saying that you want row.cell[0] to reference the same DOMElement as otherRow.cells[0].
I'm guessing you want row.cells[0] to have the same text or HTML as otherRow.cells[0]; in which case, the second code snippet will do just that, since you are actually modifying the DOMElement, and not just changing which DOMElement you are referencing.

How to get the value of the selected check-box value in XUl JavaScript

This is my check-box and it's created dynamically by getting the value of the XUL tree.
var yyahoo = tree.view.getCellText(i, tree.columns.getNamedColumn("yahoo"));
var existing = document.getElementById('box');
var checkbox = document.createElement('checkbox');
capt.appendChild(checkbox);
checkbox.setAttribute('label', yyahoo);
checkbox.setAttribute("checked", "false")
checkbox.setAttribute('style', 'color: green;');
Like this I have dynamically created many check-boxes in my XUL file.
When I checked Mozilla website, it is explained that, i have to use hasAttribute() to get the value of the selected check-box, which is confusing to me.
Please help me to get the value of the selected check-box.
This is the button to get the values on-click.
<row><button label="get" oncommand="get();"/></row>
This is function: This function is not working 'cause something is missing in my function.
function get()
{
// check that the attribute exists before setting a value
var d = document.getElementById("box");
if (d.hasAttribute("checkbox")) {
alert(d);
}
}
Thanks for your support.
The checkbox is a child of the element with ID box, not an attribute. Try something like this:
function get() {
// check that the attribute exists before setting a value
var table = document.getElementById("box");
var cells = table.getElementsByTagName("checkbox");
for (var i = 0; i < cells.length; i++) {
var cell = cells[i];
if(cell.checked) {
alert(cell.getAttribute("label"));
// or cell.label
}
}
}
The checked property tells you whether the checkbox is currently selected or not. hasAttribute('checked') tells you whether the attribute was set or not. Maybe you have to use both, I don't know.
Apparently, the checkbox [MDN] element has no attribute value, so I don't know which value you are talking about.

Categories

Resources