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
  2. We could alter the value of the target attribute for every link in the page.
  3. We could alter the value of the target attribute for only those links in the page that are marked for alteration.

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"

onClick="targetForm = this.form"

checked>

<label for="target_self_0"

accesskey="s"

title="Open links in this window"

><u>S</u>elf</label>]

[<input type="radio"

name="target"

id="target_same_0"

value="_same"

tabindex="2"

title="Open links in the same new window"

onClick="targetForm = this.form">

<label for="target_same_0"

accesskey="a"

title="Open links in same new window"

>S<u>a</u>me</label>]

[<input type="radio"

name="target"

id="target_blank_0"

value="_blank"

tabindex="3"

title="Open links in a new window for each link"

onClick="targetForm = this.form">

<label for="target_blank_0"

accesskey="n"

title="Open links in a new window for each link"

><u>N</u>ew</label>]

</form>

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/"

onClick="return setTarget_0(this)"

>evolt.org</a>

<a href="http://www.slashdot.org/"

onClick="return setTarget_0(this)"

>/.</a>

<a href="http://www.microsoft.com/"

onClick="return setTarget_0(this)"

>Microsoft</a>

<a href="http://www.netscape.com/"

onClick="return setTarget_0(this)"

>Netscape</a>

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

[

]

[

]

[

]


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"

onClick="setTarget_1(this.value)" checked>

<label for="target_self"

accesskey="s"

title="Open links in this window"

><u>S</u>elf</label>]

[<input type="radio"

name="target"

id="target_same"

value="_same"

tabindex="2"

title="Open links in the same new window"

onClick="setTarget_1(this.value)">

<label for="target_same"

accesskey="a"

title="Open links in same new window"

>S<u>a</u>me</label>]

[<input type="radio"

name="target"

id="target_blank"

value="_blank"

tabindex="3"

title="Open links in a new window for each link"

onClick="setTarget_1(this.value)">

<label for="target_blank"

accesskey="n"

title="Open links in a new window for each link"

><u>N</u>ew</label>]

</form>

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

[

]

[

]

[

]


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"

onClick="setTarget_2(this.value)" checked>

<label for="target_self_2"

accesskey="s"

title="Open links in this window"

><u>S</u>elf</label>]

[<input type="radio"

name="target"

id="target_same_2"

value="_same"

tabindex="2"

title="Open links in the same new window"

onClick="setTarget_2(this.value)">

<label for="target_same_2"

accesskey="a"

title="Open links in same new window"

>S<u>a</u>me</label>]

[<input type="radio"

name="target"

id="target_blank_2"

value="_blank"

tabindex="3"

title="Open links in a new window for each link"

onClick="setTarget_2(this.value)">

<label for="target_blank_2"

accesskey="n"

title="Open links in a new window for each link"

><u>N</u>ew</label>]

</form>

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

[

]

[

]

[

]


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