appetizer-ui 0.1.0 → 0.2.1
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/.gitignore +1 -0
- data/appetizer-ui.gemspec +1 -1
- data/lib/appetizer/ui/app/js/appetizer.coffee +5 -0
- data/lib/appetizer/ui/app/js/appetizer/core.coffee +19 -0
- data/lib/appetizer/ui/app/js/appetizer/router.coffee +70 -0
- data/lib/appetizer/ui/app/js/appetizer/view.coffee +2 -1
- data/lib/appetizer/ui/app/js/appetizer/xdr.coffee +12 -1
- data/lib/appetizer/ui/vendor/js/underscore.string.js +480 -10
- metadata +24 -23
data/.gitignore
CHANGED
data/appetizer-ui.gemspec
CHANGED
@@ -2,8 +2,13 @@
|
|
2
2
|
#= require jquery
|
3
3
|
#= require underscore
|
4
4
|
#= require underscore.string
|
5
|
+
|
5
6
|
#= require backbone
|
6
7
|
|
7
8
|
#= require appetizer/core
|
8
9
|
#= require appetizer/model
|
9
10
|
#= require appetizer/view
|
11
|
+
|
12
|
+
# Mixin non-conflicting methods to underscore.
|
13
|
+
|
14
|
+
_.mixin _.str.exports()
|
@@ -1 +1,20 @@
|
|
1
1
|
window.Appetizer ||= {}
|
2
|
+
|
3
|
+
# All Backbone's classes that inherit from Backbone.Event
|
4
|
+
# are also given a "one" method, which can be used to fire
|
5
|
+
# a callback only on the next occurence of a given event.
|
6
|
+
|
7
|
+
one =
|
8
|
+
one: (ev, callback, context) ->
|
9
|
+
self = this
|
10
|
+
|
11
|
+
fn = ->
|
12
|
+
callback.apply this, arguments
|
13
|
+
self.unbind.apply self, [ev, fn]
|
14
|
+
|
15
|
+
this.bind ev, fn, context
|
16
|
+
|
17
|
+
_.extend Backbone.Model.prototype, one
|
18
|
+
_.extend Backbone.Collection.prototype, one
|
19
|
+
_.extend Backbone.View.prototype, one
|
20
|
+
_.extend Backbone.Router.prototype, one
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# A superclass for Backbone.router. It adds the following features:
|
2
|
+
# * Register dynamic routes: the method @dynamicRoutes, if present,
|
3
|
+
# is executed when initializing the router. Using the provided @register
|
4
|
+
# method, it is then possible to register routes within the @dynamicRoutes
|
5
|
+
# method.
|
6
|
+
#
|
7
|
+
# * Components facilities: the property @components should contain an
|
8
|
+
# array of components used in the application, such as "page", "panel",
|
9
|
+
# "sidebar", etc..
|
10
|
+
# For each component, a method showFoo is created, which can then be used
|
11
|
+
# to show a component. For instance, showPage App.View.Page, options. Upon
|
12
|
+
# calling showFoo App.View.Bar the following is performed:
|
13
|
+
# - Call @foo.hide true if @foo exists
|
14
|
+
# - Instanciate a fresh @foo = new App.View.Bar options
|
15
|
+
# - Save current route in @foo.currentRoute
|
16
|
+
# - Emit "foo:showing", @foo
|
17
|
+
# - Call @foo.show()
|
18
|
+
# - Emit "foo:shown", @foo when @foo has been shown
|
19
|
+
#
|
20
|
+
# Component facilites can be used to properly implement your application's
|
21
|
+
# logic. For instance, you can do the following:
|
22
|
+
# components: ["page", "sidebar"]
|
23
|
+
#
|
24
|
+
# initialize: ->
|
25
|
+
# # Show the sidebar corresponding to current shown page.
|
26
|
+
# @bind "page:shown", (page) -> @showSidebar @findSidebarForPage(page)
|
27
|
+
|
28
|
+
class Appetizer.Router extends Backbone.Router
|
29
|
+
initialize: ->
|
30
|
+
@children = []
|
31
|
+
|
32
|
+
@dynamicRoutes() if @dynamicRoutes?
|
33
|
+
|
34
|
+
# Create showItem functions
|
35
|
+
|
36
|
+
if @components?
|
37
|
+
@addShowFunction item for item in @components
|
38
|
+
|
39
|
+
register: (route, name) =>
|
40
|
+
@route route, name, this[name]
|
41
|
+
|
42
|
+
# Create an instance of a view, set this as the view's parent, and
|
43
|
+
# add the view to the router's list of children.
|
44
|
+
|
45
|
+
createChild: (kind, options) ->
|
46
|
+
child = new kind options
|
47
|
+
child.parent = this
|
48
|
+
@children.push child
|
49
|
+
child
|
50
|
+
|
51
|
+
# Required for Appetizer.View hierarchy management.
|
52
|
+
|
53
|
+
removeChild: (view) ->
|
54
|
+
@children.splice _.indexOf(@children, view), 1
|
55
|
+
this
|
56
|
+
|
57
|
+
addShowFunction: (item) ->
|
58
|
+
fn = "show#{item.charAt(0).toUpperCase()}#{item.slice 1}"
|
59
|
+
|
60
|
+
this[fn] = (kind, options) ->
|
61
|
+
if this[item]?
|
62
|
+
this[item].hide true
|
63
|
+
@removeChild this[item]
|
64
|
+
|
65
|
+
this[item] = @createChild(kind, options)
|
66
|
+
this[item].currentRoute = Backbone.history.getFragment()
|
67
|
+
|
68
|
+
@trigger "#{item}:showing", this[item]
|
69
|
+
this[item].bind "shown", => @trigger "#{item}:shown", this[item]
|
70
|
+
this[item].show()
|
@@ -12,7 +12,8 @@ class Appetizer.View extends Backbone.View
|
|
12
12
|
@bindings = []
|
13
13
|
@children = []
|
14
14
|
@parent = options.parent if options?.parent?
|
15
|
-
|
15
|
+
@route = options?.route or @constructor.route
|
16
|
+
|
16
17
|
@bind "ancestor:shown", ->
|
17
18
|
child.trigger "ancestor:shown" for child in @children
|
18
19
|
@shown = true
|
@@ -27,7 +27,18 @@ Appetizer.transportXDR = (settings, original, xhr) ->
|
|
27
27
|
console.log "FIX: xdr onerror"
|
28
28
|
|
29
29
|
xdr.onload = ->
|
30
|
-
[status, headers, body] =
|
30
|
+
[status, headers, body] =
|
31
|
+
try
|
32
|
+
$.parseJSON xdr.responseText
|
33
|
+
catch err
|
34
|
+
headers =
|
35
|
+
"Content-Type" : "application/json;charset=UTF-8"
|
36
|
+
|
37
|
+
body = JSON.stringify
|
38
|
+
request : ["Unexpected platform error."]
|
39
|
+
original : xdr.responseText
|
40
|
+
|
41
|
+
[503, headers, body]
|
31
42
|
|
32
43
|
description = statii[status] or "UNKNOWN"
|
33
44
|
responses = text: body
|
@@ -1,10 +1,480 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
1
|
+
// Underscore.string
|
2
|
+
// (c) 2010 Esa-Matti Suuronen <esa-matti aet suuronen dot org>
|
3
|
+
// Underscore.strings is freely distributable under the terms of the MIT license.
|
4
|
+
// Documentation: https://github.com/epeli/underscore.string
|
5
|
+
// Some code is borrowed from MooTools and Alexandru Marasteanu.
|
6
|
+
|
7
|
+
// Version 2.0.0
|
8
|
+
|
9
|
+
(function(root){
|
10
|
+
'use strict';
|
11
|
+
|
12
|
+
// Defining helper functions.
|
13
|
+
|
14
|
+
var nativeTrim = String.prototype.trim;
|
15
|
+
|
16
|
+
var parseNumber = function(source) { return source * 1 || 0; };
|
17
|
+
|
18
|
+
var strRepeat = function(i, m) {
|
19
|
+
for (var o = []; m > 0; o[--m] = i) {}
|
20
|
+
return o.join('');
|
21
|
+
};
|
22
|
+
|
23
|
+
var slice = function(a){
|
24
|
+
return Array.prototype.slice.call(a);
|
25
|
+
};
|
26
|
+
|
27
|
+
var defaultToWhiteSpace = function(characters){
|
28
|
+
if (characters) {
|
29
|
+
return _s.escapeRegExp(characters);
|
30
|
+
}
|
31
|
+
return '\\s';
|
32
|
+
};
|
33
|
+
|
34
|
+
var sArgs = function(method){
|
35
|
+
return function(){
|
36
|
+
var args = slice(arguments);
|
37
|
+
for(var i=0; i<args.length; i++)
|
38
|
+
args[i] = args[i] == null ? '' : '' + args[i];
|
39
|
+
return method.apply(null, args);
|
40
|
+
};
|
41
|
+
};
|
42
|
+
|
43
|
+
// sprintf() for JavaScript 0.7-beta1
|
44
|
+
// http://www.diveintojavascript.com/projects/javascript-sprintf
|
45
|
+
//
|
46
|
+
// Copyright (c) Alexandru Marasteanu <alexaholic [at) gmail (dot] com>
|
47
|
+
// All rights reserved.
|
48
|
+
|
49
|
+
var sprintf = (function() {
|
50
|
+
function get_type(variable) {
|
51
|
+
return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase();
|
52
|
+
}
|
53
|
+
|
54
|
+
var str_repeat = strRepeat;
|
55
|
+
|
56
|
+
var str_format = function() {
|
57
|
+
if (!str_format.cache.hasOwnProperty(arguments[0])) {
|
58
|
+
str_format.cache[arguments[0]] = str_format.parse(arguments[0]);
|
59
|
+
}
|
60
|
+
return str_format.format.call(null, str_format.cache[arguments[0]], arguments);
|
61
|
+
};
|
62
|
+
|
63
|
+
str_format.format = function(parse_tree, argv) {
|
64
|
+
var cursor = 1, tree_length = parse_tree.length, node_type = '', arg, output = [], i, k, match, pad, pad_character, pad_length;
|
65
|
+
for (i = 0; i < tree_length; i++) {
|
66
|
+
node_type = get_type(parse_tree[i]);
|
67
|
+
if (node_type === 'string') {
|
68
|
+
output.push(parse_tree[i]);
|
69
|
+
}
|
70
|
+
else if (node_type === 'array') {
|
71
|
+
match = parse_tree[i]; // convenience purposes only
|
72
|
+
if (match[2]) { // keyword argument
|
73
|
+
arg = argv[cursor];
|
74
|
+
for (k = 0; k < match[2].length; k++) {
|
75
|
+
if (!arg.hasOwnProperty(match[2][k])) {
|
76
|
+
throw(sprintf('[_.sprintf] property "%s" does not exist', match[2][k]));
|
77
|
+
}
|
78
|
+
arg = arg[match[2][k]];
|
79
|
+
}
|
80
|
+
} else if (match[1]) { // positional argument (explicit)
|
81
|
+
arg = argv[match[1]];
|
82
|
+
}
|
83
|
+
else { // positional argument (implicit)
|
84
|
+
arg = argv[cursor++];
|
85
|
+
}
|
86
|
+
|
87
|
+
if (/[^s]/.test(match[8]) && (get_type(arg) != 'number')) {
|
88
|
+
throw(sprintf('[_.sprintf] expecting number but found %s', get_type(arg)));
|
89
|
+
}
|
90
|
+
switch (match[8]) {
|
91
|
+
case 'b': arg = arg.toString(2); break;
|
92
|
+
case 'c': arg = String.fromCharCode(arg); break;
|
93
|
+
case 'd': arg = parseInt(arg, 10); break;
|
94
|
+
case 'e': arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential(); break;
|
95
|
+
case 'f': arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg); break;
|
96
|
+
case 'o': arg = arg.toString(8); break;
|
97
|
+
case 's': arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg); break;
|
98
|
+
case 'u': arg = Math.abs(arg); break;
|
99
|
+
case 'x': arg = arg.toString(16); break;
|
100
|
+
case 'X': arg = arg.toString(16).toUpperCase(); break;
|
101
|
+
}
|
102
|
+
arg = (/[def]/.test(match[8]) && match[3] && arg >= 0 ? '+'+ arg : arg);
|
103
|
+
pad_character = match[4] ? match[4] == '0' ? '0' : match[4].charAt(1) : ' ';
|
104
|
+
pad_length = match[6] - String(arg).length;
|
105
|
+
pad = match[6] ? str_repeat(pad_character, pad_length) : '';
|
106
|
+
output.push(match[5] ? arg + pad : pad + arg);
|
107
|
+
}
|
108
|
+
}
|
109
|
+
return output.join('');
|
110
|
+
};
|
111
|
+
|
112
|
+
str_format.cache = {};
|
113
|
+
|
114
|
+
str_format.parse = function(fmt) {
|
115
|
+
var _fmt = fmt, match = [], parse_tree = [], arg_names = 0;
|
116
|
+
while (_fmt) {
|
117
|
+
if ((match = /^[^\x25]+/.exec(_fmt)) !== null) {
|
118
|
+
parse_tree.push(match[0]);
|
119
|
+
}
|
120
|
+
else if ((match = /^\x25{2}/.exec(_fmt)) !== null) {
|
121
|
+
parse_tree.push('%');
|
122
|
+
}
|
123
|
+
else if ((match = /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(_fmt)) !== null) {
|
124
|
+
if (match[2]) {
|
125
|
+
arg_names |= 1;
|
126
|
+
var field_list = [], replacement_field = match[2], field_match = [];
|
127
|
+
if ((field_match = /^([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
|
128
|
+
field_list.push(field_match[1]);
|
129
|
+
while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') {
|
130
|
+
if ((field_match = /^\.([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
|
131
|
+
field_list.push(field_match[1]);
|
132
|
+
}
|
133
|
+
else if ((field_match = /^\[(\d+)\]/.exec(replacement_field)) !== null) {
|
134
|
+
field_list.push(field_match[1]);
|
135
|
+
}
|
136
|
+
else {
|
137
|
+
throw('[_.sprintf] huh?');
|
138
|
+
}
|
139
|
+
}
|
140
|
+
}
|
141
|
+
else {
|
142
|
+
throw('[_.sprintf] huh?');
|
143
|
+
}
|
144
|
+
match[2] = field_list;
|
145
|
+
}
|
146
|
+
else {
|
147
|
+
arg_names |= 2;
|
148
|
+
}
|
149
|
+
if (arg_names === 3) {
|
150
|
+
throw('[_.sprintf] mixing positional and named placeholders is not (yet) supported');
|
151
|
+
}
|
152
|
+
parse_tree.push(match);
|
153
|
+
}
|
154
|
+
else {
|
155
|
+
throw('[_.sprintf] huh?');
|
156
|
+
}
|
157
|
+
_fmt = _fmt.substring(match[0].length);
|
158
|
+
}
|
159
|
+
return parse_tree;
|
160
|
+
};
|
161
|
+
|
162
|
+
return str_format;
|
163
|
+
})();
|
164
|
+
|
165
|
+
|
166
|
+
|
167
|
+
// Defining underscore.string
|
168
|
+
|
169
|
+
var _s = {
|
170
|
+
|
171
|
+
VERSION: '2.0.0',
|
172
|
+
|
173
|
+
isBlank: sArgs(function(str){
|
174
|
+
return (/^\s*$/).test(str);
|
175
|
+
}),
|
176
|
+
|
177
|
+
stripTags: sArgs(function(str){
|
178
|
+
return str.replace(/<\/?[^>]+>/ig, '');
|
179
|
+
}),
|
180
|
+
|
181
|
+
capitalize : sArgs(function(str) {
|
182
|
+
return str.charAt(0).toUpperCase() + str.substring(1).toLowerCase();
|
183
|
+
}),
|
184
|
+
|
185
|
+
chop: sArgs(function(str, step){
|
186
|
+
step = parseNumber(step) || str.length;
|
187
|
+
var arr = [];
|
188
|
+
for (var i = 0; i < str.length;) {
|
189
|
+
arr.push(str.slice(i,i + step));
|
190
|
+
i = i + step;
|
191
|
+
}
|
192
|
+
return arr;
|
193
|
+
}),
|
194
|
+
|
195
|
+
clean: sArgs(function(str){
|
196
|
+
return _s.strip(str.replace(/\s+/g, ' '));
|
197
|
+
}),
|
198
|
+
|
199
|
+
count: sArgs(function(str, substr){
|
200
|
+
var count = 0, index;
|
201
|
+
for (var i=0; i < str.length;) {
|
202
|
+
index = str.indexOf(substr, i);
|
203
|
+
index >= 0 && count++;
|
204
|
+
i = i + (index >= 0 ? index : 0) + substr.length;
|
205
|
+
}
|
206
|
+
return count;
|
207
|
+
}),
|
208
|
+
|
209
|
+
chars: sArgs(function(str) {
|
210
|
+
return str.split('');
|
211
|
+
}),
|
212
|
+
|
213
|
+
escapeHTML: sArgs(function(str) {
|
214
|
+
return str.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>')
|
215
|
+
.replace(/"/g, '"').replace(/'/g, "'");
|
216
|
+
}),
|
217
|
+
|
218
|
+
unescapeHTML: sArgs(function(str) {
|
219
|
+
return str.replace(/</g, '<').replace(/>/g, '>')
|
220
|
+
.replace(/"/g, '"').replace(/'/g, "'").replace(/&/g, '&');
|
221
|
+
}),
|
222
|
+
|
223
|
+
escapeRegExp: sArgs(function(str){
|
224
|
+
// From MooTools core 1.2.4
|
225
|
+
return str.replace(/([-.*+?^${}()|[\]\/\\])/g, '\\$1');
|
226
|
+
}),
|
227
|
+
|
228
|
+
insert: sArgs(function(str, i, substr){
|
229
|
+
var arr = str.split('');
|
230
|
+
arr.splice(parseNumber(i), 0, substr);
|
231
|
+
return arr.join('');
|
232
|
+
}),
|
233
|
+
|
234
|
+
include: sArgs(function(str, needle){
|
235
|
+
return str.indexOf(needle) !== -1;
|
236
|
+
}),
|
237
|
+
|
238
|
+
join: sArgs(function(sep) {
|
239
|
+
var args = slice(arguments);
|
240
|
+
return args.join(args.shift());
|
241
|
+
}),
|
242
|
+
|
243
|
+
lines: sArgs(function(str) {
|
244
|
+
return str.split("\n");
|
245
|
+
}),
|
246
|
+
|
247
|
+
reverse: sArgs(function(str){
|
248
|
+
return Array.prototype.reverse.apply(String(str).split('')).join('');
|
249
|
+
}),
|
250
|
+
|
251
|
+
splice: sArgs(function(str, i, howmany, substr){
|
252
|
+
var arr = str.split('');
|
253
|
+
arr.splice(parseNumber(i), parseNumber(howmany), substr);
|
254
|
+
return arr.join('');
|
255
|
+
}),
|
256
|
+
|
257
|
+
startsWith: sArgs(function(str, starts){
|
258
|
+
return str.length >= starts.length && str.substring(0, starts.length) === starts;
|
259
|
+
}),
|
260
|
+
|
261
|
+
endsWith: sArgs(function(str, ends){
|
262
|
+
return str.length >= ends.length && str.substring(str.length - ends.length) === ends;
|
263
|
+
}),
|
264
|
+
|
265
|
+
succ: sArgs(function(str){
|
266
|
+
var arr = str.split('');
|
267
|
+
arr.splice(str.length-1, 1, String.fromCharCode(str.charCodeAt(str.length-1) + 1));
|
268
|
+
return arr.join('');
|
269
|
+
}),
|
270
|
+
|
271
|
+
titleize: sArgs(function(str){
|
272
|
+
var arr = str.split(' '),
|
273
|
+
word;
|
274
|
+
for (var i=0; i < arr.length; i++) {
|
275
|
+
word = arr[i].split('');
|
276
|
+
if(typeof word[0] !== 'undefined') word[0] = word[0].toUpperCase();
|
277
|
+
i+1 === arr.length ? arr[i] = word.join('') : arr[i] = word.join('') + ' ';
|
278
|
+
}
|
279
|
+
return arr.join('');
|
280
|
+
}),
|
281
|
+
|
282
|
+
camelize: sArgs(function(str){
|
283
|
+
return _s.trim(str).replace(/(\-|_|\s)+(.)?/g, function(match, separator, chr) {
|
284
|
+
return chr ? chr.toUpperCase() : '';
|
285
|
+
});
|
286
|
+
}),
|
287
|
+
|
288
|
+
underscored: function(str){
|
289
|
+
return _s.trim(str).replace(/([a-z\d])([A-Z]+)/g, '$1_$2').replace(/\-|\s+/g, '_').toLowerCase();
|
290
|
+
},
|
291
|
+
|
292
|
+
dasherize: function(str){
|
293
|
+
return _s.trim(str).replace(/([a-z\d])([A-Z]+)/g, '$1-$2').replace(/^([A-Z]+)/, '-$1').replace(/\_|\s+/g, '-').toLowerCase();
|
294
|
+
},
|
295
|
+
|
296
|
+
humanize: function(str){
|
297
|
+
return _s.capitalize(this.underscored(str).replace(/_id$/,'').replace(/_/g, ' '));
|
298
|
+
},
|
299
|
+
|
300
|
+
trim: sArgs(function(str, characters){
|
301
|
+
if (!characters && nativeTrim) {
|
302
|
+
return nativeTrim.call(str);
|
303
|
+
}
|
304
|
+
characters = defaultToWhiteSpace(characters);
|
305
|
+
return str.replace(new RegExp('\^[' + characters + ']+|[' + characters + ']+$', 'g'), '');
|
306
|
+
}),
|
307
|
+
|
308
|
+
ltrim: sArgs(function(str, characters){
|
309
|
+
characters = defaultToWhiteSpace(characters);
|
310
|
+
return str.replace(new RegExp('\^[' + characters + ']+', 'g'), '');
|
311
|
+
}),
|
312
|
+
|
313
|
+
rtrim: sArgs(function(str, characters){
|
314
|
+
characters = defaultToWhiteSpace(characters);
|
315
|
+
return str.replace(new RegExp('[' + characters + ']+$', 'g'), '');
|
316
|
+
}),
|
317
|
+
|
318
|
+
truncate: sArgs(function(str, length, truncateStr){
|
319
|
+
truncateStr = truncateStr || '...';
|
320
|
+
length = parseNumber(length);
|
321
|
+
return str.length > length ? str.slice(0,length) + truncateStr : str;
|
322
|
+
}),
|
323
|
+
|
324
|
+
/**
|
325
|
+
* _s.prune: a more elegant version of truncate
|
326
|
+
* prune extra chars, never leaving a half-chopped word.
|
327
|
+
* @author github.com/sergiokas
|
328
|
+
*/
|
329
|
+
prune: sArgs(function(str, length, pruneStr){
|
330
|
+
// Function to check word/digit chars including non-ASCII encodings.
|
331
|
+
var isWordChar = function(c) { return ((c.toUpperCase() != c.toLowerCase()) || /[-_\d]/.test(c)); }
|
332
|
+
|
333
|
+
var template = '';
|
334
|
+
var pruned = '';
|
335
|
+
var i = 0;
|
336
|
+
|
337
|
+
// Set default values
|
338
|
+
pruneStr = pruneStr || '...';
|
339
|
+
length = parseNumber(length);
|
340
|
+
|
341
|
+
// Convert to an ASCII string to avoid problems with unicode chars.
|
342
|
+
for (i in str) {
|
343
|
+
template += (isWordChar(str[i]))?'A':' ';
|
344
|
+
}
|
345
|
+
|
346
|
+
// Check if we're in the middle of a word
|
347
|
+
if( template.substring(length-1, length+1).search(/^\w\w$/) === 0 )
|
348
|
+
pruned = _s.rtrim(template.slice(0,length).replace(/([\W][\w]*)$/,''));
|
349
|
+
else
|
350
|
+
pruned = _s.rtrim(template.slice(0,length));
|
351
|
+
|
352
|
+
pruned = pruned.replace(/\W+$/,'');
|
353
|
+
|
354
|
+
return (pruned.length+pruneStr.length>str.length) ? str : str.substring(0, pruned.length)+pruneStr;
|
355
|
+
}),
|
356
|
+
|
357
|
+
words: function(str, delimiter) {
|
358
|
+
return String(str).split(delimiter || " ");
|
359
|
+
},
|
360
|
+
|
361
|
+
pad: sArgs(function(str, length, padStr, type) {
|
362
|
+
var padding = '',
|
363
|
+
padlen = 0;
|
364
|
+
|
365
|
+
length = parseNumber(length);
|
366
|
+
|
367
|
+
if (!padStr) { padStr = ' '; }
|
368
|
+
else if (padStr.length > 1) { padStr = padStr.charAt(0); }
|
369
|
+
switch(type) {
|
370
|
+
case 'right':
|
371
|
+
padlen = (length - str.length);
|
372
|
+
padding = strRepeat(padStr, padlen);
|
373
|
+
str = str+padding;
|
374
|
+
break;
|
375
|
+
case 'both':
|
376
|
+
padlen = (length - str.length);
|
377
|
+
padding = {
|
378
|
+
'left' : strRepeat(padStr, Math.ceil(padlen/2)),
|
379
|
+
'right': strRepeat(padStr, Math.floor(padlen/2))
|
380
|
+
};
|
381
|
+
str = padding.left+str+padding.right;
|
382
|
+
break;
|
383
|
+
default: // 'left'
|
384
|
+
padlen = (length - str.length);
|
385
|
+
padding = strRepeat(padStr, padlen);;
|
386
|
+
str = padding+str;
|
387
|
+
}
|
388
|
+
return str;
|
389
|
+
}),
|
390
|
+
|
391
|
+
lpad: function(str, length, padStr) {
|
392
|
+
return _s.pad(str, length, padStr);
|
393
|
+
},
|
394
|
+
|
395
|
+
rpad: function(str, length, padStr) {
|
396
|
+
return _s.pad(str, length, padStr, 'right');
|
397
|
+
},
|
398
|
+
|
399
|
+
lrpad: function(str, length, padStr) {
|
400
|
+
return _s.pad(str, length, padStr, 'both');
|
401
|
+
},
|
402
|
+
|
403
|
+
sprintf: sprintf,
|
404
|
+
|
405
|
+
vsprintf: function(fmt, argv){
|
406
|
+
argv.unshift(fmt);
|
407
|
+
return sprintf.apply(null, argv);
|
408
|
+
},
|
409
|
+
|
410
|
+
toNumber: function(str, decimals) {
|
411
|
+
var num = parseNumber(parseNumber(str).toFixed(parseNumber(decimals)));
|
412
|
+
return (!(num === 0 && (str !== "0" && str !== 0))) ? num : Number.NaN;
|
413
|
+
},
|
414
|
+
|
415
|
+
strRight: sArgs(function(sourceStr, sep){
|
416
|
+
var pos = (!sep) ? -1 : sourceStr.indexOf(sep);
|
417
|
+
return (pos != -1) ? sourceStr.slice(pos+sep.length, sourceStr.length) : sourceStr;
|
418
|
+
}),
|
419
|
+
|
420
|
+
strRightBack: sArgs(function(sourceStr, sep){
|
421
|
+
var pos = (!sep) ? -1 : sourceStr.lastIndexOf(sep);
|
422
|
+
return (pos != -1) ? sourceStr.slice(pos+sep.length, sourceStr.length) : sourceStr;
|
423
|
+
}),
|
424
|
+
|
425
|
+
strLeft: sArgs(function(sourceStr, sep){
|
426
|
+
var pos = (!sep) ? -1 : sourceStr.indexOf(sep);
|
427
|
+
return (pos != -1) ? sourceStr.slice(0, pos) : sourceStr;
|
428
|
+
}),
|
429
|
+
|
430
|
+
strLeftBack: sArgs(function(sourceStr, sep){
|
431
|
+
var pos = sourceStr.lastIndexOf(sep);
|
432
|
+
return (pos != -1) ? sourceStr.slice(0, pos) : sourceStr;
|
433
|
+
}),
|
434
|
+
|
435
|
+
exports: function() {
|
436
|
+
var result = {};
|
437
|
+
|
438
|
+
for (var prop in this) {
|
439
|
+
if (!this.hasOwnProperty(prop) || prop == 'include' || prop == 'contains' || prop == 'reverse') continue;
|
440
|
+
result[prop] = this[prop];
|
441
|
+
}
|
442
|
+
|
443
|
+
return result;
|
444
|
+
}
|
445
|
+
|
446
|
+
};
|
447
|
+
|
448
|
+
// Aliases
|
449
|
+
|
450
|
+
_s.strip = _s.trim;
|
451
|
+
_s.lstrip = _s.ltrim;
|
452
|
+
_s.rstrip = _s.rtrim;
|
453
|
+
_s.center = _s.lrpad;
|
454
|
+
_s.ljust = _s.lpad;
|
455
|
+
_s.rjust = _s.rpad;
|
456
|
+
_s.contains = _s.include;
|
457
|
+
|
458
|
+
// CommonJS module is defined
|
459
|
+
if (typeof exports !== 'undefined') {
|
460
|
+
if (typeof module !== 'undefined' && module.exports) {
|
461
|
+
// Export module
|
462
|
+
module.exports = _s;
|
463
|
+
}
|
464
|
+
exports._s = _s;
|
465
|
+
|
466
|
+
// Integrate with Underscore.js
|
467
|
+
} else if (typeof root._ !== 'undefined') {
|
468
|
+
// root._.mixin(_s);
|
469
|
+
root._.string = _s;
|
470
|
+
root._.str = root._.string;
|
471
|
+
|
472
|
+
// Or define it
|
473
|
+
} else {
|
474
|
+
root._ = {
|
475
|
+
string: _s,
|
476
|
+
str: _s
|
477
|
+
};
|
478
|
+
}
|
479
|
+
|
480
|
+
}(this || window));
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: appetizer-ui
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1
|
4
|
+
version: 0.2.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2012-01-10 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: appetizer
|
16
|
-
requirement: &
|
16
|
+
requirement: &70117728740140 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0.0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70117728740140
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: coffee-script
|
27
|
-
requirement: &
|
27
|
+
requirement: &70117728739100 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '2.2'
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70117728739100
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: eco
|
38
|
-
requirement: &
|
38
|
+
requirement: &70117728738120 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ~>
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '1.0'
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70117728738120
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: rack-ssl
|
49
|
-
requirement: &
|
49
|
+
requirement: &70117728737340 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ~>
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: '1.3'
|
55
55
|
type: :runtime
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *70117728737340
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: sass
|
60
|
-
requirement: &
|
60
|
+
requirement: &70117728736820 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ~>
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: '3.1'
|
66
66
|
type: :runtime
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *70117728736820
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: sinatra
|
71
|
-
requirement: &
|
71
|
+
requirement: &70117728736340 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ~>
|
@@ -76,10 +76,10 @@ dependencies:
|
|
76
76
|
version: '1.3'
|
77
77
|
type: :runtime
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *70117728736340
|
80
80
|
- !ruby/object:Gem::Dependency
|
81
81
|
name: sprockets
|
82
|
-
requirement: &
|
82
|
+
requirement: &70117728735860 !ruby/object:Gem::Requirement
|
83
83
|
none: false
|
84
84
|
requirements:
|
85
85
|
- - ~>
|
@@ -87,10 +87,10 @@ dependencies:
|
|
87
87
|
version: '2.1'
|
88
88
|
type: :runtime
|
89
89
|
prerelease: false
|
90
|
-
version_requirements: *
|
90
|
+
version_requirements: *70117728735860
|
91
91
|
- !ruby/object:Gem::Dependency
|
92
92
|
name: uglifier
|
93
|
-
requirement: &
|
93
|
+
requirement: &70117728735360 !ruby/object:Gem::Requirement
|
94
94
|
none: false
|
95
95
|
requirements:
|
96
96
|
- - ~>
|
@@ -98,10 +98,10 @@ dependencies:
|
|
98
98
|
version: '1.0'
|
99
99
|
type: :runtime
|
100
100
|
prerelease: false
|
101
|
-
version_requirements: *
|
101
|
+
version_requirements: *70117728735360
|
102
102
|
- !ruby/object:Gem::Dependency
|
103
103
|
name: yajl-ruby
|
104
|
-
requirement: &
|
104
|
+
requirement: &70117728734860 !ruby/object:Gem::Requirement
|
105
105
|
none: false
|
106
106
|
requirements:
|
107
107
|
- - ~>
|
@@ -109,10 +109,10 @@ dependencies:
|
|
109
109
|
version: '1.0'
|
110
110
|
type: :runtime
|
111
111
|
prerelease: false
|
112
|
-
version_requirements: *
|
112
|
+
version_requirements: *70117728734860
|
113
113
|
- !ruby/object:Gem::Dependency
|
114
114
|
name: yui-compressor
|
115
|
-
requirement: &
|
115
|
+
requirement: &70117728734280 !ruby/object:Gem::Requirement
|
116
116
|
none: false
|
117
117
|
requirements:
|
118
118
|
- - ~>
|
@@ -120,7 +120,7 @@ dependencies:
|
|
120
120
|
version: '0.9'
|
121
121
|
type: :runtime
|
122
122
|
prerelease: false
|
123
|
-
version_requirements: *
|
123
|
+
version_requirements: *70117728734280
|
124
124
|
description: A painfully opinionated Appetizer extension for web apps.
|
125
125
|
email:
|
126
126
|
- tech@audiosocket.com
|
@@ -137,6 +137,7 @@ files:
|
|
137
137
|
- lib/appetizer/ui/app/js/appetizer.coffee
|
138
138
|
- lib/appetizer/ui/app/js/appetizer/core.coffee
|
139
139
|
- lib/appetizer/ui/app/js/appetizer/model.coffee
|
140
|
+
- lib/appetizer/ui/app/js/appetizer/router.coffee
|
140
141
|
- lib/appetizer/ui/app/js/appetizer/view.coffee
|
141
142
|
- lib/appetizer/ui/app/js/appetizer/xdr.coffee
|
142
143
|
- lib/appetizer/ui/app/views/client/appetizer/missing.jst.eco
|
@@ -174,7 +175,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
174
175
|
version: '0'
|
175
176
|
requirements: []
|
176
177
|
rubyforge_project:
|
177
|
-
rubygems_version: 1.8.
|
178
|
+
rubygems_version: 1.8.10
|
178
179
|
signing_key:
|
179
180
|
specification_version: 3
|
180
181
|
summary: Helpers for rich clients using Sinatra, Sass, and CoffeeScript.
|