speed issues traversing the DOM.

  • Thread starter The Natural Philosopher
  • Start date
T

The Natural Philosopher

I raised this last week, and found a reasonable hack, but would like to
get a better solution, and hopefully a more elegant solution..that runs
a heck of a lot faster.

basically its a flyout menu system,

of this sort of form

<Div frame>
<div an elemenet onmuosover selcet child frame and cancel others>click
me</div>
.......

...

</div> <!-- end the frame. -->


This lot is php created, so its no big deal to utterly change the 2000
odd elements with mouseovers attached.

Now currently each frame has an ID so I can traverse them all, switching
off the ones no longer wanted, and switching on the one that is.


The trouble is, the HTML and script to tell each JS onmouseover which to
turn on and which to turn off would be massive.

That would kill the page load time.

By traversing all the divs, till the right ones are found, its not too
bad, but when I added a second example of this type to the same page,
there seems to be a 4 times slowdown.

Its got unacceptable. i have around 2000 divs on the page, and scanning
the lot and checking each one seems to take about half a second in
firefox, and nearly two seconds in Ie7.

My previous hack consisted in registering which ones were relevant into
a table. Do if a div had been turned ON, it would be in the table, and
if not well..then you had to find it to turn it on. This worked fairly
well after a few slow scans, as te tale was then mostly complete.

But it would be nice to know a better way of creating a subset of all
the divs in the page that cold be searched faster. Preferable when te
page is assembled, rather than when it is run.

So teh questions are of two basic kinds.

Firstly, how can you at page creation time build a set of references to
DOM objects..?

Sort of <div <script> register(this)</script>> </div> ?

Is anything like that possible?

If thats not possible how is teh DOM structired..fir example if I give
te parent conainers and ID, can I merely search their children, rather
then the whole p[ge?

i.e. if I do a
document.geteElementById('container').getElementsByTagName('div') is
that efficient to isolate only those divs inside that container?

Another useful one would be a docment.getElementsByZIndex('n') :-()

So how to efficiently either register, or find, certain divs is the
problem. Given a bloody lot of them in the first place, most of which
are superfluous to the search.
 
T

The Natural Philosopher

The said:
I raised this last week, and found a reasonable hack, but would like to
get a better solution, and hopefully a more elegant solution..that runs
a heck of a lot faster.

basically its a flyout menu system,

of this sort of form

<Div frame>
<div an elemenet onmuosover selcet child frame and cancel others>click
me</div>
......

..

</div> <!-- end the frame. -->


This lot is php created, so its no big deal to utterly change the 2000
odd elements with mouseovers attached.

Now currently each frame has an ID so I can traverse them all, switching
off the ones no longer wanted, and switching on the one that is.


The trouble is, the HTML and script to tell each JS onmouseover which to
turn on and which to turn off would be massive.

That would kill the page load time.

By traversing all the divs, till the right ones are found, its not too
bad, but when I added a second example of this type to the same page,
there seems to be a 4 times slowdown.

Its got unacceptable. i have around 2000 divs on the page, and scanning
the lot and checking each one seems to take about half a second in
firefox, and nearly two seconds in Ie7.

My previous hack consisted in registering which ones were relevant into
a table. Do if a div had been turned ON, it would be in the table, and
if not well..then you had to find it to turn it on. This worked fairly
well after a few slow scans, as te tale was then mostly complete.

But it would be nice to know a better way of creating a subset of all
the divs in the page that cold be searched faster. Preferable when te
page is assembled, rather than when it is run.

So teh questions are of two basic kinds.

Firstly, how can you at page creation time build a set of references to
DOM objects..?

Sort of <div <script> register(this)</script>> </div> ?

Is anything like that possible?

If thats not possible how is teh DOM structired..fir example if I give
te parent conainers and ID, can I merely search their children, rather
then the whole p[ge?

i.e. if I do a
document.geteElementById('container').getElementsByTagName('div') is
that efficient to isolate only those divs inside that container?

Another useful one would be a docment.getElementsByZIndex('n') :-()

So how to efficiently either register, or find, certain divs is the
problem. Given a bloody lot of them in the first place, most of which
are superfluous to the search.


Bit of an update: I traced this to several problems, the real crawler
being a redundant mouseover event that was searching every div in the
document.

What it basically boils down to that getElementByDiv() is only about
2500 divs/sec on a rather dull PC on IE7. Its about 2-3 times that on
Firefox.

I've hacked a workaround that gives me the speed I want, by storing each
<div> I turn on in an array, that can be run through to turn them off,
but I'd still like an answer to a better way to do it. To essentially
pre-load the array.
 
S

SAM

Le 11/29/08 12:41 PM, The Natural Philosopher a écrit :
I raised this last week, and found a reasonable hack, but would like to
get a better solution, and hopefully a more elegant solution..that runs
a heck of a lot faster.

basically its a flyout menu system,

of this sort of form

<Div frame>
<div an elemenet onmuosover selcet child frame and cancel others>click

what does mean 'selcet' ? select ?

what does mean "to select child *frame*" ?
what do you want to do with the children ?

is that an obligation to work only with divs ?
and with "more than 2000" of them ?
Can't you serialize/organize your presentation ?
<div>
<h2>title</h2>
<p>Normal viewed text</p>
<p class="hid">content to reveal on mouse over</p>
</div>

Can't you use only CSS ?
demo:
<http://cjoint.com/?lDsFPCPNv4>

If really you prefer to use javascript :
using JS to fix the onmouseOver and onmouseOut on 2400 elements
- my FF.3 needs 0.1 second
- my IE.6 needs 1.1 second
demo:
<http://cjoint.com/?lDsIHv3nDn>

To fix the mouse events you don't need to loop all the 'DIVs'
then, while looping, you don't need to retain the correct ones.
Try to use what HTML gives as special tags and loop only this ones
(in the demo I used the tag 'DL')

Before to show the correct one, the function show/hide has not to
disabled all divs that have this mouse events.

onmouseover="show(this);"
monmouseout="hide(this);"

Or with the bit of code above :

<div
onmouseover="this.className='show';"
onmouseout="this.className=''>
<h2>title</h2>
<p>Normal viewed text</p>
<p class="hid">content to reveal on mouse over</p>
</div>

And the associated css :

div .hid { display: none; }
div.show .hid { display: block; }
 
D

David Mark

Le 11/29/08 6:57 PM, SAM a écrit :




and using document.all instead of document.getElementById('DL')
it is a few longer
<http://cjoint.com/?lDt5zsSAVm>

You would have to be mad to use this code.

/* ***** no javascript except to fill up the page with 2000 items and
more ******* */

No, there is some.

function see(what) {
what.className = what.className==''? 'show' : '';
}

The "what" argument is unnecessary and foreshadows a bigger problem.

window.onload = function() {
// is it IE ?
var IE = false; /*@cc_on IE = true @*/

Needless. Use CC only when necessary (virtually never.)

// installation of 200 divs with each having 12 objects
var m = function() { return document.getElementById('menu').cloneNode
(true);};
for(var i=0; i<200; i++) {
var m1 = m();
m1.id = 'm_'+i;
m1.getElementsByTagName('h3')[0].innerHTML = 'Menu #'+(+i+2);
document.body.appendChild(m1);
}

It needs gEBTN, appendChild, cloneNode and the non-standard innerHTML
property just to get started, but detects nothing.

// stop before following
alert('all 2400 elements in place\ncreation of the 4800 mouse
events');

Implied global.

var t1 = new Date()
// creation of mouse events on the 2400 items
if(IE) {

Use feature detection for this.

var d = document.all, n = d.length;
for(var i=0; i<n; i++) if(d.tagName.toLowerCase() == 'dl')
{
d.onmouseover = function() { see(this); };
d.onmouseout = function() { see(this); };

Needless inner functions, which also create circular references
involving elements.

http://www.jibbering.com/faq/faq_notes/closures.html#clMem

}
}
else {
var d = document.getElementsByTagName('DL'), n = d.length;
for(var i=0; i<n; i++) {
d.onmouseover = function() { see(this); };
d.onmouseout = function() { see(this); };

Same.

}
}
var t2 = new Date();

alert('Mouse events finished in : '+(+t2-t1)/1000+' seconds');

And lots of memory leaked. Set d to null to break the 2400 x 2
chains.

}

Use one listener for things like this. Delegate based on the event
target. And don't create memory leaks.
 
S

SAM

Ça y est c'est mon tour.
Je sens que ça va être ma fête ! !

Le 11/29/08 8:30 PM, David Mark a écrit :
You would have to be mad to use this code.

The next line is a mistake
(coming from a previous file that had no JS, see previous link in
previous post)
/* ***** no javascript except to fill up the page with 2000 items and
more ******* */

No, there is some.

Yes, a bit.
function see(what) {
what.className = what.className==''? 'show' : '';
}

The "what" argument is unnecessary and foreshadows a bigger problem.

Some light about the bigger problem ?
If no argument, what do you propose ?
window.onload = function() {
// is it IE ?
var IE = false; /*@cc_on IE = true @*/

Needless. Use CC only when necessary (virtually never.)

I use that code when I want ! non mais !

As some browsers accept document.all when in same time they prefer GDBI
I use CC to be sure to speak exclusively to IE (unlovely that catches IE
Mac too).
// installation of 200 divs with each having 12 objects

Yes, I'll not copy-paste 200 times same lines.
(and come back on them to change the IDs and the texts, 12 times was enough)
var m = function() { return document.getElementById('menu').cloneNode
(true);};
for(var i=0; i<200; i++) {
var m1 = m();
m1.id = 'm_'+i;
m1.getElementsByTagName('h3')[0].innerHTML = 'Menu #'+(+i+2);
document.body.appendChild(m1);
}

It needs gEBTN, appendChild, cloneNode and the non-standard innerHTML
property just to get started, but detects nothing.

The non-standard innerHTML is de facto a standard if used knowing what
it does.
What do you want it detects ? (what is "it" ?)
maybe : getElementsByTagName ?
// stop before following
alert('all 2400 elements in place\ncreation of the 4800 mouse
events');

Implied global.

Not understood.
var t1 = new Date()
// creation of mouse events on the 2400 items
if(IE) {

Use feature detection for this.

Can you give me a detection will ensure that the browser is IE
and *only* IE ?
var d = document.all, n = d.length;
for(var i=0; i<n; i++) if(d.tagName.toLowerCase() == 'dl')
{
d.onmouseover = function() { see(this); };
d.onmouseout = function() { see(this); };

Needless inner functions, which also create circular references
involving elements.


I asked Google to help me understand your sentence in pure pain
(Needless inner functions ?)

Je ne comprends rien aux closures, il n'y a pas de mot francais pour en
traduire le sens.
I definitively understand nothing about closures.
Isn't it enough to close the page to leave the closure ?

I do not see a circular reference in
onmouseover="see(this)"
except on same element (on itself).
And it is well the goal : to do something with itself.
(to do not have an argument wouldn't have to change something about
circular ref)
}
}
else {
var d = document.getElementsByTagName('DL'), n = d.length;
for(var i=0; i<n; i++) {
d.onmouseover = function() { see(this); };
d.onmouseout = function() { see(this); };

Same.

}
}
var t2 = new Date();

alert('Mouse events finished in : '+(+t2-t1)/1000+' seconds');

And lots of memory leaked.


Pas grave, il doit en rester.
With UC that have in this time 2Go and more memory, what could do a
little leak like that ?
Have I to put in my pages a button to relaunch Windows ?
Set d to null to break the 2400 x 2
chains.

}

Use one listener for things like this. Delegate based on the event
target. And don't create memory leaks.

OK, I will try.
Just I don't remember how to do.
<http://cjoint.com/?lDx3fnF8XZ>
(don't look at the JS copyclone : I have no server access on cjoint)

The listener takes 20% more time in my FF.3 and 10 times more time (tts:
14 to 16 seconds) in my IE.6 than the leaking memory.
Perhaps there is something wrong in my code ?
(I found somewhere the listener function)
 
T

The Natural Philosopher

SAM said:
Le 11/29/08 12:41 PM, The Natural Philosopher a écrit :

what does mean 'selcet' ? select ?

what does mean "to select child *frame*" ?
what do you want to do with the children ?
Its a hierarchical tree menu. Elements are in pages
I call a flyout page a frame.

There are an indefinite amount of elements within each flyout page. Each
one is either a mouseover event that spawns yet another leaf, or a
clickable entity, so each one is a div. Perhaps it needn't be, but that
makes absolute formatting easier. It is extremely difficult to establish
when one frame flys out, what others should be canceled, so the
algorithnm simply un-dispalys all at the same level or below, except the
direct child of the mouseover one.

That means a reasonable amount of frames have to be canned. Ive limited
it to just the flyout frames now, which has speeded things up a lot.

The problem resolves to the simplest way of creating a substructure to
scan, that has pointers into only the relevant DOM elements that need
scanning.

My hack is to register each frame as it is turned on by adding it to an
array of elements 'that have been turned on' and to turn off the ones in
that array solely.

I was just hoping that there might be a way to have that array loaded at
download time, but I don't see a simple way of passing a pointer to a
dom object before javascript actually runs, or, how to perform the scan
of the relevant elements efficiently at load time.


If you like,. given a random selection of DOM elements that you want to
access and modify via javascript, how can you tag them so that they and
they alone can be the subject of efficient searches?

So far I have only found one way, and that is to have an onmouseover
event tell a registration fubction 'hey I am a mousover elements child,
I'm the one that needs to be in your data structure: then one
getelementById once, identifies the object that will need undisplaying
later.

So, the function that uniquely sets a container of menu elements to
'block' also registers that element on the list of elements to be
undisplayed

Hers is a fragment from a simplert tow level meenu strictire that
illustates this
*************************************
var menus =new Array() // array for our menus.

// switch on div whose id is 'name'+'id' and register it, all others off


function show (id) // expands a menu of this name at this level with
this parent id.
{
var ourdiv;
var ourid= 'menu'+id; // the div id to switch on.
if(!menus[ourid] && (ourdiv=document.getElementById(ourid)))
{
menus[ourid]=ourdiv;
}
var i;
for (i in menus)
{
if(i==ourid) // thats us
{
menus.style.display='block';
document.getElementById("transparent").style.display='block';
// this is a catchall 'glass' screen at lower Zindex that traps movement
// outside the menus
}
else menus.style.display='none';
// this collpases all other menus that are registered
}
}


is that an obligation to work only with divs ?

Well, I am a goodish coder, but not a great javascripter, and DOMmer and
divs seemed the way to get entities that were absolutely positioned,
could take an ID, and could take mouse events. If you know better, let
me know..
and with "more than 2000" of them ?

Yup. I am handling a stores with over 1000 items in about 30 categories,
any one of which must be selectable. The code is generic, but the screen
I am working on is multi-level kitting, so I need to both select a part
- say 'box of chocolates' and craate an assembly that says '2 caramel,
three hazelnut, 1 cherry' and 'box' 'insert' 'contents list' and '5 mins
of packing labour' etc etc.

So the need is to rapidly search through a very large number of
categories and actual items, to insert them in a data structure
representing 'the box of chocolates'

The same code will be used when entering orders as well, so you can pick
from (a salable subset of) the inventory.

I tried using straight <SEECT> <OPTION> but that only allowed a one
dimensional search and selecet, and was too clumsy to be functional. The
customer rejected it.
Can't you serialize/organize your presentation ?
<div>
<h2>title</h2>
<p>Normal viewed text</p>
<p class="hid">content to reveal on mouse over</p>
</div>

It is done that way. But class is not a unique identifier,,have ti use IDS


Can't you use only CSS ?
demo:
<http://cjoint.com/?lDsFPCPNv4>

If really you prefer to use javascript :
using JS to fix the onmouseOver and onmouseOut on 2400 elements
- my FF.3 needs 0.1 second
- my IE.6 needs 1.1 second

Yup. That was consistent with my findings. Customer has IE7, and I have
that on a scrappy oldish PC. Mostly I run a mac for the desk, and the
codes on linux/apache/php/mysql

AsI say, I have a solution, just hoping for a better one.
demo:
<http://cjoint.com/?lDsIHv3nDn>

To fix the mouse events you don't need to loop all the 'DIVs'
then, while looping, you don't need to retain the correct ones.
Try to use what HTML gives as special tags and loop only this ones
(in the demo I used the tag 'DL')

you can create a special 'tag' in CSS?
I thought it was styles alone..

Can you give me an example?
Before to show the correct one, the function show/hide has not to
disabled all divs that have this mouse events.

onmouseover="show(this);"
monmouseout="hide(this);"

Onmouseout proved to be very unreliable with much bubbling.

In fact part of te problem I had was with having a second menu 'screen'
that would also clear a selection of primary menus. So a menu clear was
needlessly clearing three menus, inneficiently, each one of which was
scanning every div in the page. So I was up to around 7500 div searches.
Not good.

I've cleaned that up a lot, by teh registration code above. It works ok,
and seems browaer generic, but it seemed a bit of a hack, thats all.
and I wondered if there was a better way.
Or with the bit of code above :

<div
onmouseover="this.className='show';"
onmouseout="this.className=''>
<h2>title</h2>
<p>Normal viewed text</p>
<p class="hid">content to reveal on mouse over</p>
</div>

And the associated css :

div .hid { display: none; }
div.show .hid { display: block; }

Well that's not nearly good enough. I dont want to clear parent menus
when I move to a child, not least because that leaves my cursor hanging
over nothing.


I'd post the URL so you can see it working, but sadly that would nee a
name/password and you then get access to real data on my database which
ain't mine to give away, and contains not a little =intellectual
property. It ain't boxes of chocolates.. ;-)
 
D

David Mark

Ça y est c'est mon tour.
Je sens que ça va être ma fête ! !

Le 11/29/08 8:30 PM, David Mark a écrit :



The next line is a mistake
(coming from a previous file that had no JS, see previous link in
previous post)



Yes, a bit.



Some light about the bigger problem ?

As mentioned, memory leaks. See below.
If no argument, what do you propose ?

Using the "this" identifier in the listener.
I use that code when I want ! non mais !

As some browsers accept document.all when in same time they prefer GDBI
I use CC to be sure to speak exclusively to IE (unlovely that catches IE
Mac too).

Which is silly. Always test the standard (gEBI in this case) first,
then you won't have a problem.

[snip]
The non-standard innerHTML is de facto a standard if used knowing what
it does.

No matter. Is isn't needed for this and you didn't test it (or
anything else.)
What do you want it detects ? (what is "it" ?)
maybe : getElementsByTagName ?

That would be a start.
Not understood.



Can you give me a detection will ensure that the browser is IE
and *only* IE ?

That isn't what you are trying to detect here. You want to know if
you can use document.all without throwing an exception, so you should
detect document.all (only after testing gEBI.)

Right there it will blow up if some new version of IE eliminates
document.all.
     for(var i=0; i<n; i++) if(d.tagName.toLowerCase() == 'dl')
        {
        d.onmouseover = function() { see(this); };
        d.onmouseout = function() { see(this); };

Needless inner functions, which also create circular references
involving elements.

I asked Google to help me understand your sentence in pure pain


I know the feeling.
(Needless inner functions ?)

Yes. Hark back to the "what" argument.
Je ne comprends rien aux closures, il n'y a pas de mot francais pour en
traduire le sens.
I definitively understand nothing about closures.
Isn't it enough to close the page to leave the closure ?

What are you doing creating closures if you know nothing about them?
As the cited article indicates, they can be dangerous in IE. Read the
article. If you print it out double-spaced it is maybe three pages.
I do not see a circular reference in
   onmouseover="see(this)"

I don't know what that is, but your example created such references.
except on same element (on itself).
And it is well the goal : to do something with itself.
(to do not have an argument wouldn't have to change something about
circular ref)

You are wrong. No argument = no inner function = no closure = no
circular reference = no memory leak.
        }
     }
  else {
   var d = document.getElementsByTagName('DL'), n = d.length;
   for(var i=0; i<n; i++) {
    d.onmouseover = function() { see(this); };
    d.onmouseout = function() { see(this); };

    }
  }
  var t2 = new Date();

  alert('Mouse events finished in : '+(+t2-t1)/1000+' seconds');
And lots of memory leaked.

Pas grave, il doit en rester.


Do you mind? I don't speak French.
With UC that have in this time 2Go and more memory, what could do a
little leak like that ?

Open your task manager and find out. Or just set the nodelist
reference to null as mentioned.
Have I to put in my pages a button to relaunch Windows ?

No, you need to learn to write proper scripts.
OK, I will try.
Just I don't remember how to do.

I gave you a link.
<http://cjoint.com/?lDx3fnF8XZ>
(don't look at the JS copyclone : I have no server access on cjoint)

I am through looking at it.
The listener takes 20% more time in my FF.3 and 10 times more time (tts:
14 to 16 seconds) in my IE.6 than the leaking memory.
Perhaps there is something wrong in my code ?

Yes. Lots of things.
(I found somewhere the listener function)

Throw it back.
 
J

Jorge

But it would be nice to know a better way of creating a subset of all
the divs in the page that cold be searched faster. Preferable when te
page is assembled, rather than when it is run.

When the page is assembled: put the <script> tag at the end of the
<body>, right before the </body>, and don't wrap it with
window.onload= function () { the script code };. This gives you back
some extra time: the time that the browser kept waiting before
dispatching the "load" event to the "onload" event-handler:

<html>
<head></head>
<body>
<script>
//The dom is ready, all the elements are in-place, but the page
has not been drawn into the screen yet.
</script>
</body>
</html>

Instead, this waits until after everything else has been loaded and
the page has been drawn:

<html>
<head></head>
<body>
<script>
//The dom is ready, all the elements are in-place. Page has not
been drawn yet.
window.onload= function () {
//But this won't run until after the page has been drawn and all
its resources have been loaded.
};
</script>
</body>
</html>

AFAIK,
 
J

Jorge

When the page is assembled: put the <script> tag at the end of the
<body>, right before the </body>, and don't wrap it with
window.onload= function () { the script code };. This gives you back
some extra time: the time that the browser kept waiting before
dispatching the "load" event to the "onload" event-handler:

<html>
<head></head>
<body>
  <script>
    //The dom is ready, all the elements are in-place, but the page
has not been drawn into the screen yet.
  </script>
</body>
</html>

Instead, this waits until after everything else has been loaded and
the page has been drawn:

<html>
<head></head>
<body>
  <script>
    //The dom is ready, all the elements are in-place. Page has not
been drawn yet.
    window.onload= function () {
      //But this won't run until after the page has been drawn and all
its resources have been loaded.
    };
  </script>
</body>
</html>

AFAIK,

The page's html goes before our <script> tag, obviously:

<body>

<h1>The page</h1>

etc etc.

The last tag ought to be the script:
<script>
 
T

The Natural Philosopher

Jorge said:
When the page is assembled: put the <script> tag at the end of the
<body>, right before the </body>, and don't wrap it with
window.onload= function () { the script code };. This gives you back
some extra time: the time that the browser kept waiting before
dispatching the "load" event to the "onload" event-handler:

<html>
<head></head>
<body>
<script>
//The dom is ready, all the elements are in-place, but the page
has not been drawn into the screen yet.
</script>
</body>
</html>

Instead, this waits until after everything else has been loaded and
the page has been drawn:

<html>
<head></head>
<body>
<script>
//The dom is ready, all the elements are in-place. Page has not
been drawn yet.
window.onload= function () {
//But this won't run until after the page has been drawn and all
its resources have been loaded.
};
</script>
</body>
</html>

AFAIK,
Wellthat is handy enough and worth knowing, but only answers half the
question..

I suspect my problem is that I am unused to interpreted languages.

In a compiled language and element like a DIV gets a label, and you can
refer to it anywhere you like as you WRITE the code.

It seems that in the javascript DOM context all you can do is give it an
ID and then have the code LOOK for it at runtime.

Is that essentially the case?
 
T

The Natural Philosopher

Jorge said:
The page's html goes before our <script> tag, obviously:

<body>

<h1>The page</h1>

etc etc.

The last tag ought to be the script:
<script>

Sorry, you have confused me - script inside the body, or outside.

<html>
<head>
</head>
<body>
a lot of body
<script>
startup stuff
</script>
</body>
</html>

Or

<html>
<head>
</head>
<body>
a lot of body
</body>
<script>
startup stuff
</script>
</html>

???
<
 
D

David Mark

When the page is assembled: put the <script> tag at the end of the
<body>, right before the </body>, and don't wrap it with
window.onload= function () { the script code };. This gives you back
some extra time: the time that the browser kept waiting before
dispatching the "load" event to the "onload" event-handler:

It doesn't give you extra time, it causes the script to run before the
body has finished loading.
<html>
<head></head>
<body>
  <script>
    //The dom is ready, all the elements are in-place, but the page

The DOM cannot be considered "ready" at this point. And all of the
elements are not in place. The body hasn't even closed. Google
"Operation Aborted" and IE.

[snip]
 
D

David Mark

Wellthat is handy enough and worth knowing,  but only answers half the
question..

I suspect my problem is that I am unused to interpreted languages.

I wouldn't close the investigation just yet.
In a compiled language and element like a DIV gets a label, and you can
refer to it anywhere you like as you WRITE the code.

Well, I am glad we got that sorted out.
It seems that in the javascript DOM context all you can do is give it an
  ID and then have the code LOOK for it at runtime.

You've been told repeatedly that the DOM is not part of the language.
This looks like VK syndrome.
Is that essentially the case?

Your case worker will be with you shortly.
 
S

SAM

Le 11/30/08 11:58 AM, The Natural Philosopher a écrit :
Sorry, you have confused me - script inside the body, or outside.

both please.


<head>
<script ..>
all the necessary functions
- array creation
- events
- and so on
</script>
</head>
<body>

.... blah
.... blah

<script ...>
init(); // start the JS job in the head
</script>
</body>
 
S

SAM

Le 11/30/08 12:19 PM, David Mark a écrit :
[snip]
Sorry, you have confused me - script inside the body, or outside.

Well, it could hardly be after the body could it?


I saw JS after the html tag closing.

</html>
<script ...>

(and it seemed to work !)
 
D

David Mark

J

Jorge

In a compiled language and element like a DIV gets a label, and you can
refer to it anywhere you like as you WRITE the code.

It seems that in the javascript DOM context all you can do is give it an
ID and then have the code LOOK for it at runtime.

Is that essentially the case?

If the element has been inserted into the DOM by the html parser, then
yes, you need to find it first somehow, at least once, (walkTheDOM,
use a DOM search method (.getElementXXX) or lookup into an
htmlCollection) in order to get (and save) a reference to it.
If it was inserted into the DOM by your (JS) code, you already have a
reference to it (that you can save) so there's never the need to
search for it.

You can build the contents of that shop's catalog at the server and
send it prebuilt tagged as html, or
You can build it dynamically, client-side, by sending the *data* from
the server, not markup no html (usually JSON).

For example: the server's PHP can send it either:

prebuilt as html:

<div id="reference456">Chocolat Cookies</div>
<div id="reference457">Plum Cake</div>

Or as data:

<script>
var catalog= {
'reference456': 'Chocolat Cookies',
'reference457': 'Plum Cake'
};
</script>

In the second case, the browser has the catalog as data, and the JS
code (client-side) has to build the presentation of that data:

<script>
(function () {
if (catalog && (typeof catalog === "object")) {

var itemRef, itemName, itemDOMElement;

for ( itemRef in catalog ) {
if (catalog.hasOwnProperty(itemRef)) {

//create the DOM element
itemDOMElement= document.createElement('div');
//Fill the div's content
itemDOMElement.innerHTML= itemName= catalog[itemRef];

//Pack it all into an object
catalog[itemRef]= {
'itemName': itemName,
'itemDOMElement': itemDOMElement,
'anotherUsefulProperty': Math.random()
};

//And insert the element into the page.
document.body.appendChild(itemDOMElement);
/* or:
document.body.appendChild(catalog[itemRef].itemDOMElement);
/*
}
}
}
})();
</script>

You'd end up with a nice JS data structure (object) : catalog= {
'reference456': {
'itemName': "Chocolat Cookies",
'itemDOMElement': (referenceToTheDivDOMElement),
'anotherUsefulProperty': (a random number)
},

'reference457': {
'itemName': "Plum Cake",
'itemDOMElement': (referenceToTheDivDOMElement),
'anotherUsefulProperty': (a random number)
}
}

....and no need to ever search the DOM. But, then, your page is turning
more and more into a webApp.
 
J

Jorge

The DOM cannot be considered "ready" at this point.  And all of the
elements are not in place.  The body hasn't even closed.  Google
"Operation Aborted" and IE.

Well, that you can't append to the body does not mean that the
(already, previously) parsed html elements aren't in-place. They are.
In any case, if you want to be able to append to the (not yet closed)
body tag just wrap the script into a setTimeout( ,0). That's all:

<script>
window.window.window.setTimeout(function () {
// put the code here in order to cure another of
// (the seemingly interminable list of)
// IE's inconvenient "oddities"
},0);
</script>
 

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

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top