こんにちは。 VOYAGE GROUP でエンジニアをしています tatenosystem です。
 
最近、社内で slack というサービスを良く使っているのです。 
しかし、結構書き込みを見逃しがちで 「定期的に確認するのはめんどくさいなぁ」 と思ったら、なんとデスクトップ上に通知をしてくれる 「Web Notification」 に対応しているじゃないですか。これは便利!

WEBページからの通知があると、PC画面上に 「通知ウィンドウ」 が出てきます。
こんな感じ。

slacknotice
 
しかもブラウザの機能で行っているので、特別なプログラムはいらないです。
まぁ、対応しているブラウザでないとダメなんですが。。。

かなり前(たしか2010年くらい?)から 「Web Notification」 の名前は聞いたことはありましたが、本格的にサービスとして使っているサイトは始めてみました。さすが slack。

誰も使わずに滅んだと見せかけて、急に使われだすというのは 「Bluetooth規格」 を思い出します。

そんな訳で個人的に盛り上がったので、WEBサービスに 「Web Notification」 を実装するにはどうしたらいいか妄想してみました。

調べたところ、勝手に通知がポコポコ上がると鬱陶しいので、ドメインごとに「許可」する必要があるみたいです。
「Web Notification」 の状態(Permission)は以下の3つ。

<Web Notification Permissions>
  • default … ユーザーの承認を取っていない状態
  • granted … 許可された状態
  • denied … 拒否された状態

では、最初に 「Permission を取得できる関数」 を JavaScript で作ります。
非対応ブラウザも状態として取得したかったので、勝手に「unusable」という状態を追加した関数を作成しました。

function noticPermission()
{
  if (! window.Notification) return "unusable";
  if (Notification.permission) {
    return Notification.permission;
  } else {
    return ((new Notification("check")).permission);
  }
}

次に HTML ですが、Permission 状態で表示する内容が違うので状態ごと4種類の表示内容を記載します。
HTML DOM の id は「状態+"WebNotice"」としました。初期状態はすべて非表示です(style="display:none")

<p>[設定] </p>
<p>
<div id="unusableWebNotice" class="infoWebNotice" style="display:none">
    Your browser does not support desktop notifications.
</div>
<div id="defaultWebNotice" class="infoWebNotice" style="display:none">
    <button id="requestPermission">Enable desktop notifications</button>
</div>
<div id="grantedWebNotice" class="infoWebNotice" style="display:none">
    <input id="canWebNotice" type="checkbox"><span>Desktop Notifications</span>&nbsp;<a href="#" id="showWebNoticeTest">Send test notification</a>
</div>
<div id="deniedWebNotice" class="infoWebNotice" style="display:none">
    Desktop Notifications are currently disabled.
</div>
</p>
Permission 状態ごとの表示内容はこんな感じ。

  • unusable … 非対応ブラウザだよーというメッセージを出します
  • default … 「承認ボタン」を表示します
  • granted … Web Notification(デスクトップ通知)を使用するかどうかのチェックボックスを表示
  • denied … Web Notification(デスクトップ通知)が拒否されてるよーというメッセージを出します
granted の場合はテストリンクも表示するようにします。
完全に slack の パク リスペクト。

すべてを表示すると、こんな表示になります。

confightml01

Permission に合わせた HTML を表示 しなくてはなりません。
というわけで関数を作成します。
HTML DOM の id を「状態+"WebNotice"」としたので、簡単に DOM 指定ができて便利です。

function showInfoWebNotice()
{
  $(".infoWebNotice").hide();
  $("#"+noticPermission()+"WebNotice").show();
}

で、ページ表示のタイミングでこの関数を実行するわけですが、私が好きな jQuery を使います。

$(function(){
  showInfoWebNotice();
});

つぎに 「承認ボタン」を押された時 の事を考えます。
 「Web Notification」 の Notification.requestPermission() を使用してユーザーに承認要求を行います。
「承認ボタン」のクリックイベントに Notification.requestPermission() を設定します。
コールバックが指定できるので、コールバックで先ほど作った showInfoWebNotice() を呼び出し、「承認」もしくは「拒否」された直後、画面表示を切り替えます。

$(function(){
  showInfoWebNotice()

  $('#requestPermission').click(function(){
      Notification.requestPermission(function(){
        showInfoWebNotice();
      });
  });
});

いよいよ本命の Web Notification を行う関数を作ります。
slack の Web Notification は数秒で自動で消えますので、これも真似しましょう。
setTimeout を利用して一定時間後に自動で通知ウィンドが消えるようにします。
「チェックボック」を確認して、チェックされていなかったら処理を行わないようにします。 

この関数には、「タイトル、本文、アイコン、表示時間(ms)、テストの有無」 を引数で渡せるようにします。

表示時間(ms) は「0」指定で無制限。
テストモードの場合は「チェックボック」にチェックがなくても「通知」できるようにします。

function doWebNotification(title, body, icon, timer, test)
{
    if(typeof timer === "undefined") timer = 0;
    if(typeof icon === "undefined") icon = "";
    if(typeof test === "undefined") test = false;
    
    if (! test) {
        if (! $("#canWebNotice").is(':checked')) return;
        if (noticPermission() != "granted") return;
    }
    
    var notification;
    notification = new Notification(title, {body: body, iconUrl: icon, icon: icon});
    notification.onclick = function() {
        notification.close();
    };
    
    if (timer != 0) {
        setTimeout(function(){
            notification.close();
        }, timer);
    }
}

これで Web Notification を使う準備ができました。
さて、いよいよ doWebNotification() を使ってみましょう。

チェックボックスの右にある 「Send test notification」 をクリックした時、テストモードで doWebNotification() を呼び出すようにします。1.7秒後に自動で通知が消えるようにします。 

$(function(){
  
  ………
  
  $("#showWebNoticeTest").click(function(){
      doWebNotification("Hello", "Hello WebNotification", "", 1700, true);
      return false;
  });
});

テストモード以外の通知ボタンも作りましょう。ボタンを押したら Web Notification を行うようにします。
HTMLにボタンを配置して、

<button id="showWebNotice1">SHOW NOTICE 1</button>
<button id="showWebNotice2">SHOW NOTICE 2</button>
<button id="showWebNotice3">SHOW NOTICE 3</button>
<button id="showWebNotice4">SHOW NOTICE 4</button>

イベントを設定します。

$(function(){
  ……
  
  $("#showWebNotice1").click(function(){
      doWebNotification("テスト", "ヘ(^o^)ヘ\n  |∧\n  /", "testicon.png", 1500);
  });
  $("#showWebNotice2").click(function(){
      doWebNotification("テスト", "  (^o^)/\n /(  )\n/ >", "testicon.png", 1500);
  });
  $("#showWebNotice3").click(function(){
      doWebNotification("テスト", " (^o^) 三\n (\\ 三\n< \ 三", "testicon.png", 1500);
  });
  $("#showWebNotice4").click(function(){
      doWebNotification("テスト", " \\n (/o^)\n ( /\n / く", "testicon.png", 1500);
  });
});

これで、チェックボックにチェックを入れ、ボタンを押すとPC画面上に「通知」が行われます。

webnotice01

↓今回のプログラムは下記ページで実行できます。

なお、今回作成した JavaScript は「Windows Chrome v36.0.1985.125m」でしか動作確認していません。ご了承ください。多分対応しているブラウザなら動くとは思います。
次回は 「Web Notification」 を使って、なにかサービスを作って見たいたいですね。