knockout.js SPAでURL指定でアクセスできるようにする

2012/04/13

目的

各リンクをクリックしないとデータが表示されなかったのをURLを直打ち可能にする。

「Sent」のデータを見たいときは「http://xxx.xxx/ko_spa.html」にアクセス後「Sent」をクリックして初めて「Sent」のデータが表示。これを「http://xxx.xxx/ko_spa.html#Sent」でアクセスしてきたら「Sent」のデータを表示。

メリットは「Sent」に対して直リンクをはれたり、リロードしてもページが最初に戻らなくなる。

ソース

  1. <!DOCTYPE html>
  2. <html lang="ja">
  3. <head>
  4. <meta charset="UTF−8">
  5. <title>knockoutjsちゅーとりある:SPA(webMail)URL指定でアクセスできるようにする</title>
  6. <script type="text/javascript" src="jquery−1.5.1.min.js"></script>
  7. <script type="text/javascript" src="knockout−2.1.0beta.js"></script>
  8. <script type="text/javascript" src="sammy.js"></script>
  9.  
  10. <style>
  11. body { font−family: Helvetica, Arial }
  12. input:not([type]), input[type=text], input[type=password], select { background−color: #FFFFCC; border: 1px solid gray; padding: 2px; }
  13. body { font−family: Helvetica, Arial}
  14.  
  15. .folders { background−color: #bbb; list−style−type: none; padding: 0; margin: 0; border−radius: 7px; background−image: −webkit−gradient(linear, left top, left bottom, color−stop(0, #d6d6d6), color−stop(0.4, #c0c0c0), color−stop(1,#a4a4a4)); margin: 10px 0 16px 0; font−size: 0px; }
  16. .folders li:hover { background−color: #ddd; }
  17. .folders li:first−child { border−left: none; border−radius: 7px 0 0 7px; }
  18. .folders li { font−size: 16px; font−weight: bold; display: inline−block; padding: 0.5em 1.5em; cursor: pointer; color: #444; text−shadow: #f7f7f7 0 1px 1px; border−left: 1px solid #ddd; border−right: 1px solid #888; }
  19. .folders li { *display: inline !important; } /* IE7 only */
  20. .folders .selected { background−color: #444 !important; color: white; text−shadow:none; border−right−color: #aaa; border−left: none; box−shadow:inset 1px 2px 6px #070707; }
  21.  
  22. .mails { width: 100%; table−layout:fixed; border−spacing: 0; }
  23. .mails thead { background−color: #bbb; font−weight: bold; color: #444; text−shadow: #f7f7f7 0 1px 1px; }
  24. .mails tbody tr:hover { cursor: pointer; background−color: #68c !important; color: White; }
  25. .mails th, .mails td { text−align:left; padding: 0.4em 0.3em; white−space: nowrap; overflow: hidden; text−overflow: ellipsis; }
  26. .mails th { border−left: 1px solid #ddd; border−right: 1px solid #888; padding: 0.4em 0 0.3em 0.7em; }
  27. .mails th:nth−child(1), .mails td:nth−child(1) { width: 20%; }
  28. .mails th:nth−child(2), .mails td:nth−child(2) { width: 15%; }
  29. .mails th:nth−child(3), .mails td:nth−child(3) { width: 45%; }
  30. .mails th:nth−child(4), .mails td:nth−child(4) { width: 15%; }
  31. .mails th:last−child { border−right: none }
  32. .mails tr:nth−child(even) { background−color: #EEE; }
  33.  
  34. .viewMail .mailInfo { background−color: #dae0e8; padding: 1em 1em 0.5em 1.25em; border−radius: 1em; }
  35. .viewMail .mailInfo h1 { margin−top: 0.2em; font−size: 130%; }
  36. .viewMail .mailInfo label { color: #777; font−weight: bold; min−width: 2.75em; text−align:right; display: inline−block; }
  37. .viewMail .message { padding: 0 1.25em; }
  38. </style>
  39.  
  40. <script type="text/javascript">
  41.   $(document).ready(function () {
  42.     function WebmailViewModel() {
  43.       var self = this;
  44.  
  45.       // フォルダのデータ
  46.       self.folders = ['Inbox', 'Archive', 'Sent', 'Spam'];
  47.  
  48.       // データに対してIDをつけるけど、とりあえず何もなしと思われる。
  49.       self.chosenFolderId = ko.observable();
  50.       self.chosenFolderData = ko.observable();
  51.       self.chosenMailData = ko.observable();
  52.  
  53.       // Behaviours
  54.       self.goToFolder = function(folder) {
  55.         location.hash = folder;
  56.       };
  57.  
  58.       self.goToMail = function(mail) {
  59.         location.hash = mail.folder + '/' + mail.id;
  60.       };
  61.  
  62.       // Client−side routes
  63.       Sammy(function() {
  64.         // メール一覧の出力
  65.         // #:folder(http://xxx.xxx/#Inbox、http://xxx.xxx/#Archiveなど)にアクセスされたとき
  66.         this.get('#:folder', function() {
  67.           // 対象のメールフォルダの設定
  68.           self.chosenFolderId(this.params.folder);
  69.  
  70.           // メール詳細のHTMLは非表示
  71.           self.chosenMailData(null);
  72.  
  73.           // フォルダに合わせて読み込むファイルを変更
  74.           //$.get("/mail", { folder: this.params.folder }, self.chosenFolderData);
  75.           var fileName = "./" + this.params.folder + ".txt";
  76.           $.getJSON(fileName, {}, self.chosenFolderData);
  77.         });
  78.  
  79.         // メール詳細の出力
  80.         // #:folder/:mailId(http://xxx.xxx/#Inbox/1、http://xxx.xxx/#Archive/3など)にアクセスされたとき
  81.         this.get('#:folder/:mailId', function() {
  82.           // 対象のメールフォルダの設定
  83.           self.chosenFolderId(this.params.folder);
  84.  
  85.           // メール一覧のHTMLは非表示
  86.           self.chosenFolderData(null);
  87.  
  88.           // フォルダに合わせて読み込むファイルを変更
  89.           //$.get("/mail", { mailId: this.params.mailId }, self.chosenMailData);
  90.           var fileName = "./mail/mailId" + this.params.mailId + ".txt";
  91.           $.getJSON(fileName, {}, self.chosenMailData);
  92.         });
  93.  
  94.         // ''にアクセスされたとき(一番最初)
  95.         this.get('', function() {
  96.           this.app.runRoute('get', '#Inbox')
  97.         });
  98.       }).run();
  99.     }
  100.  
  101.     ko.applyBindings(new WebmailViewModel());
  102.   });
  103. </script>
  104.  
  105. </head>
  106. <body>
  107.  
  108. <!−− フォルダ一覧 Folders −−>
  109. <ul class="folders" data−bind="foreach: folders">
  110. <li data−bind="text: $data, css: { selected: $data == $root.chosenFolderId() }, click: $root.goToFolder"></li>
  111. </ul>
  112.  
  113. <!−− メール一覧 chosenFolderData −−>
  114. <table class="mails" data−bind="with: chosenFolderData">
  115.   <thead><tr><th>From</th><th>To</th><th>Subject</th><th>Date</th></tr></thead>
  116.   <tbody data−bind="foreach: mails">
  117.     <tr data−bind="click: $root.goToMail">
  118.       <td data−bind="text: from"></td>
  119.       <td data−bind="text: to"></td>
  120.       <td data−bind="text: subject"></td>
  121.       <td data−bind="text: date"></td>
  122.     </tr>
  123.   </tbody>
  124. </table>
  125.  
  126. <!−− メール詳細 chosenMailData −−>
  127. <div class="viewMail" data−bind="with: chosenMailData">
  128.   <div class="mailInfo">
  129.     <h1 data−bind="text: subject"></h1>
  130.     <p><label>From</label>: <span data−bind="text: from"></span></p>
  131.     <p><label>To</label>: <span data−bind="text: to"></span></p>
  132.     <p><label>Date</label>: <span data−bind="text: date"></span></p>
  133.   </div>
  134.   <p class="message" data−bind="html: messageContent" />
  135. </div>
  136.  
  137. </body>
  138. </html>

めも

sammy.jsを使う

「クライアントサイド・ナビゲーション」ってヤツを使うために「sammy.js」(8行目)っての使う。
「sammy.js」はJqueryのライブラリになるみたい。

クリックされた場合

110・117行目で設定されているgoToFolderやgoToMailから54・58行目が実行。
その後、「sammy.js」側が何かしてくれて63行目を実行してくれるみたい。引数も取得してくれるみたい。

参考:「Sammy.jsでAjaxコンテンツのセッションを操る | Mach3.laBlog

URLからアクセスされてきた場合

「sammy.js」側が何かしてくれて63行目を実行してくれるみたい。引数も取得してくれるみたい。

新着(ニュース関連以外)

2018-07-26
年賀状で「新春」とか書くけど・・・何故なんだろうと8月を目前にした今、疑問に思った。
2018-05-16
PHPで画像のヘッダ情報(?)の「Orientation」を元に画像回転させたい。
2018-03-05
Android Studioをインストール。エミュレータを軽くするトコまで終わらせたかったけど、挫折した。
2018-02-23
プッシュ通知について調べてた時にでてきたServiceWorker。そのServiceWorkerについてのメモ。
2017-12-13
jqueryで取得したDOM要素をオブジェクトじゃなくて、配列で受け取りたい