Use jQuery to make all offsite links open in a new window

XHTML Strict does not allow opening links in a new window using target=””_blank”” so instead you can use jQuery to add the target attribute to all <a> tags after the page has loaded and still have the page validate as XHTML strict. (But refer to my updated note at the end of the article regarding the base tag and the un-deprecation of the target attribute).

jQuery Code

Simply add the following piece of code into your $(document).ready(function() { } section of code (more about that in my jQuery’s document ready initialization post):

$(""a"").filter(function() {
    return this.hostname && this.hostname !== location.hostname;
}).attr('target', '_blank');

What this does is to add target=’_blank’ to all <a> tags in the current webpage that do not link to the domain you are currently on.

Therefore on my blog, applying the jQuery code above would make the following open in the same window:

<a href=""/jquery-open-offsite-links-new-window/""> ... </a>
<a href=""https://electrictoolbox.com/jquery-open-offsite-links-new-window/""> ... </a>

and the following in a new window:

<a href=""http://www.google.com""> ... </a>
<a href=""http://www.yahoo.com""> ... </a>

It’s then possible to replace attr() with other functions to do things to external links on a page. The next post shows how to add one of those offsite link images after the link with jQuery.

Update September 23rd 2011

With HTML5, the W3C has un-deprecated the target attribute so you can add target attributes to <a> and <form> tags and have the document still validate. Using jQuery as shown above can still be useful if you have a lot of pages and don’t wish to have to manually update all the links.

Inject HTML content into Disqus and jQuery

My last post looked at how to run Javascript functions after Disqus has loaded using their undocumented callback functions. The reason I needed to do this myself was to inject some additional content in the Disqus HTML, which I show how to do this in this. Update for Disqus 2012 (June 15th 2012) The disqus_config() …

Read more

Open a jQuery Facebox on page load

I was asked this morning how to go about opening a jQuery Facebox when the page loads; while I normally find dialogs that open in this way somewhat annoying they do have their uses when trying to show some form of disclaimer. This post shows how to do this.

Download Facebox

Download the Facebox plugin and associated files from http://defunkt.io/facebox/ There are a number of examples on that page but here I present a full HTML skeleton for you to start with.

Download jQuery from http://jquery.com/

Working example

View the working example here. This opens a new page and as soon as it’s loaded the jQuery Facebox dialog will be displayed without any user intervention.

The code

Here’s the full HTML and Javascript required to achieve this. Obviously you need to subsitute the Javascript and CSS url locations to where you have these located.

<!DOCTYPE html> 
 <html>
 <head>
 <title>Facebox on load</title>
 <link rel="stylesheet" href="/facebox/facebox.css" />
 <script src="/js/jquery-1.4.2.min.js"></script>
 <script src="/facebox/facebox.js"></script>
 <script>
 $(document).ready(function() { 
 .facebox.settings.opacity = 0.5; 
 $.facebox('This will display after the page has finished loading');
 });
 </script>
 
 </head>
 <body>
 
 </body>
 </html>

After the page loads, the dialog will display with the text “This will display after the page has finished loading”.

Getting the content via an Ajax request

To get the content from an Ajax request instead of it being hard coded into the HTML/JS, change this line:

$.facebox('This will display after the page has finished loading');
 

to this, changing the /path/to/remote.html to the URL of your content:

$.get('/path/to/remote.html', function(html) {
 $.facebox(html);
 });
 

Find the index of an item in a Javascript array

Javascript 1.6 introduced the Array.indexOf() function. Javascript 1.6 is available in Firefox from version 1.5 and current versions of Chrome, Safari and Opera; importantly, it is not in any versions of Internet Explorer at all (as at the time of this post).

Array.indexOf() function

Browsers that do not support indexOf() can easily have it added using the following function which extends the Array prototype.

I found the function in numerous sources on the Internet most of whichattribute it to the Mozilla Foundation, but I could not find theultimate source of the function. If anyone knows please let me know inthe comments at the end of this post and I can link to the originalsource.

//This prototype is provided by the Mozilla foundation and
 //is distributed under the MIT license.
 //http://www.ibiblio.org/pub/Linux/LICENSES/mit.license
 
 if (!Array.prototype.indexOf)
 {
 Array.prototype.indexOf = function(elt /*, from*/)
 {
 var len = this.length;
 
 var from = Number(arguments[1]) || 0;
 from = (from < 0)
 ? Math.ceil(from)
 : Math.floor(from);
 if (from < 0)
 from += len;
 
 for (; from < len; from++)
 {
 if (from in this &&
 this[from] === elt)
 return from;
 }
 return -1;
 };
 }

Note the “if (!Array.prototype.indexOf)” line means that the prototype will only be added if it doesn’t already exist. This means browsers which already have the function natively defined will use their own internal function instead of the one defined in the code above.

You can then do something like this:

var a = new Array("a", "b", "c", "d");
 alert(a.indexOf("c"));
 

which would alert “2” in a dialog box.

jQuery Superfish Menus Plug-in and Caching the menu

My last jQuery post looked at the Superfish plug-in showing how easy it is to turn an HTML unordered list into a flyout menu. The only downside with it is if the menu structure is very big there’s quite a large overhead in your HTML template with the menu. I present a simple solution in this post which involves caching the menu structure as a Javascript variable in a separate .js file.

The menu in the HTML template

The menu in the HTML template only needs to contain the top level menu, and needs to be surrounded by a containing <div>. For example:

<div id="menu">
 <ul class="sf-menu">
 <li><a href="#">Item 1</a></li>
 <li><a href="#">Item 2</a></li>
 <li><a href="#">Item 3</a></li>
 </ul>
 </div>
 

The menu in the Javascript file

The Javascript file contains the entire menu as a variable. For example (and using the same menu as used in the previous post):

var menu = ' 
 <ul class="sf-menu"> 
  
     <li><a href="#">Item 1</a> 
         <ul> 
             <li><a href="#">Subitem 1.1</a> 
                 <ul> 
                     <li><a href="#">Subitem 1.1.1</a></li> 
                     <li><a href="#">Subitem 1.1.2</a></li> 
                     <li><a href="#">Subitem 1.1.3</a></li> 
                 </ul> 
             </li> 
             <li><a href="#">Subitem 1.2</a></li> 
             <li><a href="#">Subitem 1.3</a></li> 
             <li><a href="#">Subitem 1.4</a></li> 
         </ul> 
     </li> 
  
     <li><a href="#">Item 2</a> 
         <ul> 
             <li><a href="#">Subitem 2.1</a></li> 
             <li><a href="#">Subitem 2.2</a></li> 
             <li><a href="#">Subitem 2.3</a></li> 
             <li><a href="#">Subitem 2.4</a></li> 
         </ul> 
     </li> 
  
     <li><a href="#">Item 3</a> 
         <ul> 
             <li><a href="#">Subitem 3.1</a></li> 
             <li><a href="#">Subitem 3.2</a></li> 
             <li><a href="#">Subitem 3.3</a></li> 
             <li><a href="#">Subitem 3.4</a></li> 
         </ul> 
     </li> 
 
 </ul> 
 ';
 

Note in the above example the allows line breaks to be contained in the Javascript. I have only done this for legibility because in my own code there are no line breaks for this Javascript variable.

Injecting the Javascript variable into the HTML with jQuery

When the page has finished loading, use jQuery to replace the HTML within the “menu” <div> with the HTML from the “menu” variable, and then call the .superfish() function to initialise the menu like so:

$(document).ready(function(){
     $("#menu").html(menu);
 $("#menu ul.sf-menu").superfish();
 });
 

Putting it all together

The following would then be present in the <head> section of your HTML template, where X.Y.Z are the appropriate version numbers and /path/to is replaced with the actual paths to the files, and “menu.js” is the file containing the menu variable (although you could consolidate it with other data and/or Javascript code in another file):

<script language="javascript" src="/path/to/jquery-X.Y.Z.min.js"></script>
 <script language="javascript" src="/path/to/menu.js"></script>
 <link rel="stylesheet" type="text/css" href="/path/to/superfish.css" />
 <script language="javascript" src="/path/to/superfish.js"></script>
 
 <script language="javascript">
 
 $(document).ready(function() {
     $("#menu").html(menu);
 $("#menu ul.sf-menu").superfish();
 });
 
 </script>
 

Conclusion

It’s really easy to make flyout menus with the Superfish jQuery plug-in. It’s also very easy to cache the menu structure into a separate Javascript file, as shown in this post, so it doesn’t add extra weight to the webpages as they are served. The Javascript file containing the meun will be cached which helps to speed up page load.

In a later post I’ll show how I’ve styled the Superfish plug-in to match a different template; I’ve been using it in the new version of the healthy.co.nz website which is due to go into production in a few weeks.

In the meantime, be sure to check out the Superfish website for more examples and full documentation for the effects possible. The plug-in can be downloadedhere from the jQuery website.