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」に対して直リンクをはれたり、リロードしてもページが最初に戻らなくなる。
ソース
- <!DOCTYPE html>
- <html lang="ja">
- <head>
- <meta charset="UTF−8">
- <title>knockoutjsちゅーとりある:SPA(webMail)URL指定でアクセスできるようにする</title>
- <script type="text/javascript" src="jquery−1.5.1.min.js"></script>
- <script type="text/javascript" src="knockout−2.1.0beta.js"></script>
- <script type="text/javascript" src="sammy.js"></script>
- <style>
- body { font−family: Helvetica, Arial }
- input:not([type]), input[type=text], input[type=password], select { background−color: #FFFFCC; border: 1px solid gray; padding: 2px; }
- body { font−family: Helvetica, Arial}
- .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; }
- .folders li:hover { background−color: #ddd; }
- .folders li:first−child { border−left: none; border−radius: 7px 0 0 7px; }
- .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; }
- .folders li { *display: inline !important; } /* IE7 only */
- .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; }
- .mails { width: 100%; table−layout:fixed; border−spacing: 0; }
- .mails thead { background−color: #bbb; font−weight: bold; color: #444; text−shadow: #f7f7f7 0 1px 1px; }
- .mails tbody tr:hover { cursor: pointer; background−color: #68c !important; color: White; }
- .mails th, .mails td { text−align:left; padding: 0.4em 0.3em; white−space: nowrap; overflow: hidden; text−overflow: ellipsis; }
- .mails th { border−left: 1px solid #ddd; border−right: 1px solid #888; padding: 0.4em 0 0.3em 0.7em; }
- .mails th:nth−child(1), .mails td:nth−child(1) { width: 20%; }
- .mails th:nth−child(2), .mails td:nth−child(2) { width: 15%; }
- .mails th:nth−child(3), .mails td:nth−child(3) { width: 45%; }
- .mails th:nth−child(4), .mails td:nth−child(4) { width: 15%; }
- .mails th:last−child { border−right: none }
- .mails tr:nth−child(even) { background−color: #EEE; }
- .viewMail .mailInfo { background−color: #dae0e8; padding: 1em 1em 0.5em 1.25em; border−radius: 1em; }
- .viewMail .mailInfo h1 { margin−top: 0.2em; font−size: 130%; }
- .viewMail .mailInfo label { color: #777; font−weight: bold; min−width: 2.75em; text−align:right; display: inline−block; }
- .viewMail .message { padding: 0 1.25em; }
- </style>
- <script type="text/javascript">
- $(document).ready(function () {
- function WebmailViewModel() {
- var self = this;
- // フォルダのデータ
- self.folders = ['Inbox', 'Archive', 'Sent', 'Spam'];
- // データに対してIDをつけるけど、とりあえず何もなしと思われる。
- self.chosenFolderId = ko.observable();
- self.chosenFolderData = ko.observable();
- self.chosenMailData = ko.observable();
- // Behaviours
- self.goToFolder = function(folder) {
- location.hash = folder;
- };
- self.goToMail = function(mail) {
- location.hash = mail.folder + '/' + mail.id;
- };
- // Client−side routes
- Sammy(function() {
- // メール一覧の出力
- // #:folder(http://xxx.xxx/#Inbox、http://xxx.xxx/#Archiveなど)にアクセスされたとき
- this.get('#:folder', function() {
- // 対象のメールフォルダの設定
- self.chosenFolderId(this.params.folder);
- // メール詳細のHTMLは非表示
- self.chosenMailData(null);
- // フォルダに合わせて読み込むファイルを変更
- //$.get("/mail", { folder: this.params.folder }, self.chosenFolderData);
- var fileName = "./" + this.params.folder + ".txt";
- $.getJSON(fileName, {}, self.chosenFolderData);
- });
- // メール詳細の出力
- // #:folder/:mailId(http://xxx.xxx/#Inbox/1、http://xxx.xxx/#Archive/3など)にアクセスされたとき
- this.get('#:folder/:mailId', function() {
- // 対象のメールフォルダの設定
- self.chosenFolderId(this.params.folder);
- // メール一覧のHTMLは非表示
- self.chosenFolderData(null);
- // フォルダに合わせて読み込むファイルを変更
- //$.get("/mail", { mailId: this.params.mailId }, self.chosenMailData);
- var fileName = "./mail/mailId" + this.params.mailId + ".txt";
- $.getJSON(fileName, {}, self.chosenMailData);
- });
- // ''にアクセスされたとき(一番最初)
- this.get('', function() {
- this.app.runRoute('get', '#Inbox')
- });
- }).run();
- }
- ko.applyBindings(new WebmailViewModel());
- });
- </script>
- </head>
- <body>
- <!−− フォルダ一覧 Folders −−>
- <ul class="folders" data−bind="foreach: folders">
- <li data−bind="text: $data, css: { selected: $data == $root.chosenFolderId() }, click: $root.goToFolder"></li>
- </ul>
- <!−− メール一覧 chosenFolderData −−>
- <table class="mails" data−bind="with: chosenFolderData">
- <thead><tr><th>From</th><th>To</th><th>Subject</th><th>Date</th></tr></thead>
- <tbody data−bind="foreach: mails">
- <tr data−bind="click: $root.goToMail">
- <td data−bind="text: from"></td>
- <td data−bind="text: to"></td>
- <td data−bind="text: subject"></td>
- <td data−bind="text: date"></td>
- </tr>
- </tbody>
- </table>
- <!−− メール詳細 chosenMailData −−>
- <div class="viewMail" data−bind="with: chosenMailData">
- <div class="mailInfo">
- <h1 data−bind="text: subject"></h1>
- <p><label>From</label>: <span data−bind="text: from"></span></p>
- <p><label>To</label>: <span data−bind="text: to"></span></p>
- <p><label>Date</label>: <span data−bind="text: date"></span></p>
- </div>
- <p class="message" data−bind="html: messageContent" />
- </div>
- </body>
- </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行目を実行してくれるみたい。引数も取得してくれるみたい。