[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.javascript

A few problems with looping thru a set of elements with the same "name" specifier.

R.Wieser

4/17/2016 11:22:00 AM

Hello all,

#1: I've written a script to address an element with the attribute name
"foo". The problem is that a certain, bit older browser fails on
"document.foo.length" if there are less than 2 elements available. Is
there a certain trick involved to have it return the values One and Zero too
?

Related: With two-or-more elements I can address a single one by referring
to it in an array-like fashion: "document.foo[i].getAttribute(...)". With
only a single element being present using
"document.foo[0].getAttribute(...)" fails, but works without the "[0]".

#2: Can I give two different elements the same "name" propery and than
address them individually, something like "document.div.foo.*" perhaps ?

Related: How can I refer to embedded elements ("document.foo.h1.*" perhaps)
?

#3: The script is supposed to executed every few seconds, so I added

setTimeout("scriptName()", Timeout)

as the last line of the script. The problem is that some browsers seem to
block this, probably because of some kind of popup protection. Is there a
method/function I should be using instead of that "setTimeout" that will not
run into those troubles ?

#4: If I call the script from the element itself and use "this" as an
argument to the script (as a reference to the current object), how am I
supposed to put that argument in the "setTimeout" call ? The below does
not seem to work:

setTimeout("scriptName("+ this +")",Timeout)

Regards,
Rudy Wieser



10 Answers

Stefan Weiss

4/17/2016 1:31:00 PM

0

R.Wieser wrote:
> #1: I've written a script to address an element with the attribute name
> "foo". The problem is that a certain, bit older browser fails on
> "document.foo.length" if there are less than 2 elements available. Is
> there a certain trick involved to have it return the values One and Zero too
> ?
>
> Related: With two-or-more elements I can address a single one by referring
> to it in an array-like fashion: "document.foo[i].getAttribute(...)". With
> only a single element being present using
> "document.foo[0].getAttribute(...)" fails, but works without the "[0]".
>
> #2: Can I give two different elements the same "name" propery and than
> address them individually, something like "document.div.foo.*" perhaps ?
>
> Related: How can I refer to embedded elements ("document.foo.h1.*" perhaps)
> ?

Use getElementsByName() or querySelector() / querySelectorAll(). Maybe these
will work on the "certain older browser", maybe not. Unfortunately, we don't
know what browser that is.

> #3: The script is supposed to executed every few seconds, so I added
>
> setTimeout("scriptName()", Timeout)
>
> as the last line of the script. The problem is that some browsers seem to
> block this, probably because of some kind of popup protection. Is there a
> method/function I should be using instead of that "setTimeout" that will not
> run into those troubles ?
>
> #4: If I call the script from the element itself and use "this" as an
> argument to the script (as a reference to the current object), how am I
> supposed to put that argument in the "setTimeout" call ? The below does
> not seem to work:
>
> setTimeout("scriptName("+ this +")",Timeout)

Your terminology is all over the place - I had to re-read all of your
questions several times before I figured out what you meant...
You cannot call scripts, only functions. I assume this means that you really
added the setTimeout() call as the last line of your _function_.

Why would a popup blocker prevent execution? Does your function open a new
window? If so, why would you call it every few seconds? Hard to say, without
knowing what the (oddly named) scriptName() function does. Also, which
browsers are "some browsers"?

"Calling the script from the element itself" could mean that you're using
event handler attributes in your HTML. How can you pass arguments to the
callback function, possibly also avoiding problems with `this`? It depends
on what that "certain older browser" is. For current browsers, you can just
add the arguments in the setTimeout() call; for IE9 and below you will have
to use a workaround. This is explained in detail here:

https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/...


- stefan

Stefan Weiss

4/17/2016 1:37:00 PM

0

R.Wieser wrote:
> #2: Can I give two different elements the same "name" propery and than
> address them individually, something like "document.div.foo.*" perhaps ?

Addendum: not all HTML elements have "name" attributes. For example, DIV
elements do not. A common way to group elements for collective use by
JavaScript is to assign them the same (CSS) class and then to use
getElementsByClassName(). Possibly with a polyfill for the "certain old
browser".

- stefan

R.Wieser

4/17/2016 4:54:00 PM

0

Stefan,

> Use getElementsByName() or querySelector() / querySelectorAll().

I take it thats the answer to questions #1 and #2, including the related one
(?).

Too bad, the function will get a bit more complex because of it (I take it
your answer equals an "cannot be done", not "don't know if its possible")

> Unfortunately, we don't know what browser that is.

Thats on purpose. The script should run on as many browsers as possible.
I would not want you to waste time to find a solution for a specific
browser, only to than being told it doesn't work for yet another one.

> Your terminology is all over the place -
....
> You cannot call scripts, only functions.

My apologies for having used incorrect terminology.

> I assume this means that you really added the setTimeout()
> call as the last line of your _function_.

Indeed.

> Why would a popup blocker prevent execution?

Sorry, you're asking the wrong person. Its just that I saw that name as
the caption of the popup box that told me it stopped a popup from appearing
(quite a bit of irony there :-) )

> Does your function open a new window?

Yes. At one point in time I had an "alert" box in the function to show me
the contents of the "document.foo.length" property (thats how I discovered
it would not work for a single element).

Though when I removed it the script still got, at some other computer and
browser, blocked at some point.

> For current browsers, you can just add the arguments in
> the setTimeout() call; for IE9 and below you will have
> to use a workaround. This is explained in detail here: [snip link]

That was pretty-much exactly the answer I was looking for: A
browser-unspecific description of possible aproaches. Thanks.

> Addendum: not all HTML elements have "name" attributes.
> For example, DIV elements do not.

If I cannot use the "document.[element name].*" short form but instead have
to use a function that becomes rather moot, as I can than select them by ID,
class, tag or element name. :-)

Regards,
Rudy Wieser


-- Origional message:
Stefan Weiss <krewecherl@gmail.com> schreef in berichtnieuws
nf035v$b42$1@news.albasani.net...
> R.Wieser wrote:
> > #1: I've written a script to address an element with the attribute name
> > "foo". The problem is that a certain, bit older browser fails on
> > "document.foo.length" if there are less than 2 elements available. Is
> > there a certain trick involved to have it return the values One and Zero
too
> > ?
> >
> > Related: With two-or-more elements I can address a single one by
referring
> > to it in an array-like fashion: "document.foo[i].getAttribute(...)".
With
> > only a single element being present using
> > "document.foo[0].getAttribute(...)" fails, but works without the "[0]".
> >
> > #2: Can I give two different elements the same "name" propery and than
> > address them individually, something like "document.div.foo.*" perhaps ?
> >
> > Related: How can I refer to embedded elements ("document.foo.h1.*"
perhaps)
> > ?
>
> Use getElementsByName() or querySelector() / querySelectorAll(). Maybe
these
> will work on the "certain older browser", maybe not. Unfortunately, we
don't
> know what browser that is.
>
> > #3: The script is supposed to executed every few seconds, so I added
> >
> > setTimeout("scriptName()", Timeout)
> >
> > as the last line of the script. The problem is that some browsers seem
to
> > block this, probably because of some kind of popup protection. Is
there a
> > method/function I should be using instead of that "setTimeout" that will
not
> > run into those troubles ?
> >
> > #4: If I call the script from the element itself and use "this" as an
> > argument to the script (as a reference to the current object), how am I
> > supposed to put that argument in the "setTimeout" call ? The below
does
> > not seem to work:
> >
> > setTimeout("scriptName("+ this +")",Timeout)
>
> Your terminology is all over the place - I had to re-read all of your
> questions several times before I figured out what you meant...
> You cannot call scripts, only functions. I assume this means that you
really
> added the setTimeout() call as the last line of your _function_.
>
> Why would a popup blocker prevent execution? Does your function open a new
> window? If so, why would you call it every few seconds? Hard to say,
without
> knowing what the (oddly named) scriptName() function does. Also, which
> browsers are "some browsers"?
>
> "Calling the script from the element itself" could mean that you're using
> event handler attributes in your HTML. How can you pass arguments to the
> callback function, possibly also avoiding problems with `this`? It depends
> on what that "certain older browser" is. For current browsers, you can
just
> add the arguments in the setTimeout() call; for IE9 and below you will
have
> to use a workaround. This is explained in detail here:
>
> https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/...
>
>
> - stefan



Stefan Weiss

4/18/2016 5:47:00 PM

0

R.Wieser wrote:
>> Use getElementsByName() or querySelector() / querySelectorAll().
>
> I take it thats the answer to questions #1 and #2, including the related one
> (?).
>
> Too bad, the function will get a bit more complex because of it (I take it
> your answer equals an "cannot be done", not "don't know if its possible")

I never use shortcuts like `document.{name}`, myself, when there are methods
that explicitly select what I want. I just checked in Chromium and Firefox,
and neither of them just add elements to `document` by their `name`
attributes... maybe I misunderstood what you were talking about.

Either way, the method calls aren't that complex. They are also explicit in
what they do, and allow you to avoid naming conflicts with other properties
of `document` (and apparently, browser compatibility issues). They also
always return a collection of elements or a single element, depending on
which method is used, but independent of how many matches exist in the document.

>> Unfortunately, we don't know what browser that is.
>
> Thats on purpose. The script should run on as many browsers as possible.
> I would not want you to waste time to find a solution for a specific
> browser, only to than being told it doesn't work for yet another one.

Then that's a relevant requirement in itself. If you really want to support
as many browsers as possible, that limits the range of possible solutions.
The query selector methods, for example, do not exist natively on all
browsers. IMHO, you will probably have to define a cut-off point somewhere,
or you'll find yourself supporting horribly outdated and broken engines for
little actual benefit.

>> Why would a popup blocker prevent execution?
>
> Sorry, you're asking the wrong person. Its just that I saw that name as
> the caption of the popup box that told me it stopped a popup from appearing
> (quite a bit of irony there :-) )
>
>> Does your function open a new window?
>
> Yes. At one point in time I had an "alert" box in the function to show me
> the contents of the "document.foo.length" property (thats how I discovered
> it would not work for a single element).
>
> Though when I removed it the script still got, at some other computer and
> browser, blocked at some point.

Dialogs (alert, confirm, prompt) usually don't trigger popup blockers, and
certainly not after they've been removed from the code :)
It's impossible to say what's going on here without looking at the code.


- stefan

R.Wieser

4/18/2016 6:29:00 PM

0

Stefan,

> I just checked in Chromium and Firefox, and neither of them
> just add elements to `document` by their `name` attributes...

I'm not quite sure about what you are trying to saying there ... I'm
trying to *refer* to elements, not add them.

> maybe I misunderstood what you were talking about.

No, I think you got it right. At least, you seemed to do when you referred
to the DIV element not recognising the "name" attribute (did not yet test
that though).

> Either way, the method calls aren't that complex.

True, but more complex than that "document.{name}" method. And I quite
favor KISS methods. :-)

> Then that's a relevant requirement in itself.

True. I should maybe have explicitily mentioned that requirement, but I did
not want to start with limiting possible responses.

> IMHO, you will probably have to define a cut-off point somewhere,

Agreed.

> Dialogs (alert, confirm, prompt) usually don't trigger popup
> blockers, and certainly not after they've been removed from
> the code :)

That was my thought too, so you can imagine my confusion when the function
refused to repeat itself on that one computer running FF for its browser ...

> It's impossible to say what's going on here without looking at the code.

And it will be impossible to know with the code. Remember, it works on a
few computers, just not on yet another one. In other words: Its most likely
the computer, not the script thats to "blame"

But ... As you think its relevant, here it is:

<script language="JavaScript">
var i = 0;
function nextSlideImage() {
alert(document.slide.length);
for (i=0; i<document.slide.length;i++) {
if (!document.slide[i].hasAttribute("slide"+
++document.slide[i].slideIndex)) document.slide[i].slideIndex=1;
document.slide[i].src =
document.slide[i].getAttribute("slide"+document.slide[i].slideIndex);
}
setTimeout("nextSlideImage()",3000);
}
window.onload=nextSlideImage;
</script>

<img name="slide" src="..."
slide1="..."
slide2="..."
slide3="..."
/>

One remark/warning though : I'm *not* looking for any "hey, just use {fill
in your poisson} instead !" response. I'm trying to get the above to run,
or, if that is not possible, understand why it won't.

In other words: although a working end-product is icing on the cake, I'm
much more interrested in learing what happens (or not happens) with that
code -- specifically with parts thereof -- and why (which is why I was/am
hesitant to even mention what the script is supposed to do).

Regards
Rudy Wieser


-- Origional message:
Stefan Weiss <krewecherl@gmail.com> schreef in berichtnieuws
nf36i5$an2$1@news.albasani.net...
> R.Wieser wrote:
> >> Use getElementsByName() or querySelector() / querySelectorAll().
> >
> > I take it thats the answer to questions #1 and #2, including the related
one
> > (?).
> >
> > Too bad, the function will get a bit more complex because of it (I take
it
> > your answer equals an "cannot be done", not "don't know if its
possible")
>
> I never use shortcuts like `document.{name}`, myself, when there are
methods
> that explicitly select what I want. I just checked in Chromium and
Firefox,
> and neither of them just add elements to `document` by their `name`
> attributes... maybe I misunderstood what you were talking about.
>
> Either way, the method calls aren't that complex. They are also explicit
in
> what they do, and allow you to avoid naming conflicts with other
properties
> of `document` (and apparently, browser compatibility issues). They also
> always return a collection of elements or a single element, depending on
> which method is used, but independent of how many matches exist in the
document.
>
> >> Unfortunately, we don't know what browser that is.
> >
> > Thats on purpose. The script should run on as many browsers as
possible.
> > I would not want you to waste time to find a solution for a specific
> > browser, only to than being told it doesn't work for yet another one.
>
> Then that's a relevant requirement in itself. If you really want to
support
> as many browsers as possible, that limits the range of possible solutions.
> The query selector methods, for example, do not exist natively on all
> browsers. IMHO, you will probably have to define a cut-off point
somewhere,
> or you'll find yourself supporting horribly outdated and broken engines
for
> little actual benefit.
>
> >> Why would a popup blocker prevent execution?
> >
> > Sorry, you're asking the wrong person. Its just that I saw that name
as
> > the caption of the popup box that told me it stopped a popup from
appearing
> > (quite a bit of irony there :-) )
> >
> >> Does your function open a new window?
> >
> > Yes. At one point in time I had an "alert" box in the function to show
me
> > the contents of the "document.foo.length" property (thats how I
discovered
> > it would not work for a single element).
> >
> > Though when I removed it the script still got, at some other computer
and
> > browser, blocked at some point.
>
> Dialogs (alert, confirm, prompt) usually don't trigger popup blockers, and
> certainly not after they've been removed from the code :)
> It's impossible to say what's going on here without looking at the code.
>
>
> - stefan


Stefan Weiss

4/18/2016 8:54:00 PM

0

R.Wieser wrote:
>> I just checked in Chromium and Firefox, and neither of them
>> just add elements to `document` by their `name` attributes...
>
> I'm not quite sure about what you are trying to saying there ... I'm
> trying to *refer* to elements, not add them.
>
>> maybe I misunderstood what you were talking about.
>
> No, I think you got it right. At least, you seemed to do when you referred
> to the DIV element not recognising the "name" attribute (did not yet test
> that though).

I see from the code you posted that your named element is an image. IMG
elements are special in that references to them will indeed be added to the
`document` object if they have a `name` attribute. There are only a handful
of other elements with similar shortcuts: APPLET, OBJECT, EMBED, FORM, IFRAME.
Other elements can be named, but that does not make them accessible via
`document.{name}`: I had only tested INPUT and A earlier, and wrongly
concluded that named elements just don't show up on `document` in Firefox
and Chrome.

The whole thing is almost certainly a legacy feature that had to be kept in
the standard because many existing scripts rely on it. But it is in the
standard, and documented in detail here:

https://html.spec.whatwg.org/multipage/dom.html#dom-tree...
(at the end of section 3.1.3)

This section also defines that either a single element or an HTMLCollection
of elements is returned, depending on the number of elements with that name.


> <script language="JavaScript">
> var i = 0;
> function nextSlideImage() {
> alert(document.slide.length);
> for (i=0; i<document.slide.length;i++) {
> if (!document.slide[i].hasAttribute("slide"+
> ++document.slide[i].slideIndex)) document.slide[i].slideIndex=1;
> document.slide[i].src =
> document.slide[i].getAttribute("slide"+document.slide[i].slideIndex);
> }
> setTimeout("nextSlideImage()",3000);
> }
> window.onload=nextSlideImage;
> </script>
>
> <img name="slide" src="..."
> slide1="..."
> slide2="..."
> slide3="..."
> />
>
> One remark/warning though : I'm *not* looking for any "hey, just use {fill
> in your poisson} instead !" response. I'm trying to get the above to run,
> or, if that is not possible, understand why it won't.
>
> In other words: although a working end-product is icing on the cake, I'm
> much more interrested in learing what happens (or not happens) with that
> code -- specifically with parts thereof -- and why (which is why I was/am
> hesitant to even mention what the script is supposed to do).

Showing the code helped me understand the context better. Now that I can see
what's going on, it seems there are two situations that aren't handled
correctly:

1) When there is no image with the name "slide" - then `document.slide` is
undefined and `document.slide.length` throws a ReferenceError.

2) When there is exactly one such image, `document.slide` is the image
object itself and `document.slide.length` is undefined (images don't have a
`length` property), so the loop is not entered.

Both of these can be solved by using getElementsByName(), which always
returns an array-like collection (which may or may not contain items):

function nextSlideImage ()
{
var slides = document.getElementsByName("slide");
for (var i = 0; i < slides.length; ++i) {
var slide = slides[i];
++slide.slideIndex;
if (!slide.hasAttribute("slide" + slide.slideIndex)) {
slide.slideIndex = 1;
}
slide.src = slide.getAttribute("slide" + slide.slideIndex);
}
setTimeout("nextSlideImage()",3000);
}

As requested, this is the same basic approach, with only minor adjustments
for readability.

There are still issues:

* The original code doesn't declare the `i` variable, creating an
unnecessary global variable.

* It uses custom element attributes. This leads to validation errors (if the
HTML is ever validated, which it should), and can be avoided by using
`data-*` attributes instead.

* It augments host objects (adds a `slideIndex` property to the image
objects). While the current major browsers all support this, it has
historically led to problems that were hard to debug. In general, it's best
avoided, and there are other ways to associate custom values with objects.

* The original image (in the "src" attribute) is loaded, but then
immediately switched out for slide1. This is unnecessary.

* The original code uses `a+ ++b`, which I personally think is a capital
offense in coding ;) What this does:
- use ++ to put `undefined` in a numeric context, giving 0
- use ++ to pre-increment that value, giving 1
- use + for string concatenation, giving "slide1"
All that in the conditional expression in an `if` statement.

* Referring to `document.slides[i]` six times makes the code unnecessarily
wordy. It's better to store that value in a temporary variable.

* <script language="JavaScript"> is quite obsolete now. Use
<script type="text/javascript"> or just <script> instead.


Concerning the popup blocking issue, consider using the console for
debugging instead of alert(). Calling alert() in a loop is asking for trouble.


- stefan

R.Wieser

4/19/2016 9:25:00 AM

0

Stefan,

> There are only a handful of other elements with similar
> shortcuts: APPLET, OBJECT, EMBED, FORM, IFRAME.

:-) There goes my idea to use the "name" approach to add a byline under the
image.

> The whole thing is almost certainly a legacy feature that had to
> be kept in the standard because many existing scripts rely on it.

That would explain why only a few elements have it.

> 1) When there is no image with the name "slide" - then
> `document.slide` is undefined and `document.slide.length`
> throws a ReferenceError.

I assumed as much, but as I needed a Zero result I thought it could not hurt
to ask it that was at all possible.

> 2) When there is exactly one such image, `document.slide` is the
> image object itself and `document.slide.length` is undefined (images
> don't have a `length` property), so the loop is not entered.

Yep, that is what I thought too (it being the object itself, not a
single-element array). But the same as the above, I thought it could not
hurt to ask.

> Both of these can be solved by using getElementsByName(),
> which always returns an array-like collection (which may or
> may not contain items):

Understood, and the best approach in the light of the above-described
problems (different results for Zero, one and more-than-one named element
situations).

> There are still issues:
>
> * The original code doesn't declare the `i` variable, creating
> an unnecessary global variable.

:-) I blame my novice status in regard to JS here. But yes, thats not
nessesary. Note to self: I need to look up the rules in regard to the
scope of variables.

> * It uses custom element attributes. This leads to validation
> errors (if the HTML is ever validated, which it should), and
> can be avoided by using `data-*` attributes instead.

Thanks for the reference, have to look into them.

> * It augments host objects (adds a `slideIndex` property to the image
> objects). While the current major browsers all support this, it has
> historically led to problems that were hard to debug. In general, it's
best
> avoided, and there are other ways to associate custom values with objects.

A guess: using the above mentioned "data-*" attributes ?

> * The original image (in the "src" attribute) is loaded, but then
> immediately switched out for slide1. This is unnecessary.

Not quite: That first image will be visible for anyone having JS blocked.
It was a consious decision to have it behave that way.

> * The original code uses `a+ ++b`, which I personally think is a
> capital offense in coding ;) What this does:
> - use ++ to put `undefined` in a numeric context, giving 0
> - use ++ to pre-increment that value, giving 1
> - use + for string concatenation, giving "slide1"
> All that in the conditional expression in an `if` statement.

Well, I also thought about that (being an offence). But as I have worked
with other languages where non-existing variables where simply
created-on-use and given the value Zero, I did not see anything strange in
JS doing the same.

As for it being part of a conditional expression, the language C{something}
does not seem to have any troubles with it, so I did/do not see a problem
here either.

> * Referring to `document.slides[i]` six times makes the code unnecessarily
> wordy.

Yes, I thought about that too. But here I gave priority of the code being
small over being absolutily easily readable.

> * <script language="JavaScript"> is quite obsolete now. Use
> <script type="text/javascript"> or just <script> instead.

Thanks for the suggestion. I assume that "script" now just defaults to JS
(as opposed to Microsofts own VBS) ?

By the way, any idea why a script type should be "*text*/javascript" ? Are
there any other types of JS available (precompiled (semy-)binary blobs
perhaps?) ? In other words, that "text" seems to be rather superfluous ...

> Concerning the popup blocking issue, consider using the
> console for debugging instead of alert(). Calling alert() in
> a loop is asking for trouble.

True. Especially when you do it with a small, or even no delay at all. :-)

I also realized that I need to check if JS has some sortof debug-output
available (writing to a/the JS debug console).

But, as I mentioned, when I removed that "alert" popup box the (not posted)
script/function only catering to a single named IMG element failed to run
properly on a certain machine, and I have no clue why (other than the
assumption that something on that computer purposely interfered with the
script for some reason). It however worked perfectly wit the posted
script, and *two* named IMG elements.


Thanks for all the info.

Regards,
Rudy Wieser


-- Origional message:
Stefan Weiss <krewecherl@gmail.com> schreef in berichtnieuws
nf3hhc$g4$1@news.albasani.net...
> R.Wieser wrote:
> >> I just checked in Chromium and Firefox, and neither of them
> >> just add elements to `document` by their `name` attributes...
> >
> > I'm not quite sure about what you are trying to saying there ... I'm
> > trying to *refer* to elements, not add them.
> >
> >> maybe I misunderstood what you were talking about.
> >
> > No, I think you got it right. At least, you seemed to do when you
referred
> > to the DIV element not recognising the "name" attribute (did not yet
test
> > that though).
>
> I see from the code you posted that your named element is an image. IMG
> elements are special in that references to them will indeed be added to
the
> `document` object if they have a `name` attribute. There are only a
handful
> of other elements with similar shortcuts: APPLET, OBJECT, EMBED, FORM,
IFRAME.
> Other elements can be named, but that does not make them accessible via
> `document.{name}`: I had only tested INPUT and A earlier, and wrongly
> concluded that named elements just don't show up on `document` in Firefox
> and Chrome.
>
> The whole thing is almost certainly a legacy feature that had to be kept
in
> the standard because many existing scripts rely on it. But it is in the
> standard, and documented in detail here:
>
> https://html.spec.whatwg.org/multipage/dom.html#dom-tree...
> (at the end of section 3.1.3)
>
> This section also defines that either a single element or an
HTMLCollection
> of elements is returned, depending on the number of elements with that
name.
>
> > <script language="JavaScript">
> > var i = 0;
> > function nextSlideImage() {
> > alert(document.slide.length);
> > for (i=0; i<document.slide.length;i++) {
> > if (!document.slide[i].hasAttribute("slide"+
> > ++document.slide[i].slideIndex)) document.slide[i].slideIndex=1;
> > document.slide[i].src =
> > document.slide[i].getAttribute("slide"+document.slide[i].slideIndex);
> > }
> > setTimeout("nextSlideImage()",3000);
> > }
> > window.onload=nextSlideImage;
> > </script>
> >
> > <img name="slide" src="..."
> > slide1="..."
> > slide2="..."
> > slide3="..."
> > />
> >
> > One remark/warning though : I'm *not* looking for any "hey, just use
{fill
> > in your poisson} instead !" response. I'm trying to get the above to
run,
> > or, if that is not possible, understand why it won't.
> >
> > In other words: although a working end-product is icing on the cake, I'm
> > much more interrested in learing what happens (or not happens) with that
> > code -- specifically with parts thereof -- and why (which is why I
was/am
> > hesitant to even mention what the script is supposed to do).
>
> Showing the code helped me understand the context better. Now that I can
see
> what's going on, it seems there are two situations that aren't handled
> correctly:
>
> 1) When there is no image with the name "slide" - then `document.slide` is
> undefined and `document.slide.length` throws a ReferenceError.
>
> 2) When there is exactly one such image, `document.slide` is the image
> object itself and `document.slide.length` is undefined (images don't have
a
> `length` property), so the loop is not entered.
>
> Both of these can be solved by using getElementsByName(), which always
> returns an array-like collection (which may or may not contain items):
>
> function nextSlideImage ()
> {
> var slides = document.getElementsByName("slide");
> for (var i = 0; i < slides.length; ++i) {
> var slide = slides[i];
> ++slide.slideIndex;
> if (!slide.hasAttribute("slide" + slide.slideIndex)) {
> slide.slideIndex = 1;
> }
> slide.src = slide.getAttribute("slide" + slide.slideIndex);
> }
> setTimeout("nextSlideImage()",3000);
> }
>
> As requested, this is the same basic approach, with only minor adjustments
> for readability.
>
> There are still issues:
>
> * The original code doesn't declare the `i` variable, creating an
> unnecessary global variable.
>
> * It uses custom element attributes. This leads to validation errors (if
the
> HTML is ever validated, which it should), and can be avoided by using
> `data-*` attributes instead.
>
> * It augments host objects (adds a `slideIndex` property to the image
> objects). While the current major browsers all support this, it has
> historically led to problems that were hard to debug. In general, it's
best
> avoided, and there are other ways to associate custom values with objects.
>
> * The original image (in the "src" attribute) is loaded, but then
> immediately switched out for slide1. This is unnecessary.
>
> * The original code uses `a+ ++b`, which I personally think is a capital
> offense in coding ;) What this does:
> - use ++ to put `undefined` in a numeric context, giving 0
> - use ++ to pre-increment that value, giving 1
> - use + for string concatenation, giving "slide1"
> All that in the conditional expression in an `if` statement.
>
> * Referring to `document.slides[i]` six times makes the code unnecessarily
> wordy. It's better to store that value in a temporary variable.
>
> * <script language="JavaScript"> is quite obsolete now. Use
> <script type="text/javascript"> or just <script> instead.
>
>
> Concerning the popup blocking issue, consider using the console for
> debugging instead of alert(). Calling alert() in a loop is asking for
trouble.
>
>
> - stefan



Stefan Weiss

4/19/2016 1:43:00 PM

0

R.Wieser wrote:
>> * It augments host objects (adds a `slideIndex` property to the image
>> objects). While the current major browsers all support this, it has
>> historically led to problems that were hard to debug. In general, it's
> best
>> avoided, and there are other ways to associate custom values with objects.
>
> A guess: using the above mentioned "data-*" attributes ?

That's one possibility. I would probably keep the index in a closure, but
that would require a completely different approach.

Since `slideIndex` only holds an integer number, it's very unlikely to cause
trouble, even in older browsers. The potential for naming conflicts should
probably be mentioned - e.g., image objects getting a native "slideIndex"
property in the future. This is equally unlikely, but it's one more reason
why augmenting host objects is usually avoided.

>> * The original image (in the "src" attribute) is loaded, but then
>> immediately switched out for slide1. This is unnecessary.
>
> Not quite: That first image will be visible for anyone having JS blocked.
> It was a consious decision to have it behave that way.

I see, that makes sense. It may cause some duplication ("src" will probably
contain the same URL as "slide1"). In that case, I would use something like
this:

<img src="slide1.png" data-slides="slide2.png|slide3.png|..."

>> * The original code uses `a+ ++b`, which I personally think is a
>> capital offense in coding ;) What this does:
>> - use ++ to put `undefined` in a numeric context, giving 0
>> - use ++ to pre-increment that value, giving 1
>> - use + for string concatenation, giving "slide1"
>> All that in the conditional expression in an `if` statement.
>
> Well, I also thought about that (being an offence). But as I have worked
> with other languages where non-existing variables where simply
> created-on-use and given the value Zero, I did not see anything strange in
> JS doing the same.
>
> As for it being part of a conditional expression, the language C{something}
> does not seem to have any troubles with it, so I did/do not see a problem
> here either.

The interpreter has no problem with it, my eyes do ;)
It works as intended. My issue is that it's hard to read: it requires
knowledge about operator precedence and two different type conversions, and
it creates and initializes the `slideIndex` property in the conditional.
There's just too much going on for this line to be easily understood by
another programmer.

>> * <script language="JavaScript"> is quite obsolete now. Use
>> <script type="text/javascript"> or just <script> instead.
>
> Thanks for the suggestion. I assume that "script" now just defaults to JS
> (as opposed to Microsofts own VBS) ?
>
> By the way, any idea why a script type should be "*text*/javascript" ? Are
> there any other types of JS available (precompiled (semy-)binary blobs
> perhaps?) ? In other words, that "text" seems to be rather superfluous ...

That's a very good question. The value of the "type" attribute is supposed
to be the MIME type of the contained (or referenced) script. Official MIME
types are published by IANA and consist of a top level type ("text",
"application", "image", "video", ...) and a subtype. A script is program
source code, not text, so it should theoretically be in the "application"
category. According to RFC 4329 (2006), the proper MIME type is either
"application/javascript" or "application/ecmascript" (and the two are not
exactly the same). That RFC also officially defined "text/javascript" and
"text/ecmascript" but immediately marked them as obsolete.

So much for theory. In practice, "text/javascript" has been used in the
overwhelming majority of cases, while any of the mentioned alternatives
caused some browsers (notably IE) to ignore the script completely, making
them technically correct but useless. Conversely, scripts without any "type"
or "language" attributes have always been interpreted by browsers as
JavaScript. HTML5 has now codified this behavior, defining that the absence
of type/language attributes defaults to the type "text/javascript", and
defining JavaScript as the default scripting language (with some side notes
about the naming of the language).

Recently, another use for the "type" attribute has been added to define
scripts as modules. This is an interesting new development, but irrelevant
for you if you want broad browser support.

I fully expect our resident standards expert to chime in with some
invaluable corrections and ridicule concerning the last few paragraphs.


- stefan

R.Wieser

4/19/2016 3:09:00 PM

0

Stefan,

> I would probably keep the index in a closure, but
> that would require a completely different approach.

Hmm ... Instead of storing the counter in the element it is ment for, its
stored in the script. To be honest, I'm not so sure I would like that.

And even if that approach does work for the current script, I think that
calling a function using the "this" argument would than throw a big wrench
into the machinery.

> I see, that makes sense. It may cause some duplication ("src" will
probably
> contain the same URL as "slide1"). In that case, I would use something
like
> this:

Possible, but not nessesarily. The first image could be collage of what the
slides would offer, or even an animated GIF with just a few slides. Yes, I
did put some tought into it :-).

> <img src="slide1.png" data-slides="slide2.png|slide3.png|..."

Thought about that too. But than I would need to "explode" that
"data-slides" string into an array before usage. Every time any of the
images slides would change, as each image could have its own slides (and
ammount thereof).

Also, it would make it rather unreadable if someone uses images from another
host (using full URLs).

> The interpreter has no problem with it, my eyes do ;)

To be honest, so did mine.

I did however defer looking into it until I had the other problems nailed.
Maybe just placing a set of brackets around the pre-incremented property
would solve the readability problem.

> The value of the "type" attribute is supposed to be the MIME
> type of the contained (or referenced) script.

Yes, I recognised it as a MIME type.

But I have no clue to why it is used in an HTML environment. If there is
only a single way to include JavaScript into a HTML page and there is no
fall-back available for it its... rather superfluous. Its different for
email, where the fallback could be to (just) display the the contents as the
primary type (in this case, text).

Ofcourse, this would not work for an "image" primary type ...

> I fully expect our resident standards expert to chime in with
> some invaluable corrections and ridicule concerning the last
> few paragraphs.

Hmmm ... I'm not really theoretically inclined. I normally take such
commitee-generated documents as informational, and than look at how its
implemented in the real world. 'Cause *thats* what I have to work with.

Regards,
Rudy Wieser


-- Origional message:
Stefan Weiss <krewecherl@gmail.com> schreef in berichtnieuws
nf5ckn$b6k$1@news.albasani.net...
> R.Wieser wrote:
> >> * It augments host objects (adds a `slideIndex` property to the image
> >> objects). While the current major browsers all support this, it has
> >> historically led to problems that were hard to debug. In general, it's
> > best
> >> avoided, and there are other ways to associate custom values with
objects.
> >
> > A guess: using the above mentioned "data-*" attributes ?
>
> That's one possibility. I would probably keep the index in a closure, but
> that would require a completely different approach.
>
> Since `slideIndex` only holds an integer number, it's very unlikely to
cause
> trouble, even in older browsers. The potential for naming conflicts should
> probably be mentioned - e.g., image objects getting a native "slideIndex"
> property in the future. This is equally unlikely, but it's one more reason
> why augmenting host objects is usually avoided.
>
> >> * The original image (in the "src" attribute) is loaded, but then
> >> immediately switched out for slide1. This is unnecessary.
> >
> > Not quite: That first image will be visible for anyone having JS
blocked.
> > It was a consious decision to have it behave that way.
>
> I see, that makes sense. It may cause some duplication ("src" will
probably
> contain the same URL as "slide1"). In that case, I would use something
like
> this:
>
> <img src="slide1.png" data-slides="slide2.png|slide3.png|..."
>
> >> * The original code uses `a+ ++b`, which I personally think is a
> >> capital offense in coding ;) What this does:
> >> - use ++ to put `undefined` in a numeric context, giving 0
> >> - use ++ to pre-increment that value, giving 1
> >> - use + for string concatenation, giving "slide1"
> >> All that in the conditional expression in an `if` statement.
> >
> > Well, I also thought about that (being an offence). But as I have
worked
> > with other languages where non-existing variables where simply
> > created-on-use and given the value Zero, I did not see anything strange
in
> > JS doing the same.
> >
> > As for it being part of a conditional expression, the language
C{something}
> > does not seem to have any troubles with it, so I did/do not see a
problem
> > here either.
>
> The interpreter has no problem with it, my eyes do ;)
> It works as intended. My issue is that it's hard to read: it requires
> knowledge about operator precedence and two different type conversions,
and
> it creates and initializes the `slideIndex` property in the conditional.
> There's just too much going on for this line to be easily understood by
> another programmer.
>
> >> * <script language="JavaScript"> is quite obsolete now. Use
> >> <script type="text/javascript"> or just <script> instead.
> >
> > Thanks for the suggestion. I assume that "script" now just defaults to
JS
> > (as opposed to Microsofts own VBS) ?
> >
> > By the way, any idea why a script type should be "*text*/javascript" ?
Are
> > there any other types of JS available (precompiled (semy-)binary blobs
> > perhaps?) ? In other words, that "text" seems to be rather superfluous
....
>
> That's a very good question. The value of the "type" attribute is supposed
> to be the MIME type of the contained (or referenced) script. Official MIME
> types are published by IANA and consist of a top level type ("text",
> "application", "image", "video", ...) and a subtype. A script is program
> source code, not text, so it should theoretically be in the "application"
> category. According to RFC 4329 (2006), the proper MIME type is either
> "application/javascript" or "application/ecmascript" (and the two are not
> exactly the same). That RFC also officially defined "text/javascript" and
> "text/ecmascript" but immediately marked them as obsolete.
>
> So much for theory. In practice, "text/javascript" has been used in the
> overwhelming majority of cases, while any of the mentioned alternatives
> caused some browsers (notably IE) to ignore the script completely, making
> them technically correct but useless. Conversely, scripts without any
"type"
> or "language" attributes have always been interpreted by browsers as
> JavaScript. HTML5 has now codified this behavior, defining that the
absence
> of type/language attributes defaults to the type "text/javascript", and
> defining JavaScript as the default scripting language (with some side
notes
> about the naming of the language).
>
> Recently, another use for the "type" attribute has been added to define
> scripts as modules. This is an interesting new development, but irrelevant
> for you if you want broad browser support.
>
> I fully expect our resident standards expert to chime in with some
> invaluable corrections and ridicule concerning the last few paragraphs.
>
>
> - stefan


Thomas 'PointedEars' Lahn

4/19/2016 6:08:00 PM

0

Stefan Weiss wrote:

> The interpreter has no problem with it, my eyes do ;)

The interpreter does not even see the code; the (JIT-)compiler does. It is
a common misconception that source code of ECMAScript implementations would
be executed as it is. Instead, a compiler turns it into bytecode to be
interpreted by (the interpreter of) a virtual machine, or into native
machine code. This is the also the case with several other scripting
languages.

--
PointedEars
FAQ: <http://PointedEars.... | SVN: <http://PointedEars.de...
Twitter: @PointedEars2 | ES Matrix: <http://PointedEars.de/es-...
Please do not cc me. / Bitte keine Kopien per E-Mail.