Javascript, Dynamic Table insert option boxes into table - javascript

I have been using excel for my project for a few years. I have finally decided to move it into a html project instead. It kinda sucks as I need to learn everything about JS, CSS and html and probably much more. And my excel project is quite advanced at this point.
But I will just have to start at the beginning and add things as I learn. In the end I think it will be worth it.
So after many hours of trial and error I have been able to create this simple code:
function myFunction2() {
var table = document.getElementById("Table1");
var row = table.insertRow(table.length);
for (i = 0; i < 10; i++) {
row.insertCell(i);
}
row.insertCell(1).innerHTML = "NEW CELL1";
}
And here is the delete function, is that phrased correctly as I thought the numbers where acting strangely
function myDeleteFunction() {
var x = document.getElementById('Table1').rows.length;
var x = (+x - +1);
if (x >= 1) {
document.getElementById("Table1").deleteRow(x);
}
}
This basically insets one new row to my table, However in cells(0,3,4,5,6,7,10) I would need a dropdown list How would I go about to add this ?
Any help would be much appreciated.

In the world of HTML the nearest analogy of a dropdown list is probably select element; a simple example would be (at the end of your myFunction2):
row.insertCell(0).innerHTML = '<select><option>opt A</option><option>opt B</option></select>';
You might want to use the DOM API (to save some parsing & prevent problems from creating HTML directly) - see for example this SO question on how to do so.

Hi guys thanks for your replies. I actually found an answer while waiting , Not sure if my way is the best:
function myFunction2() {
var img = new Image();
var table = document.getElementById("Table1");
var row = table.insertRow(table.length);
for (i = 0; i < 12; i++) {
row.insertCell(i);
}
//Add Txt
row.insertCell(1).innerHTML = "insert";
//Add drop-down list
var dd = document.createElement("select");
dd.name = "SportSelector";
dd.id = "id";
dd.options[dd.length] = new Option("Soccer", "value");
dd.options[dd.length] = new Option("Basket", "value");
dd.options[dd.length] = new Option("Hockey", "value");
row.insertCell(0).appendChild(dd);
//Done
}
I will need to study this. looks like my code was a little long. But of course I solve one problem and I get 10 more :) lol
I'm not sure if it considered polite to ask for a follow up question here as question is solved.
However I feel my next question is closely related to the first one. As my code will add a ton of these drop-downs in the end. I would need somehow to "find" the drop-down again with my next js function.
How would it be possible to add a code that "catches" which drop-down i edit and return a popup msg or something ?
frederik

For adding row you can do something like this
function myFunction2() {
var table = document.getElementById("Table1");
var row = table.insertRow(table.length);
var dropDownHtml = "<select><option>A</option><option>B</option><option>C</option></select>";
var cell;
for (i = 0; i <= 10; i++) {
cell = row.insertCell(i);
if (i == 0 || i == 10 || (i >= 3 && i <= 7)) {
cell.innerHTML = dropDownHtml;
}
}
}
FYI : You can add/remove row at starting my using index 0 and at the end by using index as -1 for insertRow()/deleteRow()
You can modify your delete row function as follows
function myDeleteFunction() {
var x = document.getElementById('Table1').rows.length;
x = (x - 1); //do you want to not allow header to be removed or what ?
if (x >= 1) {
document.getElementById("Table1").deleteRow(x);
}
}

Related

Dynamically adding multiple rows to a datatable

I see similar questions have been asked before but I cannot find the answer I'm after.
My question is, how do I add multiple rows of data at the same time, I have a working example below which will slowly add 1000 rows using the row.add() but I cannot for the life of me work out how to add these rows in one batch using the rows.add()
$('#addRow').on( 'click', function () {
for (i =0; i < 1000; i++) {
r = [i+'.1', i+'.2', i+'.3', i+'.4', i+'.5', i+'.6', i+'.7'];
mytable.row.add( [ r ] ).draw( false );
}
});
I have gone through all the examples on the web I can find but all of the examples I have found work using a set amount of predefined data, not how to handle an unknown number of rows.
Any help would be greatly appreciated.
Regards, Chris
Without a proper example, I am unable to test the results. Consider the following code.
function addRows(n, tbl) {
var lastRow = tbl.row(":last");
var index = lastRow.index();
for (var i = (index + 1); i < (index + n); i++) {
r = [i + '.1', i + '.2', i + '.3', i + '.4', i + '.5', i + '.6', i + '.7'];
tbl.row.add(r).draw(false);
}
}
$('#addRow').on('click', function() {
addRows(1000, mytable);
});
Assuming you have an amount of data in place, you want to find the last row in the Table and then build on that. You cannot build rows with an infinite number of rows, but you can use a dynamic variable amount. You can also build an Object of Rows and then use table.rows.add().
See More:
https://datatables.net/reference/api/rows()
https://datatables.net/examples/api/add_row.html
https://datatables.net/reference/api/rows.add()
OK I've got it working, so if anyone else gets stuck on this same issue, this is my code now :
$('#addRow').on( 'click', function () {
var arrayAll = [];
for (i =0; i < 1000; i++) {
var arrayRow = [i+'.1', i+'.2', i+'.3', i+'.4', i+'.5', i+'.6', i+'.7'];
arrayAll = arrayAll.concat([arrayRow]);
}
t.rows.add( arrayAll ).draw();
} );
This will add a 1000 rows within a second :)

Trouble creating unordered list with number of list items controlled by user input

I tried to make a function that would generate a number of list items based on the user input from a prompt. It does not work although I believe it should.
I'm looking for an explanation of what's wrong with my code even if an alternate solution is also provided, if possible.
On the HTML side I have entered <div class="freshList"></div> in the body so that it can be picked up by the function and have the list placed in that location
Code is below:
function makeAList()
{
var freshList = document.getElementsByClassName("freshList");
var listLength = prompt("Enter number of list items");
var listString = "<ul>";
for (var i=0; i < listLength; i++)
{
listString+= "<li>"+"</li>"
}
listString += "</ul>"
document.innerHTML = listString;
}
makeAList();
// end code
Now the only way I have been able to get this to work was by accident when using the document.Write method at various points in the code to see what was working (I tried console log first which said that the function was called and the loop was proceeding but no output was coming so I switched to doc.write instead). I used document.Write(listString); and this was able to forcibly print the bullet points onto the screen but that is not my desire. I want it in the HTML not just printed on the screen (so that I can manipulate it with other functions I have made).
Altogether I wanted to make a series of functions to perform the following action: Ask if the user would like to make a new list. Call the makeNewList function which would prompt the user for the number of items. Then ask the user if they would like to edit the list and call the editList function with new prompts for each list item. Finally leaving an output of # of bullet points with user input on each point. I am sure this is a ridiculous idea that nobody would use but it was more a lesson for myself to try an idea I had rather than something functional. Full (attempted) code below:
function makeAList()
{
var freshList = document.getElementsByClassName("freshList");
var listLength = prompt("Enter number of list items");
var listString = "<ul>";
for (var i=0; i < listLength; i++)
{
listString+= "<li>"+"</li>"
}
listString += "</ul>"
document.innerHTML = listString;
}
makeAList();
function editAList() {
var list = document.getElementsByTagName("li");
for (var i = 0; i < list.length; i++)
{
list[i].innerHTML = prompt("Place list text below","")
}
function checkList(){
var resp1 = confirm("Would you like to make a new list?")
if(resp1 == true)
{
makeAList();
}
else
{
}
if(resp1 === false){
var resp2 = prompt("Would you like to edit an existing list instead?")
}
else if(resp2 === true){
editAList();
}
else{
alert("You have chosen not to make a new list or edit an existing one")
}
}
checkList();
My friend looked at my code and made some changes as well as detailed comments with the places I went wrong. For anyone who views this question in the future here is his response. All credit to him but I don't know his stack overflow handle to tag him.
Here is his js bin updated and heavily commented code
Code below in case that link dies:
// hi
// i've changed a few things, i've left the original code in comments (//)
function makeAList()
{
// what does the following code return? a single element? a list of elements?
//var freshList = document.getElementsByClassName("freshList")
var freshList = document.getElementById("freshList");
var listLength = prompt("Enter number of list items");
// var listString = "<ul>";
// you can create a 'ul' element and append the list string later
// https://developer.mozilla.org/en-US/docs/Web/API/ParentNode/append
var ul = document.createElement('ul');
ul.setAttribute('id', 'theList');
// there's an even shorter way of doing all this, but since you're starting out, we can save that for later
for (var i=0; i < listLength; i++)
{
//i would probably append here too, but just demonstrating insertAdjacent
ul.insertAdjacentHTML('beforeend', '<li></li>');
}
// document.innerHtml = listString //this was the reason why this function didn't work
// document has no inner html, instead, you want to append the list to the .freshList div that you created
// and then append that to the listOfLists that you queried
// the reason why we don't want to manually set innerHTML is because the DOM has to be reparsed and recreated
// every time innerHTML is set. if you have 1000s of lists, this would be extremely slow
// there are DOM apis that create and insert html elements much more faster and efficient (appendChild)
// if you want to create html elements as strings, as you have done previously, use insertAdjacentHTML: https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML
// it is faster and more efficient
freshList.appendChild(ul);
}
makeAList();
function editAList() {
var list = document.getElementsByTagName("li");
// there's a much more efficient way to do this, but keep this here for now
var insertText = function(i) {
var input = prompt("Place list text below", "");
console.log(i);
list[i].append(input);
}
for (var i = 0; i < list.length; i++)
{
// why would we use settimeout? http://www.w3schools.com/jsref/met_win_settimeout.asp
setTimeout(insertText.bind(null, i), 1000); // why bind? https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
}
}
editAList();
// function checkList(){
// var resp1 = confirm("Would you like to make a new list?")
// if(resp1 == true)
// {
// makeAList();
// }
// else
// {
// }
// if(resp1 === false){
// var resp2 = prompt("Would you like to edit an existing list instead?")
// }
// else if(resp2 === true){
// editAList();
// }
// else{
// alert("You have chosen not to make a new list or edit an existing one")
// }
// }
// checkList();

Adobe LiveCycle working with Repeating Subforms

I have repeating subforms with buttons on them.
I want to be able to remove buttons that have been added with each addition of a subform.
By the searching I've done, the following code should work, but it doesn't. Can someone please set me straight?
var IGdelbut = xfa.resolveNodes("ItemGroup[*].ItemHeader.Delbutton");
for (var i = 0; i < IGdelbut; i++) {
IGdelbut.presence = "invisible";
}
(I apologize for repeating my earlier question, but I'm hoping I'm giving someone better information to work with.)
Your script has a couple of issues iterating over the result of resolveNodes() call. If i get this right, you are trying to hide all the *DelButton*s on the subforms.
Try the following
var allDeleteButtons = xfa.resolveNodes("ItemGroup[*].ItemHeader.Delbutton");
var len = allDeleteButtons.length;
for (var i = 0; i < len; i++) {
allDeleteButtons.item(i).presence = "invisible";
}
Assuming you have this script on the parent subform of repeating ItemGroup subforms.

Changing a class with z-index

I'm still in the process of learning JavaScript. and I would like to complete the task using only JavaScript and no Jquery.
I have multiple div/images that I’m trying to manipulate using the z-index, and a button that randomize the images to come to the front.
I got the random image array to work but as you could see in image[1]…setting each changeZ index will be laborious. So I’m embarking on changing the class’s (as seen in image[0] so I could add current to the new image and send current to the background on the next go around and then removing the class attribute. I have got the element to work separate but having trouble putting it together in a array.
function changeZIndex(i,id) {
document.getElementById(id).style.zIndex=i;};
function changeClassZIndex(i,tagName){
document.getElementsByTagName("*").style.zIndex=i;};
function getImage(){
var whichImage=Math.floor(Math.random()*3);
var image=new Array()
var currentPhoto = div.current
image[0]=function() {
changeZIndex(5,"scene1");
changeClassZIndex(-5,"current");
currentPhoto.removeClass('current')
document.getElementById("scene1").className += "current"; };
image[1]=function() {
changeZIndex(5,"scene2");
changeZIndex(-5,"scene1");
changeZIndex(-5,"scene3");
changeZIndex(-5,"scene");
};
image[2]=function() {
changeZIndex(5,"scene3");
changeZIndex(-5,"scene");
changeZIndex(-5,"scene2");
changeZIndex(-5,"scene1");
};
image[whichImage].apply(undefined);};
It's because document.getElementsByTagName() returns an array of elements, which you can't do operations like that on. Instead, you need to enumerate through them and do the operations individually.
Here's a working jsfiddle which shows exactly how to do it: jsfiddle
As a side note: if there's one thing a lot of web programming will teach you, its this:
Dont ever, ever, rule out jQuery as an option.
JQuery is your best friend, and the use of it in this situation would cut down your lines of code by well over half.
Firstly, I believe your problem is probably in changeClassZIndex(i,tagName)
which should probably look something like this:
if (document.getElementsByClassName == undefined) {
document.getElementsByClassName = function(className)
{
var hasClassName = new RegExp("(?:^|\\s)" + className + "(?:$|\\s)");
var allElements = document.getElementsByTagName("*");
var results = [];
var element;
for (var i = 0; (element = allElements[i]) != null; i++) {
var elementClass = element.className;
if (elementClass && elementClass.indexOf(className) != -1 && hasClassName.test(elementClass))
results.push(element);
}
return results;
}
}
function changeClassZIndex(z,className) {
var e = document.getElementsByClassName(className);
for(var i = 0; i < e.length; i++) {
e[i].style.zIndex = z;
}
};
I am defining the getElementsByClassName function if it does not exist because some browsers may not support it.
I may suggest taking a different approach to your problem however:
var images = new Array("scene1", "scene2", "scene3");
var currentPhoto = div.current
var whichImage = Math.floor(Math.random()*images.length);
// change all images to the background
for(var i = 0; i < images.length; i++)
{
changeZIndex(-5, images[i]);
}
// change the one you want to the top
changeZIndex(5, images[whichImage]);
That way you do not have to write functions for each image, and adding images is as easy as adding to the array.

Javascript Insert Row

I have an HTML Table consisting of several rows. I am trying to insert rows at a specific position in the table. For example if I mark an already existing row and click insert a new row should be inserted below. At the moment adding rows at the bottom of the table works. What I need is to insert the already build row at a certain position.
Here is my code:
function addLine(lineNumberGlobal,columnnumber,insertion)
{
var newrow = document.createElement("tr");
newrow.setAttribute('id', globalObj.lineNumberGlobal);
newrow.setAttribute('onmousedown', "setCurIdG(getAttribute(\"id\"))");
for (j = 1; j <= globalObj.monthdays + 1; j++)
{
//build row cells with content
}
if (insertion == true)
{
var newrowinsert = globalObj.bodyGlobal.insertRow(globalObj.currenIdGlobal);
//this actually inserts a new empty row but I want to append my existing row "newrow"
}
else if (insertion == false)
{
globalObj.bodyGlobal.appendChild(newrow);
}
}
Any help would be appreciated ...
You can use the insertBefore DOM method. If you want to insert after the row that you have marked, you would need to use that row's nextSibling to find the row after it, and then insert before that.
If I assume that globalObj.currenIdGlobal is the ID of the row you want to insert after, that would look like this:
var refElement = document.getElementById(globalObj.currenIdGlobal);
if (refElement) { // Being defensive here, you probably know it _does_ exist
globalObj.bodyGlobal.insertBefore(newrow, refElement.nextSibling);
}
That assumes that your HTML is structured with no whitespace or similar between rows (since nextSibling will return the next node after the row, which can be a text node rather than an element). If you need to be more defensive:
function findNextSiblingElement(elm, tagName) {
do {
elm = elm.nextSibling;
} while (elm && (elm.nodeType != 1 || elm.tagName != tagName));
return elm;
}
and then change the above to:
var refElement = document.getElementById(globalObj.currenIdGlobal);
if (refElement) { // Being defensive here, you probably know it _does_ exist
globalObj.bodyGlobal.insertBefore(newrow, findNextSiblingElement(refElement, 'TR'));
}
Note that if you pass null as the second argument to insertBefore, it appends to the end.
FWIW, operations like these can be made a bit easier if you use a library like Prototype, jQuery, Closure, or any of several others.
Use insertRow to create the row.
Also: Don't use setAttribute, it's broken in IE. And an event handler requires a function reference and not a string.
function addLine(lineNumberGlobal,columnnumber,insertion)
{
var newrow = globalObj.bodyGlobal.insertRow(insertion ? globalObj.currenIdGlobal : -1);
newrow.id = globalObj.lineNumberGlobal;
newrow.onmousedown = function() { setCurIdG(this.id); };
for (j = 1; j <= globalObj.monthdays + 1; j++)
{
//build row cells with content
}
}
BTW, you seem to be using the id to "re-find" the table rows. Consider keeping a reference to the row instead.

Categories

Resources