ultimate-base 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/.gitignore +5 -0
- data/.rvmrc +2 -0
- data/.rvmrc.example +2 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +14 -0
- data/LICENSE +5 -0
- data/README.md +1 -0
- data/Rakefile +1 -0
- data/app/assets/javascripts/backbone/backbone.js +1452 -0
- data/app/assets/javascripts/backbone/ultimate/app.js.coffee +25 -0
- data/app/assets/javascripts/backbone/ultimate/collection.js.coffee +12 -0
- data/app/assets/javascripts/backbone/ultimate/model.js.coffee +12 -0
- data/app/assets/javascripts/backbone/ultimate/router.js.coffee +13 -0
- data/app/assets/javascripts/backbone/ultimate/view.js.coffee +96 -0
- data/app/assets/javascripts/ultimate/base.js.coffee +103 -0
- data/app/assets/javascripts/ultimate/bus.js.coffee +57 -0
- data/app/assets/javascripts/ultimate/devise.js.coffee +18 -0
- data/app/assets/javascripts/ultimate/experimental/_inflections/dzone.inflections.js +154 -0
- data/app/assets/javascripts/ultimate/experimental/_inflections/inflections.js.coffee +2 -0
- data/app/assets/javascripts/ultimate/experimental/_inflections/plur.js +29 -0
- data/app/assets/javascripts/ultimate/experimental/_inflections/underscore.inflection.js +175 -0
- data/app/assets/javascripts/ultimate/experimental/fuzzy-json-generator.js.coffee +48 -0
- data/app/assets/javascripts/ultimate/helpers/array.js.coffee +63 -0
- data/app/assets/javascripts/ultimate/helpers/asset_tag.js.coffee +63 -0
- data/app/assets/javascripts/ultimate/helpers/decor.js.coffee +14 -0
- data/app/assets/javascripts/ultimate/helpers/forms.js.coffee +0 -0
- data/app/assets/javascripts/ultimate/helpers/tags.js.coffee +70 -0
- data/app/assets/javascripts/ultimate/helpers.js.coffee +149 -0
- data/app/assets/javascripts/ultimate/improves/datepicker.js.coffee +34 -0
- data/app/assets/javascripts/ultimate/improves/form-errors.js.coffee +146 -0
- data/app/assets/javascripts/ultimate/improves/form.js.coffee +155 -0
- data/app/assets/javascripts/ultimate/improves/magic-radios.js.coffee +41 -0
- data/app/assets/javascripts/ultimate/improves/tablesorter.js +59 -0
- data/app/assets/javascripts/ultimate/improves/typed-field.js.coffee +98 -0
- data/app/assets/javascripts/ultimate/underscore/underscore.js +1059 -0
- data/app/assets/javascripts/ultimate/underscore/underscore.string.js +480 -0
- data/app/assets/javascripts/ultimate/widgets/dock.js.coffee +70 -0
- data/app/assets/javascripts/ultimate/widgets/gear.js.coffee +84 -0
- data/app/assets/javascripts/ultimate/widgets/jquery-ext.js.coffee +104 -0
- data/app/assets/javascripts/ultimate/widgets/jquery.adapter.js.coffee +62 -0
- data/app/assets/javascripts/ultimate/widgets/widget.js.coffee +115 -0
- data/app/assets/stylesheets/polyfills/PIE.htc +96 -0
- data/app/assets/stylesheets/polyfills/boxsizing.htc +300 -0
- data/app/assets/stylesheets/ultimate/mixins/_routines.css.scss +95 -0
- data/app/assets/stylesheets/ultimate/mixins/_vendors.css.scss +34 -0
- data/app/assets/stylesheets/ultimate/mixins/css3/_text-shadow.scss +37 -0
- data/app/assets/stylesheets/ultimate/mixins/css3.css.scss +328 -0
- data/app/assets/stylesheets/ultimate/mixins/decor.css.scss +86 -0
- data/app/assets/stylesheets/ultimate/mixins/fonts.css.scss +100 -0
- data/app/assets/stylesheets/ultimate/mixins/microstructures.css.scss +188 -0
- data/app/assets/stylesheets/ultimate/structures/slider.css.scss +53 -0
- data/lib/ultimate-base/engine.rb +6 -0
- data/lib/ultimate-base/extensions/directive_processor.rb +64 -0
- data/lib/ultimate-base/extensions/sass_script_functions.rb +39 -0
- data/lib/ultimate-base/version.rb +5 -0
- data/lib/ultimate-base.rb +10 -0
- data/ultimate-base.gemspec +25 -0
- metadata +102 -0
@@ -0,0 +1,480 @@
|
|
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));
|
@@ -0,0 +1,70 @@
|
|
1
|
+
@Ultimate =
|
2
|
+
Proto: {}
|
3
|
+
Widgets: {}
|
4
|
+
LazyWidgets: {}
|
5
|
+
Observers: {}
|
6
|
+
Plugins: {}
|
7
|
+
|
8
|
+
scopes: {}
|
9
|
+
|
10
|
+
widgetsHeap: []
|
11
|
+
|
12
|
+
initialize: ->
|
13
|
+
@scopes =
|
14
|
+
Proto : @Proto
|
15
|
+
Widgets : @Widgets
|
16
|
+
LazyWidgets : @LazyWidgets
|
17
|
+
Observers : @Observers
|
18
|
+
Plugins : @Plugins
|
19
|
+
@distributeClassNames()
|
20
|
+
|
21
|
+
# get last instance by default
|
22
|
+
getWidgetByName: (widgetClassName, instanceIndex = -1) ->
|
23
|
+
if widgetClass = @Widgets[widgetClassName] or @LazyWidgets[widgetClassName]
|
24
|
+
if _.isArray(widgetClass.instances)
|
25
|
+
instanceIndex += widgetClass.instances.length if instanceIndex < 0
|
26
|
+
widgetClass.instances[instanceIndex]
|
27
|
+
|
28
|
+
gcWidgets: ->
|
29
|
+
newHeap = []
|
30
|
+
garbage = []
|
31
|
+
for widget in @widgetsHeap
|
32
|
+
if widget.isGarbage()
|
33
|
+
instances = widget.constructor.instances
|
34
|
+
i = _.indexOf instances, widget
|
35
|
+
instances.splice i, 1 if i >= 0
|
36
|
+
garbage.push widget
|
37
|
+
else
|
38
|
+
widget.heapIndex = newHeap.push widget
|
39
|
+
@widgetsHeap = newHeap if garbage.length
|
40
|
+
garbage
|
41
|
+
|
42
|
+
isWidget: (candidate) ->
|
43
|
+
candidate instanceof @Proto.Widget
|
44
|
+
|
45
|
+
isWidgetClass: (candidate) ->
|
46
|
+
(candidate::) instanceof @Proto.Widget
|
47
|
+
|
48
|
+
# This is the best way to create an instance of the widget.
|
49
|
+
createWidget: (widgetClass, jContainer, options = {}) ->
|
50
|
+
widget = null
|
51
|
+
if widgetClass.canCreateInstance()
|
52
|
+
unless jContainer.hasWidget widgetClass
|
53
|
+
widget = new widgetClass jContainer, options
|
54
|
+
widget.heapIndex = @widgetsHeap.push widget
|
55
|
+
else
|
56
|
+
warning "Ultimate.createWidget() can't create widget on passed jContainer, because it already has widget #{widgetClass.className}"
|
57
|
+
else
|
58
|
+
warning "Ultimate.createWidget() can't create widget, because blocked by widgetClass.canCreateInstance()"
|
59
|
+
widget
|
60
|
+
|
61
|
+
distributeClassNames: (widgetClassesOrScopes = @scopes, deep = true) ->
|
62
|
+
if deep
|
63
|
+
for scopeName, scope of widgetClassesOrScopes
|
64
|
+
@distributeClassNames scope, false
|
65
|
+
else
|
66
|
+
for widgetName, widgetClass of widgetClassesOrScopes
|
67
|
+
widgetClass.className = widgetName
|
68
|
+
|
69
|
+
#
|
70
|
+
_.bindAll Ultimate
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# Ultimate base object
|
2
|
+
# * base OOP improves
|
3
|
+
# * instances controls
|
4
|
+
# * options and settings controls
|
5
|
+
# * translations
|
6
|
+
|
7
|
+
console.log 'Ultimate.Proto.Gear', Ultimate if console?
|
8
|
+
|
9
|
+
class Ultimate.Proto.Gear
|
10
|
+
|
11
|
+
@className: 'Gear'
|
12
|
+
|
13
|
+
# commented because must be uniq for independent widgets
|
14
|
+
#@instances: []
|
15
|
+
@maxInstances: Infinity # 0 for intrfaces, 1 for singleton
|
16
|
+
|
17
|
+
@canCreateInstance = ->
|
18
|
+
cout 'info', 'Gear.canCreateInstance', @name, @instances, @maxInstances
|
19
|
+
(@instances or []).length < @maxInstances
|
20
|
+
|
21
|
+
@pushInstance = (instance) ->
|
22
|
+
@instances ||= []
|
23
|
+
@instances.push instance
|
24
|
+
|
25
|
+
|
26
|
+
|
27
|
+
@defaults:
|
28
|
+
constants: {}
|
29
|
+
locales:
|
30
|
+
'en':
|
31
|
+
description: 'Base Ultimate js Class'
|
32
|
+
'ru':
|
33
|
+
description: 'Базовай Ultimate js-класс'
|
34
|
+
options:
|
35
|
+
locale: 'en'
|
36
|
+
translations: {}
|
37
|
+
|
38
|
+
settings: {}
|
39
|
+
|
40
|
+
uniqId: null
|
41
|
+
|
42
|
+
debugMode: false
|
43
|
+
|
44
|
+
constructor: (options = {}) ->
|
45
|
+
@uniqId = _.uniqueId @constructor.className
|
46
|
+
@constructor.pushInstance @
|
47
|
+
@updateSettings @constructor.defaults.options
|
48
|
+
@updateSettings @initTranslations(options)
|
49
|
+
@debug "#{@constructor.className}.constructor()", @uniqId, options
|
50
|
+
|
51
|
+
# use I18n, and modify locale and translations in options
|
52
|
+
# modify and return merged data
|
53
|
+
initTranslations: (options) ->
|
54
|
+
# if global compatible I18n
|
55
|
+
if I18n? and I18n.locale and I18n.t
|
56
|
+
options['locale'] ?= I18n.locale
|
57
|
+
if options['locale'] is I18n.locale
|
58
|
+
# pointing to defaults locales of language specified in I18n
|
59
|
+
_defaultLocales = @constructor.defaults.locales[I18n.locale]
|
60
|
+
unless _defaultLocales['loaded']
|
61
|
+
_defaultLocales['loaded'] = true
|
62
|
+
# try read localized strings
|
63
|
+
if _localesFromI18n = I18n.t options['i18nKey'] or _.underscored(@constructor.className)
|
64
|
+
# fill it from I18n
|
65
|
+
_defaultLocales[_.camelize key] = value for key, value of _localesFromI18n
|
66
|
+
options
|
67
|
+
|
68
|
+
getSettings: ->
|
69
|
+
@settings
|
70
|
+
|
71
|
+
setSettings: (settings) ->
|
72
|
+
@settings = settings
|
73
|
+
|
74
|
+
updateSettings: (options) ->
|
75
|
+
cout 'updateSettings', options
|
76
|
+
for optionsKey, optionsValue of options when optionsKey in @ then @[optionsKey] = optionsValue
|
77
|
+
translations = if (l = options['locale']) then @constructor.defaults.locales[l] or {} else {}
|
78
|
+
$.extend true, @settings, translations: translations, options
|
79
|
+
|
80
|
+
debug: ->
|
81
|
+
if @settings.debugMode
|
82
|
+
a = ["DEBUG | #{@constructor.className} >>> "]
|
83
|
+
Array::push.apply a, arguments
|
84
|
+
cout.apply @, a
|