How to count the total number of div elements that are contained in another div using javascript?
The getElementsByTagName() is not only a document method, but one that can run on any DOM element.
element.getElementsByTagName is
similar to
document.getElementsByTagName, except
that its search is restricted to those
elements which are descendants of the
specified element
see more at https://developer.mozilla.org/en/DOM/element.getElementsByTagName
So the actual code that does what you ask is
var container_div = document.getElementById('id_of_container_div');
var count = container_div.getElementsByTagName('div').length;
You can use #davidcmoulton's handy Gist:
https://gist.github.com/davidcmoulton/a76949a5f35375cfbc24
I find it quite useful that it doesn't only count DIVs but also lists the count of all element types of your page.
Here is a copy of the Gist for further reference:
(function (window, undefined) {
// Counts all DOM elements by name & logs resulting object to console.
var forEach = Array.prototype.forEach,
counter = {},
incrementElementCount = function (elementName) {
if (counter.hasOwnProperty(elementName)) {
counter[elementName] += 1;
} else {
counter[elementName] = 1;
}
},
processNode = function (node) {
var currentNode = node;
if (currentNode.nodeType === currentNode.ELEMENT_NODE) {
incrementElementCount(currentNode.nodeName);
if (currentNode.hasChildNodes) {
forEach.call(currentNode.childNodes, function (childNode) {
if (childNode.nodeType === currentNode.ELEMENT_NODE) {
processNode(childNode);
}
});
}
}
};
processNode(window.document.firstElementChild);
console.log(counter);
}(this));
There are many way to count divs element using jquery.
But most popular and simple way are:
$(document).ready(function(){
var divCount = $("div").size();
alert(divCount);
});
AND
$(document).ready(function(){
var divCount = $("div").length;
alert(divCount);
});
Its helpful for you
Related
I have a function that is currently using the .getElementBy... DOM calls in JavaScript.
var $ = function (selector) {
var elements = [];
var lastSelector = selector.substring(selector.search(/[^#.]+$/), selector.length);
if(selector.includes('#') !== true || selector.includes('.') !== true) {
elements.push(document.getElementsByTagName(lastSelector));
elements = Array.prototype.slice.call(elements[0]);
}
return elements;
};
There are a number of other if statements in the function using the code:
elements.push(document.getElementsByTagName(lastSelector));
elements = Array.prototype.slice.call(elements[0]);
or
elements.push(document.getElementsByClassName(lastSelector));
elements = Array.prototype.slice.call(elements[0]);
Ideally i'd like to DRY up the repeated:
elements = Array.prototype.slice.call(elements[0]);
but I cannot define it before the if statements because elements has not yet been populated. It therefore tries to run the code on an empty array and errors.
Any suggestions?
Instead of using a home-brew limited function for selecting elements by a selector, you could just use the standard querySelectorAll() available in all browsers including IE8+.
As for converting an array-like object (e. g. a DOM collection) to a real Array (what Array.prototype.slice.call() is used for in your code), I use the following function:
var arrayFrom = function(arrayLike) {
if (Array.from) {
return Array.from(arrayLike);
}
var items;
try {
items = Array.prototype.slice.call(arrayLike, 0);
}
catch(e) {
items = [];
var count = arrayLike.length;
for (var i = 0; i < count; i++) {
items.push(arrayLike[i]);
}
}
return items;
};
or its following simplified version if browsers not supporting passing a non-Array argument to Array.prototype.slice.call() (IE8- if I recall correctly) don’t matter:
var arrayFrom = function(arrayLike) {
return Array.from
? Array.from(arrayLike);
: Array.prototype.slice.call(arrayLike, 0);
};
Certainly consider #marat-tanalin answer. In the case where using querySelectorAll() is not an option, the following worked for me, thanks #master565 for the help:
To start, wrapping the lines:
elements.push(document.getElementsByTagName(lastSelector));
elements = Array.prototype.slice.call(elements[0]);
in a function:
function pushByTag(selector) {
elements.push(document.getElementsByTagName(selector));
elements = Array.prototype.slice.call(elements[0]);
}
Dried things up considerably. Then setting a variable for the if argument helped a lot:
if(selector.includes('#') !== true || selector.includes('.') !== true)
became:
var noClassOrId = selector.includes('#') !== true || selector.includes('.') !== true;
Both these refactors allowed me to single line my if statement in to something I'd argue was fairly readable:
if (noClassOrId) pushByTag(lastSelector);
I've created a little plugin to check if an element is in position : fixed and to get it's height if it is. What I want is to run this function through all elements in my document to find all fixed elements and get their heights, but I dont know how to write it down
$.fn.isFixed = function () {
if ($(this).css('position') === 'fixed'){
var height = ($(this).height());
return height;
}
else {
return false;
};
}
This is my code.
In that case you may have to return an array since there can be more than one element. Also to make sure that the value indexes are maintained I'm inserting undefined to the array if the position is not fixed
$.fn.isFixed = function () {
var array = [];
this.each(function(){
if ($(this).css('position') === 'fixed') {
array.push($(this).height());
}else{
array.push(undefined);
}
})
return array;
}
var allElements = $("*").contents();
Then use .each() function on allElements variable.
Hope this helps
This search only in declared stylesheets.
var selectorsArray = [];
for (i in document.styleSheets) {
for (k in document.styleSheets[i].cssRules) {
if (document.styleSheets[i].cssRules[k].style.position === "fixed") {
selectorsArray.push(document.styleSheets[i].cssRules[k].selectorText);
}
}
}
So the rest of elements you can select with:
$('[style~=fixed]').each(function(i,e){});
I want to loop over an array continuously on click. Extra props if you can work in a delay between class switches :-)
I got this far:
// Define word
var text = "textthing";
// Define canvas
var canvas = 'section';
// Split word into parts
text.split();
// Loop over text
$(canvas).click(function() {
$.each(text, function(key, val) {
$(canvas).removeAttr('class').addClass(val);
});
});
Which is not too far at all :-)
Any tips?
The following will wait until you click the selected element(s) in the var el. In this example var el = $('section') will select all <section>...</section> elements in your document.
Then it will start cycling through the values in cssClassNames, using each, in turn as the css class name on the selected element(s). A delay of delayInMillis will be used between each class change.
var cssClassNames = ['c1', 'c2', 'c3'];
var el = $('section');
var delayInMillis = 1000;
// Loop over text
el.click(function() {
var i = 0;
function f() {
if( i >= cssClassNames.length ) {
i = 0;
}
var currentClass = cssClassNames[i];
i += 1;
el.removeClass().addClass(currentClass);
setTimeout(f, delayInMillis);
}
f();
});
I believe you want a delay of X milliseconds between removing a class and adding a class. I'm not sure that you have to have the lines marked // ? or even that they do the job, but what you do have to have is a way to get the value's into the function. Also, the setTimeout anon function might not actually need the parameters, but it should give you an idea.
$(canvas).click(function() {
$.each(text, function(key, val) {
$(canvas).removeAttr('class')
var $canvas = $(canvas) //?
var class_val = val //?
setTimeout(function ($canvas, class_val) {
$canvas.addClass(class_val);
}, 2000);
});
});
Edit: I'd do this instead
function modify_element($element, class_name){
$element.removeClass('class');
setTimeout(function ($element) {
$element.addClass(class_name);
}, 1000);
//adds the class 1 second after removing it
}
$(canvas).click(function() {
$.each(text, function(key, val) {
setTimeout(modify_element($(canvas), val),2000);
//this will loop over the elements with 2 seconds between elements
});
});
"loop over an array continuously" this sounds like a infinite loop, I don't think you want that. About pausing the loop, this is possible, you can use this
I was doing a challenge of building a tree from all html elements. And I am 90% done, but I got stuck...
How do I change this string into a tree?:
mystring= "red1/(none)-red2/red1-blue1/red2-blue2/red2-blue3/red2-red3/red1-red4/red3-red5/red4-red6/red5-blue4/red6";
After splitting them by "-" we will have:
10 groups of -> (parameter1)/(parameter2)
The first parameter it is the object,
The second parameter is the 'in-what-it-will-be-contained'
I have no idea how to move every 'parameter1' inside 'parameter2'. (note: sometimes the parameter1 will be the parameter2 of a parameter1)
Visual example of what I mean with a parameter is inside another parameter: (this example uses exactly the string above)
Probably we should use arrays?, idk... I am totally lost :sadface:
I think this is a little more concise and straight forward. It uses an object as a dictionary to lookup the parent, rather than a function that has to recursively iterate the tree to find the parent. That recursive function is expensive. An object lookup is quick.
First, for convenience, I'd define an object type:
function TreeNode(name) {
this.Name = name;
this.Children = [];
}
Then I'd add a method to do the work. This parses your tree string:
TreeNode.ParseTree = function (treeString) {
var root = new TreeNode("");
var nodes = {};
var pairs = treeString.split("-");
pairs.forEach(function(pair) {
var parts = pair.split("/");
var parentName = parts[1];
var childName = parts[0];
var node;
if (parentName == "(none)") {
node = root;
root.Name = childName;
}
else {
node = new TreeNode(childName);
nodes[parentName].Children.push(node);
}
nodes[childName] = node;
});
return root;
};
That's it! Now, to get visual representations of your tree, you can add some prototype methods to TreeNode. First, override .toString():
TreeNode.prototype.toString = function(indent) {
indent = indent || "";
var strings = [indent + this.Name];
this.Children.forEach(function(child) {
strings.push(child.toString(indent + " "));
});
return strings.join("\n");
};
Then, add a .Render() method to display the tree within a web page:
TreeNode.prototype.Render = function(container) {
var nodeEl = container.appendChild(document.createElement("div"));
nodeEl.className = "treeNode";
var nameEl = nodeEl.appendChild(document.createElement("div"));
nameEl.className = "treeNodeName";
nameEl.appendChild(document.createTextNode(this.Name));
var childrenEl = nodeEl.appendChild(document.createElement("div"));
childrenEl.className = "treeNodeChildren";
this.Children.forEach(function(child) {
child.Render(childrenEl);
});
return nodeEl;
};
Here it is in action: http://jsfiddle.net/gilly3/wwFBx/
Edit: I didn't notice the jQuery tag in your post, here's a render method that's all jQuery, and produces simpler HTML which you seem to imply is what you want:
TreeNode.prototype.Render = function(container) {
var el = $("<div>").appendTo(container).text(this.Name);
$.each(this.Children, function() {
this.Render(el);
});
return el;
};
This JSFiddle uses jQuery, even replacing Array.forEach with $.each: http://jsfiddle.net/wwFBx/1/
As an alternative, you might consider just serializing your tree as JSON. Eg:
"{\"Name\":\"red1\",\"Children\":[{\"Name\":\"red2\",\"Children\":[{\"Name\":\"blue1\",\"Children\":[]},{\"Name\":\"blue2\",\"Children\":[]},{\"Name\":\"blue3\",\"Children\":[]}]},{\"Name\":\"red3\",\"Children\":[{\"Name\":\"red4\",\"Children\":[{\"Name\":\"red5\",\"Children\":[{\"Name\":\"red6\",\"Children\":[{\"Name\":\"blue4\",\"Children\":[]}]}]}]}]}]}"
or maybe:
"{\"red1\":{\"red2\":{\"blue1\":{},\"blue2\":{},\"blue3\":{}},\"red4\":{\"red5\":{\"red6\":{\"blue4\":{}}}}}}"
Parse the string via JSON.parse().
Disclaimer: I've referenced Array.forEach() and JSON.parse() which are built-in to modern browsers but are not supported by older browsers. To enable these functions in older browsers, see this documentation on Array.forEach() and this shim for JSON.parse().
Here's about how I would do it, using an array of "unplaced" elements and looping through it until they're all placed:
var str = "red1/(none)-red2/red1-blue1/red2-blue2/red2-blue3/red2-red3/red1-red4/red3-red5/red4-red6/red5-blue4/red6";
var unplaced = [];
var tree = null;
var elements = str.split(/[\/\-]/);
function findNodeByName(nodeName, context) {
if(context.name === nodeName) return context;
for(var i = 0; i < context.children.length; i++) {
var subSearch = findNodeByName(nodeName, context.children[i]);
if(subSearch) return subSearch;
}
return null;
}
var element, node, parent, thisElement, i;
for(i = 0; node = elements[i]; i += 2) {
node = elements[i];
parent = elements[i + 1];
thisElement = {name: node, children: []};
if(!tree && parent === '(none)') {
tree = thisElement;
} else if(tree) {
var parentNode = findNodeByName(parent, tree);
if(parentNode) {
parentNode.children.push(thisElement);
} else {
unplaced.push(thisElement);
}
}
}
var oldLength;
while(unplaced.length) {
oldLength = unplaced.length;
for(i = 0; element = unplaced[i]; i++) {
var parentNode = findNodeByName(parent, tree);
if(parentNode) {
parentNode.children.push(element);
unplaced.splice(i, 1);
i--;
}
}
if(oldLength === unplaced.length) {
throw new SyntaxError("The string is not a valid tree.");
}
}
// The result is contained in "tree".
You can see the result at: http://jsfiddle.net/minitech/tJSpN/
One with a function: http://jsfiddle.net/minitech/tJSpN/1/
And one with more error-checking: http://jsfiddle.net/minitech/tJSpN/2/
Actually, I found a simpler/shorter/neater way using the JQuery function AppendTo()
We just need to:
Split the parameters...
Create one div for each (parameter1)
Use a loop to move every (parameter1) inside (parameter2) using the
AWESOME AppendTo() function that JQuery offers
The best thing is that they are actually inside them, so you can easily put a Hide/Show effect to make a cool effect
You may try to create tree nodes of the form :
node = {
str:"red1",
subBranches : new Array()
}
Once you have that, you may add the sub-branches iterating through the array, adding such nodes for each found correct couple, and removing the couples already placed in rootNode.subBranches. Then you recursively do the same for every sub-branche.
I am building a small app which captures mouse clicks. I wrote the prototype in jQuery but, since it is a small app focusing on speed, embedding jQuery to use just one function would be an overkill.
I tried to adapt this example from JavaScriptKit:
document.getElementById("alphanumeric").onkeypress=function(e){
//blah..blah..blah..
}
but it didn't work when I tried this:
document.getElementsByTagName("x").onclick
What am I doing wrong?
Say you have a list of p tags you would like to capture the click for the <p> tag:
var p = document.getElementsByTagName("p");
for (var i = 0; i < p.length; i++) {
p[i].onclick = function() {
alert("p is clicked and the id is " + this.id);
}
}
Check out an example here for more clarity:
http://jsbin.com/onaci/
In your example you are using getElementsByTagName() method, which returns you an array of DOM elements. You could iterate that array and assign the onclick handler to each element, for example:
var clickHandler = function() {
alert('clicked!');
}
var elements = document.getElementsByTagName('div'); // All divs
for (var i = 0; i < elements.length; i++) {
elements[i].onclick = clickHandler;
}
it looks a little bit like you miss more than just the click function of jQuery. You also miss jquery's selector engine, chaining, and automatic iteration across collections of objects. With a bit more effort you can minimally reproduce some of those things as well.
var myClickCapture = function (selector) {
var method, name,iterator;
if(selector.substr(0,1) === "#") {
method = "getElementById";
name = selector.substr(1);
iterator = function(fn) { fn(document[method](name)); };
} else {
method = "getElementsByTagName";
name = selector;
iterator = function(fn) {
var i,c = document[method](name);
for(i=0;i<c.length;i++){
fn(c[i]);
};
};
myClickCapture.click = function (fn){
iterator(function(e){
e.onclick=fn;
})
}
return myClickCapture;
}
I haven't tested the code, but in theory, it gets you something like this:
myClickCapture("x").click(function(e){ alert("element clicked") });
Hopefully this gives you a sense of the sorts of things jquery is doing under the covers.
document.getElementsByTagName("x")
returns an array of elements having the tagname 'x'.
You have to right event for each element in the returned array.