making getelementbyid plural - javascript

In the context of the code below (or anywhere), is it possible for a getelementbyid function to work plurally? Or do I need a different function, or possibly Jquery?
<script type="text/javascript">
window.onload = function()
{
var test = document.getElementById('test');
if (test)
{
test.className = 'unactive';
test.firstChild.onclick = function()
{
if(this.parentNode.className == 'unactive') {
this.parentNode.className = 'active';
}
else
{
this.parentNode.className = 'unactive';
}
}
}
};
</script>

You can use this;
document.getAllById = function(id){
if(document.all)
return document.all[id];
var elements = [],
all = document.getElementsByTagName('*');
for(var i=0;i<all.length;i++)
if(all[i].getAttribute('id')===id)
elements.push(all);
return elements;
}
Anyway, as #Pointy said, the id attribute is supposed to be unique, while class is used to define one or more elements that has some common properties

I assume you want to act on multiple elements using a list of IDs. (If I am wrong, and you actually want to select multiple elements with the same ID, you have done a Bad Thing, since IDs should be unique. In that case, you should use classes instead.)
In jQuery, you can accomplish this with a comma-separated list of id selectors (like $("#foo, #bar, #baz")) and implement your function like:
$("#foo, #bar, #baz").addClass("unactive")
.children(":first-child").click(function() {
var $this = $(this);
var $parent = $this.parent();
$parent.toggleClass("active unactive");
});
Without jQuery, this small function takes a list of IDs and results an array of nodes:
document.getElementsByIdList() {
var results = [];
for(var i=0; i<arguments.length; ++i) {
results.push(document.getElementById(arguments[i]));
}
return results;
}
Use it with you current code with:
var myNodeArray = document.getElementsByIdList("foo", "bar", "baz");
for(var i=0; i<myNodeArray.length; ++i) {
var test = myNodeArray[i];
if(test) {
// your code goes in here...
}
}

Related

How to use obj.init in my document.getElements?

I am new to this framework and I am just converting my javascript/jquery to ajax.
I have this code:
var Obj = {
Init:function(config){
this.config = config;
this.BindEvents();
},
BindEvents:function(){
$this = Obj.config;
Obj.ReturnArray();
},
ReturnArray:function(){
$this = Obj.config;
for(x = 0; x < itemNames.length; x++){
var obj = {itemName:itemNames[x],itemPrice:itemPrices[x]};
console.log(obj);
prods.push(obj);
}
for(var ctr = 0; ctr < prods.length; ctr++){
var rows = parseInt(document.getElementById("modalTable").getElementsByTagName("tbody")[0].rows.length);
var table = document.getElementById("modalTable").getElementsByTagName("tbody")[0];
}
}
}
Obj.Init({
modalTable : $("#modalTable"),
mainTable : $("#mainTable"),
btnAddToTable : $("btnAddToTable"),
mainCellQuantity : $(".mainCellQuantity"),
mainTBody : $("#mainTBody")
});
But I want to you use the object being initialized in Obj.Init({});
var rows = parseInt(document.getElementById("modalTable").getElementsByTagName("tbody")[0].rows.length);
var table = document.getElementById("modalTable").getElementsByTagName("tbody")[0];
just to be like this
var rows = parseInt(modalTable.mainTbody.rows.length);
To sum it all, I want all javascript's document be objects. Is there any way to do that?
I am by phone so cannot try it.
In my understanding you want that all the dom elements inherit from your Obj.
Considering that all the document objects inherit from Element, what you could try is to extend the Element prototype with your prototype.
It could be something like:
Element.prototype = Object.create(Obj.prototype);
So, someone suggested to use jquery.each() so I tried, and luckily, I solved my problem. I'll share my answer so anyone might see this helpful
$.each(prods_(this_is_the_array)_, function(index){
var row = modalTBody_(the_tbody)_.insertRow(index);
});

how to turn this to into a tree?

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.

Jquery to Prototype

How do I convert the jquery code below to prototype?
<script>
$(document).ready (function() {
$("#valor").keyup(function(){
var resultVal = 0.0;
var objRegExp = '\s+';
$("#valor").each ( function() {
resultVal += parseFloat ( $j(this).val().replace(/\s/g,'').replace(',','.'));
});
$("#total").val(resultVal);
});
});
</script>
Thanks.
I don't know, but pure JavaScript is always nice:
function doLoad() {
var valor = document.getElementById("valor");
valor.onkeyup = function() {
var resultVal = 0.0;
var objRegExp = '\s+';
for(var i = 0; i < valor.childNodes.length; i++) {
var n = valor.childNodes[i];
if(n.nodeType === 1) resultVal += parseFloat(n.value.replace(/\s/g, '').replace(',', '.'));
}
document.getElementById("total").value = resultVal.toString();
};
}
if(window.addEventListener)
window.addEventListener("load", doLoad, false);
else
window.attachEvent("onload", doLoad);
Here's a working example with the migration:
http://jsfiddle.net/MaQA5/
Code:
eventObserver = function() {
var resultVal = 0.0;
var objRegExp = '\s+';
$$(".valor").each(function(el) {
resultVal += parseFloat($(el).getValue().replace(/\s/g, '').replace(',', '.'));
});
$("total").setValue(resultVal);
};
$$('.valor').each(function(el) {
el.observe('keyup', eventObserver);
});
Some comments:
From your code, I supposed you have several inputs with the same id (valor). If this is the case, that's wrong, as ids must be unique in the whole DOM.
That's why I changed that for a class named valor.
Prototype has a special $$ function to get elements by css-selector. But uses $ for id search or to turn a DOM element into a Prototype-empowered element.
When calling to each method, instead of using this as every element in the original collection (like you do in jQuery), you must use the first argument in the function: el.
Instead of calling the keyup jQuery method, you must use observe('keyup', ....
In my opinion, jQuery is more elegant, or at least, the Prototype that I know is not that fancy :)

how to count total number of divs inside another div using javascript

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

Pure JavaScript equivalent of jQuery click()?

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.

Categories

Resources