jim 0.1.2 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/HISTORY +28 -0
- data/README.rdoc +1 -1
- data/Rakefile +2 -1
- data/jim.gemspec +67 -9
- data/lib/jim/bundler.rb +14 -11
- data/lib/jim/cli.rb +51 -9
- data/lib/jim/index.rb +3 -7
- data/lib/jim/installer.rb +140 -22
- data/lib/jim/templates/commands +21 -6
- data/lib/jim/version_parser.rb +2 -3
- data/lib/jim.rb +19 -2
- data/test/fixtures/jimfile +3 -3
- data/test/fixtures/sammy-0.5.0/HISTORY.md +135 -0
- data/test/fixtures/sammy-0.5.0/LICENSE +22 -0
- data/test/fixtures/sammy-0.5.0/README.md +81 -0
- data/test/fixtures/sammy-0.5.0/Rakefile +174 -0
- data/test/fixtures/sammy-0.5.0/examples/backend/README.md +23 -0
- data/test/fixtures/sammy-0.5.0/examples/backend/Rakefile +15 -0
- data/test/fixtures/sammy-0.5.0/examples/backend/app.rb +17 -0
- data/test/fixtures/sammy-0.5.0/examples/backend/app.ru +3 -0
- data/test/fixtures/sammy-0.5.0/examples/backend/public/javascripts/app.js +106 -0
- data/test/fixtures/sammy-0.5.0/examples/backend/public/javascripts/jquery.cloudkit.js +840 -0
- data/test/fixtures/sammy-0.5.0/examples/backend/public/javascripts/jquery.js +19 -0
- data/test/fixtures/sammy-0.5.0/examples/backend/public/javascripts/sammy.js +1013 -0
- data/test/fixtures/sammy-0.5.0/examples/backend/public/templates/index.html.erb +11 -0
- data/test/fixtures/sammy-0.5.0/examples/backend/public/templates/task.html.erb +4 -0
- data/test/fixtures/sammy-0.5.0/examples/backend/public/templates/task_details.html.erb +4 -0
- data/test/fixtures/sammy-0.5.0/examples/backend/views/app.sass +63 -0
- data/test/fixtures/sammy-0.5.0/examples/backend/views/index.haml +18 -0
- data/test/fixtures/sammy-0.5.0/examples/form_handling/files/form.html +12 -0
- data/test/fixtures/sammy-0.5.0/examples/form_handling/index.html +65 -0
- data/test/fixtures/sammy-0.5.0/examples/hello_world/index.html +50 -0
- data/test/fixtures/sammy-0.5.0/examples/location_override/README.md +15 -0
- data/test/fixtures/sammy-0.5.0/examples/location_override/data.html +110 -0
- data/test/fixtures/sammy-0.5.0/examples/location_override/index.html +79 -0
- data/test/fixtures/sammy-0.5.0/examples/location_override/test.html +121 -0
- data/test/fixtures/sammy-0.5.0/lib/min/sammy-0.5.0.min.js +5 -0
- data/test/fixtures/sammy-0.5.0/lib/min/sammy-lastest.min.js +5 -0
- data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.cache.js +117 -0
- data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.haml.js +539 -0
- data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.json.js +362 -0
- data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.mustache.js +415 -0
- data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.nested_params.js +118 -0
- data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.storage.js +515 -0
- data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.template.js +117 -0
- data/test/fixtures/sammy-0.5.0/lib/sammy.js +1367 -0
- data/test/fixtures/sammy-0.5.0/test/fixtures/partial +1 -0
- data/test/fixtures/sammy-0.5.0/test/fixtures/partial.html +1 -0
- data/test/fixtures/sammy-0.5.0/test/fixtures/partial.noengine +1 -0
- data/test/fixtures/sammy-0.5.0/test/fixtures/partial.template +1 -0
- data/test/fixtures/sammy-0.5.0/test/index.html +84 -0
- data/test/fixtures/sammy-0.5.0/test/test_sammy_application.js +953 -0
- data/test/fixtures/sammy-0.5.0/test/test_sammy_event_context.js +252 -0
- data/test/fixtures/sammy-0.5.0/test/test_sammy_location_proxy.js +91 -0
- data/test/fixtures/sammy-0.5.0/test/test_sammy_plugins.js +296 -0
- data/test/fixtures/sammy-0.5.0/test/test_sammy_storage.js +175 -0
- data/test/fixtures/sammy-0.5.0/test/test_server +27 -0
- data/test/fixtures/sammy-0.5.0/vendor/jquery-1.4.1.js +6078 -0
- data/test/fixtures/sammy-0.5.0/vendor/jquery-1.4.1.min.js +152 -0
- data/test/fixtures/sammy-0.5.0/vendor/jsdoc/doc.haml +58 -0
- data/test/fixtures/sammy-0.5.0/vendor/jsdoc/jsdoc.rb +143 -0
- data/test/fixtures/sammy-0.5.0/vendor/jslitmus.js +670 -0
- data/test/fixtures/sammy-0.5.0/vendor/qunit/qunit.css +119 -0
- data/test/fixtures/sammy-0.5.0/vendor/qunit/qunit.js +1043 -0
- data/test/fixtures/sammy-0.5.0/vendor/qunit-spec.js +127 -0
- data/test/helper.rb +23 -3
- data/test/test_jim_bundler.rb +9 -8
- data/test/test_jim_cli.rb +21 -12
- data/test/test_jim_installer.rb +152 -35
- data/test/test_jim_version_parser.rb +4 -0
- metadata +117 -27
- data/.document +0 -5
@@ -0,0 +1,515 @@
|
|
1
|
+
(function($) {
|
2
|
+
|
3
|
+
Sammy = Sammy || {};
|
4
|
+
|
5
|
+
// Sammy.Store is an abstract adapter class that wraps the multitude of in
|
6
|
+
// browser data storage into a single common set of methods for storing and
|
7
|
+
// retreiving data. The JSON library is used (through the inclusion of the
|
8
|
+
// Sammy.JSON) plugin, to automatically convert objects back and forth from
|
9
|
+
// stored strings.
|
10
|
+
//
|
11
|
+
// Sammy.Store can be used directly, but within a Sammy.Application it is much
|
12
|
+
// easier to use the <tt>Sammy.Storage</tt> plugin and its helper methods.
|
13
|
+
//
|
14
|
+
// Sammy.Store also supports the KVO pattern, by firing DOM/jQuery Events when
|
15
|
+
// a key is set.
|
16
|
+
//
|
17
|
+
// === Example
|
18
|
+
//
|
19
|
+
// // create a new store named 'mystore', tied to the #main element, using HTML5 localStorage
|
20
|
+
// // Note: localStorage only works on browsers that support it
|
21
|
+
// var store = new Sammy.Store({name: 'mystore', element: '#element', type: 'local'});
|
22
|
+
// store.set('foo', 'bar');
|
23
|
+
// store.get('foo'); //=> 'bar'
|
24
|
+
// store.set('json', {obj: 'this is an obj'});
|
25
|
+
// store.get('json'); //=> {obj: 'this is an obj'}
|
26
|
+
// store.keys(); //=> ['foo','json']
|
27
|
+
// store.clear('foo');
|
28
|
+
// store.keys(); //=> ['json']
|
29
|
+
// store.clearAll();
|
30
|
+
// store.keys(); //=> []
|
31
|
+
//
|
32
|
+
// === Arguments
|
33
|
+
//
|
34
|
+
// The constructor takes a single argument which is a Object containing these possible options.
|
35
|
+
//
|
36
|
+
// +name+:: The name/namespace of this store. Stores are unique by name/type. (default 'store')
|
37
|
+
// +element+:: A selector for the element that the store is bound to. (default 'body')
|
38
|
+
// +type+:: The type of storage/proxy to use (default 'memory')
|
39
|
+
//
|
40
|
+
// Extra options are passed to the storage constructor.
|
41
|
+
// Sammy.Store supports the following methods of storage:
|
42
|
+
//
|
43
|
+
// +memory+:: Basic object storage
|
44
|
+
// +data+:: jQuery.data DOM Storage
|
45
|
+
// +cookie+:: Access to document.cookie. Limited to 2K
|
46
|
+
// +local+:: HTML5 DOM localStorage, browswer support is currently limited.
|
47
|
+
// +session+:: HTML5 DOM sessionStorage, browswer support is currently limited.
|
48
|
+
//
|
49
|
+
Sammy.Store = function(options) {
|
50
|
+
this.options = options || {};
|
51
|
+
this.name = this.options.name || 'store';
|
52
|
+
this.element = this.options.element || 'body';
|
53
|
+
this.$element = $(this.element);
|
54
|
+
this.type = this.options.type || 'memory';
|
55
|
+
this.meta_key = this.options.meta_key || '__keys__';
|
56
|
+
this.storage = new Sammy.Store[Sammy.Store.stores[this.type]](this.name, this.element, this.options);
|
57
|
+
};
|
58
|
+
|
59
|
+
Sammy.Store.stores = {
|
60
|
+
'memory': 'Memory',
|
61
|
+
'data': 'Data',
|
62
|
+
'local': 'LocalStorage',
|
63
|
+
'session': 'SessionStorage',
|
64
|
+
'cookie': 'Cookie'
|
65
|
+
};
|
66
|
+
|
67
|
+
$.extend(Sammy.Store.prototype, {
|
68
|
+
// Checks for the availability of the current storage type in the current browser/config.
|
69
|
+
isAvailable: function() {
|
70
|
+
if ($.isFunction(this.storage.isAvailable)) {
|
71
|
+
return this.storage.isAvailable();
|
72
|
+
} else {
|
73
|
+
true;
|
74
|
+
}
|
75
|
+
},
|
76
|
+
// Checks for the existance of <tt>key</tt> in the current store. Returns a boolean.
|
77
|
+
exists: function(key) {
|
78
|
+
return this.storage.exists(key);
|
79
|
+
},
|
80
|
+
// Sets the value of <tt>key<tt> with <tt>value</tt>. If <tt>value<tt> is an
|
81
|
+
// object, it is turned to and stored as a string with <tt>JSON.stringify</tt>.
|
82
|
+
// It also tries to conform to the KVO pattern triggering jQuery events on the
|
83
|
+
// element that the store is bound to.
|
84
|
+
//
|
85
|
+
// === Example
|
86
|
+
//
|
87
|
+
// var store = new Sammy.Store({name: 'kvo'});
|
88
|
+
// $('body').bind('set-kvo.foo', function() {
|
89
|
+
// alert('foo changed!')
|
90
|
+
// });
|
91
|
+
// store.set('foo', 'bar'); // alerted: foo changed!
|
92
|
+
//
|
93
|
+
set: function(key, value) {
|
94
|
+
var string_value = (typeof value == 'string') ? value : JSON.stringify(value);
|
95
|
+
key = key.toString();
|
96
|
+
this.storage.set(key, string_value);
|
97
|
+
if (key != this.meta_key) {
|
98
|
+
this._addKey(key);
|
99
|
+
this.$element.trigger('set-' + this.name + '.' + key, [key, value]);
|
100
|
+
};
|
101
|
+
return string_value;
|
102
|
+
},
|
103
|
+
// Returns the set value at <tt>key</tt>, parsing with <tt>JSON.parse</tt> and
|
104
|
+
// turning into an object if possible
|
105
|
+
get: function(key) {
|
106
|
+
var value = this.storage.get(key);
|
107
|
+
if (typeof value == 'undefined' || value == null || value == '') {
|
108
|
+
return value;
|
109
|
+
}
|
110
|
+
try {
|
111
|
+
return JSON.parse(value);
|
112
|
+
} catch(e) {
|
113
|
+
return value;
|
114
|
+
}
|
115
|
+
},
|
116
|
+
// Removes the value at <tt>key</tt> from the current store
|
117
|
+
clear: function(key) {
|
118
|
+
this._removeKey(key);
|
119
|
+
return this.storage.clear(key);
|
120
|
+
},
|
121
|
+
// Clears all the values for the current store.
|
122
|
+
clearAll: function() {
|
123
|
+
var self = this;
|
124
|
+
$.each(this.keys(), function(i, key) {
|
125
|
+
self.clear(key);
|
126
|
+
});
|
127
|
+
},
|
128
|
+
// Returns the all the keys set for the current store as an array.
|
129
|
+
// Internally Sammy.Store keeps this array in a 'meta_key' for easy access.
|
130
|
+
keys: function() {
|
131
|
+
return this.get(this.meta_key) || [];
|
132
|
+
},
|
133
|
+
// Returns the value at <tt>key</tt> if set, otherwise, runs the callback
|
134
|
+
// and sets the value to the value returned in the callback.
|
135
|
+
//
|
136
|
+
// === Example
|
137
|
+
//
|
138
|
+
// var store = new Sammy.Store;
|
139
|
+
// store.exists('foo'); //=> false
|
140
|
+
// store.fetch('foo', function() {
|
141
|
+
// return 'bar!';
|
142
|
+
// }); //=> 'bar!'
|
143
|
+
// store.get('foo') //=> 'bar!'
|
144
|
+
// store.fetch('foo', function() {
|
145
|
+
// return 'baz!';
|
146
|
+
// }); //=> 'bar!
|
147
|
+
//
|
148
|
+
fetch: function(key, callback) {
|
149
|
+
if (!this.exists(key)) {
|
150
|
+
return this.set(key, callback.apply(this));
|
151
|
+
} else {
|
152
|
+
return this.get(key);
|
153
|
+
}
|
154
|
+
},
|
155
|
+
// loads the response of a request to <tt>path</tt> into <tt>key</tt>.
|
156
|
+
//
|
157
|
+
// === Example
|
158
|
+
//
|
159
|
+
// In /mytemplate.tpl:
|
160
|
+
//
|
161
|
+
// My Template
|
162
|
+
//
|
163
|
+
// In app.js:
|
164
|
+
//
|
165
|
+
// var store = new Sammy.Store;
|
166
|
+
// store.load('mytemplate', '/mytemplate.tpl', function() {
|
167
|
+
// s.get('mytemplate') //=> My Template
|
168
|
+
// });
|
169
|
+
//
|
170
|
+
load: function(key, path, callback) {
|
171
|
+
var s = this;
|
172
|
+
$.get(path, function(response) {
|
173
|
+
s.set(key, response);
|
174
|
+
if (callback) { callback.apply(this, [response]); }
|
175
|
+
});
|
176
|
+
},
|
177
|
+
_addKey: function(key) {
|
178
|
+
var keys = this.keys();
|
179
|
+
if ($.inArray(key, keys) == -1) { keys.push(key); }
|
180
|
+
this.set(this.meta_key, keys);
|
181
|
+
},
|
182
|
+
_removeKey: function(key) {
|
183
|
+
var keys = this.keys();
|
184
|
+
var index = $.inArray(key, keys);
|
185
|
+
if (index != -1) { keys.splice(index, 1); }
|
186
|
+
this.set(this.meta_key, keys);
|
187
|
+
}
|
188
|
+
});
|
189
|
+
|
190
|
+
// Tests if the type of storage is available/works in the current browser/config.
|
191
|
+
// Especially useful for testing the availability of the awesome, but not widely
|
192
|
+
// supported HTML5 DOM storage
|
193
|
+
Sammy.Store.isAvailable = function(type) {
|
194
|
+
try {
|
195
|
+
return Sammy.Store[Sammy.Store.stores[type]].prototype.isAvailable();
|
196
|
+
} catch(e) {
|
197
|
+
return false;
|
198
|
+
}
|
199
|
+
};
|
200
|
+
|
201
|
+
// Memory ('memory') is the basic/default store. It stores data in a global
|
202
|
+
// JS object. Data is lost on refresh.
|
203
|
+
Sammy.Store.Memory = function(name, element) {
|
204
|
+
this.name = name;
|
205
|
+
this.element = element;
|
206
|
+
this.namespace = [this.element, this.name].join('.');
|
207
|
+
Sammy.Store.Memory.store = Sammy.Store.Memory.store || {};
|
208
|
+
Sammy.Store.Memory.store[this.namespace] = Sammy.Store.Memory.store[this.namespace] || {};
|
209
|
+
this.store = Sammy.Store.Memory.store[this.namespace];
|
210
|
+
};
|
211
|
+
$.extend(Sammy.Store.Memory.prototype, {
|
212
|
+
isAvailable: function() { return true; },
|
213
|
+
exists: function(key) {
|
214
|
+
return (typeof this.store[key] != "undefined");
|
215
|
+
},
|
216
|
+
set: function(key, value) {
|
217
|
+
return this.store[key] = value;
|
218
|
+
},
|
219
|
+
get: function(key) {
|
220
|
+
return this.store[key];
|
221
|
+
},
|
222
|
+
clear: function(key) {
|
223
|
+
delete this.store[key];
|
224
|
+
}
|
225
|
+
});
|
226
|
+
|
227
|
+
// Data ('data') stores objects using the jQuery.data() methods. This has the advantadge
|
228
|
+
// of scoping the data to the specific element. Like the 'memory' store its data
|
229
|
+
// will only last for the length of the current request (data is lost on refresh/etc).
|
230
|
+
Sammy.Store.Data = function(name, element) {
|
231
|
+
this.name = name;
|
232
|
+
this.element = element;
|
233
|
+
this.$element = $(element);
|
234
|
+
};
|
235
|
+
$.extend(Sammy.Store.Data.prototype, {
|
236
|
+
isAvailable: function() { return true; },
|
237
|
+
exists: function(key) {
|
238
|
+
return (typeof this.$element.data(this._key(key)) != "undefined");
|
239
|
+
},
|
240
|
+
set: function(key, value) {
|
241
|
+
return this.$element.data(this._key(key), value);
|
242
|
+
},
|
243
|
+
get: function(key) {
|
244
|
+
return this.$element.data(this._key(key));
|
245
|
+
},
|
246
|
+
clear: function(key) {
|
247
|
+
this.$element.removeData(this._key(key));
|
248
|
+
},
|
249
|
+
_key: function(key) {
|
250
|
+
return ['store', this.name, key].join('.');
|
251
|
+
}
|
252
|
+
});
|
253
|
+
|
254
|
+
// LocalStorage ('local') makes use of HTML5 DOM Storage, and the window.localStorage
|
255
|
+
// object. The great advantage of this method is that data will persist beyond
|
256
|
+
// the current request. It can be considered a pretty awesome replacement for
|
257
|
+
// cookies accessed via JS. The great disadvantage, though, is its only available
|
258
|
+
// on the latest and greatest browsers.
|
259
|
+
//
|
260
|
+
// For more info on DOM Storage:
|
261
|
+
// [https://developer.mozilla.org/en/DOM/Storage]
|
262
|
+
// [http://www.w3.org/TR/2009/WD-webstorage-20091222/]
|
263
|
+
//
|
264
|
+
Sammy.Store.LocalStorage = function(name, element) {
|
265
|
+
this.name = name;
|
266
|
+
this.element = element;
|
267
|
+
};
|
268
|
+
$.extend(Sammy.Store.LocalStorage.prototype, {
|
269
|
+
isAvailable: function() {
|
270
|
+
return ('localStorage' in window) && (window.location.protocol != 'file:');
|
271
|
+
},
|
272
|
+
exists: function(key) {
|
273
|
+
return (this.get(key) != null);
|
274
|
+
},
|
275
|
+
set: function(key, value) {
|
276
|
+
return window.localStorage.setItem(this._key(key), value);
|
277
|
+
},
|
278
|
+
get: function(key) {
|
279
|
+
return window.localStorage.getItem(this._key(key));
|
280
|
+
},
|
281
|
+
clear: function(key) {
|
282
|
+
window.localStorage.removeItem(this._key(key));;
|
283
|
+
},
|
284
|
+
_key: function(key) {
|
285
|
+
return ['store', this.element, this.name, key].join('.');
|
286
|
+
}
|
287
|
+
});
|
288
|
+
|
289
|
+
// .SessionStorage ('session') is similar to LocalStorage (part of the same API)
|
290
|
+
// and shares similar browser support/availability. The difference is that
|
291
|
+
// SessionStorage is only persistant through the current 'session' which is defined
|
292
|
+
// as the length that the current window is open. This means that data will survive
|
293
|
+
// refreshes but not close/open or multiple windows/tabs. For more info, check out
|
294
|
+
// the <tt>LocalStorage</tt> documentation and links.
|
295
|
+
Sammy.Store.SessionStorage = function(name, element) {
|
296
|
+
this.name = name;
|
297
|
+
this.element = element;
|
298
|
+
};
|
299
|
+
$.extend(Sammy.Store.SessionStorage.prototype, {
|
300
|
+
isAvailable: function() {
|
301
|
+
return ('sessionStorage' in window);
|
302
|
+
},
|
303
|
+
exists: function(key) {
|
304
|
+
return (this.get(key) != null);
|
305
|
+
},
|
306
|
+
set: function(key, value) {
|
307
|
+
return window.sessionStorage.setItem(this._key(key), value);
|
308
|
+
},
|
309
|
+
get: function(key) {
|
310
|
+
return window.sessionStorage.getItem(this._key(key));
|
311
|
+
},
|
312
|
+
clear: function(key) {
|
313
|
+
window.sessionStorage.removeItem(this._key(key));;
|
314
|
+
},
|
315
|
+
_key: function(key) {
|
316
|
+
return ['store', this.element, this.name, key].join('.');
|
317
|
+
}
|
318
|
+
});
|
319
|
+
|
320
|
+
// .Cookie ('cookie') storage uses browser cookies to store data. JavaScript
|
321
|
+
// has access to a single document.cookie variable, which is limited to 2Kb in
|
322
|
+
// size. Cookies are also considered 'unsecure' as the data can be read easily
|
323
|
+
// by other sites/JS. Cookies do have the advantage, though, of being widely
|
324
|
+
// supported and persistent through refresh and close/open. Where available,
|
325
|
+
// HTML5 DOM Storage like LocalStorage and SessionStorage should be used.
|
326
|
+
//
|
327
|
+
// .Cookie can also take additional options:
|
328
|
+
// +expires_in+:: Number of seconds to keep the cookie alive (default 2 weeks).
|
329
|
+
// +path+:: The path to activate the current cookie for (default '/').
|
330
|
+
//
|
331
|
+
// For more information about document.cookie, check out the pre-eminint article
|
332
|
+
// by ppk: [http://www.quirksmode.org/js/cookies.html]
|
333
|
+
//
|
334
|
+
Sammy.Store.Cookie = function(name, element, options) {
|
335
|
+
this.name = name;
|
336
|
+
this.element = element;
|
337
|
+
this.options = options || {};
|
338
|
+
this.path = this.options.path || '/';
|
339
|
+
// set the expires in seconds or default 14 days
|
340
|
+
this.expires_in = this.options.expires_in || (14 * 24 * 60 * 60);
|
341
|
+
};
|
342
|
+
$.extend(Sammy.Store.Cookie.prototype, {
|
343
|
+
isAvailable: function() {
|
344
|
+
return ('cookie' in document) && (window.location.protocol != 'file:');
|
345
|
+
},
|
346
|
+
exists: function(key) {
|
347
|
+
return (this.get(key) != null);
|
348
|
+
},
|
349
|
+
set: function(key, value) {
|
350
|
+
return this._setCookie(key, value);
|
351
|
+
},
|
352
|
+
get: function(key) {
|
353
|
+
return this._getCookie(key);
|
354
|
+
},
|
355
|
+
clear: function(key) {
|
356
|
+
this._setCookie(key, "", -1);
|
357
|
+
},
|
358
|
+
_key: function(key) {
|
359
|
+
return ['store', this.element, this.name, key].join('.');
|
360
|
+
},
|
361
|
+
_getCookie: function(key) {
|
362
|
+
var escaped = this._key(key).replace(/(\.|\*|\(|\)|\[|\])/g, '\\$1');
|
363
|
+
var match = document.cookie.match("(^|;\\s)" + escaped + "=([^;]*)(;|$)")
|
364
|
+
return (match ? match[2] : null);
|
365
|
+
},
|
366
|
+
_setCookie: function(key, value, expires) {
|
367
|
+
if (!expires) { expires = (this.expires_in * 1000) }
|
368
|
+
var date = new Date();
|
369
|
+
date.setTime(date.getTime() + expires);
|
370
|
+
var set_cookie = [
|
371
|
+
this._key(key), "=", value,
|
372
|
+
"; expires=", date.toGMTString(),
|
373
|
+
"; path=", this.path
|
374
|
+
].join('');
|
375
|
+
document.cookie = set_cookie;
|
376
|
+
}
|
377
|
+
});
|
378
|
+
|
379
|
+
// Sammy.Storage is a plugin that provides shortcuts for creating and using
|
380
|
+
// Sammy.Store objects. Once included it provides the <tt>store()</tt> app level
|
381
|
+
// and helper methods. Depends on Sammy.JSON (or json2.js).
|
382
|
+
Sammy.Storage = function(app) {
|
383
|
+
this.use(Sammy.JSON);
|
384
|
+
|
385
|
+
this.stores = this.stores || {};
|
386
|
+
|
387
|
+
// <tt>store()</tt> creates and looks up existing <tt>Sammy.Store</tt> objects
|
388
|
+
// for the current application. The first time used for a given <tt>'name'</tt>
|
389
|
+
// initializes a <tt>Sammy.Store</tt> and also creates a helper under the store's
|
390
|
+
// name.
|
391
|
+
//
|
392
|
+
// === Example
|
393
|
+
//
|
394
|
+
// var app = $.sammy(function() {
|
395
|
+
// this.use(Sammy.Storage);
|
396
|
+
//
|
397
|
+
// // initializes the store on app creation.
|
398
|
+
// this.store('mystore', {type: 'cookie'});
|
399
|
+
//
|
400
|
+
// this.get('#/', function() {
|
401
|
+
// // returns the Sammy.Store object
|
402
|
+
// this.store('mystore');
|
403
|
+
// // sets 'foo' to 'bar' using the shortcut/helper
|
404
|
+
// // equivilent to this.store('mystore').set('foo', 'bar');
|
405
|
+
// this.mystore('foo', 'bar');
|
406
|
+
// // returns 'bar'
|
407
|
+
// // equivilent to this.store('mystore').get('foo');
|
408
|
+
// this.mystore('foo');
|
409
|
+
// // returns 'baz!'
|
410
|
+
// // equivilent to:
|
411
|
+
// // this.store('mystore').fetch('foo!', function() {
|
412
|
+
// // return 'baz!';
|
413
|
+
// // })
|
414
|
+
// this.mystore('foo!', function() {
|
415
|
+
// return 'baz!';
|
416
|
+
// });
|
417
|
+
//
|
418
|
+
// this.clearMystore();
|
419
|
+
// // equivilent to:
|
420
|
+
// // this.store('mystore').clearAll()
|
421
|
+
// });
|
422
|
+
//
|
423
|
+
// });
|
424
|
+
//
|
425
|
+
// === Arguments
|
426
|
+
//
|
427
|
+
// +name+:: The name of the store and helper. the name must be unique per application.
|
428
|
+
// +options+:: A JS object of options that can be passed to the Store constuctor on initialization.
|
429
|
+
//
|
430
|
+
this.store = function(name, options) {
|
431
|
+
// if the store has not been initialized
|
432
|
+
if (typeof this.stores[name] == 'undefined') {
|
433
|
+
// create initialize the store
|
434
|
+
var clear_method_name = "clear" + name.substr(0,1).toUpperCase() + name.substr(1);
|
435
|
+
this.stores[name] = new Sammy.Store($.extend({
|
436
|
+
name: name,
|
437
|
+
element: this.element_selector
|
438
|
+
}, options || {}));
|
439
|
+
// app.name()
|
440
|
+
this[name] = function(key, value) {
|
441
|
+
if (typeof value == 'undefined') {
|
442
|
+
return this.stores[name].get(key);
|
443
|
+
} else if ($.isFunction(value)) {
|
444
|
+
return this.stores[name].fetch(key, value);
|
445
|
+
} else {
|
446
|
+
return this.stores[name].set(key, value)
|
447
|
+
}
|
448
|
+
};
|
449
|
+
// app.clearName();
|
450
|
+
this[clear_method_name] = function() {
|
451
|
+
return this.stores[name].clearAll();
|
452
|
+
}
|
453
|
+
// context.name()
|
454
|
+
this.helper(name, function() {
|
455
|
+
return this.app[name].apply(this.app, arguments);
|
456
|
+
});
|
457
|
+
// context.clearName();
|
458
|
+
this.helper(clear_method_name, function() {
|
459
|
+
return this.app[clear_method_name]();
|
460
|
+
});
|
461
|
+
}
|
462
|
+
return this.stores[name];
|
463
|
+
};
|
464
|
+
|
465
|
+
this.helpers({
|
466
|
+
store: function() {
|
467
|
+
return this.app.store.apply(this.app, arguments);
|
468
|
+
}
|
469
|
+
});
|
470
|
+
};
|
471
|
+
|
472
|
+
// Sammy.Session is an additional plugin for creating a common 'session' store
|
473
|
+
// for the given app. It is a very simple wrapper around <tt>Sammy.Storage</tt>
|
474
|
+
// that provides a simple fallback mechanism for trying to provide the best
|
475
|
+
// possible storage type for the session. This means, <tt>LocalStorage</tt>
|
476
|
+
// if available, otherwise <tt>Cookie</tt>, otherwise <tt>Memory</tt>.
|
477
|
+
// It provides the <tt>session()</tt> helper through <tt>Sammy.Storage#store()</tt>.
|
478
|
+
//
|
479
|
+
// See the <tt>Sammy.Storage</tt> plugin for full documentation.
|
480
|
+
//
|
481
|
+
Sammy.Session = function(app, options) {
|
482
|
+
this.use(Sammy.Storage);
|
483
|
+
// check for local storage, then cookie storage, then just use memory
|
484
|
+
var type = 'memory';
|
485
|
+
if (Sammy.Store.isAvailable('local')) {
|
486
|
+
type = 'local';
|
487
|
+
} else if (Sammy.Store.isAvailable('cookie')) {
|
488
|
+
type = 'cookie';
|
489
|
+
}
|
490
|
+
this.store('session', $.extend({type: type}, options));
|
491
|
+
};
|
492
|
+
|
493
|
+
// Sammy.Cache provides helpers for caching data within the lifecycle of a
|
494
|
+
// Sammy app. The plugin provides two main methods on <tt>Sammy.Application<tt>,
|
495
|
+
// <tt>cache</tt> and <tt>clearCache</tt>. Each app has its own cache store so that
|
496
|
+
// you dont have to worry about collisions. As of 0.5 the original Sammy.Cache module
|
497
|
+
// has been deprecated in favor of this one based on Sammy.Storage. The exposed
|
498
|
+
// API is almost identical, but Sammy.Storage provides additional backends including
|
499
|
+
// HTML5 Storage. <tt>Sammy.Cache</tt> will try to use these backends when available
|
500
|
+
// (in this order) <tt>LocalStorage</tt>, <tt>SessionStorage</tt>, and <tt>Memory</tt>
|
501
|
+
Sammy.Cache = function(app, options) {
|
502
|
+
this.use(Sammy.Storage);
|
503
|
+
// set cache_partials to true
|
504
|
+
this.cache_partials = true;
|
505
|
+
// check for local storage, then session storage, then just use memory
|
506
|
+
var type = 'memory';
|
507
|
+
if (Sammy.Store.isAvailable('local')) {
|
508
|
+
type = 'local';
|
509
|
+
} else if (Sammy.Store.isAvailable('session')) {
|
510
|
+
type = 'session';
|
511
|
+
}
|
512
|
+
this.store('cache', $.extend({type: type}, options));
|
513
|
+
};
|
514
|
+
|
515
|
+
})(jQuery);
|
@@ -0,0 +1,117 @@
|
|
1
|
+
(function($) {
|
2
|
+
|
3
|
+
// Simple JavaScript Templating
|
4
|
+
// John Resig - http://ejohn.org/ - MIT Licensed
|
5
|
+
// adapted from: http://ejohn.org/blog/javascript-micro-templating/
|
6
|
+
// originally $.srender by Greg Borenstein http://ideasfordozens.com in Feb 2009
|
7
|
+
// modified for Sammy by Aaron Quint for caching templates by name
|
8
|
+
var srender_cache = {};
|
9
|
+
var srender = function(name, template, data) {
|
10
|
+
// target is an optional element; if provided, the result will be inserted into it
|
11
|
+
// otherwise the result will simply be returned to the caller
|
12
|
+
if (srender_cache[name]) {
|
13
|
+
fn = srender_cache[name];
|
14
|
+
} else {
|
15
|
+
if (typeof template == 'undefined') {
|
16
|
+
// was a cache check, return false
|
17
|
+
return false;
|
18
|
+
}
|
19
|
+
// Generate a reusable function that will serve as a template
|
20
|
+
// generator (and which will be cached).
|
21
|
+
fn = srender_cache[name] = new Function("obj",
|
22
|
+
"var p=[],print=function(){p.push.apply(p,arguments);};" +
|
23
|
+
|
24
|
+
// Introduce the data as local variables using with(){}
|
25
|
+
"with(obj){p.push(\"" +
|
26
|
+
|
27
|
+
// Convert the template into pure JavaScript
|
28
|
+
template
|
29
|
+
.replace(/[\r\t\n]/g, " ")
|
30
|
+
.replace(/\"/g, '\\"')
|
31
|
+
.split("<%").join("\t")
|
32
|
+
.replace(/((^|%>)[^\t]*)/g, "$1\r")
|
33
|
+
.replace(/\t=(.*?)%>/g, "\",$1,\"")
|
34
|
+
.split("\t").join("\");")
|
35
|
+
.split("%>").join("p.push(\"")
|
36
|
+
.split("\r").join("")
|
37
|
+
+ "\");}return p.join('');");
|
38
|
+
}
|
39
|
+
|
40
|
+
if (typeof data != 'undefined') {
|
41
|
+
return fn(data);
|
42
|
+
} else {
|
43
|
+
return fn;
|
44
|
+
}
|
45
|
+
};
|
46
|
+
|
47
|
+
Sammy = Sammy || {};
|
48
|
+
|
49
|
+
// <tt>Sammy.Template</tt> is a simple plugin that provides a way to create
|
50
|
+
// and render client side templates. The rendering code is based on John Resig's
|
51
|
+
// quick templates and Greg Borenstien's srender plugin.
|
52
|
+
// This is also a great template/boilerplate for Sammy plugins.
|
53
|
+
//
|
54
|
+
// Templates use <% %> tags to denote embedded javascript.
|
55
|
+
//
|
56
|
+
// === Examples
|
57
|
+
//
|
58
|
+
// Here is an example template (user.template):
|
59
|
+
//
|
60
|
+
// <div class="user">
|
61
|
+
// <div class="user-name"><%= user.name %></div>
|
62
|
+
// <% if (user.photo_url) { %>
|
63
|
+
// <div class="photo"><img src="<%= user.photo_url %>" /></div>
|
64
|
+
// <% } %>
|
65
|
+
// </div>
|
66
|
+
//
|
67
|
+
// Given that is a publicly accesible file, you would render it like:
|
68
|
+
//
|
69
|
+
// $.sammy(function() {
|
70
|
+
// // include the plugin
|
71
|
+
// this.use(Sammy.Template);
|
72
|
+
//
|
73
|
+
// this.get('#/', function() {
|
74
|
+
// // the template is rendered in the current context.
|
75
|
+
// this.user = {name: 'Aaron Quint'};
|
76
|
+
// // partial calls template() because of the file extension
|
77
|
+
// this.partial('user.template');
|
78
|
+
// })
|
79
|
+
// });
|
80
|
+
//
|
81
|
+
// You can also pass a second argument to use() that will alias the template
|
82
|
+
// method and therefore allow you to use a different extension for template files
|
83
|
+
// in <tt>partial()</tt>
|
84
|
+
//
|
85
|
+
// // alias to 'tpl'
|
86
|
+
// this.use(Sammy.Template, 'tpl');
|
87
|
+
//
|
88
|
+
// // now .tpl files will be run through srender
|
89
|
+
// this.get('#/', function() {
|
90
|
+
// this.partial('myfile.tpl');
|
91
|
+
// });
|
92
|
+
//
|
93
|
+
Sammy.Template = function(app, method_alias) {
|
94
|
+
|
95
|
+
// *Helper:* Uses simple templating to parse ERB like templates.
|
96
|
+
//
|
97
|
+
// === Arguments
|
98
|
+
//
|
99
|
+
// +template+:: A String template. '<% %>' tags are evaluated as Javascript and replaced with the elements in data.
|
100
|
+
// +data+:: An Object containing the replacement values for the template.
|
101
|
+
// data is extended with the <tt>EventContext</tt> allowing you to call its methods within the template.
|
102
|
+
// +name+:: An optional String name to cache the template.
|
103
|
+
//
|
104
|
+
var template = function(template, data, name) {
|
105
|
+
// use name for caching
|
106
|
+
if (typeof name == 'undefined') name = template;
|
107
|
+
return srender(name, template, $.extend({}, this, data));
|
108
|
+
};
|
109
|
+
|
110
|
+
// set the default method name/extension
|
111
|
+
if (!method_alias) method_alias = 'template';
|
112
|
+
// create the helper at the method alias
|
113
|
+
app.helper(method_alias, template);
|
114
|
+
|
115
|
+
};
|
116
|
+
|
117
|
+
})(jQuery);
|