I want to backup an html table to afterwards filter it using jquery:
$('.row').closest('td').not(':contains(' + v + ')').parent('tr').remove();
Since I do remove() I have to back up the rows before:
var allTable = $('#mytable').html();
And then, when filter is performed I turn back to previous table data:
$('#mytable').html($(allTable));
But this does not work. If I do:
alert($(allTable).filter('tr').length);
next to the first assignment, zero rows are returned.
Please, can you assist me?
filter() is used to find elements within an array of elements. This isn't what you need. You're looking to find() the child elements within another. Also, storing the HTML only to turn it back in to a jQuery object is a little redundant - you may as well just store the jQuery object itself. Try this:
var $table = $('#mytable');
$table.remove(); // use your existing logic here
alert($table.find('tr').length);
$table.appendTo('body'); // add the table back in to the DOM when conditions are met
Example fiddle
I ran into a similar issue when using a highlight function. I solved it by cloning the table into a hidden div and restoring it from there, instead of from a variable. see jquery highlight() breaking in dynamic table
Did you solve this problem?
I suggest a workaround.
Instead of using your cloned table, make a (temporary) copy of it and use it for alert.
var alertTable = allTable;
alert($(alertTable).filter('tr').length);
Related
I have a page which is generated and structured as a tree - nested DIVs, etc.. While the user views the page it is possible that some DIVs are updated on the server side and the changes are pushed to the client as JSON data, from which a DIV can be generated.
My problem is that even though I have the old DIV
var oldDiv = $('#foo');
and I have a new DIV generated by
var newDiv = generateDiv(jsonData);
I need to update the old one (both attributes and it's content) without deleting it. I was going to use the jQuery method .replaceWith() as such
oldDiv.replaceWith(newDiv);
but according to the documentation it is implemented as remove&create.
The .replaceWith() method removes content from the DOM and inserts new content in its place with a single call.
How can I update the old DIV without removing it? Is there some nice way to do this, or do I need to do it attribute by attribute?
As you've suggested, you may need to replace the attribute values individually. However, if it reads better, you can actually pass an object to the attr method, and it will update the values you supply.
oldDiv.attr({
attr1: newDiv.attr1,
attr2: newDiv.attr2,
attr3: newDiv.attr3
});
If you wanted to loop through the attributes to build the object, you could do that like this.
var newAttributes = {};
$.each(newDiv[0].attributes, function(index, attribute){
newAttributes[attribute.name] = attribute.value;
});
oldDiv.attr(newAttributes);
It cannot be done since a div element may contain many elements. Why dont u just append the new contents into it.
You can use jquery's append() method.
$(oldDiv).append("#new_div_id");
It will be appended as a child.
If at all you want to update any <p> element, you can use the html() function to get the contents of a tag and then
old_para_contents=("p").html();
$("p").html(old_para_contents+"New contents");
I've come up with one solution so far, but if anyone comes up with a better one, I will gladly assign it as the correct one. I need to make this as clean as possible.
var oldDiv = $('#my-old-div');
var newDiv = generateDiv(data);
oldDiv.attr("id", newDiv.attr("id"));
oldDiv.attr("class", newDiv.attr("class"));
//...
oldDiv.html(newDiv.html());
I have a rather big table where I dynamically remove some rows. It works, but it is very slow. Right now it takes approx. 1.5 seconds to remove 50 rows on IE8 and Firefox (almost no difference between the browsers).
I know that DOM manipulation is slow in general, but there must be a faster way to do this.
Right now, I'm using this syntax:
$("#myTable tr").slice(250, 300).remove();
The offsets in the slice() method may vary. I use slice() since this was recommended in jQuerys help and other methods to perform the same thing - like find() or eq() - where not faster. I read about doing an empty() before the removal, but that was even slower.
Consider using the actual javascript, in case jQuery is triggering render refreshes: http://jsfiddle.net/MbXX5/
var removeRows = function(ofTable,from,to) {
for(var row=to; row>=from; --row) {
ofTable.deleteRow(row);
}
};
As you can see in the jsfiddle, this is instant. Note that I'm traversing the array in reverse, so that the row numbers remain correct. There is a chance this improves the performance, depending on the DOM code and the JIT strategies the browser uses.
[Edit: new jsfiddle with colour-coded cells to make it really obvious which rows have gone]
The problem is that for every row that you .remove(), the table is redrawn by the browser. To make it faster, remove the table from the DOM, take out the lines and put the table back at its place.
$table = $("#myTable").clone(true,true);//First true to keep events, second true to deepcopy childs too. Remove it if you do not need it to make it faster.
$table.find("tr").slice(250,300);remove();
$("#myTable").replaceWith($table);
You can use filter but I don't think it will be faster
$("#myTable tr").filter(function(index){
return index > 250 && index < 300;
).remove();
The problem is the browser tries to update the screen view of the DOM on each row removal.
You can do it by one of
removing the table, from the document, removing all rows and after
that inserting it back
cloning the table, removing elements on the clone, replacing the table with the clone
or if the amount of rows remaining is less than the ones remove, you could create a new table, insert all the rows in that and replace the existing table with the new one
The main idea is for the table to not be attached to the DOM when you do the removals, this way it will only update the view once all the rows are removed.
Is it possible you add an ID to each row? And then select the rows directly by ID and removing the rows? Like so:
var el = document.GetElementById("RowID_1");
document.removeChild(el);
jQuery is on top of Javascript. I guess using javascript directly is faster.
edit:
Ofcourse you can create a loop like this:
for(i=250;i<=300;i++)
{
var el = document.GetElementById("RowID_" + i);
document.removeChild(el);
}
edit 2:
Hide the table while editing so the browser does not update after each removal ? ;)
Try this . i hope it will help you
$("#myTable tr").slice(250, 300).html('');
This is the same question as this:
Referring to a div inside a div with the same ID as another inside another
except for one thing.
The reason there are two elements with the same ID is because I'm adding rows to a table, and I'm doing that by making a hidden div with the contents of the row as a template. I make a new div, copy the innerhtml of the template to my new div, and then I just want to edit bits of it, but all the bits have the same ID as the template.
I could dynamically create the row element by element but it's a VERY complex row, and there's only a few things that need to be changed, so it's a lot easier to just copy from a template and change the few things I need to.
So how do I refer to the elements in my copy, rather than the template?
I don't want to mess up the template itself, or I'll never be able to get at the bits for a second use.
Or is there another simpler way to solve the problem?
It will probably just be easiest when manipulating the innerHtml to do a replace on the IDs for that row. Maybe something like...
var copiedRow = templateRow.innerHTML.replace(/id=/g,"$1copy")
This will make the copied divs be prefixed with "copy". You can develop this further for the case that you have multiple copies by keeping a counter and adding that count variable to the replace() call.
When you want to make a template and use it multiple times its best to make it of DOM, in a documentFragment for example.
That way it doesn't respond to document.getElementById() calls in the "live" DOM.
I made an example here: http://jsfiddle.net/PM5544/MXHRr/
id's should be unique on the page.
PM5544...
In reality, there's no use to change the ID to something unique, even though your document may not be valid.
Browsers' selector engines treat IDs pretty much the same as class names. Thus, you may use
document.querySelector('#myCopy #idToLookFor');
to get the copy.
IDs on a page are supposed to be unique, even when you clone them from a template.
If you dynamically create content on your page, then you must change the id of your newly cloned elements to something else. If you want to access all cloned elements, but not the template, you can add a class to them, so you can refer to all elements with that class:
var clonedElement = template.cloneNode(yes); // make a deep copy
clonedElement.setAttribute("id", "somethingElse"); // change the id
clonedElement.setAttribute("class",
clonedElement.getAttribute("class") + " cloned"
);
To access all cloned elements by classname, you can use the getElementsByClassName method (available in newer browsers) or look at this answer for a more in-depth solution: How to getElementByClass instead of GetElementById with Javascript?
Alternatively, if you have jQuery available, you can do this is far less lines of code:
$("#template").clone().attr("id","somethingElse")
.addClass("cloned").appendTo("#someDiv");
The class lookup is even simpler:
$(".cloned").doSomethingWithTheseElements();
Try to avoid using IDs in the child elements of the cloned structure, as all ids of the cloned element should be changed before adding the clone to the page. Instead, you can refer to the parent element using the new id and traverse the rest of the structure using classnames. Class names do not need to be unique, so you can just leave them as they are.
If you really must use ID's (or unique "name" attributes in form fields), I can strongly suggest using a framework like jQuery or Prototype to handle the DOM traversal; otherwise, it is quite a burden to resolve all the cross-browser issues. Here is an example of some changes deeper in the structure, using jQuery:
$("#template").clone().attr("id","somethingElse")
.addClass("cloned") // add a cloned class to the top element
.find("#foo").attr("id","bar").end() // find and modify a child element
.appendTo("#someDiv"); // finally, add the node to the page
Check out my ugly but functional cheese. I wrote a function that works like getelementbyid, but you give it a start node instead of the document. Works like a charm. It may be inefficient but I have great faith in the microprocessors running today's browsers' javascript engines.
function getelement(node, findid)
{
if (node)
if (node.id)
if (node.id == findid)
return node;
node = node.firstChild;
while(node)
{
var r = getelement(node, findid);
if (r != null)
return r;
node = node.nextSibling;
}
return null;
}
When you copy the row, don't you end up having a reference to it? At that point can't you change the ID?
Is there a way to make calls within an HTML variable that is not in the DOM? For example, my code copies an existing row and then places it in the DOM. The problem is, I need to change some things within it. Code like:
newHTML = $$('.someRow')[0].innerHTML;
//Need to change form fieldName1 to fieldName2 in the newHTML variable, etc
$(this).up(1).insert({
before: newHTML
});
Right now I am changing things after, but it makes it difficult when there is a radio button that retains the same fieldname and changes the checked value of the original row.
Thanks.
You should be able to do this if you clone the node that you want to insert. e.g.
var newNode = $$('.someRow')[0].clone(true);
The cloned node is not inserted into the DOM until you insert it so you can manipulate it in whatever way you choose before doing so, its just a prototype Element.
I created a 3x3 table. Each column is generated using a function. The function basically returns a "td" element. Else where in the code I trigger an event based on some conditions. Whenever the event is triggered, I want to update one particular cell of the table. None of the cells have ids attached to them.
My question is how can I link up the "td" that I want to be updated with the event?
I have no specific context that refers to this td alone.
If you're not using any other tools like jQuery my approach might be to find the table which I assume you can do with Javascript. Then for each td element in the table inject a class to them that is unique. You could just give them numbers or something easy. Assuming the numbering never changes you now have an easy way to lookup the td elements later in your code without having to keep a reference to the td element you want.
Instead of adding a class you could just get all the td elements in the table and if you knew the 4th element was always the cell you wanted then you could just keep a reference to that td element.
Without using jQuery or anything, you can use DOM selectors such as .childNodes (and iterating till you're satisfied), .lastChild, .firstChild, .parentNode etc.
This link gets you through some examples.
Although, if you are using this a lot, create ID dynamically in JS. Like iterating once through all your table (with .childNodes), assigning an ID (like row1-col2) to every td. It will simplify the rest of your code.
Here is a jsFiddle to show you how with jQuery:
http://jsfiddle.net/HzBFE/