reptile7's JavaScript blog
Thursday, August 25, 2005
 
The DevGuru Redesign
Blog Entry #20

On its Copyright page, DevGuru states, "We reserve the right to change and/or update this site at any time and without prior notice", and on Thursday, August 18, DevGuru did just that, rolling out a redesigned Web site. The URLs of the DevGuru JavaScript and HTML "Quick References" now have different pathnames, so my many "deep links" to DevGuru Web pages are all null and void...sigh...it happens to the best of us, I suppose...

"But what about the redesign itself?"

The loss of my links wouldn't be so bad if the new DevGuru were an improved DevGuru, but it isn't, at least as far as the JavaScript section is concerned.

"But are sequels ever as good as the original?"

Good point, but come, let us count the ways that DevGuru's new JavaScript Quick Reference gets my goat...

(1) Ditching the index map

The best feature of the old DevGuru JavaScript Quick Reference was that every page thereof had at its top an image map (more precisely, two image maps) that indexed and linked to the various subsections of the Quick Reference:


This truly useful accessory is now gone.

(2) Ditching the methods and properties pages

The new DevGuru JavaScript Quick Reference no longer has separate pages for JavaScript methods and properties; in their wake is a Main Index containing a mishmash of objects, methods, properties, and event handlers all on one page.

"But neither JavaScript Kit nor IRT has separate methods and properties pages."

Indeed, they do not. But sinking to the level of others should never be on the menu, should it now? (HTML Goodies has such pages, but they're in serious need of updating.)

(3) Unintuitive file names

The HTML files defining the Web pages of the old DevGuru JavaScript Quick Reference had intuitive names - window.html, document.html, image.html, etc. - that facilitated interpage navigation. Suppose you were at the form object page, and you wanted to go directly to the text object page; no problem: simply highlight "form" in the Address Bar URL:

http://www.devguru.com/Technologies/ecmascript/quickref/form.html

then type in "text" and hit return/enter to get to your destination. Unfortunately, page hopping of this sort is now not possible because the underlying Quick Reference files have been renamed numerically (the document object page corresponds to a "10629.html" file, for example).

(4) Removal of browser limitations

DevGuru formerly placed and symbols next to those JavaScript properties that are specific to Netscape and Internet Explorer, respectively. Inexplicably, this information has now been edited out.

(5) Command statement style

Before: window.defaultStatus( = "message")

After: window.defaultStatus( = "message")

Let's see: we've (a) subtracted the color coding of the statement's parts, (b) unboldened the text, (c) shrunk the font size (the site's fonts are now smaller across the board, actually), and (d) rerendered the text in a difficult-to-read silvery color (whose hex code, appropriately enough, is "666666"). Can anyone in his right mind view these changes as stylistic improvements? Paging Leonard Pinth-Garnell: we've got a contender for the next episode of "Bad Web Site Redesign".

"The punctuation on your own blog displays rather faintly."

Well, I'm not very happy about that, either.

(6) Constructor and prototype madness

Bizarrely, the individual pages of all of the objects on the new DevGuru JavaScript Objects page (whose object alphabetization has been botched, you'll notice) now list, in their Properties sections, "constructor" and "prototype" properties. As noted in the previous entry, these properties are indeed applicable to JavaScript's predefined core ('built-in') objects, but of all of the host objects that JavaScript makes use of, only the Image and Option objects are constructible, and neither of these objects has a constructor or prototype property, as you can verify from Netscape's reference material, and because only those objects that can call constructor functions have the constructor and prototype properties (or at least this is implied by DevGuru's prototype property page), it follows that none of the other host objects have these properties.

BTW, the definition of the constructor property should read: "This specifies a function to create an object's property prototype and is inherited by all objects [i.e., by all constructed instances of an object] from their prototype."

(7) And dial-up users, beware: DevGuru's pages definitely load more slowly than they used to.

And that about does it...having said all this, we will continue to make use of the DevGuru resource, as needed - as Sting once famously said, "When the world is running down, you make the best of what's still around" - one can only hope that at least some of the shortcomings cited above will be rectified in due course.

reptile7

Tuesday, August 16, 2005
 
Properties VIII: The History and Location Objects
Blog Entry #19

Although there are a number of other JavaScript objects whose properties we could discuss, we will, in the name of moving forward, confine ourselves in the last entry of our Properties series to the remaining two objects (besides navigator and document) that Joe Burns covers in HTML Goodies' JavaScript Primers #7, namely, the History and Location objects.

The History Object

As noted at the end of the last entry, the History object is itself a property of the window object. As an object, History represents the set of URLs of the Web pages that you have visited in your current online session, i.e., since you opened your browser and began surfing the Web; it does not represent or provide access to the hundreds of URLs that are listed in your browser's History folder.

The History object's one property of note, duly addressed in Primer #7, is the read-only length property, which returns the number of pages that the user has visited in the current online session, including the current page (notwithstanding the Primer #7 script's implication that history.length counts the "pages before this [the current] one").

Besides length, DevGuru and IRT list three other Netscape-specific History properties at their respective History object pages: current, next, and previous, which return respectively the URLs of the current, next (Forward), and previous (Back) pages of the user's running History list. (JavaScript Kit's History object page lists only the length property.) However, IRT notes, "The UniversalBrowserRead privilege is required to access th[ese] property value[s]"; Netscape's reference material on the History object further states that these properties "ha[ve] no value if you do not have this privilege." In any case, my attempt to read history.current gave "Error: uncaught exception: Permission denied to get property History.current" (history.next and history.previous returned analogous errors).

I also tried to write the current property; I was curious as to whether history.current = "http://www.some_web_page.com" would set up a link, like a window.location command. No dice. An attempt to execute history.current = "http://www.yahoo.com/" gave "Error: setting a property that has only a getter."

We won't see the History object again in the remaining HTML Goodies JavaScript primers. The History object and its go( ) method, briefly mentioned in Primer #7, do crop up once in the HTML Goodies JavaScript Script Tips, in a script that spans Script Tips #5-9.

The Location Object

We've briefly touched on the Location object before, both in Blog Entry #10, when we discussed the parent.location command, and in Blog Entry #14, when we discussed the JavaScript Link object. Again as noted at the end of the last entry, the Location object, like the History object, is a property of the window object. Of the resources I usually consult, DevGuru provides the best definition of the Location object: "It contains the complete URL of a given window object, or, if none is specified, of the current window object."

In analogy to the properties of the Link object, the properties of the Location object represent the constituent parts of the browser window URL, which we can generalize as:

protocol//hostname[:port][/pathname][#hash][?search]
(the parts in square brackets are optional)

Accordingly, DevGuru, JavaScript Kit, and Netscape list the following eight standard properties* for the Location object:

hash, host, hostname, href, pathname, port, protocol, search
for which:
host = hostname:port (hostname ≠ host:port, as incorrectly stated at Netscape's page)
href = protocol//hostname[:port][/pathname][#hash][?search]

(*IRT also lists "target", "text", "x", and "y" properties for the Location object. However, my attempts to read location.text, location.x, and location.y gave "undefined" for each command when using MSIE or Netscape.)

Of the above properties, Joe oddly chose to discuss the host and hostname properties in Primer #7 - these properties don't appear in the remaining primers or in any of the script tips - much better to highlight the href property; the location.href command (a) does crop up in future primers, (b) returns a full URL (unlike location.host and location.hostname), and (c) is as effective as the window.location command in setting up a link to another Web page.

A quick comment on host and hostname: unless the URL in question specifies a port number (and I'm not sure I've ever seen a URL with a port number, quite frankly), then location.host and location.hostname read identically - location.host will not return "www.some_web_page.com:80", 80 being the default HTTP network port number.

Joe works the location.host command into the end-of-primer assignment, which asks the reader to write a script creating a link from www.you.com to www.you.com/joe.html. The href attribute of an anchor tag requires a full URL, so it is necessary in the assignment answer to concatenate "http://" (location.protocol + "//") with the location.host return; clearly, use of a location.href command would be more efficient.

But because all we're doing is tacking a pathname onto a URL, then why not use a location.pathname command? Problematically, if the www.you.com document contains a script with a location.pathname = "/joe.html" command, then we will go straight to www.you.com/joe.html (with only a transient stop at www.you.com) when we try to load the www.you.com page. We can circumvent the automatic loading of www.you.com/joe.html, however, by triggering the location.pathname command with an appropriate event handler, for example:

Click <span style="color:blue;text-decoration:underline;cursor:pointer;" onclick="location.pathname='/2005/03/intro.html';">here</span> to go to Blog Entry #1.

giving: Click here to go to Blog Entry #1.

If you'd rather keep the anchor tag, a mouseover link also works well:

Move your mouse over <a href="" onmouseover="location.pathname='/2005/03/primer-1.html';">these words</a> to go to Blog Entry #2.

giving: Move your mouse over these words to go to Blog Entry #2.

One would think that an onclick event handler could also be used in an anchor tag to execute a location.pathname command; not so. On my computer at least, clicking the link in:

Click <a href="" onclick="location.pathname='/2005/03/primer-1.html';">here</a> to go to Blog Entry #2.

simply reloads the page, i.e., the onclick command does not override the link's default behavior.

Lagniappe: The Date Object

The JavaScript Date object was introduced in Primer #3, so I thought we could sneak in some commentary on its properties to conclude this entry. According to the HTML Goodies JavaScript Objects Keyword Reference page, the Date object "does not have any properties"; however, DevGuru's Date object page lists two properties for the Date object: constructor and prototype. These relatively abstract properties relate to the fact that the built-in JavaScript Date object serves as a prototype, or blueprint, for the specific instances of the Date object that are created with a constructor statement and the new operator (as discussed in Blog Entry #5).

For a specific Date object, the constructor property returns:

function Date() { [native code] }

which is supposedly a reference to the code that created the Date object prototype, even as it is not necessary for the user to create the Date prototype, which is built-in to JavaScript. The Date prototype property is used not with specific Date objects but with the Date prototype itself to add a custom method or property to the Date prototype:

Date.prototype.custom_method = JavaScript_command(s);
Date.prototype.custom_property = null;

More generally, the constructor and prototype properties apply to all of the built-in JavaScript objects (except the JavaScript Math object), as noted by DevGuru's JavaScript properties page, as well as to custom JavaScript objects, with which constructor and prototype seem to be used most often and which we might discuss at some point in the future.

Next up: HTML Goodies' JavaScript Primers #8 and the JavaScript object hierarchy. After the last several posts, Primer #8's material will be somewhat of a review, but a little reviewing never hurt anyone.

reptile7

Saturday, August 06, 2005
 
Properties VII: The Window Object
Blog Entry #18

References
JavaScript window object pages:
(1) DevGuru
(2) JavaScript Kit
(3) IRT

In at least one respect, I can see why Joe Burns skipped over the window object in his treatment of JavaScript properties in HTML Goodies' JavaScript Primers #7; many window object properties are supported by Netscape but, frustratingly, not by MSIE. Nonetheless, we at reptile7's JavaScript blog are ready to put these properties under the microscope. (Indeed, as Dan Quayle might say, we are ready for any foreseen or unforeseen property that may or may not occur in JavaScript. ;-)) In this entry, we will briefly address the following window properties-related issues:
• referencing the window object
• the constituent parts of a window
• dimensions of a window
• positioning of a window and of the document therein
• status of a window
• child objects of the window object

Referencing a Window: window vs. self vs. parent vs. top

There are five properties of the window object that relate, if overlappingly, to referencing a window:

opener, parent, self, top, window

No, that's not a mistake - there really is a window property of the window object. As a property, window specifically refers to the browser window or to the frame of the browser window that is currently active, as does the synonymous self property. To the best of my knowledge, window and self refer to the same window or frame under all circumstances, and to use one or the other is purely a stylistic choice. But what about the parent and top properties? Let's look at an example that distinguishes between window/self, parent, and top (and thus shows why there's a need for a window property for the window object).

Consider a frameset page, fram1.html, comprising a left frame and a right frame, fram2.html and fram3.html, respectively:

<frameset cols="70%,30%">
<frame src="fram2.html">
<frame src="fram3.html">
</frameset>

In this situation, the fram1.html window is the parent of the fram2.html and fram3.html windows. If we put in fram3.html the following script:

<script type="text/javascript">
window.document.bgColor = "yellow";
parent.document.title = "I'm the parent.";
</script>

then we will color the right frame yellow and set a new title for the frameset page, which is the page we actually see (the title, if any, of the isolated fram3.html page is unaffected).

The window.document.bgColor = "yellow" command can alternately be written as:
window.window.document.bgColor = "yellow"; or
window.self.document.bgColor = "yellow"; or
self.document.bgColor = "yellow"; or, more sanely, just
document.bgColor = "yellow";
In most cases, it is not necessary to reference window either as an object or as a property.

Besides being a parent window, the fram1.html window is also a top window, defined as the topmost browser window. It follows that the parent.document.title = "I'm the parent." command can alternately be written as:
window.parent.document.title = "I'm the parent."; or
window.top.document.title = "I'm the parent."; or
top.document.title = "I'm the parent.";

But let's suppose that fram2.html is itself a frameset page that comprises a upper frame and a lower frame, fram4.html and fram5.html, respectively. The fram2.html window is now the parent of the fram4.html and fram5.html windows; the fram1.html window is still the top window and is still the parent of the fram2.html and fram3.html windows. Got all that? A locally hosted, iframe-containing version of this structure appears below:



Outside of a frames situation, window, self, parent, and top all refer to the currently active window and can be used interchangeably.

Lastly, the opener property refers to a window that has opened one or more windows; we'll return to this property when we discuss the opening of new windows with JavaScript in Primer #11. We'll also see in this primer that the window name property is used to target the 'output' of a window to another window. Unlike the objects that we've been talking about in the last few entries, however, a window object is not referenced by its name.

The Parts of a Window

There are eight properties of the window object that represent constituent parts of the browser window:

document, locationbar, menubar, personalbar, scrollbars, sidebar, statusbar, toolbar

Except for document, all of these properties are supported by Netscape but not by MSIE. Except for sidebar, the window.–bar expression for the various bars of the window returns [object BarProp] (when using Netscape, and undefined when using MSIE).

All of these window parts are themselves JavaScript objects. We have already discussed the document object and many of its properties in Blog Entry #13. Except for sidebar, the window bars, as objects, have a single boolean property, visible, whose default value is true but which can be set to false so as to hide/collapse the bar(s) in question. Back in the day when Netscape Communicator 4.x was Netscape's state-of-the-art browser, Netscape required a scriptwriter to obtain a UniversalBrowserWrite privilege via a signed script in order to write the visible property, but this has evidently been phased out, as I am able to set the value of window.–bar.visible for most of the window bars above when using Netscape 6.2 and Netscape 7.02.

Here is a Netscape 7.02 screenshot from my computer

Netscape 7.02 screenshot

showing the full complement of browser bars listed under the View menu:

The Netscape 7.02 View menu and its Show/Hide submenu

(a) When I set window.locationbar.visible = false (boolean true and false values are not put in quotes), this part

The Netscape 7.02 location bar

of the navigation bar

The Netscape 7.02 navigation bar

disappears.

(b) On my iMac, the browser menubar

The Netscape 7.02 menu bar

is not part of the window but is separate therefrom, and setting window.menubar.visible = false has no effect.

(c) When I set window.personalbar.visible = false, this bar disappears:

The Netscape 7.02 personal bar

(d) When setting window.scrollbars.visible = false, I find that the page must be reloaded to make the scrollbars disappear (FYI: when using MSIE, a document.body.scroll = "no" command will lose the scrollbars).

(e) When I set window.statusbar.visible = false, both the status bar and the component bar (the small bar to the left of the status bar)

The Netscape 7.02 component bar

disappear. The component bar's buttons correspond to the commands under the Window menu:

The Netscape 7.02 Window menu

(f) Setting window.toolbar.visible = false subtracts the Back, Forward, Reload, Stop, and Print buttons of the navigation bar.

To bring these bars back, neither simply reloading the page nor toggling the Navigation Toolbar, Personal Toolbar, and Status Bar commands under the View menu is effective; rather, in each case window.–bar.visible must be reset, to true. (Again, revisualizing the scrollbars requires a page reload.)

As far as I am aware, the window object does not have navigationbar, tabbar, and componentbar properties.

Introduced with Netscape 6, the sidebar

The Netscape 7.02 sidebar

stands apart from the other browser bars; the sidebar functions in effect as a frame of the browser window, much like MSIE's Explorer Bar, and its content is programmable. Propertywise, the window.sidebar expression on my computer cryptically returns:

[xpconnect wrapped (nsISupports, nsISidebar, nsIClassInfo)]

As an object, the sidebar does not have a visible property (window.sidebar.visible returns undefined) but has four methods, listed here, whose discussion is outside the scope of this blog entry.

Window Dimensions

The window object does not have simple width and height properties (even as the JavaScript event, Image, and screen objects all do) but instead has specialized innerWidth, innerHeight, outerWidth, and outerHeight properties that are all read/write but that are, annoyingly, supported by Netscape but not by MSIE. The outerWidth and outerHeight properties specify respectively the total width and height in pixels of the browser window, including all of the browser bars and presumably also the title bar and the window border. In turn, the innerWidth and innerHeight properties specify respectively the width and height in pixels of the document content area. Having said this, on my computer window.innerWidth and window.outerWidth return the same value with and without the right scrollbar.

JavaScript Kit's window object page claims that there are for MSIE document.body.clientWidth and document.body.clientHeight properties that are equivalent to window.innerWidth and window.innerHeight, respectively; not quite. As noted at Stephen Le Hunte's HTMLib Index resource, the clientWidth and clientHeight properties of the <body> element/object are read-only.

However, at least the width and height of newly opened windows can be set straightforwardly, as we'll see in Primer #11 (vide supra).

Window Positioning

At their window object pages, JavaScript Kit and IRT list screenX and screenY properties that specify "the x and y coordinates of the window relative to the user's monitor screen", quoting JavaScript Kit; these properties are again supported by Netscape but not by MSIE. (DevGuru lists screenX and screenY properties for the event object but not for the window object.) More specifically, a window's x coordinate is the number of pixels separating the window's left border from the monitor screen's left boundary, whereas a window's y coordinate is the number of pixels separating the window's top border from the monitor screen's top boundary (much like the x and y properties of the Image object, which we briefly discussed in Blog Entry #15). The window screenX and screenY properties are reliably readable, even if the browser window is moved manually beyond the monitor screen's boundaries; for example, window.screenX and window.screenY dutifully return negative numbers if the window is moved to the left and above the screen's left and top boundaries, respectively.

The screenX and screenY properties are writable to an extent, and can be used to move the window across the screen without incident as long as the movement does not bring the window into contact with the screen's boundaries; this works best, clearly, for smaller windows. Assigning suitably large values to window.screenX and window.screenY will not move a window off-screen and may cause larger windows to shrink in size in an unpredictable way (at least this is what happened when I tried to shift with screenX/screenY a full-sized browser window).

JavaScript Kit lists "IE5+ only" window screenLeft and screenTop properties whose descriptions are identical to those of screenX and screenY; however, MSIE returns undefined for both window.screenLeft and window.screenTop on my iMac. Sure enough, QuirksMode.org notes that screenLeft and screenTop are not supported by IE5 for the Macintosh.

The window object also has two properties, pageXOffset and pageYOffset, relating to the position of the document in the window. The pageXOffset and pageYOffset properties return the number of pixels that the document has been scrolled, horizontally and vertically, from the leftmost and topmost positions of the document within the window, respectively; these properties are not supported by MSIE, and are read-only. (My attempts to write them gave "Error: setting a property that has only a getter".)

JavaScript Kit notes that the IE4+ equivalents of pageXOffset and pageYOffset are document.body.scrollLeft and document.body.scrollTop, respectively. Gratifyingly, I find that the scrollLeft and scrollTop properties of the body object are recognized by both MSIE and Netscape, and are read/write.

Roll your mouse over these words to read the scrollTop property.

(Mind you, Webmasters who create Web pages that require horizontal scrolling should be tarred and feathered, IMHO, but that's another blog entry for another time.)

Window Status, revisited

We discussed the window status property in some detail in Blog Entry #7. The window object also has a related defaultStatus property that can be used to write a new default status bar message in place of the browser's normal default status bar message, which on my computer is "Internet zone" and "Document:Done (x.xxx secs)" for MSIE and Netscape, respectively.

In setting a new default status bar message, I find that window.defaultStatus and window.status commands can be used interchangeably. When using Netscape, the window.defaultStatus = "message" (or window.status = "message") command can be put in a script and executed in either the document head or the document body. When using MSIE, which seems to be more sensitive to the timing of browser/script events than is Netscape, I am only able to execute window.defaultStatus = "message" (or window.status = "message") when I assign it to an onload attribute in the document <body> tag (or trigger it by some other event handler of a document body element) - this also works for Netscape.

DevGuru notes that a window.status message should transiently supplant a window.defaultStatus message; however, IRT warns on its window object page that "the default status value may not be properly restored on some platforms", and this is indeed the case on my computer, with a window.status message permanently overriding a window.defaultStatus message. The converse is not true; a window.defaultStatus message will not displace a preceding window.status message. If you put

onload="window.status = 'This is message #1.'; window.defaultStatus = 'This is message #2.';"

in the document <body> tag, then you'll see 'This is message #1.' in the status bar. On the other hand, a not-so-transient window.status message will be displaced by a subsequent window.status message.

Other Window Children

Besides document and the browser bars, there are a number of other JavaScript objects, some of them admittedly obscure, whose immediate parent in the JavaScript object hierarchy is the window object, and are thus properties of the window object, including:

clientInformation, crypto, event, Frame, History, Location, navigator, netscape, Packages, pkcs11, screen

The next post will conclude our discourse on JavaScript properties with a brief look at the properties of the History and Location objects.

reptile7


Powered by Blogger

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