HTML 5.1 のmenuitem
要素を使ってコンテキストメニューをカスタマイズする
- 投稿
- 最終更新
HTML 5.1がアップデートされましたね。
変更点はDifferences from HTML4にまとまっていますが、main
要素の追加、hgroup
要素の削除などとともに個人的に注目しているのは menu API が刷新されたことです。
HTML4 以前の話も含め、改めておさらいしてみたいと思います。
menu
要素の生い立ち
menu
要素の歴史は古く、1993年のいわゆるHTML 1.0の Internet Draft 文書には ul
や dir
などとともに定義されています。当時の意味づけは ul
と似た順不同リストのようで、 "smaller paragraphs" を表す点などが異なりました。ところがブラウザはそうは描画しなかったようで、HTML 3.2ではIn practice, Mosaic and most other user agents have ignored this advice and instead render DIR and MENU in an identical way to UL elements.
と書かれてしまっています。
HTML 4ではこの要素は Deprecated(推奨しない)とされ、代わりに ul
要素を使うよう推奨されています。
HTML5 のmenu要素とcommand要素
HTML5では従来非推奨とされ、また実際もほとんど使われていなかった [要出典] menu
要素がコマンドリストを示すものとして復活しました。さらにcommand
要素が登場し、menu
要素と組み合わせることでツールバーやコンテキストメニューを作ることが可能、とされました。
ただし、私の知る限りcommand
要素をサポートしたブラウザは存在しません。
2013年8月8日追記2013年8月6日版(CR)でcommand
要素とmenu
要素は削除されました。
HTML 5.1 のmenu
要素とmenuitem
要素
去年12月に HTML5 が勧告候補(CR)になるとともに最初の草案が発表された HTML 5.1 ですが、先日1回目のアップデートが行われました。menu API 関連の主な変更点はこんなところです。
command
要素を止めて新たにmenuitem
要素が追加menu
要素のtype
が変更、属性を省略した場合のデフォルトも変わっているbutton
要素のtype
にmenu
が追加
HTML5 では、menu
要素のtype
は「context
(コンテキストメニュー)」「toolbar
(ツールバー)」、および省略時の「リスト」の3種類とされていました。HTML 5.1 ではこれが「popup
(ポップアップメニュー)」「toolbar
(ツールバー)」に変更されています。
コンテキストメニューはポップアップメニューに含まれていますが、現状は唯一(?)対応しているFirefoxが popup
を認識しないため、コンテキストメニューを出したい場合は従来どおり context
を指定する必要があります。
menuitem
要素は実例を見た方が早いでしょう。コンテキストメニューをカスタマイズするにはこんなマークアップを行います。
<p contextmenu="my_context">Firefox 8 以降でこの文章上を右クリックすると独自のコンテキストメニューを表示します。</p>
<menu type="context" id="my_context">
<menuitem label="独自のコンテキストメニューです" icon="context_icon.png"/>
</menu>
- コンテキストメニューの場合、
label
属性は必須です。
これだけではあくまで右クリックしたときなどに表示を行うだけで、それを選択しても何も起こりません。実際の動作はスクリプトで定義することになります。
実例: 引用文のcite
属性へ遷移する機能を作ってみる
HTML4では引用を表す blockquote
, q
要素にcite
属性が定義され、機械可読可能な形で出典の提示が行えるようになりました。一方、cite
属性値を画面に表示したり、自動リンクするようなブラウザは存在しないため、閲覧者に対して出典を明示する場合はa
要素でリンクを併記するなどの対応が必要です。
一応、Operaは次のような拡張スタイルシートを使えばリンクすることができるのですが、次バージョンの Opera 15 ではレンダリングエンジンの変更に伴って使えなくなりますし、そもそも現状誰も使っていない [要出典] でしょうし…。
blockquote[cite],
q[cite] {
-o-link: attr(cite);
-o-link-source: current;
}
ともかくそんな状況ですので、menuitem
要素を使って「引用元ページを見る」機能を付けてみます。
<!DOCTYPE html>
<html lang="ja">
<head>
<title>menuitem要素を使って引用元ページ(cite属性)へ遷移するメニューを作る</title>
<script>
window.addEventListener("load", function() {
/**
* menuitem要素を使って引用元ページ(cite属性)へ遷移するメニューを作る
*/
(function() {
if (!("contextMenu" in document.body) || !("HTMLMenuItemElement" in window)) {
// menuitem要素によるコンテキストメニューのカスタマイズに対応していない場合
return;
}
var target;
var quotes = document.querySelectorAll('blockquote[contextmenu], q[contextmenu]');
for (var i = 0, quoteLen = quotes.length; i < quoteLen; i++) {
quotes[i].addEventListener("mousemove", function(ev) {
// contextmenu属性が設定された blockquote, q 要素にマウスが乗ったときは当該要素を記録する
target = ev.currentTarget;
}, false);
}
var menuitem = document.createElement("menuitem");
menuitem.label = "引用元ページを見る";
menuitem.icon = "context_icon.png";
menuitem.addEventListener("click", function() {
// 対象コンテキストを押下した場合、当該引用文のcite属性値のリソースへ遷移する
location.assign(target.cite);
}, false);
// 生成したmenuitem要素をmenu要素に挿入する
document.getElementById("quote_cite").appendChild(menuitem);
})();
}, false);
</script>
</head>
<body>
<p>menu要素について、HTML 2.0(RFC 1866)では以下のように定義されていました。</p>
<blockquote lang="en" cite="http://tools.ietf.org/html/rfc1866#section-5.6.4" contextmenu="quote_cite">
<p>The <MENU> element is a list of items with typically one line per item. The menu list style is typically more compact than the style of an unordered list.</p>
</blockquote>
<p>ところが、HTML 3.2では
<q cite="http://www.w3.org/TR/REC-html32#menu" contextmenu="quote_cite">In practice, Mosaic and most other user agents have ignored this advice and instead render DIR and MENU in an identical way to UL elements.</q>
と書かれてしまっています。</p>
<menu type="context" id="quote_cite"></menu>
</body>
</html>
- jsdo.itに動作サンプル(
jsdo.it
)をアップしています。
Firefoxで引用文上で右クリックすると、コンテキストメニューの最上段に「引用元ページを見る」が出現し、文字の左側にはアイコン(context_icon.png)も表示されます。
このコードでは、HTMLにはmenu
要素のみを書いておき、menuitem
要素はJavaScriptで挿入しています。スクリプト無効環境では独自のコンテキストメニューを表示する意味が無い(押しても動作しない)ので、このような実装をしています。
また、blockquote
やq
要素のcontextmenu
属性はcite
属性が存在し、かつその値がURLな場合のみを付与することになります。もし条件にかかわらず属性を一律付与しなければならない場合は、JavaScript側でcite
属性が存在しない場合やURNだった場合の除外判定を入れる必要があるでしょう。
ところでこのコードには「キーボード操作では独自コンテキストメニューが表示されない」という問題があります。Firefoxでは、F7キーを押すことによりキャレットブラウズモード(support.mozilla.org
)になりますが、その状態で Shift + F10 キーなどでコンテキストメニューを表示しても、menuitem
要素で定義した項目は現れません。この問題はBug 699709(bugzilla.mozilla.org
)に上がっていますが、今のところ解決されていないようです。
Webサイト側でできる解決方法として、当該要素に tabindex="0"
を付けることでキー操作においても独自コンテキストメニューを表示することができます。ただ、本来フォーカスさせる必要のない要素にtabindex
を設定するのはちょっと不毛な感じもしますが…。
まあどちらにしても現状は Firefox でしか使えない機能ですし、JavaScriptを無効にしているユーザーや、コンテキストメニューを出せない・出しにくい環境のこと考えると、(menu APIのブラウザ実装が普及したとしても)従来どおりa
要素によるリンクは残しておいた方が良いのかな、と思います。
menuitem
要素で使っているアイコン画像はNIXUS Icon Pack: 60 Beautiful Premium Icons (Free) | Tutorial9(www.tutorial9.net
)のものを使用しました。