ihower / spakit
- Source
- Commits
- Network (0)
- Issues (0)
- Downloads (0)
- Wiki (1)
- Graphs
-
Tree:
dea74c0
Wen-Tien Chang (author)
Tue Apr 08 01:41:59 -0700 2008
spakit / README.txt
| dea74c04 » | Wen-Tien Chang | 2008-04-08 | 1 | Author:: Wen-Tien Chang(mailto:ihower@handlino.com), hlb(mailto:hlb@handlino.com) | |
| bcc0c3bc » | Wen-Tien Chang | 2008-04-04 | 2 | Copyright:: Copyright (c) 2007 Handlino Inc. | |
| 3 | License:: Distributed under the New BSD License | ||||
| 4 | |||||
| 5 | == Description == | ||||
| 6 | Spakit is a plugin that makes it very easy to turn your Rails App | ||||
| 7 | Into a "single page application" (SPA). | ||||
| 8 | |||||
| 9 | To enable SPA, simply install the plug-in, create a spakit layout and use Spakit helper. | ||||
| 10 | Don't need modify any model/controller code... ;) | ||||
| 11 | |||||
| 12 | Spakit will send xhr request(i.e. prototype's Ajax.Updater ) with ?layout=spakit, | ||||
| 13 | and controller return HTML with spakit layout. Note that spakit_form_for not support file upload submit. | ||||
| 14 | |||||
| 15 | By the way, Message plugin is another SPA plugin,using different approach. | ||||
| 16 | |||||
| dea74c04 » | Wen-Tien Chang | 2008-04-08 | 17 | == Requirements | |
| 18 | * Rails 2.0.2 | ||||
| 19 | |||||
| 20 | == Install == | ||||
| 21 | * gem install spakit | ||||
| 22 | * cd /your_app/vendor/plugin/ | ||||
| 23 | * gem unpack spakit | ||||
| 24 | |||||
| bcc0c3bc » | Wen-Tien Chang | 2008-04-04 | 25 | == Usage == | |
| 26 | |||||
| 27 | For now, Spakit provide three helper: | ||||
| 28 | |||||
| 29 | * spakit_link_to, just like remote_link_to | ||||
| 30 | * spakit_form_for, just like form_for, but you must specify :url | ||||
| 31 | * spakit_form_tag, just like form_tag | ||||
| 32 | |||||
| 33 | by default spakit will replace HTML element called #content. | ||||
| 34 | |||||
| 35 | == Layout code example == | ||||
| 36 | You should write flash message here because we often place that in application layout. | ||||
| 37 | |||||
| 38 | # /view/layouts/spakit.rhtml | ||||
| 39 | |||||
| 40 | <p><%= flash[:notice] %></p> | ||||
| 41 | <%= yield %> | ||||
| 42 | |||||
| 43 | == History Bookmarks == | ||||
| 44 | |||||
| 45 | We recommend Really Simple History(RSH) library to handle browser forward/back. | ||||
| 46 | |||||
| 47 | Example code: | ||||
| 48 | |||||
| 49 | # environment.rb | ||||
| 50 | |||||
| 51 | module SpakitHelper | ||||
| 52 | @@spa_options = { | ||||
| 53 | :update => 'content-region', | ||||
| 54 | :loading => 'SPA.loading', | ||||
| 55 | :complete => 'SPA.complete' | ||||
| 56 | } | ||||
| 57 | end | ||||
| 58 | |||||
| 59 | # application.js | ||||
| 60 | # We use jquery syntax, you can use prototype to define your function. | ||||
| 61 | |||||
| 62 | var $j = jQuery.noConflict(); | ||||
| 63 | |||||
| 64 | (function($) { | ||||
| 65 | SPA = { | ||||
| 66 | currentHash: null, | ||||
| 67 | currentLocation: null, | ||||
| 68 | init: function() { | ||||
| 69 | if ( $('#waiting-message').length == 0 ) { | ||||
| 70 | $('<div id="waiting-message"><img src="/images/ajax-loader.gif"></div>').appendTo('#bd'); | ||||
| 71 | $('#waiting-message').hide(); | ||||
| 72 | } | ||||
| 73 | }, | ||||
| 74 | loading: function() { | ||||
| 75 | this.init(); | ||||
| 76 | $('#waiting-message').show(); | ||||
| 77 | }, | ||||
| 78 | hide: function() { | ||||
| 79 | $('#waiting-message').hide(); | ||||
| 80 | }, | ||||
| 81 | historyChange: function(newLocation, historyData, isFresh) { | ||||
| 82 | if (isFresh == null) { | ||||
| 83 | if (historyStorage.hasKey(newLocation)) { | ||||
| 84 | if (newLocation == "start") { | ||||
| 85 | newLocation = location.pathname; | ||||
| 86 | } | ||||
| 87 | |||||
| 88 | $.ajax({ | ||||
| 89 | type: "GET", | ||||
| 90 | url: newLocation, | ||||
| 91 | data: { layout: "spakit" }, | ||||
| 92 | beforeSend: function(){ SPA.loading(); }, | ||||
| 93 | complete: function(res, status){ | ||||
| 94 | if ( status == "success" || status == "notmodified" ) { | ||||
| 95 | $('#content-region').html(res.responseText); | ||||
| 96 | } | ||||
| 97 | SPA.hide(); | ||||
| 98 | } | ||||
| 99 | }); | ||||
| 100 | } | ||||
| 101 | } else { | ||||
| 102 | /* new data */ | ||||
| 103 | dhtmlHistory.add(newLocation, historyData); | ||||
| 104 | } | ||||
| 105 | }, | ||||
| 106 | complete: function(newLocation) { | ||||
| 107 | this.historyChange(newLocation, "", true); | ||||
| 108 | this.hide(); | ||||
| 109 | } | ||||
| 110 | }; | ||||
| 111 | |||||
| 112 | SPA.currentHash = window.location.hash; | ||||
| 113 | if (SPA.currentHash.length) { | ||||
| 114 | if (SPA.currentHash.charAt(0) == '#' && SPA.currentHash.charAt(1) == '/') { | ||||
| 115 | SPA.currentLocation = SPA.currentHash.slice(1); | ||||
| 116 | } | ||||
| 117 | } | ||||
| 118 | |||||
| 119 | $(document).ready(function(){ | ||||
| 120 | dhtmlHistory.initialize(); | ||||
| 121 | if (SPA.currentLocation) { | ||||
| 122 | if (SPA.currentLocation != '#start') { | ||||
| 123 | window.location.href = SPA.currentLocation; | ||||
| 124 | } | ||||
| 125 | } else { | ||||
| 126 | dhtmlHistory.addListener(SPA.historyChange); | ||||
| 127 | if (dhtmlHistory.isFirstLoad()) { | ||||
| 128 | dhtmlHistory.add("start", ""); | ||||
| 129 | } | ||||
| 130 | } | ||||
| 131 | }); | ||||
| 132 | |||||
| 133 | })(jQuery); | ||||
| 134 | |||||
| 135 | window.dhtmlHistory.create({ | ||||
| 136 | toJSON: function(o) { | ||||
| 137 | return JSON.stringify(o); | ||||
| 138 | }, | ||||
| 139 | fromJSON: function(s) { | ||||
| 140 | return JSON.parse(s); | ||||
| 141 | } | ||||
| 142 | }); | ||||
