新規ウィンドウを開く手段を Valid と両立させる考察

2007/06/10

以前に書いた
Numb. – _blank を使わない新規ウィンドウの開き方
の続きにあたる記事です。一応、もう一度おさらいしてみます。

06/13 追記:
大事な部分を丸ごと書き忘れていることに気付きました orz
javascript 関連の部分を追記いたしました。

新規ウィンドウを開かせる手段を実装したい、という場合は以下の 2 種類が有名だと思います。

  • a に target=”_blank” を指定する
  • javascript で設定する

しかし「ウィンドウを新たに開くかどうか」はユーザーが決めるべきことなので、作り手が決め手はいけない、という話もあります。
そのためか、XHTML 1.1 や XHTML Basic では target=”_blank” という書き方は準拠していない、とされ NG になってしまいます。
「マークアップ言語である HTML で、ウィンドウ操作をする」という点も問題なのだと思います。マークアップ目的以外になるので。

でもユーザーの中にも新規ウィンドウを開く手段を実装しておいて欲しいという人もいます。
いやいや余計なお世話だから、こっちに決めさせてくれ、そんなことは実装しておかないでくれ、という人もいます。
実装して欲しい・欲しくない、という人が両方いる…ということで、じゃあ両方のリンクを制作しておけばいいんじゃ!と思いまして。今回はそんな方向でやってみました。

ポイント

  • rel 属性は XHTML1.0 Transitional では OK 。HTML4.0 では rel に指定できる値が決まっている。rel を使うのならば、XHTML1.0 Transitional で書いておくようにする。今回はより柔軟に対応するために、class 属性を使用。
  • マークアップ言語である HTML でウィンドウ操作はしない(つまり _blank は使用しない)。新規ウィンドウを開く部分は javascript で window.open を使って実装。

実装方法は次のような形。

見本

Numb.

テキスト部分のリンクをクリックすると同じウィンドウで開き、矢印の画像部分のリンクをクリックすると新しいウィンドウで開きます。

※現在違う方法で実装を始めたため、この見本では新規ウィンドウが開きません。

実装方法

  • ) か b ) どちらかの方法を選び、javascript を保存。HTML に外部ファイルとしてこれを読み込ませる。
  • た目を整えるための、style.css にコレ用の CSS を追記。
  • ウィンドウを開くリンクとしておきたい a タグに `class=”external”` をつける。
    ※ウィンドウを開かないリンクも一緒に記述します。
  • おまけ。 Firefox の方は Copy+ を使って簡単に記述できるようにすると便利です。ここは任意。

1. javascript

prototype.js を利用する場合と、利用しない場合では少しだけ javascript が違います。
もし Litebox 等、body に onload を書くものを利用している場合は prototype.js を利用するほうを選んでください。

参考:prototype.jsを使ってみる 2-Event.observe[to-R]

a ) prototype.js を利用しない場合

function externalLinks() {
	if (! document.getElementsByTagName ) return;
	var anchors = document.getElementsByTagName("a");
	for (var i=0; i<anchors .length; i++) {
		var anchor = anchors[i];
		if (anchor.getAttribute("href") && anchor.getAttribute("class") == "external") {
			anchor.onclick = function(event){return newWindow(this, event);}
			anchor.onkeypress = function(event){return newWindow(this, event);}
		}
	}
}
function newWindow(anchor, event){
	var keyCode;
	if (event && event.type == 'keypress') {
		if (event.keyCode)
		keyCode = event.keyCode;
		else if (event.which)
		keyCode = event.which;
		// 13 == Return key. 32 == space key
		if (keyCode != 13 && keyCode != 32)
		return true;
	}
	return !window.open(anchor);
}
window.onload = externalLinks;

上記 javascript を「externalLink.js」と名前をつけて保存。
以下の 1 行を HTML の header 内に書く。

<script type="text/javascript" src="/path/externalLink.js">

上記の方法は onload を最後の 1 行に書いています。
onload イベントは 1 ページに 1 回しか使えないため、もし onload を他のスクリプト( Litebox など)で使用している場合、この記述方法では実装できません。
そんな方は b ) prototype.js を利用する場合、のほうを使ってください。

b ) prototype.js を利用する場合の javascript

function externalLinks() {
	if (! document.getElementsByTagName ) return;
	var anchors = document.getElementsByTagName("a");
	for (var i=0; i</anchors><anchors .length; i++) {
		var anchor = anchors[i];
		if (anchor.getAttribute("href") && anchor.getAttribute("class") == "external") {
			anchor.onclick = function(event){return newWindow(this, event);}
			anchor.onkeypress = function(event){return newWindow(this, event);}
		}
	}
}
function newWindow(anchor, event){
	var keyCode;
	if (event && event.type == 'keypress') {
		if (event.keyCode)
		keyCode = event.keyCode;
		else if (event.which)
		keyCode = event.which;
		// 13 == Return key. 32 == space key
		if (keyCode != 13 && keyCode != 32)
		return true;
	}
	return !window.open(anchor);
}
Event.observe(window,'load', externalLinks, false);

上記 javascript を「externalLink.js」と名前をつけて保存。
以下の 2 行を HTML の header 内に書く。

<script type="text/javascript" src="/path/prototype.js">
<script type="text/javascript" src="/path/externalLink.js"></script>

javascript の最後の 1 行、`Event.observe(window,’load’, externalLinks, false);` は prototype.js を利用しています。
onload で読み込むものが他にある場合は、こちらの javascript を利用してください。

prototype.js も読み込む必要がありますが、よく使われているため「すでに prototype 使ってるよ」という方もいると思います。
その場合は再度読み込ませなくても OK ですので、externalLink.js を読み込ませる分だけ追記してください。

2. CSS

WP の使用しているテーマの style.css に以下の CSS を追記します。

/* for externalLink */
a.external {
	margin: 0 5px 0 3px;
}
a.external img {
	vertical-align: middle;
	border: none!important;
}

a.external の margin 設定は、画像の左右の余白設定です。
margin: 上 右 下 左;
という感じですので、余白を調整したい場合は変えたい場所の数字を変更してください。

a.external img のほうの設定は特に弄らなくて大丈夫だと思います。

3. XHTML

<a href="http://www.google.co.jp/" title="Google">Google</a>
<a href="http://www.google.co.jp/" title="[Google]を新しいウィンドウで開く" class="external">
<img src="http://hogehoge/hogehoge.gif" alt="[Google]を新しいウィンドウで開く" /></a>

このような形で書いています。画像のパスは自分で用意した画像ファイルのパスに適宜変更してください。
上では見やすくするために改行を入れてますが、実際には改行はなくて OK です。

アイコン探し参考:

いろいろな用途で使えるミニアイコンあれこれ – GIGAZINE

この方法の良い点

  • Valid である。
  • ページを新しいウィンドウで開くか、そのままのウィンドウで開くか、この両方を提供できる。

この方法の悪い点

  • リンク 1 つにつき 2 つ分のリンクを書くことになるので、ソースが長くなる。
  • これに対応した HTML をその都度書くのが面倒。

この悪い点の 2 つめ、書くことが面倒なのが最大の問題点だと思っています。
そんなわけで、Firefox + CopyURL+ で簡単にタグを作れるようにしました。

CopyURL+ でこの方法用のタグを生成

CopyURL+ の使い方や細かい点は「
Numb. – 「Copy URL+」+「MozShot」
」という記事に書いたので、こちらを参考になさってください。

Copy URL+ 用 user.js

user_pref('copyurlplus.menus.n.label','Create URL&Title/externalLink');
user_pref('copyurlplus.menus.n.copy','<a href="%URL%" title="%TITLE%">%TITLE%</a><a href="%URL%" title="[%TITLE%]を新しいウィンドウで開く" class="external"><img src="http://hogehoge/hogehoge.gif" alt="[%TITLE%]を新しいウィンドウで開く" /></a>
');

※user_pref(‘copyurlplus.menus.n.・・・の、n の部分は user.js 内でかぶらないように数字をつけます。
これのみなら 1 、他にすでに 1~3 まで使ってあるなら 4 、というかんじに。

※http://hogehoge/hogehoge.gif は自分の用意した画像ファイルのパスに置き換えてください。

以上です。もしよろしければお試しください :grin:

07/07/30 追記
javascript で新しいウィンドウを開くためのアイコンを自動で追加する方法に現在は至りました。
リンクに、新しいウィンドウで開くためのアイコンを自動で追加(Wpプラグイン) – Numb.