jim 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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);
|