omnom 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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