Fine, my question is as follows. I am adding rows to a table dynamically using the DOM, and everything goes really well. However, in one of the cells I need to add this calendar: http://www.softcomplex.com/products/tigra_calendar/
When I execute the code to add the calendar, it will create it wherever I place it and mess with everything. What I want to do, is to attach that calendar to the cell and that it executes whenever the nodes enter to the table. This is the code:
function addpago()
{
var i = 0;
//Create a select
var cuota=document.createElement('select');
cuota.name="cuota"+cantpagos;
cuota.id="cuota"+cantpagos;
for(i=1;i<=11;i++)
{
cuota.options[i-1]=new Option("Cuota "+i, i);
}
//Create an input and add an event, this code works correctly
var monto=document.createElement('input');
monto.type='text';
monto.name=monto.id='monto'+cantpagos;
if(monto.addEventListener)
monto.addEventListener("blur", sumpagos, false);
else if(monto.attachEvent)
monto.attachEvent("onblur", sumpagos);
else
monto.onblur = sumpagos;
monto.size=6;
//Create an input
var ncheque = document.createElement('input');
ncheque.type='text';
ncheque.name=ncheque.id='cheque'+cantpagos;
ncheque.size=10;
//Create a select
var bancos = document.createElement('select');
bancos.name=bancos.id='banco'+cantpagos;
bancos.options[0]=new Option("BANCO DE CHILE",1);
bancos.options[1]=new Option("BANCOESTADO",2);
bancos.options[2]=new Option("BANCO DE CRÉDITO E INVERSIONES",3);
bancos.options[3]=new Option("BANCO SANTANDER",4);
bancos.options[4]=new Option("BANCO ITAÚ",5);
//Create an input
var plaza = document.createElement('input');
plaza.type='text';
plaza.name=plaza.id='cheque'+cantpagos;
plaza.size=6;
//Create an input
var fecha = document.createElement('input');
fecha.type='text';
fecha.name=fecha.id='fecha'+cantpagos;
fecha.readOnly=true;
fecha.size=14;
//Create a tr, add several td's and attach each element created before to the child td's
row = document.createElement('tr');
cell = document.createElement('td');
cell.appendChild(cuota);
row.appendChild(cell);
cell = document.createElement('td');
cell.appendChild(monto);
row.appendChild(cell);
cell = document.createElement('td');
cell.appendChild(ncheque);
row.appendChild(cell);
cell = document.createElement('td');
cell.appendChild(bancos);
row.appendChild(cell);
cell = document.createElement('td');
cell.appendChild(plaza);
row.appendChild(cell);
cell = document.createElement('td');
cell.appendChild(fecha);
//I need to add the calendar at this point, but I can't figure out how
cell.appendChild(new tcal ({'formname': 'ingpagos', 'controlname': 'fecha'+cantpagos, 'imgpath': 'www.codesin.cl/Tigra/img/'}));
row.appendChild(cell);
document.getElementById('tabpagos').appendChild(row);
cantpagos++; //Global variable being updated
document.getElementById('cantpagos').value=cantpagos;
}
What should I do? Thanks beforehand...
I've used Tigra Calendar before. Why are you adding it as a node? It's an object you just instantiate, the program takes care of modifying the DOM etc. =)
You do however need to wait to instantiate it until after the input field is IN the DOM =)
...
row.appendChild(cell);
document.getElementById('tabpagos').appendChild(row);
new tcal ({'formname': 'ingpagos', 'controlname': 'fecha'+cantpagos, 'imgpath': 'www.codesin.cl/Tigra/img/'})
Though that imgpath looks suspect so you may need to play with it some =)
Related
I am trying to make a color swatch that can be used to select colors from. My thought is to create a table, and have each cell of the table be a button from which the user can click to select the color they want to use. Th this point I have not even tried to give my buttons any functionality until I can actually determine that they are generating I am simply trying to lay out the table at this point and test whether or not the buttons are appending to each cell. This is the reason for the innerHTML = 'test'. However nothing is appearing so I fear the buttons are not properly appending. I am brand new to coding and would prefer to stick with vanilla JS for the time being. Mahalo
// get reference for the pixelPainter div
let body = document.getElementById('pixelPainter');
//create the color swatch
let swatch = document.createElement('table');
swatch.id = 'swatch_base';
for (var i = 0; i<6; i++){
let row = document.createElement('tr');
//create columns and attach buttons to each cell so that the buttons can be selected to choose a color
for (var i = 0; i<10; i++){
let cell = document.createElement('td');
let colorButton = document.createElement('button');
colorButton.className('colorChoice');
colorButton.innerHTML('test'); // just trying to test for button
cell.appendChild(colorButton);
row.appendChild(cell);
}
swatch.appendChild(row);
}
body.appendChild(swatch);
swatch.setAttribute('border', '1');
try this https://jsfiddle.net/qnrra88L/
actually, className and innerHTML are not a functions, also className should be classNames
change these two lines
colorButton.className('colorChoice');
colorButton.innerHTML('test');
as
colorButton.classNames = 'colorChoice';
colorButton.innerHTML = 'test';
I am doing some basic javascripting and am creating a 3 column table created by javascript sourced from an xml. The table is created by appending all the data in rows via javascript.
The first column has an input checkbox, created via javascript, that if ticked fetches a price from the third column on that row and adds all the prices of the rows selected to give a price total.
The problem I am having is I don't seem to be able to reference the appended information to obtain the information in the related price column (third column).
I have attached both the function I am using to create the table which is working and the function I am using to try and add it up which isnt working.
I found the following two articles Getting access to a jquery element that was just appended to the DOM and How do I refer to an appended item in jQuery? but I am using only javascript not jquery and would like a javascript only solution if possible.
Can you help? - its just the calculateBill function that isn't working as expected.
Thank you in advance
function addSection() {
var section = xmlDoc.getElementsByTagName("section");
for (i=0; i < section.length; i++) {
var sectionName = section[i].getAttribute("name");
var td = document.createElement("td");
td.setAttribute("colspan", "3");
td.setAttribute("class","level");
td.appendChild(document.createTextNode(sectionName));
var tr = document.createElement("tr");
tr.appendChild(td);
tbody.appendChild(tr);
var server = section.item(i).getElementsByTagName("server");
for (j=0; j < server.length; j++) {
var createTR = document.createElement("tr");
var createTD = document.createElement("td");
var createInput = document.createElement("input");
createInput.setAttribute("type", "checkbox");
createInput.setAttribute("id", "checkInput");
createTD.appendChild(createInput);
createTR.appendChild(createTD);
var item = server[j].getElementsByTagName("item")[0].innerHTML;
var createTD2 = document.createElement("td");
var createText = document.createTextNode(item);
createTD2.appendChild(createText);
createTR.appendChild(createTD2);
var price = server[j].getElementsByTagName("price")[0].innerHTML;
var createTD3 = document.createElement("td");
var createText2 = document.createTextNode("£" + price);
createTD3.appendChild(createText2);
createTR.appendChild(createTD3);
tbody.appendChild(createTR);
}
}
}
onload = addSection();
function calculateBill() {
var finalBill = 0.0;
var checkBox = document.getElementById("checkInput");
for (i=0; i < checkBox.length; i++) {
if (checkBox[i].checked) {
var parentTR = checkBox[i].parentNode;
var priceTD = parentTR.getElementsByTagName('td')[2];
finalBill += parseFloat(priceTD.firstChild.data);
}
}
return Math.round(finalBill*100.0)/100.0;
}
var button = document.getElementById("button");
button.onClick=document.forms[0].textTotal.value=calculateBill();
When you do x.appendChild(y), y is the DOM node that you are appending. You can reference it via javascript either before or after appending it. You don't have to find it again if you just hang on to the DOM reference.
So, in this piece of code:
var createInput = document.createElement("input");
createInput.setAttribute("type", "checkbox");
createInput.setAttribute("id", "checkInput");
createTD.appendChild(createInput);
createInput is the input element. You can reference it with javascript at any time, either before or after you've inserted it in the DOM.
In this piece of code:
var price = server[j].getElementsByTagName("price")[0].innerHTML;
var createTD3 = document.createElement("td");
var createText2 = document.createTextNode("£" + price);
createTD3.appendChild(createText2);
createTR.appendChild(createTD3);
tbody.appendChild(createTR);
You're creating a <td> element and putting a price into it. createTD3 is that particular <td> element.
If you want to be able to find that element sometime in the future long after the block of code has run, then I'd suggest you give it an identifying id or class name such that you can use some sort of DOM query to find it again. For example, you could put a class name on it "price" and then be able to find it again later:
var price = server[j].getElementsByTagName("price")[0].innerHTML;
var createTD3 = document.createElement("td");
createTD3.className = "price";
var createText2 = document.createTextNode("£" + price);
createTD3.appendChild(createText2);
createTR.appendChild(createTD3);
tbody.appendChild(createTR);
Then, you could find all the price elements again with:
tbody.querySelectorAll(".price");
Assuming tbody is the table where you put all these elements (since that's what you're using in your enclosed code). If the table itself had an id on it like id="mainData", then you could simply use
document.querySelectorAll("#mainData .price")
to get all the price elements.
FYI, here's a handy function that goes up the DOM tree starting from any node and finds the first node that is of a particular tag type:
function findParent(node, tag) {
tag = tag.upperCase();
while (node && node.tagName !== tag) {
node = node.parentNode;
}
return node;
}
// example usage:
var row, priceElement, price;
var checkboxes = document.querySelectorAll(".checkInput");
for (var i = 0; i < checkboxes.length; i++) {
// go up to the parent chain to find out row
row = findParent(checkboxes[i], "tr");
// look in this row for the price
priceElement = row.querySelectorAll(".price")[0];
// parse the price out of the price element
price = parseFloat(priceElement.innerHTML.replace(/^[^\d\.]+/, ""));
// do something here with the price
}
I have a couple of javascript functions which:
show/hide some table rows
add a new row
Both work on the same page, but not under specific circumstances.
Here's the fiddle of the code below:
/*************** show/hide sections ***************/
$('.arrow').click(function(event) {
var sec_id = $(this).attr('id').split('.')[0]; // admin.link -> admin
if ($(this).closest('td').attr('class') == 'subtitle')
$('.s_'+sec_id).toggle(); // toggle hide/show for 1 item (section)
else
$(this).closest('tr').nextUntil('tr:not(.s_' + sec_id+')').toggle();
});
/*************** Add rows ***************/
$('.add_row').click(function(event) {
var sid = $(this).attr('sid'); // the id of the <tbody>
var tbody = document.getElementById(sid); // the <tbody> to add rows to
// === GENERATE NEW NAMES for inputs
// get the name of the first input in the last row
var rows = tbody.rows;
var rowinput = rows[rows.length-1].getElementsByTagName('INPUT');
// split name into array
var name_piece = rowinput[0].name.split('][');
// create name for next row; check if last row is a blank row
var reg = new RegExp('^[0-9]+$');
if (reg.test(name_piece[1])) // if integer
var iteration = parseInt(name_piece[1], 10) + 1; // convert to int with base 10
else
iteration = 1;
if (iteration < 10)
iteration = '0'+iteration; // add left padding to ensure sort order
var front = 'items['+sid.substring(2)+']['+iteration+']'; // front of input name (remove the 's_' from name)
// END GENERATE NEW NAMES for inputs
// === CREATE ROW
var row = document.createElement('tr'); // create a row
var td1 = document.createElement('td'); // create first cell
td1.setAttribute('colSpan', 2);
td1.innerHTML = '<input type="text" name="'+front+'[desc]" maxlength="100" />';
var td2 = document.createElement('td'); // create second cell
td2.innerHTML = '<input type="text" name="'+front+'[price]" maxlength="9" onChange="calc_ttl()" class="right small" />';
var td3 = document.createElement('td'); // create third cell
td3.setAttribute('colSpan', 3);
// END CREATE ROW
// output
row.appendChild(td1);
row.appendChild(td2);
row.appendChild(td3);
tbody.appendChild(row);
});
In the fiddle, you'll see 3 links, all of which work as they should. The only exception is if I add a row while the hidden rows are shown; eg.:
Click "Subsection" to show rows
Click "Add row"
Click "Subsection" to hide rows <-- Fails here
From then on, the "Subsection" link no longer works unless I reload the page. The code checks out, and Firebug reports no errors, so I'm at a loss. Any advice much appreciated.
The problem is not in the jQuery code you've posted here. It is in the HTML. In your fiddle you have:
<tr onMouseOver="this.className='highlight'" onMouseOut="this.className='normal'" class="s_grp_2d_ttl_asset" style="display: none;">
Once the row is visible, as soon as the mouse moves over it, the s_grp_2d_ttl_asset class is replaced by the highlight class, which makes your click event stop at the first element. If you used the addClass, removeClass, or toggleClass functions instead, you could make the change without completely removing the original class.
I hope you can read my code, I have an XML file on my localhost and I would like it to pull the title and year from that file (it currently has Title, Year, Artist, Price, and Country) while maintaining the H1 and button on the page.
The H1 text and button disappear onClick and I would like it to remain on the same page as the results.
<h1>Show the Album list</h1>
<script>
xmlhttp=new XMLHttpRequest();
xmlhttp.open("GET","cd_catalog.xml",false);
xmlhttp.send();
xmlDoc=xmlhttp.responseXML;
function CdCatalog()
{
document.write("<table border='1'><th>TITLE</th><th>YEAR</th>");
var x=xmlDoc.getElementsByTagName("CD");
for (i=0;i<x.length;i++)
{
document.write("<tr><td>");
document.write(x[i].getElementsByTagName("TITLE")[0].childNodes[0].nodeValue);
document.write("</td><td>");
document.write(x[i].getElementsByTagName("YEAR")[0].childNodes[0].nodeValue);
document.write("</td></tr>");
}
document.write("</table>");
}
</script>
The problem is that you're using document.write for a button's click event, which is after the document's been closed...which means it overwrites everything. Since your page is simple and only has an <h1> and button, it looks like only those things are being hidden, but it would be everything on the page (if you had more).
The solution is to use .appendChild and/or .innerHTML to add the content dynamically. I'll provide a solution in a minute :)
UPDATE:
Since you're using tables, you might as well use the native methods .insertRow and .insertCell that make table creation much easier. Here's an example of what you could use overall:
function CdCatalog(xmlDoc) {
var table = document.createElement("table");
var thead = table.createTHead(); // Where "header" rows go
// `insertRow` creates a <tr> element and appends it to `thead` automatically, returning the element
var tr = thead.insertRow(-1);
var td = document.createElement("th"); // No special method for creating "th" elements
td.innerHTML = "TITLE"; // Set its inner content
tr.appendChild(th); // Add it to the row (which is in the header)
td = document.createElement("td");
td.innerHTML = "YEAR";
tr.appendChild(td);
var x = xmlDoc.getElementsByTagName("CD");
// "tbody" is where a table's content goes, whether you do this explicitly or not
var tbody = table.tBodies[0];
for (var i = 0; i < x.length; i++) {
tr = tbody.insertRow(-1);
// `insertCell` creates a <td> element and appends it to `tr` automatically, returning the element
td = tr.insertCell(-1);
td.innerHTML = x[i].getElementsByTagName("TITLE")[0].childNodes[0].nodeValue;
td = tr.insertCell(-1);
td.innerHTML = x[i].getElementsByTagName("YEAR")[0].childNodes[0].nodeValue;
}
// Actually add the table to the DOM (the <body> element in this case)...you can specify where else to put it
document.body.appendChild(table);
}
// Make sure DOM is ready for manipulation
window.onload = function () {
var btn = document.getElementById("button_id"); // Whatever your button is
// Bind the "click" event for the button
btn.onclick = function () {
// Make your AJAX request
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", "cd_catalog.xml", false);
xmlhttp.send();
xmlDoc = xmlhttp.responseXML;
// Pass the result to the function, instead of making everything global and sharing
CdCatalog(xmlDoc);
};
};
And unless I'm mistaken, you can't nest <td> inside of <table>...you must nest them in <tr>...which are nested in <table>
Don't use document.write. It will remove everything you have inside the tag since the document is closed. Do this instead:
document.body.innerHTML += "<td>blah</td>"
-or-
var td = document.createElement("td");
td.innerHTML = "blah"
document.querySelector("table").appendChild(td);
Demo: http://jsfiddle.net/DerekL/AHZ4C/
I'm trying to insert an onmouseover when creating new rows within my table however it's not appearing. Am I missing something stupid?
var row = document.createElement("TR");
row.id = i;
row.onmouseover = hover(i);
var td1 = document.createElement("TD");
row.appendChild(td1);
tbody.appendChild(row);
The variable 'i' is the current number in the loop. The ID of the row appears fine, but not the onmouseover.
Use an anonymous function to create a closure for the value of i, and make sure you're setting a function to onmouseover, rather than the result of calling a function:
var row = document.createElement("TR");
(function (i) {
row.onmouseover = function () { hover(i) };
})(row.id);
var td1 = document.createElement("TD");
row.appendChild(td1);
tbody.appendChild(row);
Taking a proper look at your code, it appears that you're not actually setting the id attribute of the TR element. However, you might want to avoid that entirely and use this context inside the hover function:
var row = document.createElement("TR");
row.onmouseover = hover;
var td1 = document.createElement("TD");
row.appendChild(td1);
tbody.appendChild(row);
function hover() {
alert(this.rowIndex); // <-- `this` refers to the row element
}
You are assigning the result of the function to the event.
Needs to be something like
row.onmouseover=function(){hover(this);}
And it is better to use this since you have the DOM object and do not have to look up anything.
function hover( row ){
row.style.color = "red";
}
If you still what to go the i way, you need to change your id so it is valid. Ids can not start with a number.
var row = document.createElement("TR");
row.id = "row_i";
row.onmouseover = function(){ hover(this.id); }
var td1 = document.createElement("TD");
row.appendChild(td1);
tbody.appendChild(row);
Maybe try:
row.onmouseover = function() { hover(i); };