Active Frame Bookmarking JavaScript.

Updated save bookmark code.

As you know frames can be very useful for the layout and navigation of your site and they can also be a complete pain as your users can bookmark an interesting page to come back to later, and nobody likes to re navigate their way back to the one page they are interested in. This is how the idea for active frame bookmarking came about, what was needed was some program or script that can load the sub page of interest that had been bookmarked into the main frame of your main site framed page.

To do this a method is needed that can pass additional information back to main site page from the bookmark for any web browser, this can only be the use of a URL that includes the GET method of the CGI interface also know as the canned query. The next thing to do is to get hold of the URL that is being passed back to the server and extract the extra information on the browser, this is where the following function comes in.

Download activebookmark.js and the treeview.js etc.

function loadBookmark()
{
  if (self.location.protocol != "file:")
  {
    var cgiURL;
    if ((self!=top) && (self.document.referrer != ""))
    {
      cgiURL = getCGI(self.document.referrer);
    }
    else
    {
      cgiURL = getCGI(self.location.href);
    }
    if (cgiURL !="" )
    {
      self.mainFrame.location = cgiURL;
    }
  }
}

This first if statement determines if the URL is local as this type of URL can't have additional information so no bookmarking either, next if the page is not the top level frame and it's referrer is not blank it uses the referrer to extract the additional information. This is to get round the security (privacy thing) that prevents JavaScript programs accessing URL's from a different domains that there own directly in IE, so if the page is being masked by a URL masking domain parking company like my own site was, I can keep it URL masked after bookmarking, otherwise just the current pages URL to extract the additional information. The extraction of the additional information is done by the function getCGI. Finally the mainFrame's location needs to be set to the additional information if there is any.

If you don't use URL masking you only need to use this version of the loadBookmark() function.

function loadBookmark()
{
  if (self.location.protocol != "file:")
  {
    var cgiURL = getCGI(self.location.href);
    if (cgiURL !="" )
    {
      self.mainFrame.location = cgiURL;
    }
  }
}

or

function loadBookmark()
{
  var cgiURL = self.location.search;
  cgiURL = cgiURL.replace("?","");
  if (cgiURL !="" )
  {
    self.mainFrame.location = cgiURL;
  }
}

To use this function you need to set your home page up something like this.

<HTML>
<HEAD>
<TITLE>Your Home Page</TITLE>
<SCRIPT LANGUAGE="JavaScript1.2" SRC="activebookmark.js">
</SCRIPT>
</HEAD>
<FRAMESET COLS="220,1*" ROWS="*" FRAMEBORDER="NO" BORDER="0" FRAMESPACING="0" onLoad="loadBookmark();">
<FRAME NAME="navFrame" SRC="navframe.html" SCROLLING="AUTO">
<FRAME NAME="mainFrame" SRC="home.html" SCROLLING="AUTO">
</FRAMESET>
<NOFRAMES>
<BODY>
</BODY>
</NOFRAMES>
</HTML>

Now you rightly ask how do I get my users to create the bookmark that includes this additional information, well you have to have a link on your framed page that does the bookmarking for them, by calling this function.

function saveBookmark()
{
  if (self.location.protocol != "file:")
  {
    var urlPath;
    if ((self!=top) && (self.document.referrer != ""))
    {
      urlPath = getHost(self.document.referrer);
    }
    else
    {
      urlPath = getHost(self.location.href);
    }
    urlPath = urlPath + "?";
    urlPath = urlPath + getPath(self.mainFrame.location.href);
    urlPath = urlPath + getFile(self.mainFrame.location.href);
    var urlTitle = self.mainFrame.document.title;
    if (navigator.appName.indexOf("Internet Explorer") != -1)
    {
      window.external.AddFavorite(urlPath,urlTitle);
    }
    else
    {
      window.open(urlPath,"_top");
      window.alert("The current page's URL has been updated for bookmarking.\nPlease use your browsers bookmark button.");
    }
  }
}

This first if statement determines if the URL is local as this type of URL can't have additional information so no bookmarking either, next if the page is not the top level frame and it's referrer is not blank it uses the referrer to get the sites host otherwise just the current pages URL to get the sites host. If you don't use URL masking then you can replace

    var urlPath;
    if ((self!=top) && (self.document.referrer != ""))
    {
      urlPath = getHost(self.document.referrer);
    }
    else
    {
      urlPath = getHost(self.location.href);
    }

With var urlPath = getHost(self.location.href); in the saveBookmark() function, or if you don't use a user area i.e. your sites root does not looks like www.some-isp.com/~username/ then var urlPath = self.location.host; would do.
Next we add the additional information to the host this is done by adding a ? and the path to the page you wish to bookmark, this is dynamically found when the function is executed by getting the path and file from the main frame of your framed page, this assumes you are not loading pages from other sites into your main frame, if you are then you will need to add  urlPath = urlPath + getHost(self.mainFrame.location.href); or if no user area is involved urlPath = urlPath + self.mainFrame.location.host); before you add the path and file, if no user area is involved you should use urlPath = urlPath + self.mainFrame.location.pathname; for the path as well. Next we get the title of the page they are going to bookmark, this data then can be used by the bookmarking function, in IE or in the dynamic pop up page needed by Netscape, as they have not created a bookmark JavaScript function yet. The next bit either show the add to Favourites dialogue in IE or with other browsers it changes the browsers address to include the additonal information, and then lets the user know that they can bookmark the page the normal way.

Now to add this link in to you site you need to add the following HTML into you navFrame or into each of the pages loaded into you mainFrame.

<P><A HREF="javascript:void();" onClick="self.parent.saveBookmark(); return false" onMouseOver="window.status='Bookmark'; return true" onMouseOut="window.status=''; return true">Bookmark this page!</A></P>

Now with some search engines they pick up some pages that should be accessed via the site home page so to fix that problem the simple function below is used. This function checks to see if the current page is at the top and if it is then tells the browser to load the hosts home page with the virtually bookmarked current page.

function popframe()
{
  if (self==top)
  {
    top.window.location.href = getHost(self.document.URL) + "?" + getPath(self.document.URL) + getFile(self.document.URL);
  }
}

or if your site does not use a user area

function popframe()
{
  if (self==top)
  {
    top.window.location.href = self.location.host + "/?" + self.location.pathname;
  }
}

To use this just add these two lines into for sub page headers, and remember to keep the relative path to activebookmark.js correct, or use the full path, so that the browser will only download this once and then load from it's cache each time after that thus improving the speed your site loads.

<SCRIPT LANGUAGE="JavaScript1.2" SRC="activebookmark.js"></SCRIPT>
<SCRIPT LANGUAGE="JavaScript1.2">popframe();</SCRIPT>

Now to run quickly through the sub function and what they do, as they all use Regular Expressions I don't have time to explain there working in any detail lets just say they look for a pattern in a string and extract it and either return the extracted string or use it to replace the extracted pattern from the original string with a null string and return the result of that.

If you look at the expression in getHost this looks for some characters followed by a colon at the start of the string i.e. "http:" followed by some slashes followed by some none slash characters with a slash on the end i.e. "http:\\some.server.com\" followed by tilde "~" and some none slash characters followed by a slash i.e. "http:\\some.server.com\~username\" or if that fails the same thing without the tilde and some none slash characters followed by a slash i.e. just "http:\\some.other.server.com\"

This function returns the search string of the supplied URL.

function getCGI(fullURL)
{
  var result;
  var sub;
  var ExpCGI = new RegExp("^.*[\?]");
  if ((result = ExpCGI.exec(fullURL)) != null)
  {
    sub = fullURL.replace(result[0],"");
    if (navigator.appName.indexOf("Internet Explorer") == -1)
    {
      return sub.replace("?","");
    }
    else
    {
      return sub;
    }
  }
  else
  {
    return "";
  }
}

This function returns the host of the supplied URL including the ~username/ if it is present in the URL.

function getHost(fullURL)
{
  var result;
  var sub;
  var urlcgi;
  var ExpPath = new RegExp("(^.*[:][\\\/]*[^\\\/]*[\\\/][~][^\\\/]*[\\\/])|(^.*[:][\\\/]*[^\\\/]*[\\\/])");
  urlcgi = getCGI(fullURL);
  if (urlcgi != "")
  {
    sub = fullURL.replace(urlcgi,"");
    sub = sub.replace("?","");
  }
  else
  {
    sub = fullURL;
  }
  if ((result = ExpPath.exec(sub)) != null)
  {
    return result[0];
  }
  else
  {
    return "";
  }
}

This function returns the path of the supplied URL excluding the ~username/ if it is present in the URL.

function getPath(fullURL)
{
  var result;
  var sub;
  var urlcgi;
  var ExpPath = new RegExp("[^\\\/]*[\.][^\\\/]*$");
  urlcgi = getCGI(fullURL);
  if (urlcgi != "")
  {
    sub = fullURL.replace(urlcgi,"");
    sub = sub.replace("?","");
  }
  else
  {
    sub = fullURL;
  }
  sub = sub.replace(getHost(fullURL),"");
  if ((result = ExpPath.exec(sub)) != null)
  {
    return sub.replace(result[0],"");
  }
  else
  {
    return sub;
  }
}

This function returns the file of the supplied URL.

function getFile(fullURL)
{
  var result;
  var sub;
  var urlcgi;
  var ExpPath = new RegExp("[^\\\/]*[\.][^\\\/]*$");
  urlcgi = getCGI(fullURL);
  if (urlcgi != "")
  {
    sub = fullURL.replace(urlcgi,"");
    sub = sub.replace("?","");
  }
  else
  {
    sub = fullURL;
  }
  if ((result = ExpPath.exec(sub)) != null)
  {
    return result[0];
  }
  else
  {
    return "";
  }
}

© Copyright 2000 - 2008, Chris F Wood, All Rights Reserved.

Last modified on Monday, 1st January 1601.