Is this a useful solution to fetching a window object by name?

M

multicherry

Hi,

Having searched for a way to fetch a window object by name, all I came
across were answers along the line of...
"All you have to do is say windowObj = window.open("blah", "name");"
which isn't very useful if you want to fetch information from an
existing document in the window.

One solution I came up with was quite simple; open the "new" window,
giving you a reference to the object, then use window.history.back() to
force display of the previous contents. This isn't a perfect solution,
as it has the same effect as replacing the document, then clicking the
back button; but it seems to work.

The basic code required is given below. However, for those who are
interested, I've set up a working demonstration at
http://www.multicherry.com/windowbyname

*** FUNCTION:-

function get_window_object_by_name(nameStr)
{
var result = window.open('goback.htm', nameStr);
return result;
}

*** REQUIRED HTML DOCUMENT "goback.htm":-

.....<body>
<script lang="javascript" type="text/javascript">
window.history.back();
</script>
</body>....

Any thoughts?

- MCh

(This message posted to the public comp.lang.javascript Usenet
newsgroup via Google Groups. I am not associated with, nor a member of
any website/discussion-board which repackages and misrepresents such
discussions as belonging to themselves.)
 
Y

Yanick

Ressources are not saved between page transition. Thereof, any declared
window object will be lost when you replace the page content with other
date (leaving the other--popup--window opened). There is a few dirty
"hacks" to accomplish what you're trying to do, but keeping an active
link between two window objects is not in the scope the the Javascript
language.

I didn't test this, but maybe it's a start :

// put this in a js file that you will include in all you pages.
function setWindowName( name ) {
window._windowName = name;
}

function createLinkedWindow( url, name, options ) {
if ( !window._linked ) window._linked = {};

window._linked[name] = window.open( url, name, options );
window._linked[name]._linked[window._windowName] = window;
}

function changeWindowURL( url, name ) {
window._linked[name]._linked[window._windowName].location.href = url;
window._linked[name]._linked[window._windowName] = window;
}

function getWindowByName( name ) {
return window._linked[name]._linked[name];
}


Add this into a <script> section :

setWindowName( "MainWindow" ); // you should not use spaces in the
names
// create a new Window
createLinkedWindow( 'www.domain.com/some/page.html', 'AnotherWindow' );


Then, call this function whenever you're about to load a different
page, for example :

<a href="#" onclick="changeWindowURL(
'www.domain.com/another/page.html', 'AnotherWIndow' );" />Use Another
window to display another/page.html !</a>


Well... this is most likely to have a memory leak at some point, it
could be a start...
 
M

multicherry

Yanick said:
Ressources are not saved between page transition.

Does "resource" have a specific (i.e. formal) meaning here? It's clear
that *some* information can be retained, but not (apparently) variables
and fields.
Thereof, any declared
window object will be lost when you replace the page content with other
date (leaving the other--popup--window opened).

I don't understand; my demo shows that we *can* get the window object
(or one that is equivalent) and retrieve the *modified* HTML within the
old popup document. (That is, the old document retains any *changes*
made to its structure instead of just reloading "popup.htm").

Perhaps we're using the word "object" in slightly different ways. The
general problem I had (as I see it) is that when "second.htm" replaces
"first.htm" in the main window, we cannot transfer a *reference* to the
object.

Perhaps I'm incorrectly applying a Java-centric view of objects to
Javascript, but I'm assuming there's a single underlying window object
that we can have more than one reference to.
There is a few dirty
"hacks" to accomplish what you're trying to do,

Absolutely; my technique belongs to the "informal and messy" category
:)
I didn't test this, but maybe it's a start :

Your technique is interesting; I see what you're trying to do. I
haven't tried it out myself either (sorry :) ), but I see some
potential pitfalls:-

FIRST: The opened window only knows about the opening window by name.
It doesn't know about other windows its parent has opened (before OR
since the current window was created). And parents only "know" about
their children, *not* grandchildren, etc. (i.e. we have a tree-like
structure)

So although it's possible to find every window by name, we (probably)
have to find the tree root, then traverse some (or *all*) of the
branches to find the entry.

One solution might be to modify your code to either (a) Point to a
shared array containing all window names, or if that's not possible
with Javascript, (b) Copy the contents of the parent window's name
array.

Problem with (b) is that you then have to make sure that all the arrays
are kept up to date.

SECOND problem:
Here:-
window._linked[name] = window.open( url, name, options );
window._linked[name]._linked[window._windowName] = window;

I've got a horrible feeling that this may run into problems because the
new window won't be fully loaded when the second statement executes. I
might be wrong, but don't we have to wait for the window to load? How
do we do that synchronously?

Oh, apparently we can't.

(Disclaimer: I am *not* a Javascript expert. If I'm wrong, please
correct me, but I haven't come across solutions to the following
problems so far).

Sure, we can callback asynchronously via onload and friends. The major
problem (and one thing I really hate about Javascript) is that there
are times when you *don't want* to do things asynchronously; you'd like
to wait for the page to load.

AFAIK, it's not even possible to loop, doing a periodic check on some
attribute in the (new) page until it has loaded. Why? Because JS
doesn't support sleep(), so we can't put a reasonable gap between
checks. But a busy loop (e.g. while (! childWindow.check) { /* empty
loop */} ) has horrific effects on the browser performance (almost
locks it up).

I came up with a rather clever (I thought) solution to sleep() once. It
was simple; psleep() created and sent a *synchronous* XMLHttpRequest
for a "sleep.php" document, with the requested delay specified via
arguments. The document included some PHP code which caused the
*server* to sleep() for the requested number of seconds before
returning an empty (or irrelevant) document. The client, which was
waiting synchronously, was also delayed. Smart idea.

It didn't work.

Well, not under Firefox at any rate. The whole browser locked up for x
seconds, which wasn't the intention. Clearly, my best-guess mental
representation of Firefox's threading was faulty. Pity.

Why the *#$^ doesn't Javascript support sleep()? Seriously, there must
be a good reason for it, because it's a major PITA. Yes, I *know* about
setting timers/timeouts, etc., but they are *not* replacements for
sleep(); they have the same problems as described above.

Anyway, we now return you to your usual programming (no pun intended,
*cough*):-
Well... this is most likely to have a memory leak at some point, it
could be a start...

Leak? I hope not. AFAIK there's no manual malloc() in JS, so a true
leak would indicate a bug in the underlying implementation. Even valid
memory usage isn't likely to be that big for any app with a usable
number of windows...

- MCh
 
M

Matt Kruse

I came up with a rather clever (I thought) solution to sleep() once.
It was simple; psleep() created and sent a *synchronous*
XMLHttpRequest for a "sleep.php" document, with the requested delay
specified via arguments. ... Smart idea.

Horrible idea. Using synch mode for "ajax" requests is not a good practice
for the very reason you found - it locks up the entire browser and in some
cases parts of the OS until the response is received.
Why the *#$^ doesn't Javascript support sleep()?

Because there's isn't a need for it.
Javascript is single-threaded, and any activity that puts the entire browser
execution in a hold pattern for any amount of time is a bad idea.
Event-driven UI's don't like to work like that.
Leak? I hope not. AFAIK there's no manual malloc() in JS, so a true
leak would indicate a bug in the underlying implementation. Even valid
memory usage isn't likely to be that big for any app with a usable
number of windows...

It certainly is possible to create memory leaks using javascript in a
browser. Read up on it, and why MS doesn't consider it a bug in the
underlying implentation, or even worth fixing.
 
M

multicherry

Matt said:
Horrible idea.

Well, obviously. It was a reflection of what I was thinking at the
time; as I made clear, it failed horribly in practice.

But it seemed like a simple and ingenious solution at the time; and
quite frankly, unless you have a clear idea of how JS (or at least
Firefox) operates thread-wise, the flaws aren't obvious until you try
it out.
Using synch mode for "ajax" requests is not a good practice
for the very reason you found - it locks up the entire browser and in some
cases parts of the OS until the response is received.

Locking up the OS? That sounds like.... it really *shouldn't* be
allowed then.
Because there's isn't a need for it.
Javascript is single-threaded, and any activity that puts the entire browser
execution in a hold pattern for any amount of time is a bad idea.
Event-driven UI's don't like to work like that.

Are you talking about "threads" within Javascript or within the
underlying OS/browser-implementation-language?

Are you saying that (from the JS developer's POV) there's only a single
thread, and (by implication) that events must wait in a queue until the
code handling the previous events finished executing?

Or put another way, does synchronous "waiting" for (e.g.) an onload to
be triggered therefore cause the onload-handling-function to never be
called?

We're also getting into the sticky realm of what is covered by
Javascript and what isn't. Experiments I carried out whilst trying to
do a non-busy wait after a window.open() seemed to work.

However (IIRC) I checked the page load by having the parent window
script check the existence of a particular attribute/method within the
child page, rather than have the child calling back via onload. So this
doesn't necessarily contradict what you said; since page loading isn't
part of JS and thus shouldn't need another JS thread running.

Anyway, the truth is that these ideas (get_window_by_name() and
sleep()) were workarounds for problems in the architecture of a system
designed when I knew very little Javascript (and later had to abandon).
Had I known what I knew even six months later, it would have been
completely different.
It certainly is possible to create memory leaks using javascript in a
browser. Read up on it, and why MS doesn't consider it a bug in the
underlying implentation, or even worth fixing.

I will, and I'll take your word for that now, but it still sounds like
a "bug" to me, regardless of what MS say. :)

- MCh
 
R

Randy Webb

(e-mail address removed) said the following on 8/21/2006 6:50 AM:
Matt Kruse wrote:


Locking up the OS? That sounds like.... it really *shouldn't* be
allowed then.


Are you talking about "threads" within Javascript or within the
underlying OS/browser-implementation-language?

Javascript as it doesn't have multiple threads. It has single threads
and nothing more.
Are you saying that (from the JS developer's POV) there's only a single
thread, and (by implication) that events must wait in a queue until the
code handling the previous events finished executing?

That is precisely what happens.
Or put another way, does synchronous "waiting" for (e.g.) an onload to
be triggered therefore cause the onload-handling-function to never be
called?

Probably so. Test it :)
 
Y

Yanick

Does "resource" have a specific (i.e. formal) meaning here? It's clear
that *some* information can be retained, but not (apparently) variables
and fields.

What I meant by that is that any variables, objects, functions, etc.
declared (or in other words, any memory allocated by the browser for
any javascript ressource) will be cleared after the onunload event is
fired, before the new page begins to be downloaded. Thus, preserving
any value between pages is impossible without the use of cookies or
some kind of synchronisation...

You were right about the potential problems in my code (what was I
thinking ?). Synchronizing a tree of window object's references is a
good idea. But that will always have a fall back because, as you said,
knowing when the browser is done loading data is not an easy task
(especially when there's a lot of ressources to load).

Memory leaks with Javascript are easier to produce than you might
think... Here's a link that gives some explanations :
http://www.codeproject.com/jscript/LeakPatterns.asp .

Playing with server side session IDs (with the help of
XMLHttpRequests...) you could synchronize all your "registered" windows
with a server side script... Or use a frameset with a single frame
(top) to load all you different pages and keep the Javascript
environment variables in the window scope (a messy solution...).
There's no straight foreward solutions, and the language is limited in
this situation (cookies cannot store objects), you will soon find that
memory leakage and broken references (or even cyclic ones) is more an
eventuality than possibility.

Personally, I'd recommand that you find other solutions to retreive
data from child windows ; other solutions than keeping them in sync.
But I guess that, if weren't busy with all sort of things, I myself
would try to make this work.. .just for the heck of it. :)

Anyhow, good luck.
 
M

multicherry

Yanick said:
You were right about the potential problems in my code (what was I
thinking ?).

Not a problem; you pretty much said yourself that it was only a quick,
rough and untested idea, designed to illustrate a principle and nothing
more. So it wasn't my intention to hold it to the same standards as
(e.g.) the Linux kernel.... I was just proving I'd actually read it :)
Memory leaks with Javascript are easier to produce than you might
think... Here's a link that gives some explanations :
http://www.codeproject.com/jscript/LeakPatterns.asp .

Haven't had time to consider everything in the article in depth, but it
appears that one of the examples is a circular reference being missed
because it straddles the territory of the DOM garbage collector and the
Javascript one. Interesting...
Playing with server side session IDs (with the help of
XMLHttpRequests...) you could synchronize all your "registered" windows
with a server side script... Or use a frameset with a single frame
(top) to load all you different pages and keep the Javascript
environment variables in the window scope (a messy solution...).

That's the one I was thinking of, and the way I would have done it in
the first place (or at least I'd have used frames), had I not been a
complete JS newbie when I designed the code and been unable to easily
change it later.
There's no straight foreward solutions, and the language is limited in
this situation (cookies cannot store objects), you will soon find that
memory leakage and broken references (or even cyclic ones) is more an
eventuality than possibility.

I have to say that I'm always asking myself how much my frustration
with JS is down to lack of experience and how much is down to
limitations with the language. In the case of JS, it's far more
advanced than it used to be, but I'm still aware that it's a simple
scripting language with stuff added on later... not to mention issues
of compatibility and incompatibility with different browsers and older
code.

Anyway, thanks to everyone for the feedback.

Bottom line, my window-grabbing "tip" still works (if you can live with
its hackiness), but the limitations described above mean its usefulness
isn't that great for most situations. :-/


- MCh
 

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,754
Messages
2,569,527
Members
44,998
Latest member
MarissaEub

Latest Threads

Top