...

View Full Version : Simplifying a large number of similar object definitions



retired1
03-24-2009, 02:26 PM
I am looking for a way to simplify a large series of “object definitions” in the form:
var Img0 ={init:function(){Img0.div = document.getElementById("img0"); Img1.init();}};
var Img1 ={init:function(){Img1.div = document.getElementById("img1"); Img2.init();}};
var Img2 ={init:function(){Img2.div = document.getElementById("img2"); Img3.init();}};
.
.
.
The program I have developed (for animated greeting cards) works fine but for a large number of images there are an equal number of these object definitions. I am aware of such techniques as using “+i+” in place of the numbers 0, 1, 2, ... and assigning an increasing value to i in a loop. However, I do not see a way to use such a loop here. Might there be any suggestions for doing this? I am in no hurry. Thanks.

Kor
03-24-2009, 02:41 PM
If your Img0, Img1... should be global variables, the loop could be something like:


var i=0, d;
while(d=document.getElementById('img'+(i++)){
window['Img'+(i-1)]={init:function(){window['Img'+(i-1)].div = d; window['Img'+i].init();}};
}

itsallkizza
03-24-2009, 03:17 PM
If you're looking for a fun way to incorporate semantic classifying of objects, then it would be more appropriate to control your list of img objects from a higher level (ie don't place a reference to the next img object inside each img object, instead, use a higher level array and functions to control your image collection).

This is completely optional, there are hundreds of different ways to do things in JS, but if your project gets large it usually pays off to code semantically and object-orientedly (yes, that's a word ;)).

I don't know what you intend to do with these images (if you tell me what your ultimate objective is I can help you write better code) but this should give you a start:


<script type="text/javascript">
// <![CDATA[

// ImageCollection JS Class
function ImageCollection()
{
this.images = new Array();
this.current_index = 0;
this.addImages = function(ids)
{
if (typeof(id) == "string") id = [ids];
for (var i=0;i<ids.length;i++) this.images.push(new MyImage(ids[i]));
}
this.next = function()
{
return (this.images[++this.current_index]);
}
}

// MyImage JS Class
function MyImage(id)
{
this.ref_id = id;
this.div = document.getElementById("id");
}

window.onload = function()
{
my_image_collection = new ImageCollection();
my_image_collection.addImages(["img0","img1","img2","img3"]);
alert(my_image_collection.next());
}

// ]]>
</script>

freedom_razor
03-24-2009, 03:22 PM
I'm not sure what is the purpose of that init function. If you just want to add a reference to a DIV as a property of each of those Img objects, try this:

<body>
<div id="Img0"></div>
<div id="Img1"></div>
<div id="Img2"></div>
<script>
function Img(divID){ //constructor
this.div=document.getElementById(divID);
}
for (i=0;i<3;i++){ // loop creating new instances
eval('var Img'+i+'=new Img("Img'+i+'");');
}
//examples, property .div now stores a reference to another object [DIV element in that case]
Img0.div.innerHTML="Div1";
Img1.div.style.border="1px solid black";
Img2.div.innerHTML=Img2.div.offsetWidth;
</script>
</body>

itsallkizza
03-26-2009, 08:11 PM
In response to your PM...
You can do something like this (changes in red):


<script type="text/javascript">
// <![CDATA[
var img_id_pre = "img";
var total_num_imgs = 100;

// ImageCollection JS Class
function ImageCollection()
{
this.images = new Array();
this.current_index = 0;
this.addImages = function(ids)
{
if (typeof(id) == "string") id = [ids];
for (var i=0;i<ids.length;i++) this.images.push(new MyImage(ids[i]));
}
this.next = function()
{
return (this.images[++this.current_index]);
}
}

// MyImage JS Class
function MyImage(id)
{
this.ref_id = id;
this.div = document.getElementById("id");
}

window.onload = function()
{
my_image_collection = new ImageCollection();

var images_to_add = new Array();
for (var i=0;i<total_num_imgs;i++) images_to_add[images_to_add.length] = img_id_pre+i;
my_image_collection.addImages(images_to_add);

alert(my_image_collection.next());
}

// ]]>
</script>


Or this:


<script type="text/javascript">
// <![CDATA[
var img_id_pre = "img";
var total_num_imgs = 100;

// ImageCollection JS Class
function ImageCollection()
{
this.images = new Array();
this.current_index = 0;
this.addImages = function(ids)
{
if (typeof(id) == "string") id = [ids];
for (var i=0;i<ids.length;i++) this.images.push(new MyImage(ids[i]));
}
this.next = function()
{
return (this.images[++this.current_index]);
}
}

// MyImage JS Class
function MyImage(id)
{
this.ref_id = id;
this.div = document.getElementById("id");
}

window.onload = function()
{
my_image_collection = new ImageCollection();

for (var i=0;i<total_num_imgs;i++) my_image_collection.addImages(img_id_pre+i);

alert(my_image_collection.next());
}

// ]]>
</script>

Kor
03-26-2009, 08:42 PM
retired1

In response to your PM (by the way... don't use PM for matters which might be interesting for the others as well)

You said:


...
I am not familiar with the type of loop in your suggestion; in particular, how the loop stops. When I replace everything in the outer braces {} with an alert statement and the value of i, it continues forever, incrementing i each time. How is it supposed to stop?

It is also a question of mine whether the
“while (d=document...” should be written as
“while (d==document...”
...

Here's a detailed example of how that kind of while loop works:


var radio_buttons=theform['radiogroup_common_name'], i=0, r;
while(r=radio_buttons){
... statement ...
}


contains 5 distinct operations:
1. assignment: the variable r gets the value of the radio_buttons[i]. That value may be the reference of the object (which is evaluated by the conditioner as a Boolean true), or a Boolean false, if the object does not exists (if the radio_buttons overpasses the collection's length)
2. Boolean conditioner (check if the variable r is defined/true, undefined/false)
if the step 2 is passed, the next 3 steps comes (otherwise the loop stops)
[I]3. increment the indent (only at [I]this moment i becomes i+1)
4. runs the statement
5. returns to the while conditioner and starts a new loop, based now on the i+1 value increment

As you can see, the incrementation is made after the assignment, so that, inside the statement, the variable r has, lets say on first loop, the value radio_buttons[0], but the variable i has the value changed in i+1, that means 1. That means: if you need to use the index of the collection's element, but inside of that kind of loop, you should consider it as i-1.

By short, behind of what you may think it is a single assignment


r=radio_buttons[i++];

lays, in fact, two elementary, sequentially basic assignments:


r=radio_buttons[i];
i++;

=================
See an example:


var myArray=['a','b','c','d'], arr, i=0;
arr=myArray[i++];
alert(arr+'|'+i);//alerts a|1

...it is the same as:


var myArray=['a','b','c','d'], arr, i=0;
arr=myArray[i];
i++;
alert(arr+'|'+i);//alerts a|1

retired1
04-01-2009, 12:00 AM
Kor,

Thanks for taking the trouble to explain the details of this kind of while statement, of which I had been unfamiliar. I had no trouble using your suggestion with arrays (setting d=consecutive array elements); it seemed to work fine and continued to the point an array element was undefined. That has some nice applications where you don’t know how many consecutive array elements are going to be defined or don’t care to input the number.

However, for use with objects, I had trouble making your suggestion work. After considerable trial and error, I found the coding below, almost identical to yours, does just what I wanted (although even it could, perhaps, be simplified):


var Img0 =
{init:function()
{ var i = 0, d;
while(d = document.getElementById('img'+(i++)))
{window['Img'+(i-1)] = {init:function() {} };
window['Img'+(i-1)].div = d;
};
continue_on();
}
};

Img0.init is executed when all html is loaded; function “continue_on” just goes on to the next part of the program.

Your suggested method is much appreciated.

retired1

itsallkizza
04-01-2009, 03:46 PM
If you're looking for semantic object-oriented coding, I'd suggest you take another look at the code I spent the time writing up for you.

retired1
04-07-2009, 01:04 AM
itsallkizza,

I am having difficulty incorporating your code into my existing program. Specifically, I need to assign a unique zIndex to each of my images and normally do this with a loop containing statements of form:
objName.div.style.zIndex = assigned value;

Using your nomenclature, what would be objName?

Thanks.

itsallkizza
04-07-2009, 03:07 PM
If you need to assign them a z-index as you add them you can do so like this:


var img_id_pre = "img";
var total_num_imgs = 100;

// ImageCollection JS Class
function ImageCollection()
{
this.images = new Array();
this.current_index = 0;
this.addImages = function(ids)
{
if (typeof(ids) == "string") ids = [ids];
for (var i=0;i<ids.length;i++) this.images.push(new MyImage(ids[i]));
}
this.next = function()
{
return (this.images[++this.current_index]);
}
}

// MyImage JS Class
function MyImage(id)
{
this.ref_id = id;
this.div = document.getElementById("id");
}

window.onload = function()
{
my_image_collection = new ImageCollection();

for (var i=0;i<total_num_imgs;i++)
{
my_image_collection.addImages(img_id_pre+i);
my_image_collection.images[my_image_collection.images.length-1].div.style.zIndex = i;
}

alert(my_image_collection.next());
}


Or you can run through them afterward giving them a specific index of your choice, or assigning them a z-index as an inverse of the order you added them to the array (not sure what you need exactly):


var img_id_pre = "img";
var total_num_imgs = 100;

// ImageCollection JS Class
function ImageCollection()
{
this.images = new Array();
this.current_index = 0;
this.addImages = function(ids)
{
if (typeof(ids) == "string") ids = [ids];
for (var i=0;i<ids.length;i++) this.images.push(new MyImage(ids[i]));
}
this.next = function()
{
return (this.images[++this.current_index]);
}
}

// MyImage JS Class
function MyImage(id)
{
this.ref_id = id;
this.div = document.getElementById("id");
}

window.onload = function()
{
my_image_collection = new ImageCollection();

for (var i=0;i<total_num_imgs;i++) my_image_collection.addImages(img_id_pre+i);
// this gives all your new images a zIndex of 10, they will then appear (in relation to themselves) in the order they are coded in html
for (var i=0;i<my_image_collection.images.length;i++) my_image_collection.images[i].div.style.zIndex = 10;

alert(my_image_collection.next());
}



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum