reptile7's JavaScript blog
Tuesday, April 03, 2012
Bookmark, IP, Back
Blog Entry #246

We return now to our tour of HTML Goodies' "Top 10 JavaScript Snippets for Common Tasks" tutorial. In this entry we'll discuss the Add to Favorites and IP Address snippets.

Your new fave

The Add to Favorites snippet codes a link that when clicked opens a dialog box prompting the user to add the current Web page to the browser's favorite/bookmark collection.

<a href="javascript:window.external.AddFavorite('', 'Your Site Name');">Add to Favorites</a>

The AddFavorite( ) method was implemented by Microsoft in IE 5 for Windows (IE 5 for Mac doesn't support it). The first AddFavorite( ) parameter specifies the URL for the favorite; the optional second AddFavorite( ) parameter specifies a title for the favorite. As a favorite is a browser-specific datum, you'd think that the AddFavorite( ) method would be associated with the navigator object; instead, Microsoft tied AddFavorite( ) to an external object that allows access to an additional object model provided by host applications of the Windows Internet Explorer browser components.

Scott correctly notes that this snippet only works with IE; other browsers throw a window.external.AddFavorite is not a function (or equivalent) error upon clicking the Add to Favorites link. Of the browsers on my computer, Firefox, Chrome, Camino, and Netscape 9 support the external object to an extent, but none of these browsers supports the AddFavorite( ) method.

The snippet should not be deployed as is: non-IE users should at least get a 'Houston, we have a problem'-type message rather than just an error. One very good approach to this situation is to have the href JavaScript URL call a setFavorite( ) function that respectively places the AddFavorite( ) command and the non-IE message in the try and catch clauses of a try...catch statement.

function setFavorite( ) {
    try { window.external.AddFavorite("", "Your Site Name"); }
    catch(err) { window.alert("Please type Control-D/Command-D to bookmark this page."); } }

Now, if in the future non-IE browsers add support for the AddFavorite( ) method (I see that Ian 'hixie' Hickson is thinking about bringing window.external into HTML5), then users of those browsers will be good to go. An External interface has been brought into HTML5 but it doesn't include the AddFavorite( ) method.

On its AddFavorite( ) page, Dottoro notes that Firefox supports an addPanel( ) method that does what AddFavorite( ) does.

window.sidebar.addPanel("Your Site Name", "", "");

The addPanel( ) method is officially associated with Mozilla's proprietary sidebar object, and has an inverse-AddFavorite( ) syntax in that its first parameter specifies a title for the bookmark and its second parameter specifies the bookmark's URL; it also takes a required third parameter that can be used to specify a customized URL for the bookmark but is typically 'left blank' (set to an empty string).

In truth, you would never pick up from the aforelinked Mozilla window.sidebar page that the addPanel( ) method has anything to do with bookmarks at all; moreover, the page states that addPanel( ) has been obsolete since Firefox 23 [and is now only supported by Mozilla's SeaMonkey browser]. Dottoro's AddFavorite( ) page offers an AddFavorite( )/addPanel( ) code sample and accompanying demo that worked smoothly with Firefox and Netscape 9 when I first tested it

The Firefox Add Bookmark dialog box

but throws a window.sidebar.addPanel is not a function TypeError with the version of Firefox (48.0.2) currently on my computer. In its code sample, Dottoro conditions the addPanel( ) command via an if (window.sidebar) { ... } clause and the AddFavorite( ) command via an if (window.external && ("AddFavorite" in window.external)) { ... } clause; the "AddFavorite" in window.external subcondition employs the in operator, which tests if a given property or method is part of an object's interface.

Interestingly, probing the external object with a statement reveals that Firefox and Netscape 9 associate the addPanel( ) method with the external object as well as with the sidebar object.

for (var i in window.external) { document.write("window.external." + i + " = " + window.external[i] + "<br>"); }

Firefox output:
window.external.QueryInterface = function QueryInterface() { [native code] }
window.external.addPanel = function addPanel() { [native code] }
window.external.addPersistentPanel = function addPersistentPanel() { [native code] }
window.external.addSearchEngine = function addSearchEngine() { [native code] }
window.external.AddSearchProvider = function AddSearchProvider() { [native code] }
window.external.IsSearchProviderInstalled = function IsSearchProviderInstalled() { [native code] }

Besides addPanel( ), Firefox's external object interface includes a QueryInterface( ) method, an addPersistentPanel( ) method, an addSearchEngine( ) method, an AddSearchProvider( ) method, and an IsSearchProviderInstalled( ) method; Netscape 9's external object interface also includes these methods plus sixteen other 'members'. However, the Mozilla Developer Network's Web site does not have a window.external page as of this writing.

Your IP address, comrade

The IP Address snippet is a small script that displays the user's IP address:

<script type="text/javascript">
var ip = '<!--#echo var="REMOTE_ADDR"-->';
document.write("Your IP address is: " + ip);

I looked at this guy and said, "This doesn't look like JavaScript." Sure enough, the <!--#echo var="REMOTE_ADDR"--> thing that is assigned as a string to the ip variable isn't JavaScript at all but what is called a "server side include": an instruction carried out by the server that serves the page to the user.

As it happens there are three brief tutorials on server side includes ("SSI") at the HTML Goodies site:
(1) "SSI: The Include Command"
(2) "SSI: Dates and Times"
(3) "SSI: File Returns"
Written in 2000 by Joe Burns, these tutorials are not findable via the site's left-hand navigation menu (their URLs indicate that they should be in the Webmaster Tips sector, but they're not there), but they do crop up in the Text section of the site's "Master List" page.

In his "SSI: The Include Command" tutorial introduction, Joe says that Server Side Includes (SSIs) are Perl language-based commands; in fact, SSI were developed by the National Center for Supercomputing Applications (NCSA) for use by the NCSA HTTPd server. (Were the NCSA folks inspired by Perl? Maybe, I don't know.) Documentation for SSI is today maintained by the Apache Software Foundation.

Apache specifies the syntax of a basic SSI command as:

<!--#element attribute=value attribute=value ... -->

Attribute values must be quoted. The command has a <!--# open delimiter and a --> close delimiter; the former cannot be followed by white space whereas the latter is supposed to be preceded by white space. If the server is not configured to parse SSI, then on the client side the browser sees the command as a comment and does not render it.

Getting back to the IP Address snippet, the echo element and the var attribute are used to print the value of a variable, in this case REMOTE_ADDR, a standard CGI environmental variable that holds the user's IP address. The REMOTE_ADDR value is CDATA and therefore the entire command can alternatively be placed in any can-contain-#PCDATA element; it's not necessary to use JavaScript and a document.write( ) command to display the REMOTE_ADDR value.

<div>Your IP address is: <!--#echo var="REMOTE_ADDR" --></div>

For a functioning echo var="REMOTE_ADDR" demo, check out JavaScript Kit's "Cut & Paste IP address display (using SSI and JavaScript)" page and its script that loads the REMOTE_ADDR value into a readonly text box. (Frustratingly, neither the server, which I used to use for my demos, nor the server is configured to parse SSI.)

For other server-side approaches (and one client-side approach) to getting the user's IP address, see JavaScript's "Obtaining Your Visitor's IP Address" tutorial.

Lagniappe: Looking Backward

The tutorial's JavaScript Back Button snippet codes a push button interface

<input type="button" value="Previous Page" onclick="history.go(-1);">

and a link interface

<a href="javascript:history.back(1);">Previous Page</a>

for mimicking the browser's 'Back' button. Why history.go(-1) in one and history.back(1) in the other? Moreover, I was a bit suspicious about history.back(1)'s 1 argument. I looked up the back( ) method of the History object and here's what I found:

On the Microsoft side, history.back( ) can take an integer argument specifying the number of locations to go back in the browser's history list (Microsoft is not clear as to whether "history list" means "current session history") but doesn't have to, in which case history.back( ) is equivalent to history.go(-1).

On the Mozilla side, history.back( ) takes no arguments and is equivalent to history.go(-1).

The W3C has brought the History interface into HTML5 and has adopted the Mozilla history.back( ) syntax.

The tutorial's Break Out of Frames, Focus OnLoad, and Specify Referring Page snippets are not worth our while, bringing us at last to the Calendar snippet, which we'll take on in the following entry.

Comments: Post a Comment

<< Home

Powered by Blogger

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