スマートフォン端末向けにtel:を仕込む小技

2012-12-05

※この記事は、軽めのjQuery Advent Calendar 2012の5日目の記事です。

スマートフォン端末のブラウザでは、tel:スキーマを<a href="tel:0120-0000-0000">お問い合わせはこちら</a>というように利用することで、ブラウザ上でタップして電話をかけることができるようになる。

しかし、これをデスクトップブラウザで実装してしまうと、クリックした時に不明なプロトコルとしてエラーとなってしまう。

これが問題となる可能性があるのは、いわゆるレスポンシブ・ウェブデザイン的なアプローチで、モバイルブラウザとデスクトップブラウザでHTMLを一本化してしまうような場合だ。

※問題とはいってもデスクトップユーザーが電話番号を見て、クリックして電話をかける、というアクションをするかどうかというのは置いといて。

カスタムデータ属性を使ったアプローチ

前提として下記のようなマークアップをおこなう。

お問い合わせは<span data-tel="0120-9999-9999">お電話</span>で!

<img src="btn-contact.png" alt="お問い合わせはお電話で!" data-tel="0120-8888-8888">

ポイントはdata-tel属性。この中にコール先の番号をセットしておく。あとはこの要素に対し、data-telの値をhrefにセットした<a />で包括する。で、これをjQueryっぽく書いてみる。

// とりあえず簡易的な方法でdetection(iPhoneの場合)
var ua =navigator.userAgent;
if(ua.indexOf('iPhone') > -1) {
  
  $(function() {
    // data-tel属性を持つ要素に対し、
    $("[data-tel]").each(function(){
      // data-tel属性の値を取得
      var tel = $(this).attr("data-tel");
      // a要素でwrapする
      $(this).wrap("<a href=" + 'tel:' + tel + "></a>");
    });
  });

};

こんな感じ。

data()メソッドは?

せっかくカスタムデータ属性をつかっているので、よりjQueryっぽくという意味ではdata()メソッドを使う方法もある。

$(function() {
  $("[data-tel]").each(function(){
    // data()メソッドでtel属性の値を取得
    var tel = $(this).data("tel");

    $(this).wrap("<a href=" + 'tel:' + tel + "></a>");
  });
});

が、これには罠がある

つまりdata()メソッドを使うと、0からはじまる文字列が数字として扱われるので、今回のような例だと危うい。

// stringで、そのまま 0120-9999-9999 になる
<span data-tel="0120-9999-9999">お電話</span>

// numberになるので、12099999999 になる
<span data-tel="012099999999">お電話</span>

ただこれが起きるのはjQuery1.8以前で、1.8からはdata()メソッドをつかっても型は変換されない。 実際にこちらのデモ上で、左のパネルからjQueryのバージョンを変えてRunしてみるとわかる。

その他、カスタムデータ属性の参照の仕方などについては、こちらも参照するといいかも。

もうちょい考えてみると

Detectionが正直微妙で、本来ならばtel:が有効な端末でっていうのが正しいので、単純にUAとかでみるのは微妙。例として挙げておいてなんだが、これだとたぶんiPod touchも含まれる。

またこのコードではスマートフォンブラウザのときに実行される前提になってるが、非力なスマートフォンブラウザ環境よりも、むしろデスクトップブラウザで実行されるようなスクリプトの方がいいだろう。

それならば例えば、

<a href="tel:0120-9999-9999">お電話</a>

これを標準とし、デスクトップブラウザのときに下記のようなコードを実行する。

$(function() {
  // href属性がtelから始まる要素の
  $("a[href^=tel]").each(function(){
    // 中身を抜いてspanに差し替える
    $(this).replaceWith("<span>" + $(this).text() + "</span>");
  });
});

これも雑な感じではあるが、このようにすれば<a><span>に変えることで、リンクを無効化できる。

ちなみに一応知らない人がいたら、ということで補足すると、$("a[href^=tel]")は属性セレクタで、href属性がtelからはじまるa要素、というセレクタ。この例ではtel:から始まるものというはブレないので、このようにしてみた。

※この属性セレクタの話は、同アドベントカレンダーの別記事として後日書く予定。

タグは差し替えず、event.preventDefaultでリンクを無効化しても良いかもしれないが、この場合にはCSSもマウスポインタがリンク時のポインタにならないようにしておきたい。

アドベントカレンダーは続く

次はハムの人ですね、よろしくおねがいします。

Hiroki Tani

Twitter | GitHub

Front-end Engineer, Writer & Speaker