Skip to page content or skip to Accesskey List.
Search evolt.org
evolt.org login: or register

Work

Main Page Content

User-Defined Window Targeting w/ JavaScript

Rated 4.09 (Ratings: 11) (Add your rating)

Log in to add a comment
(5 comments so far)

Want more?

 
Picture of Jeff Howden

Jeff Howden

Member info | Full bio

User since: December 13, 1998

Last login: February 22, 2008

Articles written: 21

A member of thelist recently inquired about a JavaScript that would give the visitor of his webpage the choice of whether links should open in the same window, a new window for all, or new windows for each. I figured this was a fun opportunity to write the JavaScript to allow the user to choose the target of certain links on the page.

Possible Solutions

In order to address this problem with the best solution we should think of as many ways to solve it as possible. Which method is the best will depend on your needs.

  1. Add an onClick event handler to links that will be affected by the user's choice
    • Advantages
      • You can attach this to only those links you wish to have this functionality.
      • No calculations regarding targets is made until the link is clicked.
    • Disadvantages
      • You have to attach it to every link you want it to effect. This could be time-consuming depending on how many links we're talking about.
      • If you wished to have a mechanism to allow the user to affect all the links you would have no way of doing it without adding the function call to the onClick event handler for every link.
    • Application
      • This is best suited for those times when you only want this functionality to work on a few links in a page.
  2. We could alter the value of the target attribute for every link in the page.
    • Advantages
      • We don't have to alter any of the links on the page. We just call a function that handles the setting of the value of the target attribute of the link to the appropriate value depending on which choice is selected.
    • Disadvantages
      • Every link on the page would be affected.
      • There's no mechanism to turn off the behavior for certain links like on-site navigation.
    • Application
      • This is perfect for a page full of links and you want them all to be affected. This is especially nice when the links on the page are constantly being added/edited/removed since you don't have "attach" this functionality to the links individually.
  3. We could alter the value of the target attribute for only those links in the page that are marked for alteration.
    • Advantages
      • We could have different sets of links attached to different mechanisms.
      • We could have a mechanism that would affect all the links on the page.
    • Disadvantages
      • We'd have to alter those links we wanted to have use this functionality.
      • The function is altering all the marked links on the page whenever the selection is changed.
    • Application
      • Want ultimate flexibility? You've got it with this.

No matter which method you decide to use, you need to give the user some means of triggering the choice. For simplicity let's make them a group of radio buttons. It could just as easily be links that change the value of a JavaScript variable with their onClick event handler. Or, it could be a dropdown menu that calls a function with its onChange event handler. It doesn't much matter, the end result is the same. With this information in mind, let's dig in.

Solution 1 - Using the onClick event handler of the link

The Options

This method assumes that the radio buttons won't actually affect anything when they're clicked. They will only serve as a mechanism to store and display the user's choice. With that in mind, here's the code for the radio buttons.

<form>
  [<input type="radio"
          name="target"
          id="target_self_0"
          value="_self"
          tabindex="1"
          title="Open links in this window"
         >

The Links

The links are where the action is initiated. So, we need to attach some onClick event handlers to them. The onClick event handler will call the function in such a way that the event handler will be expecting a value to be returned from the function before it can do anything. This will allow us to alter the value of the target attribute before the browser follows the link.

<a href="http://www.evolt.org/"
  >

The Function

To finish this up we're going to need a function that sets the value of the target attribute of the clicked link to match the choice the user made with the radio buttons. After setting the target we'll then need to return a boolean value, true, to the event handler so the browser will execute the click action of the user and follow the link.

[Note: See my article JavaScript: The Point of No Return?! for an explanation of how return statements affect event handlers that can have their action canceled.]

<script language="JavaScript" type="text/javascript">
<!-- 
  var targetForm = null;

  function setTarget_0(obj)
  {
    if(targetForm != null)
    {
      targetLen = targetForm.elements['target'].length;
      targetText = '_self';
      for(t = 0; t < targetLen; t++)
      {
        if(targetForm.elements['target'][t].checked)
        {
          targetText = targetForm.target[t].value;
          break;
        }
      }
      obj.target = targetText;
    }
    return true;
  }
// -->
</script>

The Result

[ Self] [ Same] [ New]

Solution 2 - Changing the target Attribute for every link

The Options

This method assumes that the links are clueless as to any JavaScript that's used to affect what window they're to target. Instead, the target attributes will be altered when a radio button is clicked. With that in mind, here's the code for the radio buttons.

<form>
  [<input type="radio"
          name="target"
          id="target_self"
          value="_self"
          tabindex="1"
          title="Open links in this window"
         >

The Links

The links are what could be considered "dumb" links in that they aren't aware in any way that they're being affected by JavaScript. So, unlike the last example, these links won't have any event handlers.

<a href="http://www.evolt.org/"
>evolt.org</a>
<a href="http://www.slashdot.org/"
>/.</a>
<a href="http://www.microsoft.com/"
>Microsoft</a>
<a href="http://www.netscape.com/"
>Netscape</a>

The Function

To finish up this example we're going to need a function that sets the value of the target attribute for all links to match the choice the user made with the radio buttons.

<script language="JavaScript" type="text/javascript">
<!-- 
  function setTarget2(target)
  {
    for(a = 0; a < document.links.length; a++)
    {
      document.links[a].target = target;
    }
  }
// -->
</script>

The Result

[ Self] [ Same] [ New]

Solution 3 - Changing the target attribute for certain links

The Options

This method assumes that the links are clueless as to any JavaScript that's used to affect what window they're to target. Instead, the target attributes will be altered when a radio button is clicked. The difference between this method and the last is that we'll "mark" certain links for alteration by adding the name attribute and giving it the same value for all instances. With that in mind, here's the code for the radio buttons.

<form>
  [<input type="radio"
          name="target"
          id="target_self_2"
          value="_self"
          tabindex="1"
          title="Open links in this window"
         >

The Links

The links are what could be considered "dumb" links in that they aren't aware in any way that they're being affected by JavaScript. So, like the last example, these links won't have any event handlers. However, unlike the last example these links will have name attributes and a common value.

<a href="http://www.evolt.org/"
   name="target"
>evolt.org</a>
<a href="http://www.slashdot.org/"
   name="target"
>/.</a>
<a href="http://www.microsoft.com/"
   name="target"
>Microsoft</a>
<a href="http://www.netscape.com/"
   name="target"
>Netscape</a>

The Function

To finish up this example we're going to need a function that sets the value of the target attribute for all "marked" links to match the choice the user made with the radio buttons. This function will differ from the previous one in that it will check to make sure the value of the name attribute of the link it's going to change matches the name of the radio buttons the user is interacting with.

<script language="JavaScript" type="text/javascript">
<!-- 
  function setTarget_2(obj)
  {
    for(a = 0; a < document.links.length; a++)
    {
      if(document.links[a].name == obj.name)
        document.links[a].target = obj.value;
    }
  }
// -->
</script>

The Result

[ Self] [ Same] [ New]

Note:

  1. the value of the name attribute should not be used as an internal anchor in the page at any point
  2. the value of the name attribute must be the same value for all links
  3. the value of the name attribute for the links to be targeted by the user should exactly match the value of the name attribute of the group of radio buttons the developer wishes to tie to those same link(s)

Did I thoroughly confuse you?

In theory you could get fancy and have a different set of controls for different portions of links on the site. You could have one set of controls for all onsite links and another set for offsite links, or you could have controls for all links in a sidebar (like list of blogs or some such). The important thing to note is that they're all tied by the value of the name attributes both on the radio buttons for the links and the name attribute of the links to be affected themselves.

Good Luck!

.jeff

Jeff Howden (.jeff) is a web developer working for Vos & Howden, LLC in Portland, Oregon where he's partnered with long-time colleague, Anthony Vos. His skills include ColdFusion, JavaScript, CSS, XML, relational databases, and much, much more. His biggest professional accomplishments include, but are not limited to:

  • building a ColdFusion-based e-commerce solution for Mt. Bachelor that transacted over $1.62 million dollars in September 2001 with 0 (yes, that's zero) ColdFusion errors and then an almost completely rebuilt version transacted $2.86 million dollars in September 2002.
  • being asked to be a Technical Editor for the ColdFusion MX book, Inside ColdFusion MX from New Rider's Publishing company.
  • being asked by BrainBench to perform quality control on their JavaScript 1.5 certification test after receiving the highest beta test score out of 200 testees.
  • managing the server that hosts evolt.org and withstanding a slashdotting that brought over 1,000,000 hits to the site, over 10 gigs of data transfer, and an average in excess of 2300 unique visitor sessions per hour, all within a 24-hour period and the server never hiccuping once.

This is awesome stuff

Submitted by shaunshull on October 18, 2001 - 15:30.

Nice work, I can see many implementations for this.

login or register to post comments

link objects and name

Submitted by bobince on October 23, 2001 - 10:40.

There's a practical problem with this - HTMLLinkElements do not have a 'name' property. Internet Explorer and Mozilla implement one, but it's not in the DOM Level 1 HTML standard, and Netscape and Opera won't touch it.

How about giving all the links 'target="_self"' in the HTML, and then making the script scan through them at startup looking for the target attribute being set to '_self' and generating a list of 'link objects to affect' which is kept, and looped through when the controls are used?

(Actually I'm not convinced this is a particularly useful feature, since all browsers have "open link in new window" very easily accessible, but it's an interesting script. :-) )

login or register to post comments

Re: link objects and name

Submitted by Jeff Howden on October 23, 2001 - 15:50.

Andrew (bobince),

You are mistaken. If you take a look at the HTML 4.01 spec on anchors, you'll see that anchors do indeed have a name attribute. In fact, the name attribute goes all the way back to HTML 2.0.

The reason you don't find the name attribute for &lt;a&gt; tags in DOM Level 1 is because it's in DOM Level 0. If you think about how objects are created when the page is rendered, you'll see where the name attribute comes into play. We're all familiar with the Image object. When the page is rendered, the browser creates an array of forms, an array of images, an array of links, an array of elements for each form, etc. Any of these array elements can be accessed by their index. However, if a form, form element, image, or even link has a name attribute, we can access that element by its name. For example, most of us know we can alter the src attribute of an &lt;img&gt; tag by referring to it by it's name attribute value. The same is true for links and their attributes. This method of accessing array elements by their name instead of their numeric index is referred to as an associate array.

Additionally, if you'd take the time to test the examples in this article you will see that they work in NN3 and NN4 as well as Internet Explorer and Mozilla. They don't work with Opera because there isn't any mechanism built into this browser that allows the changing of attribute values after rendering the page. This is a flaw in Opera's product as this functionality has been in JavaScript since version 1.0.

"The target property initially reflects the TARGET attribute of the A or AREA tags; however, setting target overrides this attribute.

You can set target using a string, if the string represents a window name. The target property cannot be assigned the value of a JavaScript expression or variable.

You can set the target property at any time."

Your suggestion of giving all links a target attribute with a value of "_self" is a good one, if you don't mind having to include this attribute every time you add a link to the document. It doesn't work particularly well (i.e., overkill) if you want to have every link on the page respond to the user's window targeting preference. Additionally, this doesn't solve any of the problems you describe (those that remain) as Opera won't allow you to change any attribute values after the page is rendered. Thankfully it fails gracefully and simply opens the link in the same window without throwing any JavaScript errors.

In a final note, I agree with your parenthetical conclusion -- What's wrong with the user shift-clicking the link or right-clicking and selecting "Open in New Window?". The answer is -- there isn't anything wrong with users using their preferred method of navigation. The nice thing about this script is that it doesn't break any of the in-browser navigation aids the user might choose to use. I disagree that this isn't a practical solution though as a lot of users aren't aware of these additional navigation aids. If you'll re-read the opening paragraph, I explain that the impetus for writing this article was a question from a member of thelist about how to do it.

Thanks,

.jeff

login or register to post comments

Alternative to the javascript target solution

Submitted by mhowells on December 7, 2001 - 12:59.

One solution to the problem of changing all the links using javascript is to identify the href property of the link and changing the link target property onload. My implementation says that if the link contains http:// and doesn't contain the URL of my site (www.mark.ac), then the link should open in a new window.


body onload="outLinks('www.mark.ac')"

function outLinks(myURL){
	linkTarget="_blank";
	for (var i=0; i  
  

login or register to post comments

Cool!

Submitted by oiboi on January 9, 2002 - 18:31.

Thats some creative work there! Good job on explaining the pros and cons of the different ways of doing it.

Very clear and concise.

login or register to post comments

The access keys for this page are: ALT (Control on a Mac) plus:

evolt.orgEvolt.org is an all-volunteer resource for web developers made up of a discussion list, a browser archive, and member-submitted articles. This article is the property of its author, please do not redistribute or use elsewhere without checking with the author.