I got to the point with my project where I decided to simplify some of the js functions where I am looking for a parent in a DOM tree, then drill down to the elements many many times in one function. instead I though I will make instances of a function which will keep some data so then I can refer and operate on objects in easy way. I got it working but as I was going along, I decided to extend functionality and add some extra functions like getElementsByClassNameThenTagName.
I loop through the arrays and if add matching elements to the array.
I have noticed (sadly only now) that I am creating an array with elements rather than HTML collection. As a results, I cannot refer to the objects in my findings by typing buttons['reset'].disabled = false;. I can access my reset button by buttons[3].disabled = false; but this would cause a lot of inconvenience.
I am therefore looking for a way to convert my array with object into a HTML collection.
Please see below my current function:
this.getElementsByClassNameThenTagName = function (elementClass, elementTag) {
if (parentNode == null) {
this.init();
}
var results = [];
var regexStr = elementClass;
var regex = new RegExp(regexStr);
var x = moduleNode.getElementsByClassName(elementClass);
// console.log(x);
var y;
for ( var i = 0; i < x.length; i++ ) {
// console.log(i);
y = x[i].getElementsByTagName(elementTag);
// console.log(y);
for (var k=0; k<y.length; k++){
// console.log(y[k]);
results.push(y[k]);
}
// console.log(results);
}
return results;
};
Any suggestions please?
Thanks.
this.getElementsByClassNameThenTagName = function (elementClass, elementTag) {
if (parentNode == null) {
this.init();
}
var results = {}; // thid should be an object (collection)
var x = moduleNode.querySelectorAll("." + elementClass + " " + elementTag);
x.forEach(function(y) {
var name = y.getAttribute("name"); // if you really sure that all the matched elements have names
results[name] = y;
});
return results;
};
Now you can use the results array like this:
var someElement = results['some name'];
NOTE: All the matched elements x should have a name attribute, and all the name attributes of the matched elements should be unique.
Related
I'm sure this is really simple, I just can't work out how to do it.
I want to dynamically make an array from one variable equal to another:
var pageID = document.getElementsByClassName('page_example')[0].id;
Let's say this returned an id of page_1
var page_1 = ['value1','value2','value3'];
var page_2 = ['value4','value5','value6'];
var page_3 = ['value7','value8','value9'];
var page_array = (then have the associated pageID's array here)
So in this example,
page_array would equal ['value1','value2','value3']
Instead of storing the array in separate variables, store them in an object with the ids as the key:
var pages = {
page_1: ['value1','value2','value3'],
page_2: ['value4','value5','value6'],
page_3: ['value7','value8','value9']
}
You can access the arrays as though the object was an assosiative array:
var pageID = "page_1";
var pageArray = pages[pageID];
Depending on what you would like to achieve, you can one of two or three methods.
What I consider the easiest method is an if/else statement:
if (condition) {
page_array = page_1.slice(0);
} else if (other condition) {
page_array = page_2.slice(0);
} else if...
Another method you can use, again depending on what your ultimate goal is, would be a for loop:
for (var i = 0; i < numOfDesiredLoops; i++) {
page_array = page_1.slice(0, i);
}
Or you could use a combination of both:
for (var i = 0; i < numOfDesiredLoops; i++) {
if (condition) {
page_array = page_1.slice(0);
} else if (other condition) {
page_array = page_2.slice(1);
} else if...
}
With more information on why you need this variable to change, I can give you a better answer.
edit: keep in mind the arguments of .slice() can be whatever you want.
I've got this code that is sorting through the various items in after effects and returning all the compositions in the project, then I narrow it down based on the specific composition i'm looking for, in this case one ending with assemble. I get the name and that's great but what I really need is the index number to come along with the name, so that when I search for assemble I get a return of app.project.item(3), its index in the project window. Every time I try to get the number from the array all I seem to get is the total number of items which doesn't help.
Thanks.
function retrieveProjectItems(itemType){
var typeOptions = ["Composition", "Folder", "Footage"];
for(var t = 0; t<3; t++){
if(itemType == typeOptions[t]){
var proj, itemTotal, curItem, itemArray;
itemAry = [];
proj = app.project;
itemTotal = proj.numItems;
for(var i = 1; i <= itemTotal; i++){
curItem = proj.item(i);
//alert(curItem.name);
if(curItem.typeName == itemType){
itemAry[itemAry.length] = curItem.name;
}
}
return itemAry;
}
}
}
retrieveProjectItems("Composition");
//alert(comps); lists all COMPS in the Array
var comps = itemAry;
var compWithAssemble;
for(var i in comps){
if(comps[i].indexOf("assemble") > -1){ ///search for part of the name///////////////////////////////////
compWithAssemble = comps[i];
break;
}
}
// compWithAssemble has the string you are looking for.
alert(compWithAssemble);
//app.project.item(3).selected = true;
compWithAssemble.selected = true; //I'm looking to make this work...
I am assuming you want to programatically find the composition with a layer named "assemble"
This bit of code
if(comps[i].indexOf("assemble") > -1){ ///search for part of the name///////////////////////////////////
compWithAssemble = comps[i];
break;
}
does not give you the results you want because comps[i] is a object of CompItem, not an Array or a collection. You need to first retrieve the Layer Collection for each comp[i]. Then, when you have that LayerCollection, you can find the layer named "assemble" by using the .byName() method. If you don't get a returned layer, you'll receive null, otherwise, you'll receive a Layer Object.
It might look something like:
var comps = itemAry;
var compWithAssemble;
for (var i in comps){
if(comps[i].layers.byName("assemble") != null) {
compWithAssemble = comps[i];
break;
}
}
I need to save all the color values of the elements in the pages of my site and put them in a database. I thought I'd do it this way:
First thing I'm going to pick up the rgb values of each element so
$("*").each(function(e){
createColorArray($(this).css('backgroundColor'));
});
then in the function createColorArray store into an array all the values that are passed
function createColorArray(rgbColor)
{
//Create rgb array
}
and finally remove duplicate items from my array
function removeDoupe(ar) {
var temp = {};
for (var i = 0; i < ar.length; i++)
temp[ar[i]] = true;
var r = [];
for (var k in temp)
r.push(k);
return r;
}
now my question is,
how recommended to create the array? directly inside the $ ("*") or in a dedicated function as I'm thinking? also i need than once removed duplicates in the new array "clean" as well as the rgb value I would have also given the number of times that value was in the original.
Some example code?
As I mentioned in the comments, why not check for duplicates earlier? A simple example:
var colors = [];
$('*').each(function(i, el){
var $element = $(el),
color = $element.css('background-color');
if(!~$.inArray(color, colors))
colors.push(color);
});
console.log(colors);
http://jsfiddle.net/sL9oeywk/
The best way to do this is to do it all while you are working on it. Heres a way you could potentially do it:
var colors = new Array();
var tempColors = {};
$(".colors").each(function(){
var c = $(this).val();
// check if the color exists without looping
if(typeof tempColors[c] == "undefined"){
// if it doesn't, add it to both variables.
tempColors[c] = true;
colors.push(c);
}
});
This will result in two variables: one is an object that you don't have to loop through to find out if you defined it before, one is a colors array that you push to using standard javascript.
You shouldn't make it a dedicated function if you are not reusing it, but you could make it an object like this:
var colors = function(){
var self = this;
self.array = new Array();
// this is a dedicated check function so we don't need separate variables.
// returns true if the color exists, false otherwise
self.check = function(color){
for(var i =0; i < self.array.length; i++){
if(self.array[i] === color) return true;
}
return false;
}
self.add = function(color){
// use the check function, if it returns false, the color does not exist yet.
if(!self.check(color)){
self.array.push(c);
}
}
}
You can then instantiate a colorlist using var colorlist = new colors(); and add colors using colorlist.add("dd0300"). Accessing the array can be done by requesting colorlist.array.
I'm trying to break up a string like this one:
fname=bill&mname=&lname=jones&addr1=This%20House&...
I want to end up with an array indexed like this
myarray[0][0] = fname
myarray[0][1] = bill
myarray[1][0] = mname
myarray[1][1] =
myarray[2][0] = lname
myarray[2][1] = jones
myarray[3][0] = addr
myarray[3][1] = This House
The url is quite a bit longer than the example. This is what I've tried:
var
fArray = [],
nv = [],
myarray = [];
fArray = fields.split('&');
// split it into fArray[i]['name']="value"
for (i=0; i < fArray.length; i++) {
nv = fArray[i].split('=');
myarray.push(nv[0],nv[1]);
nv.length = 0;
}
The final product is intended to be in 'myarray' and it is, except that I'm getting a one dimensional array instead of a 2 dimensional one.
The next process is intended to search for (for example) 'lname' and returning the index of it, so that if it returned '3' I can then access the actual last name with myarray[3][1].
Does this make sense or am I over complicating things?
Your line myarray.push(nv[0],nv[1]); pushes two elements to the array myarray, not a single cell with two elements as you expect (ref: array.push). What you want is myarray.push( [nv[0],nv[1]] ) (note the brackets), or myarray.push(nv.slice(0, 2)) (ref: array.slice).
To simplify your code, may I suggest using Array.map:
var q = "foo=bar&baz=quux&lorem=ipsum";
// PS. If you're parsing from a-tag nodes, they have a property
// node.search which contains the query string, but note that
// it has a leading ? so you want node.search.substr(1)
var vars = q.split("&").map(function (kv) {
return kv.split("=", 2);
});
For searching, I would suggest using array.filter:
var srchkey = "foo";
var matches = vars.filter(function (v) { return v[0] === srchkey; });
NB. array.filter will always return an array. If you always want just a single value, you could use array.some or a bespoke searching algorithm.
for (var i = 0; i < fArray.length; i++) {
nv = fArray[i].split('=');
myarray.push([nv[0],nv[1]]);
}
nv.length = 0; is not required, since you're setting nv in each iteration of the for loop.
Also, use var i in the for-loop, otherwise, you're using / assigning a global variable i, that's asking for interference.
In prepping the objects for a game I'm making in javscript, I'm reading in a JSON object, deckData, and appending each as a child of this.discard. I'm then scheduling a job that checks to see if this.deck is empty. If it is, then the function should shuffle the array of cards listed as children of this.discard and then assign them as children of this.deck.
The whole process seems to work fairly smoothly except for the key line where I try to assign the newly shuffled array over:
this.deck.children_ = this.shuffle(this.discard.children_);
I'm looking for a solution that will succesfully append all elements that were children of this.discard as children of this.deck. And I realize I'm not yet emptying the array from this.discard yet either, but one step at a time. Full code snippet as follows:
sideboard = function(game) {
this.discard = new lime.Layer();
this.appendChild(this.discard);
for (var key in deckData) {
var cardData = deckData[key];
this.addCard(cardData);
};
this.mythosDeck = new lime.Layer();
this.appendChild(this.mythosDeck);
lime.scheduleManager.schedule(this.deckShuffler, this);
};
sideboard.prototype.deckShuffler = function() {
if (this.deck.children_.length < 1) {
this.deck.children_ = this.shuffle(this.discard.children_);
}
};
sideboard.prototype.shuffle = function(array) {
var tmp, current, top = array.length;
if(top) while(--top) {
current = Math.floor(Math.random() * (top + 1));
tmp = array[current];
array[current] = array[top];
array[top] = tmp;
}
return array;
};
Don't you just want to concatenate the two arrays and then reassign ? For example:
this.deck.children_ = this.deck.children_.concat(this.shuffle(this.discard.children_));