newbie: "array" of problems :( eech!

S

Simply Confusing!

Hi,

I'm wading my way thru JS initiation, so please bear with me!

I am setting up a site with a welcome page where there will be a scenic
image and a short descriptive text phrase, related to the image. I want to
create an array of images and phrases so that a visitor will randomly invoke
a new image and phrase whenever they arrive. I'm drawing from a bank of
about 40 images, each with an associated phrase.

My plan was to have a seperate JS file, which defines 1 array for images and
1 array for phrases; numbered sequentially so that image # will match phrase
#.

Example:

var ImageSwap = new Array(40)

ImageSwap[0]='..\images\mountains.jpg';
ImageSwap[1]='..\images\seaside.jpg';
ImageSwap[2]='..\images\sunset.jpg';
.... etc to 40


var TxtQuot = new Array(40)

TxtPhrase[0]='Alpine meadows';
TxtPhrase[1]='Beaches in Malibu';
TxtPhrase[2]='Sunset in Maui';
... etc to 40

I then set a random variable to govern which image-phrase combo is chosen:

var pp = Math.random()*40;
pp = Math.round(pp);


I then define 1 function to write out the image name (eventually to be part
of a longer doc.write statement which will write a css "body" background
defn into the doc head:

function showImage()
{document.write (ImageSwap[pp]);
}

Then a function which will write out the desriptive phrase:

function showQuote()
{document.write (TxtQuot[pp]);
}

end of external JS file
---------------------------------

so to change the body background image on the fly, I reasoned that I'd have
to have JS write out a CSS statement, incorporating the "showImage" function
above, in the doc head. This is probably the part that is bad planning, but
it is the best I can do at this time:

<script language="javascript">
document.write('<style type="text/css">'+'<br>'+'<!--'+'<br>'+'body
{'+'background-image: url(');
showImage();
document.write(')}'+'<br>'+'-->'+'<br>'+'</style>');
</script>

i'm getting a headache! (don't laugh! :)

next, I incorporate the descriptive phrase in the body of the doc:

<p align="center" class="largefont">
<script language="javascript">
showQuote();
</script>
</p>

OK, I just learned 2 things. Gotta use double back-slashes for path-name
seperators in array contents. Number two: CSS is static and can't be
re-written on the fly.

I'm dumbfounded.

Can anyone offer sympathy, cookies or help?

thanks for any direction on this..

SC
 
W

wisestpotato

Hi,

I'm wading my way thru JS initiation, so please bear with me!

I am setting up a site with a welcome page where there will be a scenic
image and a short descriptive text phrase, related to the image. I want to
create an array of images and phrases so that a visitor will randomly invoke
a new image and phrase whenever they arrive. I'm drawing from a bank of
about 40 images, each with an associated phrase.

My plan was to have a seperate JS file, which defines 1 array for images and
1 array for phrases; numbered sequentially so that image # will match phrase
#.

Example:

var ImageSwap = new Array(40)

ImageSwap[0]='..\images\mountains.jpg';
ImageSwap[1]='..\images\seaside.jpg';
ImageSwap[2]='..\images\sunset.jpg';
.... etc to 40

var TxtQuot = new Array(40)

TxtPhrase[0]='Alpine meadows';
TxtPhrase[1]='Beaches in Malibu';
TxtPhrase[2]='Sunset in Maui';
... etc to 40

I then set a random variable to govern which image-phrase combo is chosen:

var pp = Math.random()*40;
pp = Math.round(pp);

I then define 1 function to write out the image name (eventually to be part
of a longer doc.write statement which will write a css "body" background
defn into the doc head:

function showImage()
{document.write (ImageSwap[pp]);
}

Then a function which will write out the desriptive phrase:

function showQuote()
{document.write (TxtQuot[pp]);
}

end of external JS file
---------------------------------

so to change the body background image on the fly, I reasoned that I'd have
to have JS write out a CSS statement, incorporating the "showImage" function
above, in the doc head. This is probably the part that is bad planning, but
it is the best I can do at this time:

<script language="javascript">
document.write('<style type="text/css">'+'<br>'+'<!--'+'<br>'+'body
{'+'background-image: url(');
showImage();
document.write(')}'+'<br>'+'-->'+'<br>'+'</style>');
</script>

i'm getting a headache! (don't laugh! :)

next, I incorporate the descriptive phrase in the body of the doc:

<p align="center" class="largefont">
<script language="javascript">
showQuote();
</script>
</p>

OK, I just learned 2 things. Gotta use double back-slashes for path-name
seperators in array contents. Number two: CSS is static and can't be
re-written on the fly.

I'm dumbfounded.

Can anyone offer sympathy, cookies or help?

thanks for any direction on this..

SC

Any css specified within the document is read when the page first
loads. If you write any more css using document.write after the page
loads, it will not be parsed by the browser. Instead you should
manipulate the styles directly. Each element has a style object,
allowing you to manipulate the style settings for that element.

So, in the function showImage(), you should be directly setting the
background-image with something like this:

function showImage()
{
document.body.style.backgroundImage = "url('" + ImageSwap[pp] +
"')";
}


See http://www.w3schools.com/htmldom/dom_obj_style.asp for more info.

hth,

wp.
 
R

RobG

Simply said:
Hi,

I'm wading my way thru JS initiation, so please bear with me!

I am setting up a site with a welcome page where there will be a scenic
image and a short descriptive text phrase, related to the image. I want to
create an array of images and phrases so that a visitor will randomly invoke
a new image and phrase whenever they arrive. I'm drawing from a bank of
about 40 images, each with an associated phrase.

Why not do it from the server? You can randomly assign the image and
caption server-side and remove all dependence on unreliable client-side
scripting.

My plan was to have a seperate JS file, which defines 1 array for images and
1 array for phrases; numbered sequentially so that image # will match phrase
#.

You could also use one array of arrays, like:

var dataArray = [
['../images/mountains.jpg','Alpine meadows'],
['../images/seaside.jpg','Beaches in Malibu'],
...
];

Example:

var ImageSwap = new Array(40)

ImageSwap[0]='..\images\mountains.jpg';
ImageSwap[1]='..\images\seaside.jpg';
ImageSwap[2]='..\images\sunset.jpg';
.... etc to 40

Don't use back-slashes in paths on the web, use forward slashes: '/'.

[...]
I then set a random variable to govern which image-phrase combo is chosen:

var pp = Math.random()*40;
pp = Math.round(pp);

Use:

var pp = Math.random()*dataArray.length | 0;

to get an integer (I'm not sure that all browsers will handle a decimal
array index like 32.345797123751), then you don't care what length
dataArray is - you can add (or remove) members at will without changing
the code elsewhere.


[...]
<script language="javascript">

The language attribute is deprecated, type is required.

document.write('<style type="text/css">'+'<br>'+'<!--'+'<br>'+'body
{'+'background-image: url(');

Drop the HTML comment delimiters and br elements, neither are needed.

[...]
OK, I just learned 2 things. Gotta use double back-slashes for path-name
seperators in array contents.

You need to use forward slashes.

Number two: CSS is static and can't be
re-written on the fly.

Yes, it can.
 
L

-Lost

You could also use one array of arrays, like:

var dataArray = [
['../images/mountains.jpg','Alpine meadows'],
['../images/seaside.jpg','Beaches in Malibu'],
...
];

You know, I was just pondering 2 and 3 dimensional "associative" arrays in JavaScript.

Am I missing something, in that you cannot assign one in this fashion:

var arr1 = new Array;
arr1['indice_a'] = ['sub_indice_a1' = ['sub_sub_indice_a1', 'sub_sub_indice_a2']];

This *will not* yield arr1['indice_a']['sub_indice_a1'][1] for example
(sub_sub_indice_a2).

Yet, I can create separate arrays and assign them as elements of the parent array.

var arr1 = new Array;
var arr2 = new Array;
arr2['sub_indice_a1'] = ['sub_sub_indice_a1', 'sub_sub_indice_a2'];
arr1['indice_a'] = arr2;

This *will* yield arr1['indice_a']['sub_indice_a1'][1] for example (sub_sub_indice_a2).

I guess what I am asking is, can I create multi-dimensional arrays in any fashion similar
to the first method I posted (which does not work). Or is the latter the logical *and
only* method of doing it?

PHP has spoiled me.

-Lost
 
L

-Lost

Duncan Booth said:
-Lost said:
Am I missing something, in that you cannot assign one in this fashion:

var arr1 = new Array;
arr1['indice_a'] = ['sub_indice_a1' = ['sub_sub_indice_a1',
'sub_sub_indice_a2']];

This *will not* yield arr1['indice_a']['sub_indice_a1'][1] for example
(sub_sub_indice_a2).

Yuck. Why are you assigning properties like 'indice_a' to an Array? Don't
do that, it is just plain wrong.

Merely for the sake of example.
If you want to use properties like an associative array then use an Object.

The following will do what you want (at least most of the time until the
fact that javascript doesn't really have associative arrays comes back to
bite you):

Thanks. I already knew how to use an Object though. The entire purpose of the post was
to emulate "associative" arrays, or rather how to properly instantiate them, then emulate
them.
var arr1 = {};
arr1['indice_a'] = {
sub_indice_a1: ['sub_sub_indice_a1', 'sub_sub_indice_a2']
};

alert(arr1['indice_a']['sub_indice_a1'][1]);

For the record though, what is the difference between emulating associative arrays and
going the Object route?

As in, how will it come back to "bite" me in the end?

Unless I am wrong, my second illustrated method works just fine. You said "works most of
the time" about yours. Am I missing something? : )

-Lost
 
R

Richard Cornford

-Lost said:
Duncan Booth wrote:

Thanks. I already knew how to use an Object though. The
entire purpose of the post was to emulate "associative" arrays,
or rather how to properly instantiate them, then emulate them.

One of the problems with emulating "associative arrays" in javascript is
that nobody is very clear about what is meant by "associative array"
when applied to this practice. In javascript it is possible to add named
properties to all (non-host) objects at runtime by assigning values to
those properties, and then retrieve those values with the property
names. Because javascript's arrays are (non-host) objects they also
provide this facility. Differing from ordinary objects in that if the
property names used with them are "length" or an 'array index'
assignments to those property names may have side effects (and, of
course, having the - Array.prototype - object at the top of their
internal prototype chain, and so inheriting array related methods).

Whenever assignments are being made to properties of an object with
names that are not "length" or an 'array index' name (or the array
side-effects are not desired) it makes no sense to use an Array object
as the subject of the assignments. An ordinary Object object provides
all the facilities being employed.
var arr1 = {};
arr1['indice_a'] = {
sub_indice_a1: ['sub_sub_indice_a1', 'sub_sub_indice_a2']
};

alert(arr1['indice_a']['sub_indice_a1'][1]);

For the record though, what is the difference between emulating
associative arrays and going the Object route?

Assigning a non-'array index', or non-"length" to an Array object is not
distinct from assigning like-named properties to an Object object. It is
the fact that an Array is an object that facilitates the assignment,
just as it is object-ness that facilitates doing so with an Object
object.

Here your problem may be that you believe "emulating associative arrays"
is doing something specific when in reality it is doing no more than
adding a named property to an object by assigning a value to it.
As in, how will it come back to "bite" me in the end?

The problems with treating javascript objects (of any kind) as an
"associative array" is that no javascript objects are ever 'empty'. They
always start out with at least some named properties. This means that
while a common conception of an "associative array" is that it can be
used to store values by arbitrary key this cannot be achieved in
javascript.
Unless I am wrong, my second illustrated method works
just fine. You said "works most of the time" about yours.
Am I missing something? : )

If there was any possibility that the keys used to store values in an
"emulated associative array" ever included, for example, "push" (if
using an Array rather than an Object), "constructor", "valueOf" and so
on, you would find that the "associative array" was already storing
these values before they were assigned, and they would not necessarily
be the types of values expected.

So in all cases this type of storage "mostly works". Mostly collisions
between existing property names are few and far between, but the yare a
definite possibility if the property names used are truly arbitrary. On
the other hand, if you know enough about the property names being used
(such as that they will always be all uppercase sequences of characters)
then there are no issues with using javascript objects to store
name/value pairs.

Richard.
 
S

Simply Confusing!

thanks to wisestpotato & Rob G for clarifiction. I did implement wise's
change to the "showImage" function as a style-object of the body element and
invoked with the onLoad function in the body tag. It works well!

However!! one problem! this works fine in IE6, but Opera and Firebox both
do not load the background image.

also, thanks to RobG for the suggestion of fwd-shashes instead of
back-slashes; the doubling of back-slashes (this is called "escaping"?) did
work, but it seems much cleaner code to use single fwd-slashes.
You could also use one array of arrays, like:

var dataArray = [
['../images/mountains.jpg','Alpine meadows'],
['../images/seaside.jpg','Beaches in Malibu'],
...
];

I like your idea of a multi-dimensional array, but how do I access the
elements of the array? If I can de-bug WisestPotato's function so it works
in Opera & FF, it's set like this:

var pp = Math.random()*ImageSwap.length | 0;

function showImage()
{
document.body.style.backgroundImage = "url('" + ImageSwap[pp]
+
"')";
}

(current array is called ImageSwap for the image dimension)

the function that writes out the text dimension is this (from the
text-dimension array called TxtQuot):

function showQuote()
{document.write (TxtQuot[pp]);
}

What I need to know, is, if I use a multi-dimensional array, how then do I
invoke "showImage()" and "showQuote()" so as to access the 1st and 2nd
elements of the multi-dimensional array that RobG suggested ...?

thanks muchly!!

SC













[...]
I then set a random variable to govern which image-phrase combo is chosen:

var pp = Math.random()*40;
pp = Math.round(pp);

Use:

var pp = Math.random()*dataArray.length | 0;

to get an integer (I'm not sure that all browsers will handle a decimal
array index like 32.345797123751), then you don't care what length
dataArray is - you can add (or remove) members at will without changing
the code elsewhere.


[...]
<script language="javascript">

The language attribute is deprecated, type is required.

document.write('<style type="text/css">'+'<br>'+'<!--'+'<br>'+'body
{'+'background-image: url(');

Drop the HTML comment delimiters and br elements, neither are needed.

[...]
OK, I just learned 2 things. Gotta use double back-slashes for path-name
seperators in array contents.

You need to use forward slashes.

Number two: CSS is static and can't be
re-written on the fly.

Yes, it can.
 
R

RobG

RobG:
You could also use one array of arrays, like:
var dataArray = [
['../images/mountains.jpg','Alpine meadows'],
['../images/seaside.jpg','Beaches in Malibu'],
...
];

I like your idea of a multi-dimensional array, but how do I access the
elements of the array? If I can de-bug WisestPotato's function so it works
in Opera & FF, it's set like this:

var pp = Math.random()*ImageSwap.length | 0;

function showImage()
{
document.body.style.backgroundImage = "url('" + ImageSwap[pp]
+
"')";

Use 2 spaces for indentation and manually wrap your code at about 70
characters to prevent auto-wrapping.

The format of the suggested array is:

var dataArray = [
[path, caption],
[path, caption],
...
];

You access each sub-array by index: dataArray[j]. So the first
path is: dataArray[0][0] and the first caption is dataArray[0][1], and
so on.

Use something like (wrapped for posting):

document.body.style.backgroundImage = "url('"
+ ImageSwap[pp][0] + "')";
...

document.write( TxtQuot[pp][1] );


Don't forget to trim trailing junk. :)
 
L

-Lost

Duncan Booth said:
-Lost said:
Thanks. I already knew how to use an Object though. The entire
purpose of the post was to emulate "associative" arrays, or rather how
to properly instantiate them, then emulate them.

You properly emulate them by using the Object type (i.e. curly braces)
rather than Array (square brackets). That means you can write them as
literals:

var a = { 'a': 1, 'b': 2 };

and you won't get confused by the fact that arrays have a length
property which doesn't do what you expect:

var a = [];
a['a'] = 1;
alert(a.length);

will display 0. None of the special behaviour of Arrays will work on the
non-numeric property names you assign, so you shouldn't use Array to
begin with.

Right, I realized this before when attempting to iterate through the array. Only the
for-in loop allows consistent access to the elements. And of course using more code to
keep track of them does not make sense, based on your above explanation of an Object
literal (which allows for it out of the gate).
var arr1 = {};
arr1['indice_a'] = {
sub_indice_a1: ['sub_sub_indice_a1', 'sub_sub_indice_a2']
};

alert(arr1['indice_a']['sub_indice_a1'][1]);

For the record though, what is the difference between emulating
associative arrays and going the Object route?

As in, how will it come back to "bite" me in the end?

If will bite you because some property names already exist in all
objects so you cannot assume that every name you haven't assigned into
the object isn't set.

e.g.
var a = { 'a': 1, 'b': 2 };
alert(a['toString']);

so any time you think you can check whether something is in the
'associative' array you cannot (unless you remember to use
hasOwnProperty).

Which is adding more code to deal with the erroneous emulation of associative arrays using
an Array.

Duly noted!
Except in so far as it has lots of Array methods which cannot see the
properties you added: they aren't part of the array (unless they are
also integers).

Funny thing is, I knew that numeric indices and named indices did not go together (so to
speak), yet it never dawned on me that the intrinsic Array methods (and or properties)
would behave in a chaotic fashion due to the misuse.

Thank you very much for the information.

-Lost
 
L

-Lost

Richard Cornford said:
One of the problems with emulating "associative arrays" in javascript is that nobody is
very clear about what is meant by "associative array" when applied to this practice. In
javascript it is possible to add named properties to all (non-host) objects at runtime
by assigning values to those properties, and then retrieve those values with the
property names. Because javascript's arrays are (non-host) objects they also provide
this facility. Differing from ordinary objects in that if the property names used with
them are "length" or an 'array index' assignments to those property names may have side
effects (and, of course, having the - Array.prototype - object at the top of their
internal prototype chain, and so inheriting array related methods).

Whenever assignments are being made to properties of an object with names that are not
"length" or an 'array index' name (or the array side-effects are not desired) it makes
no sense to use an Array object as the subject of the assignments. An ordinary Object
object provides all the facilities being employed.

I see this now, thanks for the clarification.
var arr1 = {};
arr1['indice_a'] = {
sub_indice_a1: ['sub_sub_indice_a1', 'sub_sub_indice_a2']
};

alert(arr1['indice_a']['sub_indice_a1'][1]);

For the record though, what is the difference between emulating
associative arrays and going the Object route?

Assigning a non-'array index', or non-"length" to an Array object is not distinct from
assigning like-named properties to an Object object. It is the fact that an Array is an
object that facilitates the assignment, just as it is object-ness that facilitates doing
so with an Object object.

Here your problem may be that you believe "emulating associative arrays" is doing
something specific when in reality it is doing no more than adding a named property to
an object by assigning a value to it.

That definitely translates to me not understanding that fact. That just because an Array
can facilitate the assignment, does not mean that chaotic behavior will not insue or a
complete failure of the code altogether.

Thanks for making that a little clearer.
The problems with treating javascript objects (of any kind) as an "associative array" is
that no javascript objects are ever 'empty'. They always start out with at least some
named properties. This means that while a common conception of an "associative array" is
that it can be used to store values by arbitrary key this cannot be achieved in
javascript.


If there was any possibility that the keys used to store values in an "emulated
associative array" ever included, for example, "push" (if using an Array rather than an
Object), "constructor", "valueOf" and so on, you would find that the "associative array"
was already storing these values before they were assigned, and they would not
necessarily be the types of values expected.

More chaotic behavior that I was unaware of. Thanks.
So in all cases this type of storage "mostly works". Mostly collisions between existing
property names are few and far between, but the yare a definite possibility if the
property names used are truly arbitrary. On the other hand, if you know enough about the
property names being used (such as that they will always be all uppercase sequences of
characters) then there are no issues with using javascript objects to store name/value
pairs.

Exactly, I think I have it. Basically, if used entirely for a "dictionary" so to speak,
as in, only name:value pairs, it MIGHT work, but no guarantee if I accidentally infringe
on existing names (be they properties or methods).

My final conclusion, there is never a time when emulating associative arrays (due in part
to the inconsistent definition) is an OK practice.

Just use Objects.

Thanks again!

-Lost
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top