omnom 0.0.1 → 0.0.2

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.
@@ -1,3 +1,3 @@
1
1
  module Omnom
2
- VERSION = '0.0.1'
2
+ VERSION = '0.0.2'
3
3
  end
@@ -0,0 +1,125 @@
1
+ /*!
2
+ * jQuery imagesLoaded plugin v2.1.1
3
+ * http://github.com/desandro/imagesloaded
4
+ *
5
+ * MIT License. by Paul Irish et al.
6
+ */
7
+
8
+ /*jshint curly: true, eqeqeq: true, noempty: true, strict: true, undef: true, browser: true */
9
+ /*global jQuery: false */
10
+
11
+ ;(function($, undefined) {
12
+ 'use strict';
13
+
14
+ // blank image data-uri bypasses webkit log warning (thx doug jones)
15
+ var BLANK = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==';
16
+
17
+ $.fn.imagesLoaded = function( callback ) {
18
+ var $this = this,
19
+ deferred = $.isFunction($.Deferred) ? $.Deferred() : 0,
20
+ hasNotify = $.isFunction(deferred.notify),
21
+ $images = $this.find('img').add( $this.filter('img') ),
22
+ loaded = [],
23
+ proper = [],
24
+ broken = [];
25
+
26
+ // Register deferred callbacks
27
+ if ($.isPlainObject(callback)) {
28
+ $.each(callback, function (key, value) {
29
+ if (key === 'callback') {
30
+ callback = value;
31
+ } else if (deferred) {
32
+ deferred[key](value);
33
+ }
34
+ });
35
+ }
36
+
37
+ function doneLoading() {
38
+ var $proper = $(proper),
39
+ $broken = $(broken);
40
+
41
+ if ( deferred ) {
42
+ if ( broken.length ) {
43
+ deferred.reject( $images, $proper, $broken );
44
+ } else {
45
+ deferred.resolve( $images );
46
+ }
47
+ }
48
+
49
+ if ( $.isFunction( callback ) ) {
50
+ callback.call( $this, $images, $proper, $broken );
51
+ }
52
+ }
53
+
54
+ function imgLoadedHandler( event ) {
55
+ imgLoaded( event.target, event.type === 'error' );
56
+ }
57
+
58
+ function imgLoaded( img, isBroken ) {
59
+ // don't proceed if BLANK image, or image is already loaded
60
+ if ( img.src === BLANK || $.inArray( img, loaded ) !== -1 ) {
61
+ return;
62
+ }
63
+
64
+ // store element in loaded images array
65
+ loaded.push( img );
66
+
67
+ // keep track of broken and properly loaded images
68
+ if ( isBroken ) {
69
+ broken.push( img );
70
+ } else {
71
+ proper.push( img );
72
+ }
73
+
74
+ // cache image and its state for future calls
75
+ $.data( img, 'imagesLoaded', { isBroken: isBroken, src: img.src } );
76
+
77
+ // trigger deferred progress method if present
78
+ if ( hasNotify ) {
79
+ deferred.notifyWith( $(img), [ isBroken, $images, $(proper), $(broken) ] );
80
+ }
81
+
82
+ // call doneLoading and clean listeners if all images are loaded
83
+ if ( $images.length === loaded.length ) {
84
+ setTimeout( doneLoading );
85
+ $images.unbind( '.imagesLoaded', imgLoadedHandler );
86
+ }
87
+ }
88
+
89
+ // if no images, trigger immediately
90
+ if ( !$images.length ) {
91
+ doneLoading();
92
+ } else {
93
+ $images.bind( 'load.imagesLoaded error.imagesLoaded', imgLoadedHandler )
94
+ .each( function( i, el ) {
95
+ var src = el.src;
96
+
97
+ // find out if this image has been already checked for status
98
+ // if it was, and src has not changed, call imgLoaded on it
99
+ var cached = $.data( el, 'imagesLoaded' );
100
+ if ( cached && cached.src === src ) {
101
+ imgLoaded( el, cached.isBroken );
102
+ return;
103
+ }
104
+
105
+ // if complete is true and browser supports natural sizes, try
106
+ // to check for image status manually
107
+ if ( el.complete && el.naturalWidth !== undefined ) {
108
+ imgLoaded( el, el.naturalWidth === 0 || el.naturalHeight === 0 );
109
+ return;
110
+ }
111
+
112
+ // cached images don't fire load sometimes, so we reset src, but only when
113
+ // dealing with IE, or image is complete (loaded) and failed manual check
114
+ // webkit hack from http://groups.google.com/group/jquery-dev/browse_thread/thread/eee6ab7b2da50e1f
115
+ if ( el.readyState || el.complete ) {
116
+ el.src = BLANK;
117
+ el.src = src;
118
+ }
119
+ });
120
+ }
121
+
122
+ return deferred ? deferred.promise( $this ) : $this;
123
+ };
124
+
125
+ })(jQuery);
@@ -0,0 +1,502 @@
1
+ /**
2
+ * jQuery Masonry v2.1.08
3
+ * A dynamic layout plugin for jQuery
4
+ * The flip-side of CSS Floats
5
+ * http://masonry.desandro.com
6
+ *
7
+ * Licensed under the MIT license.
8
+ * Copyright 2012 David DeSandro
9
+ */
10
+
11
+ /*jshint browser: true, curly: true, eqeqeq: true, forin: false, immed: false, newcap: true, noempty: true, strict: true, undef: true */
12
+ /*global jQuery: false */
13
+
14
+ (function( window, $, undefined ){
15
+
16
+ 'use strict';
17
+
18
+ /*
19
+ * smartresize: debounced resize event for jQuery
20
+ *
21
+ * latest version and complete README available on Github:
22
+ * https://github.com/louisremi/jquery.smartresize.js
23
+ *
24
+ * Copyright 2011 @louis_remi
25
+ * Licensed under the MIT license.
26
+ */
27
+
28
+ var $event = $.event,
29
+ resizeTimeout;
30
+
31
+ $event.special.smartresize = {
32
+ setup: function() {
33
+ $(this).bind( "resize", $event.special.smartresize.handler );
34
+ },
35
+ teardown: function() {
36
+ $(this).unbind( "resize", $event.special.smartresize.handler );
37
+ },
38
+ handler: function( event, execAsap ) {
39
+ // Save the context
40
+ var context = this,
41
+ args = arguments;
42
+
43
+ // set correct event type
44
+ event.type = "smartresize";
45
+
46
+ if ( resizeTimeout ) { clearTimeout( resizeTimeout ); }
47
+ resizeTimeout = setTimeout(function() {
48
+ $event.dispatch.apply( context, args );
49
+
50
+ }, execAsap === "execAsap"? 0 : 100 );
51
+ }
52
+ };
53
+
54
+ $.fn.smartresize = function( fn ) {
55
+ return fn ? this.bind( "smartresize", fn ) : this.trigger( "smartresize", ["execAsap"] );
56
+ };
57
+
58
+
59
+
60
+ // ========================= Masonry ===============================
61
+
62
+
63
+ // our "Widget" object constructor
64
+ $.Mason = function( options, element ){
65
+ this.element = $( element );
66
+
67
+ this._create( options );
68
+ this._init();
69
+ };
70
+
71
+ $.Mason.settings = {
72
+ isResizable: true,
73
+ isAnimated: false,
74
+ animationOptions: {
75
+ queue: false,
76
+ duration: 500
77
+ },
78
+ gutterWidth: 0,
79
+ isRTL: false,
80
+ isFitWidth: false,
81
+ containerStyle: {
82
+ position: 'relative'
83
+ }
84
+ };
85
+
86
+ $.Mason.prototype = {
87
+
88
+ _filterFindBricks: function( $elems ) {
89
+ var selector = this.options.itemSelector;
90
+ // if there is a selector
91
+ // filter/find appropriate item elements
92
+ return !selector ? $elems : $elems.filter( selector ).add( $elems.find( selector ) );
93
+ },
94
+
95
+ _getBricks: function( $elems ) {
96
+ var $bricks = this._filterFindBricks( $elems )
97
+ .css({ position: 'absolute' })
98
+ .addClass('masonry-brick');
99
+ return $bricks;
100
+ },
101
+
102
+ // sets up widget
103
+ _create : function( options ) {
104
+
105
+ this.options = $.extend( true, {}, $.Mason.settings, options );
106
+ this.styleQueue = [];
107
+
108
+ // get original styles in case we re-apply them in .destroy()
109
+ var elemStyle = this.element[0].style;
110
+ this.originalStyle = {
111
+ // get height
112
+ height: elemStyle.height || ''
113
+ };
114
+ // get other styles that will be overwritten
115
+ var containerStyle = this.options.containerStyle;
116
+ for ( var prop in containerStyle ) {
117
+ this.originalStyle[ prop ] = elemStyle[ prop ] || '';
118
+ }
119
+
120
+ this.element.css( containerStyle );
121
+
122
+ this.horizontalDirection = this.options.isRTL ? 'right' : 'left';
123
+
124
+ var x = this.element.css( 'padding-' + this.horizontalDirection );
125
+ var y = this.element.css( 'padding-top' );
126
+ this.offset = {
127
+ x: x ? parseInt( x, 10 ) : 0,
128
+ y: y ? parseInt( y, 10 ) : 0
129
+ };
130
+
131
+ this.isFluid = this.options.columnWidth && typeof this.options.columnWidth === 'function';
132
+
133
+ // add masonry class first time around
134
+ var instance = this;
135
+ setTimeout( function() {
136
+ instance.element.addClass('masonry');
137
+ }, 0 );
138
+
139
+ // bind resize method
140
+ if ( this.options.isResizable ) {
141
+ $(window).bind( 'smartresize.masonry', function() {
142
+ instance.resize();
143
+ });
144
+ }
145
+
146
+
147
+ // need to get bricks
148
+ this.reloadItems();
149
+
150
+ },
151
+
152
+ // _init fires when instance is first created
153
+ // and when instance is triggered again -> $el.masonry();
154
+ _init : function( callback ) {
155
+ this._getColumns();
156
+ this._reLayout( callback );
157
+ },
158
+
159
+ option: function( key, value ){
160
+ // set options AFTER initialization:
161
+ // signature: $('#foo').bar({ cool:false });
162
+ if ( $.isPlainObject( key ) ){
163
+ this.options = $.extend(true, this.options, key);
164
+ }
165
+ },
166
+
167
+ // ====================== General Layout ======================
168
+
169
+ // used on collection of atoms (should be filtered, and sorted before )
170
+ // accepts atoms-to-be-laid-out to start with
171
+ layout : function( $bricks, callback ) {
172
+
173
+ // place each brick
174
+ for (var i=0, len = $bricks.length; i < len; i++) {
175
+ this._placeBrick( $bricks[i] );
176
+ }
177
+
178
+ // set the size of the container
179
+ var containerSize = {};
180
+ containerSize.height = Math.max.apply( Math, this.colYs );
181
+ if ( this.options.isFitWidth ) {
182
+ var unusedCols = 0;
183
+ i = this.cols;
184
+ // count unused columns
185
+ while ( --i ) {
186
+ if ( this.colYs[i] !== 0 ) {
187
+ break;
188
+ }
189
+ unusedCols++;
190
+ }
191
+ // fit container to columns that have been used;
192
+ containerSize.width = (this.cols - unusedCols) * this.columnWidth - this.options.gutterWidth;
193
+ }
194
+ this.styleQueue.push({ $el: this.element, style: containerSize });
195
+
196
+ // are we animating the layout arrangement?
197
+ // use plugin-ish syntax for css or animate
198
+ var styleFn = !this.isLaidOut ? 'css' : (
199
+ this.options.isAnimated ? 'animate' : 'css'
200
+ ),
201
+ animOpts = this.options.animationOptions;
202
+
203
+ // process styleQueue
204
+ var obj;
205
+ for (i=0, len = this.styleQueue.length; i < len; i++) {
206
+ obj = this.styleQueue[i];
207
+ obj.$el[ styleFn ]( obj.style, animOpts );
208
+ }
209
+
210
+ // clear out queue for next time
211
+ this.styleQueue = [];
212
+
213
+ // provide $elems as context for the callback
214
+ if ( callback ) {
215
+ callback.call( $bricks );
216
+ }
217
+
218
+ this.isLaidOut = true;
219
+ },
220
+
221
+ // calculates number of columns
222
+ // i.e. this.columnWidth = 200
223
+ _getColumns : function() {
224
+ var container = this.options.isFitWidth ? this.element.parent() : this.element,
225
+ containerWidth = container.width();
226
+
227
+ // use fluid columnWidth function if there
228
+ this.columnWidth = this.isFluid ? this.options.columnWidth( containerWidth ) :
229
+ // if not, how about the explicitly set option?
230
+ this.options.columnWidth ||
231
+ // or use the size of the first item
232
+ this.$bricks.outerWidth(true) ||
233
+ // if there's no items, use size of container
234
+ containerWidth;
235
+
236
+ this.columnWidth += this.options.gutterWidth;
237
+
238
+ this.cols = Math.floor( ( containerWidth + this.options.gutterWidth ) / this.columnWidth );
239
+ this.cols = Math.max( this.cols, 1 );
240
+
241
+ },
242
+
243
+ // layout logic
244
+ _placeBrick: function( brick ) {
245
+ var $brick = $(brick),
246
+ colSpan, groupCount, groupY, groupColY, j;
247
+
248
+ //how many columns does this brick span
249
+ colSpan = Math.ceil( $brick.outerWidth(true) / this.columnWidth );
250
+ colSpan = Math.min( colSpan, this.cols );
251
+
252
+ if ( colSpan === 1 ) {
253
+ // if brick spans only one column, just like singleMode
254
+ groupY = this.colYs;
255
+ } else {
256
+ // brick spans more than one column
257
+ // how many different places could this brick fit horizontally
258
+ groupCount = this.cols + 1 - colSpan;
259
+ groupY = [];
260
+
261
+ // for each group potential horizontal position
262
+ for ( j=0; j < groupCount; j++ ) {
263
+ // make an array of colY values for that one group
264
+ groupColY = this.colYs.slice( j, j+colSpan );
265
+ // and get the max value of the array
266
+ groupY[j] = Math.max.apply( Math, groupColY );
267
+ }
268
+
269
+ }
270
+
271
+ // get the minimum Y value from the columns
272
+ var minimumY = Math.min.apply( Math, groupY ),
273
+ shortCol = 0;
274
+
275
+ // Find index of short column, the first from the left
276
+ for (var i=0, len = groupY.length; i < len; i++) {
277
+ if ( groupY[i] === minimumY ) {
278
+ shortCol = i;
279
+ break;
280
+ }
281
+ }
282
+
283
+ // position the brick
284
+ var position = {
285
+ top: minimumY + this.offset.y
286
+ };
287
+ // position.left or position.right
288
+ position[ this.horizontalDirection ] = this.columnWidth * shortCol + this.offset.x;
289
+ this.styleQueue.push({ $el: $brick, style: position });
290
+
291
+ // apply setHeight to necessary columns
292
+ var setHeight = minimumY + $brick.outerHeight(true),
293
+ setSpan = this.cols + 1 - len;
294
+ for ( i=0; i < setSpan; i++ ) {
295
+ this.colYs[ shortCol + i ] = setHeight;
296
+ }
297
+
298
+ },
299
+
300
+
301
+ resize: function() {
302
+ var prevColCount = this.cols;
303
+ // get updated colCount
304
+ this._getColumns();
305
+ if ( this.isFluid || this.cols !== prevColCount ) {
306
+ // if column count has changed, trigger new layout
307
+ this._reLayout();
308
+ }
309
+ },
310
+
311
+
312
+ _reLayout : function( callback ) {
313
+ // reset columns
314
+ var i = this.cols;
315
+ this.colYs = [];
316
+ while (i--) {
317
+ this.colYs.push( 0 );
318
+ }
319
+ // apply layout logic to all bricks
320
+ this.layout( this.$bricks, callback );
321
+ },
322
+
323
+ // ====================== Convenience methods ======================
324
+
325
+ // goes through all children again and gets bricks in proper order
326
+ reloadItems : function() {
327
+ this.$bricks = this._getBricks( this.element.children() );
328
+ },
329
+
330
+
331
+ reload : function( callback ) {
332
+ this.reloadItems();
333
+ this._init( callback );
334
+ },
335
+
336
+
337
+ // convienence method for working with Infinite Scroll
338
+ appended : function( $content, isAnimatedFromBottom, callback ) {
339
+ if ( isAnimatedFromBottom ) {
340
+ // set new stuff to the bottom
341
+ this._filterFindBricks( $content ).css({ top: this.element.height() });
342
+ var instance = this;
343
+ setTimeout( function(){
344
+ instance._appended( $content, callback );
345
+ }, 1 );
346
+ } else {
347
+ this._appended( $content, callback );
348
+ }
349
+ },
350
+
351
+ _appended : function( $content, callback ) {
352
+ var $newBricks = this._getBricks( $content );
353
+ // add new bricks to brick pool
354
+ this.$bricks = this.$bricks.add( $newBricks );
355
+ this.layout( $newBricks, callback );
356
+ },
357
+
358
+ // removes elements from Masonry widget
359
+ remove : function( $content ) {
360
+ this.$bricks = this.$bricks.not( $content );
361
+ $content.remove();
362
+ },
363
+
364
+ // destroys widget, returns elements and container back (close) to original style
365
+ destroy : function() {
366
+
367
+ this.$bricks
368
+ .removeClass('masonry-brick')
369
+ .each(function(){
370
+ this.style.position = '';
371
+ this.style.top = '';
372
+ this.style.left = '';
373
+ });
374
+
375
+ // re-apply saved container styles
376
+ var elemStyle = this.element[0].style;
377
+ for ( var prop in this.originalStyle ) {
378
+ elemStyle[ prop ] = this.originalStyle[ prop ];
379
+ }
380
+
381
+ this.element
382
+ .unbind('.masonry')
383
+ .removeClass('masonry')
384
+ .removeData('masonry');
385
+
386
+ $(window).unbind('.masonry');
387
+
388
+ }
389
+
390
+ };
391
+
392
+
393
+ // ======================= imagesLoaded Plugin ===============================
394
+ /*!
395
+ * jQuery imagesLoaded plugin v1.1.0
396
+ * http://github.com/desandro/imagesloaded
397
+ *
398
+ * MIT License. by Paul Irish et al.
399
+ */
400
+
401
+
402
+ // $('#my-container').imagesLoaded(myFunction)
403
+ // or
404
+ // $('img').imagesLoaded(myFunction)
405
+
406
+ // execute a callback when all images have loaded.
407
+ // needed because .load() doesn't work on cached images
408
+
409
+ // callback function gets image collection as argument
410
+ // `this` is the container
411
+
412
+ $.fn.imagesLoaded = function( callback ) {
413
+ var $this = this,
414
+ $images = $this.find('img').add( $this.filter('img') ),
415
+ len = $images.length,
416
+ blank = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==',
417
+ loaded = [];
418
+
419
+ function triggerCallback() {
420
+ callback.call( $this, $images );
421
+ }
422
+
423
+ function imgLoaded( event ) {
424
+ var img = event.target;
425
+ if ( img.src !== blank && $.inArray( img, loaded ) === -1 ){
426
+ loaded.push( img );
427
+ if ( --len <= 0 ){
428
+ setTimeout( triggerCallback );
429
+ $images.unbind( '.imagesLoaded', imgLoaded );
430
+ }
431
+ }
432
+ }
433
+
434
+ // if no images, trigger immediately
435
+ if ( !len ) {
436
+ triggerCallback();
437
+ }
438
+
439
+ $images.bind( 'load.imagesLoaded error.imagesLoaded', imgLoaded ).each( function() {
440
+ // cached images don't fire load sometimes, so we reset src.
441
+ var src = this.src;
442
+ // webkit hack from http://groups.google.com/group/jquery-dev/browse_thread/thread/eee6ab7b2da50e1f
443
+ // data uri bypasses webkit log warning (thx doug jones)
444
+ this.src = blank;
445
+ this.src = src;
446
+ });
447
+
448
+ return $this;
449
+ };
450
+
451
+
452
+ // helper function for logging errors
453
+ // $.error breaks jQuery chaining
454
+ var logError = function( message ) {
455
+ if ( window.console ) {
456
+ window.console.error( message );
457
+ }
458
+ };
459
+
460
+ // ======================= Plugin bridge ===============================
461
+ // leverages data method to either create or return $.Mason constructor
462
+ // A bit from jQuery UI
463
+ // https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.widget.js
464
+ // A bit from jcarousel
465
+ // https://github.com/jsor/jcarousel/blob/master/lib/jquery.jcarousel.js
466
+
467
+ $.fn.masonry = function( options ) {
468
+ if ( typeof options === 'string' ) {
469
+ // call method
470
+ var args = Array.prototype.slice.call( arguments, 1 );
471
+
472
+ this.each(function(){
473
+ var instance = $.data( this, 'masonry' );
474
+ if ( !instance ) {
475
+ logError( "cannot call methods on masonry prior to initialization; " +
476
+ "attempted to call method '" + options + "'" );
477
+ return;
478
+ }
479
+ if ( !$.isFunction( instance[options] ) || options.charAt(0) === "_" ) {
480
+ logError( "no such method '" + options + "' for masonry instance" );
481
+ return;
482
+ }
483
+ // apply method
484
+ instance[ options ].apply( instance, args );
485
+ });
486
+ } else {
487
+ this.each(function() {
488
+ var instance = $.data( this, 'masonry' );
489
+ if ( instance ) {
490
+ // apply options & init
491
+ instance.option( options || {} );
492
+ instance._init();
493
+ } else {
494
+ // initialize new instance
495
+ $.data( this, 'masonry', new $.Mason( options, this ) );
496
+ }
497
+ });
498
+ }
499
+ return this;
500
+ };
501
+
502
+ })( window, jQuery );
@@ -0,0 +1,20 @@
1
+ // English shortened
2
+ jQuery.timeago.settings.strings = {
3
+ prefixAgo: null,
4
+ prefixFromNow: null,
5
+ suffixAgo: "",
6
+ suffixFromNow: "",
7
+ seconds: "1m",
8
+ minute: "1m",
9
+ minutes: "%dm",
10
+ hour: "1h",
11
+ hours: "%dh",
12
+ day: "1d",
13
+ days: "%dd",
14
+ month: "1mo",
15
+ months: "%dmo",
16
+ year: "1yr",
17
+ years: "%dyr",
18
+ wordSeparator: " ",
19
+ numbers: []
20
+ };
@@ -0,0 +1,184 @@
1
+ /**
2
+ * Timeago is a jQuery plugin that makes it easy to support automatically
3
+ * updating fuzzy timestamps (e.g. "4 minutes ago" or "about 1 day ago").
4
+ *
5
+ * @name timeago
6
+ * @version 1.1.0
7
+ * @requires jQuery v1.2.3+
8
+ * @author Ryan McGeary
9
+ * @license MIT License - http://www.opensource.org/licenses/mit-license.php
10
+ *
11
+ * For usage and examples, visit:
12
+ * http://timeago.yarp.com/
13
+ *
14
+ * Copyright (c) 2008-2013, Ryan McGeary (ryan -[at]- mcgeary [*dot*] org)
15
+ */
16
+
17
+ (function (factory) {
18
+ if (typeof define === 'function' && define.amd) {
19
+ // AMD. Register as an anonymous module.
20
+ define(['jquery'], factory);
21
+ } else {
22
+ // Browser globals
23
+ factory(jQuery);
24
+ }
25
+ }(function ($) {
26
+ $.timeago = function(timestamp) {
27
+ if (timestamp instanceof Date) {
28
+ return inWords(timestamp);
29
+ } else if (typeof timestamp === "string") {
30
+ return inWords($.timeago.parse(timestamp));
31
+ } else if (typeof timestamp === "number") {
32
+ return inWords(new Date(timestamp));
33
+ } else {
34
+ return inWords($.timeago.datetime(timestamp));
35
+ }
36
+ };
37
+ var $t = $.timeago;
38
+
39
+ $.extend($.timeago, {
40
+ settings: {
41
+ refreshMillis: 60000,
42
+ allowFuture: false,
43
+ localeTitle: false,
44
+ strings: {
45
+ prefixAgo: null,
46
+ prefixFromNow: null,
47
+ suffixAgo: "ago",
48
+ suffixFromNow: "from now",
49
+ seconds: "less than a minute",
50
+ minute: "about a minute",
51
+ minutes: "%d minutes",
52
+ hour: "about an hour",
53
+ hours: "about %d hours",
54
+ day: "a day",
55
+ days: "%d days",
56
+ month: "about a month",
57
+ months: "%d months",
58
+ year: "about a year",
59
+ years: "%d years",
60
+ wordSeparator: " ",
61
+ numbers: []
62
+ }
63
+ },
64
+ inWords: function(distanceMillis) {
65
+ var $l = this.settings.strings;
66
+ var prefix = $l.prefixAgo;
67
+ var suffix = $l.suffixAgo;
68
+ if (this.settings.allowFuture) {
69
+ if (distanceMillis < 0) {
70
+ prefix = $l.prefixFromNow;
71
+ suffix = $l.suffixFromNow;
72
+ }
73
+ }
74
+
75
+ var seconds = Math.abs(distanceMillis) / 1000;
76
+ var minutes = seconds / 60;
77
+ var hours = minutes / 60;
78
+ var days = hours / 24;
79
+ var years = days / 365;
80
+
81
+ function substitute(stringOrFunction, number) {
82
+ var string = $.isFunction(stringOrFunction) ? stringOrFunction(number, distanceMillis) : stringOrFunction;
83
+ var value = ($l.numbers && $l.numbers[number]) || number;
84
+ return string.replace(/%d/i, value);
85
+ }
86
+
87
+ var words = seconds < 45 && substitute($l.seconds, Math.round(seconds)) ||
88
+ seconds < 90 && substitute($l.minute, 1) ||
89
+ minutes < 45 && substitute($l.minutes, Math.round(minutes)) ||
90
+ minutes < 90 && substitute($l.hour, 1) ||
91
+ hours < 24 && substitute($l.hours, Math.round(hours)) ||
92
+ hours < 42 && substitute($l.day, 1) ||
93
+ days < 30 && substitute($l.days, Math.round(days)) ||
94
+ days < 45 && substitute($l.month, 1) ||
95
+ days < 365 && substitute($l.months, Math.round(days / 30)) ||
96
+ years < 1.5 && substitute($l.year, 1) ||
97
+ substitute($l.years, Math.round(years));
98
+
99
+ var separator = $l.wordSeparator || "";
100
+ if ($l.wordSeparator === undefined) { separator = " "; }
101
+ return $.trim([prefix, words, suffix].join(separator));
102
+ },
103
+ parse: function(iso8601) {
104
+ var s = $.trim(iso8601);
105
+ s = s.replace(/\.\d+/,""); // remove milliseconds
106
+ s = s.replace(/-/,"/").replace(/-/,"/");
107
+ s = s.replace(/T/," ").replace(/Z/," UTC");
108
+ s = s.replace(/([\+\-]\d\d)\:?(\d\d)/," $1$2"); // -04:00 -> -0400
109
+ return new Date(s);
110
+ },
111
+ datetime: function(elem) {
112
+ var iso8601 = $t.isTime(elem) ? $(elem).attr("datetime") : $(elem).attr("title");
113
+ return $t.parse(iso8601);
114
+ },
115
+ isTime: function(elem) {
116
+ // jQuery's `is()` doesn't play well with HTML5 in IE
117
+ return $(elem).get(0).tagName.toLowerCase() === "time"; // $(elem).is("time");
118
+ }
119
+ });
120
+
121
+ // functions that can be called via $(el).timeago('action')
122
+ // init is default when no action is given
123
+ // functions are called with context of a single element
124
+ var functions = {
125
+ init: function(){
126
+ var refresh_el = $.proxy(refresh, this);
127
+ refresh_el();
128
+ var $s = $t.settings;
129
+ if ($s.refreshMillis > 0) {
130
+ setInterval(refresh_el, $s.refreshMillis);
131
+ }
132
+ },
133
+ update: function(time){
134
+ $(this).data('timeago', { datetime: $t.parse(time) });
135
+ refresh.apply(this);
136
+ }
137
+ };
138
+
139
+ $.fn.timeago = function(action, options) {
140
+ var fn = action ? functions[action] : functions.init;
141
+ if(!fn){
142
+ throw new Error("Unknown function name '"+ action +"' for timeago");
143
+ }
144
+ // each over objects here and call the requested function
145
+ this.each(function(){
146
+ fn.call(this, options);
147
+ });
148
+ return this;
149
+ };
150
+
151
+ function refresh() {
152
+ var data = prepareData(this);
153
+ if (!isNaN(data.datetime)) {
154
+ $(this).text(inWords(data.datetime));
155
+ }
156
+ return this;
157
+ }
158
+
159
+ function prepareData(element) {
160
+ element = $(element);
161
+ if (!element.data("timeago")) {
162
+ element.data("timeago", { datetime: $t.datetime(element) });
163
+ var text = $.trim(element.text());
164
+ if ($t.settings.localeTitle) {
165
+ element.attr("title", element.data('timeago').datetime.toLocaleString());
166
+ } else if (text.length > 0 && !($t.isTime(element) && element.attr("title"))) {
167
+ element.attr("title", text);
168
+ }
169
+ }
170
+ return element.data("timeago");
171
+ }
172
+
173
+ function inWords(date) {
174
+ return $t.inWords(distance(date));
175
+ }
176
+
177
+ function distance(date) {
178
+ return (new Date().getTime() - date.getTime());
179
+ }
180
+
181
+ // fix for IE6 suckage
182
+ document.createElement("abbr");
183
+ document.createElement("time");
184
+ }));
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: omnom
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -445,6 +445,10 @@ files:
445
445
  - lib/omnom.rb
446
446
  - lib/tasks/omnom/heroku.rake
447
447
  - lib/tasks/omnom.rake
448
+ - vendor/assets/javascripts/omnom/jquery.imagesloaded.js
449
+ - vendor/assets/javascripts/omnom/jquery.masonry.js
450
+ - vendor/assets/javascripts/omnom/jquery.timeago.en.js
451
+ - vendor/assets/javascripts/omnom/jquery.timeago.js
448
452
  - MIT-LICENSE
449
453
  - Rakefile
450
454
  - README.md