reptile7's JavaScript blog
Sunday, August 30, 2009
 
You Get My Prime Time
Blog Entry #155

(September 2016 Update: The first page of the current "Remote Control JavaScript" tutorial is marred - wrongly, HTML has been inserted into the underlying document's openindex( ) function, thereby killing the tutorial script and preventing the display of the OpenWindow window - so I'm going to give you links to archived versions of all three tutorial pages in the discussion below.)

We've addressed the subject of HTML Goodies' "Remote Control JavaScript" tutorial at least a couple of times previously - namely, a window.open( )-opened window's document can be used to load new resources into (or otherwise manipulate) an opener window and thus act as a "remote control" for an opener window. Nevertheless, it is still worth our while to review briefly the code presented by "Remote Control JavaScript" and comment on its execution in practice.

The "Remote Control JavaScript" tutorial is actually spread over three pages. When you visit the tutorial's first page and if your browser is not set to block pop-up windows, then the remote control window below pops up:
The 'Remote Control JavaScript' remote control window
Clicking the new window's Section Two link loads the tutorial's second page into the opener window; clicking its Section Three link loads the tutorial's third page into the opener window. The "Section Two" page gives the following script for creating a remote control window:

<script type="text/javascript">

function openindex( )
{
OpenWindow = window.open("", "newwin", "height=300,width=150,toolbar=no,scrollbars=" + scroll + ",menubar=no");
OpenWindow.document.write("<title>R.C.</title>");
OpenWindow.document.write("<center>");
OpenWindow.document.write("<center><font size=+1>Remote<br />Control</font>");
OpenWindow.document.write("<a href='remote_control_2.html' target='main'>Section One</a><p>");
OpenWindow.document.write("<a href='remote_control_3.html' target='main'>Section Two</a><p>");
OpenWindow.document.write("</center>");
OpenWindow.document.close( );
self.name = "main";
}
</script>


As specified on the "Section Three" page, the script's openindex( ) function is triggered by the loading of the tutorial's first page:

<body bgcolor="ffffff" onload="openindex( );">
<!-- Some browsers will not act on a hex-code color value that is not prefixed with a hash mark (#). -->


The openindex( ) function kicks off with a window.open( ) command that pops up the remote control window and gives it the object reference OpenWindow. The command's strWindowFeatures string sets the width and height of the OpenWindow viewport to 150 pixels and 300 pixels, respectively. In addition, the strWindowFeatures string unnecessarily sets the toolbar and menubar chrome features to no (Mac users will still see a menu bar at the top of the screen) and it contains the strange scrollbars = scroll assignment that we saw in the "Remote Image" script and discussed in Blog Entry #150; the toolbar, scrollbars, and menubar features can all be subtracted from the strWindowFeatures string without incident.

The next six openindex( ) commands write the document contained by the OpenWindow window. The OpenWindow document head specifies an R.C. title for the OpenWindow title bar. The OpenWindow document body holds a Remote Control heading of sorts and, more importantly, Section One and Section Two hyperlinks that respectively target remote_control_2.html and remote_control_3.html documents to a window named main.

Following an unnecessary OpenWindow.document.close( ) command for closing the OpenWindow document, the last openindex( ) command 'completes the circle' by assigning the identifier main to the name property of the opener window, which is referenced using its self property.

In his introduction on the tutorial's first page, Joe says, If you can rewrite this so it works on Explorer, I would be glad to post it here. In fact, the "Remote Control JavaScript" script doesn't contain any Netscape-specific code and it does work with MSIE 5.2.3 for Mac OS X on my computer.

In the "HTML Inside the Remote Control Box" section of the tutorial's second page, Joe states, In addition you cannot have any quote marks in your HTML. Just don't use them. If you do - they will throw an error. I'll acknowledge that the formatting of nested quotes in JavaScript can sometimes be tricky, but this isn't the case here - indeed, in the above code Joe himself quotes the href and target attribute values for the anchor elements correctly, i.e., single quotes are placed within double quotes.

In the "Placing the Script" section of the tutorial's third page, Joe alleges, Do not place the script within the body commands. It won't run there. Not true.

OpenWindow.document presentation and related practical matters

Near the beginning of the "Section Two" page, Joe says, In order to get the two windows to play with each other, I had to make a point of [coding] them together to begin with. So I did. Actually, there's no reason why the OpenWindow document couldn't be moved to an external file; you'd have to maintain two files in that case instead of one, but on the plus side the openee document would be easier to read.

Whether the openee document is coded internally or externally, it's a good idea to get rid of its deprecated elements/attributes:

(1) The Remote Control string is marked up with a <font size='+1'> ... </font> element, which maps onto and can be replaced by a font-size:larger; CSS declaration; however, my own preference is to recast the Remote Control string, which as noted above is a heading for all practical purposes, as an h3 element, which presentationally will bold the string and give it a block-level rendering.

(2) The script seems to use two center elements to center the OpenWindow display: there's an outer center element lacking an end-tag* and a nested center element that does the actual centering. The nested center element can be replaced by a <div style='text-align:center;'> ... </div> element; the outer center element start-tag should either be thrown out or, preferably, replaced with a body element start-tag.
(*As for the div element, both the start-tag and the end-tag of the center element are required - see the center element declaration in the HTML 4.01 Transitional DTD.)

(3) If you like the aqua background in Joe's remote control window, which is imparted via a bgcolor='#00ffff' body element attribute not present in the "Section Two" script, then add a

<body style='background-color:aqua;'>

tag to the openee document.

Two last presentational points:
• The Remote Control string is split between two lines via a br element, which can of course be removed if you see no need for this effect.
• For his demo window, Joe separated the various document body strings, including the You can move this by grabbing the blue bar with your mouse string, with p elements, but in the "Section Two" script he forgot to put a <p> tag between the Remote Control string and the Section One link. Semantically, the document links are not really 'paragraphs'; you might prefer to remove the <p> tags and instead use a display:block; style to give the links a block-level rendering.

Openee focus

Upon following the Section One/Two and Section Two/Three links, Firefox and Opera maintain focus with the remote control window, as is desirable, but Safari and MSIE transfer focus to the opener window, which is then brought to the screen foreground and consequently obscures the remote control window - this problem can be solved by equipping each anchor element start-tag with an

onclick='window.setTimeout(\"window.focus( );\", 100);' /* for an internally coded remote control, or */
onclick="window.setTimeout('window.focus( );', 100);" /* for an externally coded remote control */


attribute, which will return focus to the remote control window and keep it on top of the opener window.

Strict validation and the target attribute

If the openee document is put in a separate file, then the anchor target attributes will prevent a strict validation of that document even after throwing out the font and center elements. The target attribute is one of three HTML attributes that are simultaneously (a) not deprecated but (b) excluded from the HTML 4.01 Strict DTD - the width and height attributes of the iframe element are the other two. Alternatively, strict validation of an external openee document is possible if the targeting to the main window is carried out JavaScriptically:

<script type="text/javascript">
for (i = 0; i < document.links.length; i++) document.links[i].target = "main";
</script>


Just be sure to place or reference the above script statement after the anchor elements in the document body.

Other remote control possibilities

The use of anchor elements and the target attribute is perhaps the most basic way for a remote control window to load new files into an opener window, but it definitely isn't the only way. More generally, almost any set of renderable HTML elements - form controls, small images, non-anchor text strings, table cells, anything - can be combined with suitable event handlers that take the opener window to new 'locations' by assigning URLs to the location property of the opener window. For example, the openee document could contain a selection list whose options, when selected, change the opener document; try it out below:

<title>Remote Control JavaScript</title>

Welcome to the opener document.


The above demo was inspired by HTML Goodies' JavaScript Script Tip #40.

Six down and one more "Opening New Windows With JavaScript" tutorial to go: we'll cover "New Window: No Title Bar" in the following entry.

reptile7

Wednesday, August 19, 2009
 
Sans Javamax
Blog Entry #154

A little over a year ago, we discussed the width-and-height maximization and minimization of primary browser windows in the course of going through HTML Goodies' aptly titled "Minimize/Maximize a Browser Window" tutorial. HTML Goodies also offers two tutorials with scripts for maximizing window.open( )-opened windows:
(1) "The Same Size"
(2) "So, You Want A FullScreen Browser, Huh?"
We'll take on "The Same Size" in today's post.

The "Same Size" script

Joe provides no deconstruction for the "Same Size" script but pronounces it quite brilliant. As we'll see below, it's actually a sloppily written script, although it does sport a unique and somewhat bizarre feature, namely, it contains an if block whose statements are Java (not JavaScript) expressions. The script is reproduced below as it appears on Joe's "Grab the Script" page:

<SCRIPT>
if(navigator.javaEnabled()==true)
{ w=java.awt.Toolkit.getDefaultToolkit().getScreenSize().width= java.awt.Toolkit.getDefaultToolkit().getScreenSize().height}
else {w=629; h=469}
properies="width="+w+",height="+h;
window.open("index.html","somewindowname", "toolbar=nyes,location=yes,directories=yes,status=yes,menubar=yes,
scrollbars=yes,copyhistory=no")
</SCRIPT>


"The Same Size" is the only "Opening New Windows With JavaScript" tutorial for which Joe does not provide a demo. After I cleaned up the above script

<script type="">
if (navigator.javaEnabled( )) {
w = java.awt.Toolkit.getDefaultToolkit( ).getScreenSize( ).width;
h = java.awt.Toolkit.getDefaultToolkit( ).getScreenSize( ).height; }
else { w = 629; h = 469; }
properies = "width=" + w + ",height=" + h;
window.open("index2.html", "somewindowname", "toolbar,location,directories,status,menubar,scrollbars," + properies)
</script>


I got it to open a new window (but not a maximized window) with Opera but with no other browsers on my computer.

Deconstruction

Let's begin with the script element start-tag, which in the original script is not equipped with a type attribute nor even a language attribute. I don't know if specifying a type="text/javascript" or language="javascript" script attribute would prevent the reading of the if Java statements in some platform situations. At the least we should add a type attribute set to an empty string for validation purposes (type="text/javascript" worked OK with Opera, BTW).

Next we have the aforementioned Java-holding if block, whose condition accordingly checks if the user's browser is Java-enabled. We learned in Blog Entry #142 that a true return for the javaEnabled( ) method of the navigator object does not guarantee that the user's system will in practice execute Java code, but for a moment let's assume that a suitable 'Java Runtime Environment' is in fact installed on the user's computer.

My meager knowledge of Java is not up to the task of providing a detailed explanation of the expressions in the if block, but with the aid of the JavaTM Platform, Standard Edition 6 API Specification, let me take a stab at giving you a 'tourist's guide' to what's going on:

• The expressions begin with a reference to the java.awt "package", which is documented by Sun here - awt stands for "abstract window toolkit".

• The java.awt package contains a Toolkit class, which has (among many other methods) a getDefaultTookit( ) method and a getScreenSize( ) method.

java.awt.Tookit.getDefaultTookit( ) returns the user's "default tookit", which approximately (not so approximately?) corresponds to the user's GUI as a whole.

• The getScreenSize( ) method returns a Dimension object having width and height "fields" (the Java term for properties/attributes). getScreenSize( ).width and getScreenSize( ).height are functionally equivalent to the JavaScript expressions screen.width and screen.height, respectively, i.e., they return the width (more precisely, the horizontal resolution) and height (vertical resolution) in pixels of the user's monitor screen.

The java.awt.Toolkit.getDefaultToolkit( ).getScreenSize( ).width and java.awt.Toolkit.getDefaultToolkit( ).getScreenSize( ).height returns are meant to be assigned to w and h variables, respectively. But go look at the original script, which assigns java.awt.Toolkit.getDefaultToolkit( ).getScreenSize( ).height to java.awt.Toolkit.getDefaultToolkit( ).getScreenSize( ).width*, which in turn is assigned to w. Although a = b = c expressions are in fact 'legal' in both Java and JavaScript - assignment occurs in the normal right-to-left manner, with the value of c being transferred first to b and then to a - we obviously don't want to be doing this here.
(*In analogy to JavaScript's screen.width and screen.height properties, the width and height fields for the getScreenSize( ) return should be read-only, but now that I think about it, there's no reason why they couldn't be writable - it should in theory be possible to change the user's screen resolution on the fly if doing so were desirable for a given Web page.)

Note that the w and h variables are not declared in the original script, which is allowed in JavaScript but a no-no in Java. Just out of curiosity, I prepended an

int w, h;

statement to the script code and reran the script; without getting into the details, the int line threw errors with all of the OS X browsers on my computer. FWIW: All of the Java primitive data type names - boolean, byte, char, etc. - are reserved as future keywords by the ECMAScript specification.

If the user has turned off Java support via the browser Preferences pane or is using a browser that doesn't support Java in the first place - situations for which navigator.javaEnabled( ) should return false - then the subsequent else block assigns 629 to w and 469 to h; evidently the script was written at a time when the standard/most common screen resolution was 800 x 600.

Following the if...else statement is a line that concatenates width=, w, ,height=, and h, and then assigns the resulting string to a properies variable. (properties? Whatever.)

We finally come to the window.open( ) command. Joe set the command's strUrl parameter to index.html, which is meant to be a 'dummy file name' (à la myFile.html) but is a less innocent strUrl choice than it might seem, because a file with this name will, when uploaded, supplant the current directory's normal index file. Assuming that you don't want this to happen, the new window's document should be named something else - I chose index2.html for my revised script.

Note that properies is not concatenated with the command's strWindowFeatures string in the original script - it's up to us to do that. If properies is prepended to the strWindowFeatures string, then a delineating comma should be added to the beginning of the strWindowFeatures string; conversely, if properies is appended to the strWindowFeatures string (as in my script), then a comma should be added to the end of the strWindowFeatures string.

The strWindowFeatures toolbar feature is set to "nyes" - let's assume this should be yes. The strWindowFeatures location, directories, status, menubar, and scrollbars features are also turned on, as befits a maximized window.

Curiously, the strWindowFeatures string concludes by setting a copyhistory feature to no. The copyhistory feature doesn't appear in any of Netscape's pre-DOM JavaScript specifications (which are helpfully archived here by nihonsoft LLC) and it doesn't appear on Microsoft's current window.open( ) page. My guess is that copyhistory was first implemented by Microsoft in an early version of JScript, but my attempts to locate specifications for JScript 1.0 and JScript 2.0 have not been successful.

More on copyhistory

Located via a Google search, this page defines the copyhistory feature - Copies the history listing from the opener window to the new window - and dates copyhistory's implementation to Navigator 2 and Internet Explorer 3. Navigator 2.0 'maps onto' JavaScript 1.0 (the first version of JavaScript), and therefore copyhistory should crop up in JavaScript 1.0's window.open( ) section, but it doesn't.

More recent metadata on the copyhistory feature is given by Gérard Talbot's "Complete cross-browser window.open( ) documentation" page, whose brief copyhistory entry reads:

copyhistory
Deprecated. Do not use. Always implemented in Mozilla-based browsers. There are currently no plan[s] to implement the copyhistory feature either.

Anyway, given that the script's author set copyhistory to no, it's not really worth our while to obsess about copyhistory one way or the other.

In practice

I've never seen JavaScript and Java mixed together before; you wouldn't expect such a script to work, and for the most part it doesn't. Here's what happens when I attempt to run my cleaned-up "Same Size" script with the main browsers on my computer:

• Safari throws a Can't find variable: java "ReferenceError". Equivalently, MSIE 5.2.3 for Mac OS X throws a 'java' is undefined runtime error, as does MSIE 4.5 in the SheepShaver environment.

• Firefox throws a Java class apple.awt.MyCToolkit has no public field or method named "getScreenSize" error.

• With Netscape Communicator 4.61 in the SheepShaver environment, SheepShaver crashes.

As noted above, Opera alone runs my script. The new window has the width and height of the opener window even though the script returns correct/maximized values for w and h (1680 and 1050, respectively, as determined by a window.alert("The value of the properies variable is: " + properies); command placed prior to the window.open( ) command).

Losing the Java and maximizing the window

So, do we really need Java to generate a maximized new window? Not at all - JavaScript alone is up to the job. For Firefox and MSIE, all you need to do is directly set the new window's width and height features to screen.width and screen.height, respectively:

window.open("index2.html", "somewindowname",
"toolbar,location,directories,status,menubar,scrollbars,width=" + screen.width + ",height=" + screen.height);


For Safari, adding left=0,top=0, to the above strWindowFeatures string will do the trick:

// Can also be used with Firefox and MSIE:
window.open("index2.html", "somewindowname",
"left=0,top=0,toolbar,location,directories,status,menubar,scrollbars,width=" + screen.width + ",height=" + screen.height);


Opera's execution of my "Same Size" script suggests that we can't create a maximized window with Opera: not so. I subsequently discovered that when the strWindowFeatures location feature is enabled, Opera takes control of the new window size, position, and chrome, specifically, the new window is given the size and chrome of the opener window and is slightly offset from (to the right and lower than) the opener window, regardless of what other features are or are not set in the strWindowFeatures string. Ditch the location feature and Opera will give you a maximized window with:

window.open("index2.html", "somewindowname", "width=" + screen.width + ",height=" + screen.height);

As for a location-enabled window, Opera takes control of the position and chrome of a maximized window:
• The left and top features are automatically set to 0; setting left and top to other values has no effect.
• The window has a title bar plus a small bar immediately below the title bar indicating the document server's hostname (e.g., www.htmlgoodies.com), and that's it - there's no tab bar, address bar, navigation bar, or status bar - regardless of what other features are or are not set in the strWindowFeatures string.

Time to try it all out:

Welcome to the "Same Size" demo opener page (well, div).




What also doesn't work

Regarding the other HTML Goodies window-maximization tutorials cited at the beginning of the post:

(1) "Minimize/Maximize a Browser Window" tries to minimize/maximize a window via the writing of window object properties (innerWidth, innerHeight, screenX, and screenY) that are meant to be read-only; its code works with the Mozilla/Netscape family of browsers but not with other browsers.

(2) "So, You Want A FullScreen Browser, Huh?" relies on the strWindowFeatures fullscreen feature to create a maximized window. This tutorial deserves its own entry, but for now let me say that fullscreen is supported by iCab 3.0.5 in the SheepShaver environment but not by any other browser on my computer.

The next "Opening New Windows With JavaScript" tutorial is "Remote Control JavaScript", which we'll look over in the following post.

reptile7

Friday, August 07, 2009
 
How To Disappear, But Not Completely
Blog Entry #153

In response to reader curiosity about pop-under ads, Joe has written up a "So, You Want A Pop-Under Window, Huh?" tutorial presenting a short script that first opens a new window and then promptly lowers that window below the opener window:

<script type="text/javascript">

function goNewWin( ) {


TheNewWin = window.open("popunderexample.html", "TheNewpop",
"toolbar=1,location=1,directories=1,status=1,menubar=1,scrollbars=1,resizable=1");
/* Yes, the window.open( ) command can contain line breaks if they're in the right place(s)! */

TheNewWin.blur( ); }

</script>


Quick deconstruction

Upon calling the goNewWin( ) function, a window.open( ) command opens a new window whose object reference is TheNewWin and that holds a popunderexample.html document. The TheNewWin window features a full complement of 'bars' (address bar, bookmarks bar, etc.), is resizable, and has the width and height of the opener window*. Subsequently, the TheNewWin window is popped under the opener window via the blur( ) method of the window object.
(*If the strWindowFeatures parameter is used and if no size features are defined, then the new window dimensions will be the same as the dimensions of the most recently rendered window, quoting Mozilla.)

The success of the script depends on default GUI behaviors that are easy to take for granted:
(1) If more than one window is open on the screen, then only one of those windows can have focus at a given time (in theory, there's no reason why the windows couldn't be active simultaneously).
(2) When a secondary new window is opened via the File menu's New Window command or via a window.open( ) JavaScript command, focus is given to the new window (in theory, there's no reason why focus couldn't remain with the primary window).
(3) If more than one window is open on the screen and if the active window is blurred, then the window to which focus is transferred comes to the screen foreground (in theory, there's no reason why a blurred window can't remain on top of other windows - indeed, there's a strWindowFeatures alwaysRaised feature that can produce this effect).

Calling goNewWin( ) and Joe's demo

In the tutorial's "The Effect Using onLoad" section, Joe stipulates that, à la an actual pop-under ad, [y]ou want the effect to fire as soon as the page loads...using the onload event handler in the body [element start-]tag:

<body bgcolor="white" onload="goNewWin( );">
// Alternatively, the JavaScript equivalent is:
window.onload = goNewWin;


Unfortunately, pop-up blocking stops onload-triggered window.open( ) calls dead in their tracks.

For providing a script demo, Joe for whatever reason decided to forgo the onload route and instead uses a push button to trigger the goNewWin( ) function:

<center><form>
<input type="button" name="" value="click me!" onclick="goNewWin( );" />
</form></center>


On my computer, clicking the button pops up and immediately blurs a new TheNewWin window when using
(a) Firefox with pop-up blocking enabled,
(b) Safari with pop-up blocking enabled, or
(c) MSIE 5.2.3, which does not have a pop-up blocking facility.
(Opera behaves somewhat differently - see below.) The TheNewWin window does not load the intended popunderexample.html document but rather a "404 - File not found" page because, in the "So, You Want A Pop-Under Window, Huh?" source, the window.open( ) strUrl pathway to the popunderexample.html file, /beyond/legacy/javascript/popunderexample.html, is incorrect. Switching the /beyond/ and /legacy/ directories gives the correct strUrl value, /legacy/beyond/javascript/popunderexample.html.

So, let's give Joe's pop-under window demo another shot, shall we?



I've delayed the blurring action via a window.setTimeout('popunderWindow.blur( );', 500); command to make it easier to see.

September 2016 Update:
Unless you're using an older browser, you probably won't see a pop-under effect either here or at Joe's tutorial - the modern OS X browsers on my computer do not execute my popunderWindow.blur( ); command whereas only Safari executes a corresponding window.focus( ); command - this is evidently another case of browser vendors stepping in and circumscribing the GUI in response to 'marketer abuse', if you get my drift.

Joe's demo and Opera

If you're using Opera and if the "Pop-ups" selection list in the Preferences pane's "General" subpane is set to Block all pop-ups

The Opera 'Pop-ups' menu

then clicking the button doesn't open a new window; rather, the following message

Opera's 'Pop-up blocked from...' message

will appear in the lower-right-hand corner of the screen. Per its instruction, clicking the message pops up, but does not blur, the TheNewWin window holding the 404 page, which sits on top of the tutorial window and has focus.

Opera's default "Pop-ups" menu setting is actually Block unwanted pop-ups; with this option, clicking the button pops up but again does not blur the TheNewWin window.

After a bit of experimentation, I find that I can indirectly blur pop-up windows with Opera via the following procedure:

(1) Go to the Preferences pane's "Advanced" subpane. Select the Content option in the menu on the left-hand side
Opera's Preferences/Advanced/Content menu
and then click the button.

(2) In the JavaScript Options window that opens, check the Allow raising of windows checkbox and then click the button.
Opera's JavaScript Options
(3) Close the Preferences/Content subpane and then append the following line of code to the goNewWin( ) function:

if (navigator.userAgent.indexOf("Opera") != -1) window.setTimeout("window.focus( );", 500);

In this case, the TheNewWin window is effectively blurred by returning focus to the opener window via the focus( ) method of the window object.

You may be wondering, "What about Opera's Allow lowering of windows JavaScript option? Can you use that option along with the TheNewWin.blur( ) command to blur the TheNewWin window?" I tried that: it didn't work.

We'll get to HTML Goodies' "The Same Size" tutorial next time.

reptile7


Powered by Blogger

Actually, reptile7's JavaScript blog is powered by Café La Llave. ;-)