remove all images of a cloned div - javascript

I want to remove images from a cloned div.
I tried this:
var divToPrint = document.getElementById(id);
var clonedDiv = jQuery.extend(true, {}, divToPrint)
var images = [].slice.call(clonedDiv.getElementsByTagName('img'), 0);
var l = images.length;
for (var i = 0; i < l; i++) {
images[i].parentNode.removeChild(images[i]);
}
This line is wrong, I don't know how to get all images of the cloned div:
var images = [].slice.call(clonedDiv.getElementsByTagName('img'), 0);
I get this error:
'getElementsByTagName' called on an object that does not implement interface Element.

This is not how you clone an element:
var clonedDiv = jQuery.extend(true, {}, divToPrint)
This is how you clone an element with the DOM (cloneNode):
var clonedDiv = divToPrint.cloneNode(true);
Then to find the img elements within the clone (with the DOM):
var images = clonedDiv.getElementsByTagName("img");
To remove them (with the DOM's removeChild):
while (images.length) {
images[0].parentNode.removeChild(images[0]);
}
The NodeList returned by getElementsByTagName is live, so the image will disappear from the list, putting a new one at index 0, so that removes images one by one until they're all removed. If you might have a polyfilled getElementsByTagName (but that's unlikely) that doesn't do that, just loop in reverse order instead:
for (var i = images.length - 1; i >= 0; --i) {
images[i].parentNode.removeChild(images[i]);
}
Or all of that with jQuery (clone, remove):
var clonedDiv = jQuery(divToPrint).clone();
clonedDiv.find("img").remove();

Related

JQuery not replacing html

here is the deal, i have the following jquery code that should add the array values to specific #id, buf it does not replace the code, only add more, and i need a little help to make it replace the html on othe link click.
Code:
function changeClass(curClass){
switch(curClass){
case "Schoolgirl":
case "Fighter":
var charSkillsNames = ["text1","text2","text4","text5"];
//loop show array values
listSkillsNames(charSkillsNames);
break;
}
}
function listSkillsNames(arr){
var length = arr.length,
element = null;
$("#skills").html(function(){
for (var i = 0; i < length; i++) {
element = arr[i];
$(this).append("<li>"+element+"</li>");
}
});
}
this works well but i need it to replace the html inside the "#skills" id when i click on the link that makes it work
PS: problem is really here
The issue is that you don't empty the HTML of #skills element. Use $("#skills").html("") to empty it.
function listSkillsNames(arr){
var length = arr.length,
element = null;
var $skills = $("#skills");
$skills.html(""); // empty the HTML
for (var i = 0; i < length; i++) {
element = arr[i];
$skills.append("<li>"+element+"</li>"); // append new items
}
}
The problem is because you are keep appending new items to the element always without removing the existing items.
Just empty the skill element, also there is no need to use the .html(function(){}) here
function listSkillsNames(arr) {
var length = arr.length,
element = null;
var $skill = $("#skills").empty();
for (var i = 0; i < length; i++) {
element = arr[i];
$skill.append("<li>" + element + "</li>");
}
}

How to characterize z-indexing for the DOM? (2)

I've been a bit care-less with choosing z-indexes in my CSS.
I'd like to traverse the DOM and report all the z-indexes with their respective ID's.
For example:
id z-index
header 10
main 0
menu 20
The end result would be an object whose keys are the element id and the value is the z-index. One might call it z_obj
// pseudo code
var z_obj = {el_id: el_zindex};
Getting the z-index for each element ( el ) should be easy using something like filter and the code below:
// attr is attribute
data = _.filter(el.attributes, function (attr) {
return (/^z-index/).test(atttr.name);
});
But how would I traverse the DOM to get all z-indexes and store that in an object?
I'd like to do this w/ out libraries, and using the code above if possible.
This would be a good debug tool in general.
You can get all elements with getElementsByTagName("*"), iterate over the collection with a for loop, and use window.getComputedStyle(Node). From there, you can retrieve the z-index. Here's an example:
var zObj, allEls, i, j, cur, style, zIndex;
zObj = {};
allEls = document.body.getElementsByTagName("*");
for (i = 0, j = allEls.length; i < j; i++) {
cur = allEls[i];
style = getComputedStyle(cur);
zIndex = style.getPropertyValue("z-index");
zObj[cur.id] = zIndex;
}
DEMO: http://jsfiddle.net/mj3cR/1/
Where zObj is an Object, keys represented by the id attributes, and values represented by the z-index style.
Note that getComputedStyle is not supported in IE < 9, but of course there are many polyfills :)
reportZ = function () {
var z_arr = {},
all_el = document.body.getElementsByTagName("*"),
i,
len,
cur,
style,
z_index;
for (i = 0, len = all_el.length; i < len; i++) {
cur = all_el[i];
style = win.getComputedStyle(cur);
z_index = style.getPropertyValue("z-index");
if (z_index !== "auto") {
z_arr[i] = [cur.id, cur.tagName, cur.className, z_index];
}
}
return z_arr;
};

Access childnodes' children in javascript

How do i access child nodes of a child node in javascript?
I need to target the img inside of each li and get its width and height.
I want to do this without using jquery. Just pure javascript.
<ul id="imagesUL">
<li>
<h3>title</h3>
<img src="someURL" />
</li>
</ul>
var lis = document.getElementById("imagesUL").childNodes;
The ideal way to do this is with the querySelectorAll function, if you can guarantee that it will be available (if you are designing a site for mobile browsers, for instance).
var imgs = document.querySelectorAll('#imagesUL li img');
If you can't guarantee that, however, you'll have to do the loop yourself:
var = lis = document.getElementById("imagesUL").childNodes,
imgs = [],
i, j;
for (i = 0; i < lis.length; i++) {
for (j = 0; j < lis[i].childNodes.length; j++) {
if (lis[i].childNodes[j].nodeName.toLowerCase() === 'img') {
imgs.push(lis[i].childNodes[j]);
}
}
}
The above snippet of code is an excellent argument for using a library like jQuery to preserve your sanity.
This works for me:
var children = document.getElementById('imagesUL').children;
var grandChildren = [];
for (var i = 0; i < children.length; i++)
{
var child = children[i];
for (var c = 0; c < child.children.length; c++)
grandChildren.push(child.children[c]);
}
grandChildren contains all childrens' children.
Libraries like jQuery and UnderscoreJS make this easier to write in a more declarative way.
You can provide a second parameter to the $() function to specify a scope in which to search for the images:
var lis = $('#imagesUL').children();
var images = $('img', lis)
images.each(function() {
var width = $(this).attr('width');
// ...
});

How would I generate a list of distinct HTML tags in a page using JavaScript (must work in IE6)

The end result I'm after is a JavaScript array containing a list of tag names that are used in the HTML document eg:
div, span, section, h1, h2, p, etc...
I want the list to be distinct and I'm not interested in tags within the <head> of the document (but they can be there if it's a performance hog to exclude them).
This has to work in IE 6, 7, & 8 and I don't want to use jquery.
What would be the most efficient way of doing this?
What you're looking for is document.all.tagName
At the top of my head, a for loop like this should do it (providing that you're gonna filter the tags you don't want on that list)
for(i = 0; i < document.all.length; i++)
{
console.log(document.all[i].tagName);
}
Here is a cross-browser solution:
var tags = {}; // maintains object of tags on the page and their count
var recurse = function(el) {
// if element node
if(el.nodeType == 1) {
if(!tags[el.tagName])
tags[el.tagName] = 0;
tags[el.tagName]++;
}
// recurse through the children
for(var i = 0, children = el.childNodes, len = children.length; i < len; i++) {
recurse(children[i]);
}
}
recurse(document);
// if you want just what's in the body(included)
var bodies = document.getElementsByTagName("body");
for(var i = 0; i < bodies.length; i++)
recurse(bodies[i]);
To get a unique list of tagnames in a document as an array that works in all browsers back to IE 6 and equivalent:
function listTagNames() {
var el, els = document.body.getElementsByTagName('*');
var tagCache = {};
var tagname, tagnames = [];
for (var i=0, iLen=els.length; i<iLen; i++) {
tagname = els[i].tagName.toLowerCase();
if ( !(tagname in tagCache) ) {
tagCache[tagname] = tagname;
tagnames.push(tagname);
}
}
return tagnames;
}
If you think there might be an inherited object property that is the same as a tag name, use a propertyIsEnumerable test:
if (!tagCache.propertyIsEnumerable(tagname)) {
so it will work even in Safari < 2.
Get all tagnames in the document, unique, crossbrowser, plain js:
var els = document.getElementsByTagName('*'), tags = [], tmp = {}
for (var i=0;i<els.length;i+=1){
if (!(els[i].tagName in tmp)){
tags.push(els[i].tagName);
tmp[els[i].tagName] = 1;
}
}
use
if (!(els[i].tagName in tmp)
&& !/head/i.test(els[i].parentNode.tagName)
&& !/html|head/i.test(els[i].tagName))
to exclude the <head>

appendChild to array only appends to last element

As you can see I am still a novice in javascript
Why is it so that you can append a Textnode only once? When you add it again somewhere else the first one disappears
I do not need a solution to a problem I was just curious what is causing this behavior.
Example where the textnode is only added to the last element of an array:
function hideAdd(){
var hide = document.createTextNode('Afbeelding verbergen');
var afb = collectionToArray(document.getElementsByTagName('img'));
afb.pop();
var divs = [];
for (i=0; i < afb.length; i++){
divs.push(afb[i].parentNode);
}
console.log(divs);
for ( i = 0; i < divs.length;i++){
divs[i].appendChild(hide);
}
}
This is where you use an unique textnode so it works:
function hideAdd(){
var hide = []
var afb = collectionToArray(document.getElementsByTagName('img'));
afb.pop();
var divs = [];
for (i=0; i < afb.length; i++){
divs.push(afb[i].parentNode);
hide[i] = document.createTextNode('Afbeelding verbergen');
}
console.log(divs);
for ( i = 0; i < divs.length;i++){
divs[i].appendChild(hide[i]);
}
}
Short answer is the DOM is a tree, not a network. Each node can have only one parent. If you could add a node in more than one location, it would have more than one parent.

Categories