Is a recursive function an effective way to add table rows dynamically? - javascript

In my research and attempts to use JavaScript to add rows to a HTML Table dynamically, it was important that each id tag be incremented according to the row number. I found various suggested ways of doing this. Finally, I thought I'd give a try at writing a recursive function to do the trick. The following works. But I do not know if it could be optimized. Kindly let me know what I can do to improve it.
function incrementElementID(element, incrementVal) {
if(element.hasAttribute("id")) {
idVal = element.getAttribute("id");
element.setAttribute("id",idVal+incrementVal);
}
var numChildren = element.childElementCount;
for (var i=0; i<numChildren; i++)
incrementElementID(element.children[i],incrementVal);
return;
}

Best done with a closure variable if you're not intentionally trying to use recursion.
Set a variable outside the function scope and increment it within the function.

You're better off with some simple jQuery:
var incrementVal = ...
$("[id]").each(function(index, value) {
elem = $(value);
elem.attr("id", +elem.attr("id") + incrementVal);
});
$("[id]") selects any element that has an id attribute: http://api.jquery.com/has-attribute-selector/
.each iterates through all the items in the collection: https://api.jquery.com/jQuery.each/
The + at the front of +elem.attr("id") converts the attribute value from a string to an int.

Related

Approaching this.form from innerHTML

I have a problem with dealing with functions which calls this.form.
Here is that part of my source code:
searchResult.innerHTML += "<td><div class=\"searchcard\" draggable=\"true\" ondragstart=\"isexc=0; clickselect("
searchResult.innerHTML += i
searchResult.innerHTML += "); setformparam(this.form); onDragStart(event)\"
Here I tried to perform setformparam(this.form) when I start dragging div box constructed from within innerHTML script, but it doesn't work.
Any other function like isexc=0, clickselect(i) worked well.
Please teach me how to access this.form from within inner JavaScript. Thanks.
That’s a terrible way of creating elements. Use the DOM:
var cell = document.createElement("td");
var searchCard = document.createElement("div");
searchCard.className = "searchcard";
searchCard.draggable = true;
(function(i) {
searchCard.addEventListener("dragstart", function(e) {
isexc = 0;
clickselect(i);
setformparam(someForm);
onDragStart(e);
}, false);
})(i); // I’m just assuming `i` here is a loop variable of some kind
// You should probably use Array.prototype.forEach
cell.appendChild(searchCard);
searchResult.appendChild(cell);
And use event delegation and stop using global variables. There are a ton of things to potentially clean up here, but you should probably try Code Review for that.
I'm not sure if that's what you are asking for, but if you want to get the form element as a DOM object, you can set an id to the element and call it by getElementById.
Or you can get it by document.getElementsByTagName("form")[x] where x is the index of the form you want.
try
$(this).children('form') and not 'this'

Accessing a Dynamically Named array in jQuery/javascript

I wish to name an array according to the table row containing the button that was clicked.
I get the table row thus:
var rowNum = $(this).parent().parent().index();
Now, I wish to name the array and access it.
var arrayName = 'arrTR' + rowNum;
window[arrayName] = new Array();
window[arrayName]["First"] = "Bob";
window[arrayName]["Last"] = "Roberts";
window[arrayName]["email"] = "me#there.com";
//The array should be accessible as arrTR__
alert(arrTR1["Last"]);
The alert does not work, so I am doing something wrong.
How should I refactor the code to allow me to update and access the array?
jsFiddle
What you're doing with the dynamically named variables is essentially creating an array of those variables (one for each rowNum), but giving each of those array elements its own individual named variable.
There is a much better way to do this. Instead of generating a series of dynamically named variables, make a single array or an object. Then add an element or property for each of the dynamically named variables you were going to generate.
Your test code could look like this:
var arrTR = [];
var rowNum = 1;
arrTR[rowNum] = {
First: 'Bob',
Last: 'Roberts',
email: 'me#there.com'
};
alert( arrTR[1].Last );
Alternatively, you can do something with $.data as mentioned in Johan's answer. But if you do use plain JavaScript code, use a single array as described here instead of multiple dynamically named variables.
There are several reasons to do it this way. It's cleaner and easier to understand the code, it may be faster when there are large numbers of entries, and you don't have to pollute the global namespace at all. You can define the var arrTR = []; in any scope that's visible to the other code that uses it.
Arrays and objects are made for keeping track of lists of things, so use them.
There is nothing wrong with your code, and the only place it has error is the alert since it is not defined on the first click button
see this fiddle with a little update
if(rowNum === 1)
alert(arrTR1["Last"]);
else if(rowNum === 2)
alert(arrTR2["Last"]);
fiddle
How about something like this?
$('.getinfo').click(function() {
var result = $('table tr:gt(0)').map(function(k, v){
return {
firstName: $(v).find('.fname').val(),
lastName: $(v).find('.lname').val(),
email: $(v).find('.email').val(),
}
}).get();
//update to show how you use the jQuery cache:
//1. set the value (using the body tag in this example):
$('body').data({ result: result });
//2. fetch it somewhere else:
var res = $('body').data('result');
});
Not sure how you want to handle the first row. I skip in in this case. You can access each row by result[index].
As you might have noticed, this saves all rows for each click. If you want to use the clicked row only, use the this pointer.
http://jsfiddle.net/nwW4h/4/

Is it possible to use a variable to highlight a row in jQuery?

I'm trying to highlight rows in a table using jQuery, but I'm wondering if it's possible to use a variable for the row I want highlighted. This is the code I have now, which is not working.
var rowNumber = 3 //I want to use a loop, but for testing purposes I have it set to 3
$('tr:eq(rowNumber)').addClass('highlight');
Sure, why not. You may pass a variable in :eq() selector:
$("tr:eq(" + rowNumber + ")").addClass("highlight");
or use eq() method instead:
$("tr").eq(rowNumber).addClass("highlight");
$('tr').eq(rowNumber).addClass('highlight');
Should work for you.
Let me first address isolated access (i.e. not taking into consideration optimisation for loops)
Best solution: Use .eq() (fast, nice and short)
You could try something like
$('tr').eq(rowNumber).addClass('highlight');
Explanation: .eq(index) Reduces the set of matched elements to the one at the specified index.
Source: http://api.jquery.com/eq/
Alternative solution: Use the ":eq(index)" selector (unnecessarily slower, more verbose and convoluted)
$("tr:eq("+rowNumber+")").addClass('highlight');
A third solution: (fast, but more verbose than the proposed solution)
$($('tr').get(rowNumber)).addClass('highlight');
How this one works: $('tr').get(rowNumber) gets the (rowNumber+1)th DOM element matching the query selector and then this is wrapped in jQuery goodness using the surrounding $( ).
More info at: http://api.jquery.com/get/
Feel free to experiment with the accompanying jsFiddle:
http://jsfiddle.net/FuLJE/
If you are particularly performance conscious and are indeed are going to iterate through an array you can do this instead:
var trs = $('tr').get(); //get without arguments return the entire array of matched DOM elements
var rowNumber, len = trs.length;
for(rowNumber = 0; rowNumber < len; rowNumber++) {
var $tr = $(trs[rowNumber]);
//various stuff here
$tr.addClass('highlight');
//more stuff here
}
Of course you could also use .each()
$("tr").each(function (rowNumber, tr) {
var $tr = $(tr);
//various stuff here
$tr.addClass('highlight');
//more stuff here
})
Documentation can be found here: http://api.jquery.com/each/
Just to point out the obvious: $("tr").addClass('highlight') would work if adding the highlight class to all tr was all that the OP wanted to do :-)

jQuery: `:eq(i) ` Selection

I'm trying to assign 10 div class hi with different height.
I know I can do it this way.
$(".hi:eq(0)").css("height",n[0]);
$(".hi:eq(1)").css("height",n[1]);
$(".hi:eq(2)").css("height",n[2]);
..........
$(".hi:eq(9)").css("height",n[9]);
However, when I try generating them by using a for loop it doesn't work.
for (i=0;i<10;i++){
$(".hi:eq(i)").css("height",n[i]);
}
Neither does this.
var i=0;
$(".hi:eq(i)").css("height",n[i]);
Something must be wrong with :eq(i).
This issue is that JavaScript doesn't have string interpolation.
But do it like this instead...
$(".hi").slice(0,10)
.css('height', function(i) {
return n[i];
});
This is far more efficient than repeating your DOM selection with a non-standard selector.
.slice(0,10) will give you the first 10 elements
.css() with a function passed as the second argument will assign the return value to the height css property of the current element in the iteration. The index of the current iteration is represented by the i parameter.
i can't be within the string. You probably want this:
for (i=0; i<10; i++){
$(".hi:eq(" + i + ")").css("left", n[i]);
}

dojo foreach function

I am quite new to dojo and I'm stuck with a problem here
I have a zend dojo form where I need to take sum of four elements and set the value to another element. I have assigned a class (score) to those four elements
".score" : {
"found" : function (ele) {
var widgetId = ele.getAttribute('widgetid');
dojo.connect(dijit.byId(widgetId),'onBlur', function(){
var sum = 0;
dojo.query('.score')
.forEach(function(ele){
var widgetId = ele.getAttribute('widgetid');
sum += parseInt(dijit.byId(widgetId).get('value'));
});
//***cannot get the value of sum here
dijit.byId('score_total').set('value', sum);
});
}
}
As commented I am unable to get the sum of those values outside the foreach. Is there any way to get the value out of the loop? Am I doing any thing wrong?
It seems that I had made a mistake in the code and since I am quite new to jscript I was unable to debug. foreach indeed is not a asynchronous and sum was being calculated just that the parseInt(dijit.byId(widgetId).get('value')) was returning not a number NaN hence I was unable to populate the form element, I simply added an if condition and it worked
if(parseInt(dijit.byId(widgetId).get('value'))){
sum = sum + parseInt(dijit.byId(widgetId).get('value'));
}
Sorry for the trouble
One thing to note... dojo.foreach is deprecated ...
http://livedocs.dojotoolkit.org/dojo/forEach
instead ... array.forEach
http://livedocs.dojotoolkit.org/dojo/_base/array#forEach
but i think you might also have a scoping issue as well.. try something like this..
var sum = 0;
var elements = dojo.query('.score');
array.forEach(elements, function(ele) {
var widgetId = ele.getAttribute('widgetid');
sum += parseInt(dijit.byId(widgetId).get('value'));
});
in your case, the parent context has the variable, so it will work as you have used it.
Just a side point that if you want to access the sum variable outside the parent context, you will need to use dojo.hitch or pass the context to dojo.forEach
http://www.ibm.com/developerworks/web/library/wa-aj-dojo/
see the section on "Setting method context"

Categories