kube_for_rails 0.1.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.
@@ -0,0 +1,2201 @@
1
+ /*
2
+ Kube. CSS & JS Framework
3
+ Version 6.5.2
4
+ Updated: February 2, 2017
5
+
6
+ http://imperavi.com/kube/
7
+
8
+ Copyright (c) 2009-2017, Imperavi LLC.
9
+ License: MIT
10
+ */
11
+ if (typeof jQuery === 'undefined') {throw new Error('Kube\'s requires jQuery')};
12
+ ;(function($) { var version = $.fn.jquery.split('.'); if (version[0] == 1 && version[1] < 8) {throw new Error('Kube\'s requires at least jQuery v1.8'); }})(jQuery);
13
+
14
+ ;(function()
15
+ {
16
+ // Inherits
17
+ Function.prototype.inherits = function(parent)
18
+ {
19
+ var F = function () {};
20
+ F.prototype = parent.prototype;
21
+ var f = new F();
22
+
23
+ for (var prop in this.prototype) f[prop] = this.prototype[prop];
24
+ this.prototype = f;
25
+ this.prototype.super = parent.prototype;
26
+ };
27
+
28
+ // Core Class
29
+ var Kube = function(element, options)
30
+ {
31
+ options = (typeof options === 'object') ? options : {};
32
+
33
+ this.$element = $(element);
34
+ this.opts = $.extend(true, this.defaults, $.fn[this.namespace].options, this.$element.data(), options);
35
+ this.$target = (typeof this.opts.target === 'string') ? $(this.opts.target) : null;
36
+ };
37
+
38
+ // Core Functionality
39
+ Kube.prototype = {
40
+ getInstance: function()
41
+ {
42
+ return this.$element.data('fn.' + this.namespace);
43
+ },
44
+ hasTarget: function()
45
+ {
46
+ return !(this.$target === null);
47
+ },
48
+ callback: function(type)
49
+ {
50
+ var args = [].slice.call(arguments).splice(1);
51
+
52
+ // on element callback
53
+ if (this.$element)
54
+ {
55
+ args = this._fireCallback($._data(this.$element[0], 'events'), type, this.namespace, args);
56
+ }
57
+
58
+ // on target callback
59
+ if (this.$target)
60
+ {
61
+ args = this._fireCallback($._data(this.$target[0], 'events'), type, this.namespace, args);
62
+ }
63
+
64
+ // opts callback
65
+ if (this.opts && this.opts.callbacks && $.isFunction(this.opts.callbacks[type]))
66
+ {
67
+ return this.opts.callbacks[type].apply(this, args);
68
+ }
69
+
70
+ return args;
71
+ },
72
+ _fireCallback: function(events, type, eventNamespace, args)
73
+ {
74
+ if (events && typeof events[type] !== 'undefined')
75
+ {
76
+ var len = events[type].length;
77
+ for (var i = 0; i < len; i++)
78
+ {
79
+ var namespace = events[type][i].namespace;
80
+ if (namespace === eventNamespace)
81
+ {
82
+ var value = events[type][i].handler.apply(this, args);
83
+ }
84
+ }
85
+ }
86
+
87
+ return (typeof value === 'undefined') ? args : value;
88
+ }
89
+ };
90
+
91
+ // Scope
92
+ window.Kube = Kube;
93
+
94
+ })();
95
+ /**
96
+ * @library Kube Plugin
97
+ * @author Imperavi LLC
98
+ * @license MIT
99
+ */
100
+ (function(Kube)
101
+ {
102
+ Kube.Plugin = {
103
+ create: function(classname, pluginname)
104
+ {
105
+ pluginname = (typeof pluginname === 'undefined') ? classname.toLowerCase() : pluginname;
106
+
107
+ $.fn[pluginname] = function(method, options)
108
+ {
109
+ var args = Array.prototype.slice.call(arguments, 1);
110
+ var name = 'fn.' + pluginname;
111
+ var val = [];
112
+
113
+ this.each(function()
114
+ {
115
+ var $this = $(this), data = $this.data(name);
116
+ options = (typeof method === 'object') ? method : options;
117
+
118
+ if (!data)
119
+ {
120
+ // Initialization
121
+ $this.data(name, {});
122
+ $this.data(name, (data = new Kube[classname](this, options)));
123
+ }
124
+
125
+ // Call methods
126
+ if (typeof method === 'string')
127
+ {
128
+ if ($.isFunction(data[method]))
129
+ {
130
+ var methodVal = data[method].apply(data, args);
131
+ if (methodVal !== undefined)
132
+ {
133
+ val.push(methodVal);
134
+ }
135
+ }
136
+ else
137
+ {
138
+ $.error('No such method "' + method + '" for ' + classname);
139
+ }
140
+ }
141
+
142
+ });
143
+
144
+ return (val.length === 0 || val.length === 1) ? ((val.length === 0) ? this : val[0]) : val;
145
+ };
146
+
147
+ $.fn[pluginname].options = {};
148
+
149
+ return this;
150
+ },
151
+ autoload: function(pluginname)
152
+ {
153
+ var arr = pluginname.split(',');
154
+ var len = arr.length;
155
+
156
+ for (var i = 0; i < len; i++)
157
+ {
158
+ var name = arr[i].toLowerCase().split(',').map(function(s) { return s.trim() }).join(',');
159
+ this.autoloadQueue.push(name);
160
+ }
161
+
162
+ return this;
163
+ },
164
+ autoloadQueue: [],
165
+ startAutoload: function()
166
+ {
167
+ if (!window.MutationObserver || this.autoloadQueue.length === 0)
168
+ {
169
+ return;
170
+ }
171
+
172
+ var self = this;
173
+ var observer = new MutationObserver(function(mutations)
174
+ {
175
+ mutations.forEach(function(mutation)
176
+ {
177
+ var newNodes = mutation.addedNodes;
178
+ if (newNodes.length === 0 || (newNodes.length === 1 && newNodes.nodeType === 3))
179
+ {
180
+ return;
181
+ }
182
+
183
+ self.startAutoloadOnce();
184
+ });
185
+ });
186
+
187
+ // pass in the target node, as well as the observer options
188
+ observer.observe(document, {
189
+ subtree: true,
190
+ childList: true
191
+ });
192
+ },
193
+ startAutoloadOnce: function()
194
+ {
195
+ var self = this;
196
+ var $nodes = $('[data-component]').not('[data-loaded]');
197
+ $nodes.each(function()
198
+ {
199
+ var $el = $(this);
200
+ var pluginname = $el.data('component');
201
+
202
+ if (self.autoloadQueue.indexOf(pluginname) !== -1)
203
+ {
204
+ $el.attr('data-loaded', true);
205
+ $el[pluginname]();
206
+ }
207
+ });
208
+
209
+ },
210
+ watch: function()
211
+ {
212
+ Kube.Plugin.startAutoloadOnce();
213
+ Kube.Plugin.startAutoload();
214
+ }
215
+ };
216
+
217
+ $(window).on('load', function()
218
+ {
219
+ Kube.Plugin.watch();
220
+ });
221
+
222
+ }(Kube));
223
+ /**
224
+ * @library Kube Animation
225
+ * @author Imperavi LLC
226
+ * @license MIT
227
+ */
228
+ (function(Kube)
229
+ {
230
+ Kube.Animation = function(element, effect, callback)
231
+ {
232
+ this.namespace = 'animation';
233
+ this.defaults = {};
234
+
235
+ // Parent Constructor
236
+ Kube.apply(this, arguments);
237
+
238
+ // Initialization
239
+ this.effect = effect;
240
+ this.completeCallback = (typeof callback === 'undefined') ? false : callback;
241
+ this.prefixes = ['', '-moz-', '-o-animation-', '-webkit-'];
242
+ this.queue = [];
243
+
244
+ this.start();
245
+ };
246
+
247
+ Kube.Animation.prototype = {
248
+ start: function()
249
+ {
250
+ if (this.isSlideEffect()) this.setElementHeight();
251
+
252
+ this.addToQueue();
253
+ this.clean();
254
+ this.animate();
255
+ },
256
+ addToQueue: function()
257
+ {
258
+ this.queue.push(this.effect);
259
+ },
260
+ setElementHeight: function()
261
+ {
262
+ this.$element.height(this.$element.height());
263
+ },
264
+ removeElementHeight: function()
265
+ {
266
+ this.$element.css('height', '');
267
+ },
268
+ isSlideEffect: function()
269
+ {
270
+ return (this.effect === 'slideDown' || this.effect === 'slideUp');
271
+ },
272
+ isHideableEffect: function()
273
+ {
274
+ var effects = ['fadeOut', 'slideUp', 'flipOut', 'zoomOut', 'slideOutUp', 'slideOutRight', 'slideOutLeft'];
275
+
276
+ return ($.inArray(this.effect, effects) !== -1);
277
+ },
278
+ isToggleEffect: function()
279
+ {
280
+ return (this.effect === 'show' || this.effect === 'hide');
281
+ },
282
+ storeHideClasses: function()
283
+ {
284
+ if (this.$element.hasClass('hide-sm')) this.$element.data('hide-sm-class', true);
285
+ else if (this.$element.hasClass('hide-md')) this.$element.data('hide-md-class', true);
286
+ },
287
+ revertHideClasses: function()
288
+ {
289
+ if (this.$element.data('hide-sm-class')) this.$element.addClass('hide-sm').removeData('hide-sm-class');
290
+ else if (this.$element.data('hide-md-class')) this.$element.addClass('hide-md').removeData('hide-md-class');
291
+ else this.$element.addClass('hide');
292
+ },
293
+ removeHideClass: function()
294
+ {
295
+ if (this.$element.data('hide-sm-class')) this.$element.removeClass('hide-sm');
296
+ else if (this.$element.data('hide-md-class')) this.$element.removeClass('hide-md');
297
+ else this.$element.removeClass('hide');
298
+ },
299
+ animate: function()
300
+ {
301
+ this.storeHideClasses();
302
+ if (this.isToggleEffect())
303
+ {
304
+ return this.makeSimpleEffects();
305
+ }
306
+
307
+ this.$element.addClass('kubeanimated');
308
+ this.$element.addClass(this.queue[0]);
309
+ this.removeHideClass();
310
+
311
+ var _callback = (this.queue.length > 1) ? null : this.completeCallback;
312
+ this.complete('AnimationEnd', $.proxy(this.makeComplete, this), _callback);
313
+ },
314
+ makeSimpleEffects: function()
315
+ {
316
+ if (this.effect === 'show') this.removeHideClass();
317
+ else if (this.effect === 'hide') this.revertHideClasses();
318
+
319
+ if (typeof this.completeCallback === 'function') this.completeCallback(this);
320
+ },
321
+ makeComplete: function()
322
+ {
323
+ if (this.$element.hasClass(this.queue[0]))
324
+ {
325
+ this.clean();
326
+ this.queue.shift();
327
+
328
+ if (this.queue.length) this.animate();
329
+ }
330
+ },
331
+ complete: function(type, make, callback)
332
+ {
333
+ var event = type.toLowerCase() + ' webkit' + type + ' o' + type + ' MS' + type;
334
+
335
+ this.$element.one(event, $.proxy(function()
336
+ {
337
+ if (typeof make === 'function') make();
338
+ if (this.isHideableEffect()) this.revertHideClasses();
339
+ if (this.isSlideEffect()) this.removeElementHeight();
340
+ if (typeof callback === 'function') callback(this);
341
+
342
+ this.$element.off(event);
343
+
344
+ }, this));
345
+ },
346
+ clean: function()
347
+ {
348
+ this.$element.removeClass('kubeanimated').removeClass(this.queue[0]);
349
+ }
350
+ };
351
+
352
+ // Inheritance
353
+ Kube.Animation.inherits(Kube);
354
+
355
+ }(Kube));
356
+
357
+ // Plugin
358
+ (function($)
359
+ {
360
+ $.fn.animation = function(effect, callback)
361
+ {
362
+ var name = 'fn.animation';
363
+
364
+ return this.each(function()
365
+ {
366
+ var $this = $(this), data = $this.data(name);
367
+
368
+ $this.data(name, {});
369
+ $this.data(name, (data = new Kube.Animation(this, effect, callback)));
370
+ });
371
+ };
372
+
373
+ $.fn.animation.options = {};
374
+
375
+ })(jQuery);
376
+ /**
377
+ * @library Kube Detect
378
+ * @author Imperavi LLC
379
+ * @license MIT
380
+ */
381
+ (function(Kube)
382
+ {
383
+ Kube.Detect = function() {};
384
+
385
+ Kube.Detect.prototype = {
386
+ isMobile: function()
387
+ {
388
+ return /(iPhone|iPod|BlackBerry|Android)/.test(navigator.userAgent);
389
+ },
390
+ isDesktop: function()
391
+ {
392
+ return !/(iPhone|iPod|iPad|BlackBerry|Android)/.test(navigator.userAgent);
393
+ },
394
+ isMobileScreen: function()
395
+ {
396
+ return ($(window).width() <= 768);
397
+ },
398
+ isTabletScreen: function()
399
+ {
400
+ return ($(window).width() >= 768 && $(window).width() <= 1024);
401
+ },
402
+ isDesktopScreen: function()
403
+ {
404
+ return ($(window).width() > 1024);
405
+ }
406
+ };
407
+
408
+
409
+ }(Kube));
410
+ /**
411
+ * @library Kube FormData
412
+ * @author Imperavi LLC
413
+ * @license MIT
414
+ */
415
+ (function(Kube)
416
+ {
417
+ Kube.FormData = function(app)
418
+ {
419
+ this.opts = app.opts;
420
+ };
421
+
422
+ Kube.FormData.prototype = {
423
+ set: function(data)
424
+ {
425
+ this.data = data;
426
+ },
427
+ get: function(formdata)
428
+ {
429
+ this.formdata = formdata;
430
+
431
+ if (this.opts.appendForms) this.appendForms();
432
+ if (this.opts.appendFields) this.appendFields();
433
+
434
+ return this.data;
435
+ },
436
+ appendFields: function()
437
+ {
438
+ var $fields = $(this.opts.appendFields);
439
+ if ($fields.length === 0)
440
+ {
441
+ return;
442
+ }
443
+
444
+ var self = this;
445
+ var str = '';
446
+
447
+ if (this.formdata)
448
+ {
449
+ $fields.each(function()
450
+ {
451
+ self.data.append($(this).attr('name'), $(this).val());
452
+ });
453
+ }
454
+ else
455
+ {
456
+ $fields.each(function()
457
+ {
458
+ str += '&' + $(this).attr('name') + '=' + $(this).val();
459
+ });
460
+
461
+ this.data = (this.data === '') ? str.replace(/^&/, '') : this.data + str;
462
+ }
463
+ },
464
+ appendForms: function()
465
+ {
466
+ var $forms = $(this.opts.appendForms);
467
+ if ($forms.length === 0)
468
+ {
469
+ return;
470
+ }
471
+
472
+ if (this.formdata)
473
+ {
474
+ var self = this;
475
+ var formsData = $(this.opts.appendForms).serializeArray();
476
+ $.each(formsData, function(i,s)
477
+ {
478
+ self.data.append(s.name, s.value);
479
+ });
480
+ }
481
+ else
482
+ {
483
+ var str = $forms.serialize();
484
+
485
+ this.data = (this.data === '') ? str : this.data + '&' + str;
486
+ }
487
+ }
488
+ };
489
+
490
+
491
+ }(Kube));
492
+ /**
493
+ * @library Kube Response
494
+ * @author Imperavi LLC
495
+ * @license MIT
496
+ */
497
+ (function(Kube)
498
+ {
499
+ Kube.Response = function(app) {};
500
+
501
+ Kube.Response.prototype = {
502
+ parse: function(str)
503
+ {
504
+ if (str === '') return false;
505
+
506
+ var obj = {};
507
+
508
+ try {
509
+ obj = JSON.parse(str);
510
+ } catch (e) {
511
+ return false;
512
+ }
513
+
514
+ if (obj[0] !== undefined)
515
+ {
516
+ for (var item in obj)
517
+ {
518
+ this.parseItem(obj[item]);
519
+ }
520
+ }
521
+ else
522
+ {
523
+ this.parseItem(obj);
524
+ }
525
+
526
+ return obj;
527
+ },
528
+ parseItem: function(item)
529
+ {
530
+ if (item.type === 'value')
531
+ {
532
+ $.each(item.data, $.proxy(function(key, val)
533
+ {
534
+ val = (val === null || val === false) ? 0 : val;
535
+ val = (val === true) ? 1 : val;
536
+
537
+ $(key).val(val);
538
+
539
+ }, this));
540
+ }
541
+ else if (item.type === 'html')
542
+ {
543
+ $.each(item.data, $.proxy(function(key, val)
544
+ {
545
+ val = (val === null || val === false) ? '' : val;
546
+
547
+ $(key).html(this.stripslashes(val));
548
+
549
+ }, this));
550
+ }
551
+ else if (item.type === 'addClass')
552
+ {
553
+ $.each(item.data, function(key, val)
554
+ {
555
+ $(key).addClass(val);
556
+ });
557
+ }
558
+ else if (item.type === 'removeClass')
559
+ {
560
+ $.each(item.data, function(key, val)
561
+ {
562
+ $(key).removeClass(val);
563
+ });
564
+ }
565
+ else if (item.type === 'command')
566
+ {
567
+ $.each(item.data, function(key, val)
568
+ {
569
+ $(val)[key]();
570
+ });
571
+ }
572
+ else if (item.type === 'animation')
573
+ {
574
+ $.each(item.data, function(key, data)
575
+ {
576
+ data.opts = (typeof data.opts === 'undefined') ? {} : data.opts;
577
+
578
+ $(key).animation(data.name, data.opts);
579
+ });
580
+ }
581
+ else if (item.type === 'location')
582
+ {
583
+ top.location.href = item.data;
584
+ }
585
+ else if (item.type === 'notify')
586
+ {
587
+ $.notify(item.data);
588
+ }
589
+
590
+ return item;
591
+ },
592
+ stripslashes: function(str)
593
+ {
594
+ return (str+'').replace(/\0/g, '0').replace(/\\([\\'"])/g, '$1');
595
+ }
596
+ };
597
+
598
+
599
+ }(Kube));
600
+ /**
601
+ * @library Kube Utils
602
+ * @author Imperavi LLC
603
+ * @license MIT
604
+ */
605
+ (function(Kube)
606
+ {
607
+ Kube.Utils = function() {};
608
+
609
+ Kube.Utils.prototype = {
610
+ disableBodyScroll: function()
611
+ {
612
+ var $body = $('html');
613
+ var windowWidth = window.innerWidth;
614
+
615
+ if (!windowWidth)
616
+ {
617
+ var documentElementRect = document.documentElement.getBoundingClientRect();
618
+ windowWidth = documentElementRect.right - Math.abs(documentElementRect.left);
619
+ }
620
+
621
+ var isOverflowing = document.body.clientWidth < windowWidth;
622
+ var scrollbarWidth = this.measureScrollbar();
623
+
624
+ $body.css('overflow', 'hidden');
625
+ if (isOverflowing) $body.css('padding-right', scrollbarWidth);
626
+ },
627
+ measureScrollbar: function()
628
+ {
629
+ var $body = $('body');
630
+ var scrollDiv = document.createElement('div');
631
+ scrollDiv.className = 'scrollbar-measure';
632
+
633
+ $body.append(scrollDiv);
634
+ var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth;
635
+ $body[0].removeChild(scrollDiv);
636
+ return scrollbarWidth;
637
+ },
638
+ enableBodyScroll: function()
639
+ {
640
+ $('html').css({ 'overflow': '', 'padding-right': '' });
641
+ }
642
+ };
643
+
644
+
645
+ }(Kube));
646
+ /**
647
+ * @library Kube Message
648
+ * @author Imperavi LLC
649
+ * @license MIT
650
+ */
651
+ (function(Kube)
652
+ {
653
+ Kube.Message = function(element, options)
654
+ {
655
+ this.namespace = 'message';
656
+ this.defaults = {
657
+ closeSelector: '.close',
658
+ closeEvent: 'click',
659
+ animationOpen: 'fadeIn',
660
+ animationClose: 'fadeOut',
661
+ callbacks: ['open', 'opened', 'close', 'closed']
662
+ };
663
+
664
+ // Parent Constructor
665
+ Kube.apply(this, arguments);
666
+
667
+ // Initialization
668
+ this.start();
669
+ };
670
+
671
+ // Functionality
672
+ Kube.Message.prototype = {
673
+ start: function()
674
+ {
675
+ this.$close = this.$element.find(this.opts.closeSelector);
676
+ this.$close.on(this.opts.closeEvent + '.' + this.namespace, $.proxy(this.close, this));
677
+ this.$element.addClass('open');
678
+ },
679
+ stop: function()
680
+ {
681
+ this.$close.off('.' + this.namespace);
682
+ this.$element.removeClass('open');
683
+ },
684
+ open: function(e)
685
+ {
686
+ if (e) e.preventDefault();
687
+
688
+ if (!this.isOpened())
689
+ {
690
+ this.callback('open');
691
+ this.$element.animation(this.opts.animationOpen, $.proxy(this.onOpened, this));
692
+ }
693
+ },
694
+ isOpened: function()
695
+ {
696
+ return this.$element.hasClass('open');
697
+ },
698
+ onOpened: function()
699
+ {
700
+ this.callback('opened');
701
+ this.$element.addClass('open');
702
+ },
703
+ close: function(e)
704
+ {
705
+ if (e) e.preventDefault();
706
+
707
+ if (this.isOpened())
708
+ {
709
+ this.callback('close');
710
+ this.$element.animation(this.opts.animationClose, $.proxy(this.onClosed, this));
711
+ }
712
+ },
713
+ onClosed: function()
714
+ {
715
+ this.callback('closed');
716
+ this.$element.removeClass('open');
717
+ }
718
+ };
719
+
720
+ // Inheritance
721
+ Kube.Message.inherits(Kube);
722
+
723
+ // Plugin
724
+ Kube.Plugin.create('Message');
725
+ Kube.Plugin.autoload('Message');
726
+
727
+ }(Kube));
728
+ /**
729
+ * @library Kube Sticky
730
+ * @author Imperavi LLC
731
+ * @license MIT
732
+ */
733
+ (function(Kube)
734
+ {
735
+ Kube.Sticky = function(element, options)
736
+ {
737
+ this.namespace = 'sticky';
738
+ this.defaults = {
739
+ classname: 'fixed',
740
+ offset: 0, // pixels
741
+ callbacks: ['fixed', 'unfixed']
742
+ };
743
+
744
+ // Parent Constructor
745
+ Kube.apply(this, arguments);
746
+
747
+ // Initialization
748
+ this.start();
749
+ };
750
+
751
+ // Functionality
752
+ Kube.Sticky.prototype = {
753
+ start: function()
754
+ {
755
+ this.offsetTop = this.getOffsetTop();
756
+
757
+ this.load();
758
+ $(window).scroll($.proxy(this.load, this));
759
+ },
760
+ getOffsetTop: function()
761
+ {
762
+ return this.$element.offset().top;
763
+ },
764
+ load: function()
765
+ {
766
+ return (this.isFix()) ? this.fixed() : this.unfixed();
767
+ },
768
+ isFix: function()
769
+ {
770
+ return ($(window).scrollTop() > (this.offsetTop + this.opts.offset));
771
+ },
772
+ fixed: function()
773
+ {
774
+ this.$element.addClass(this.opts.classname).css('top', this.opts.offset + 'px');
775
+ this.callback('fixed');
776
+ },
777
+ unfixed: function()
778
+ {
779
+ this.$element.removeClass(this.opts.classname).css('top', '');
780
+ this.callback('unfixed');
781
+ }
782
+ };
783
+
784
+ // Inheritance
785
+ Kube.Sticky.inherits(Kube);
786
+
787
+ // Plugin
788
+ Kube.Plugin.create('Sticky');
789
+ Kube.Plugin.autoload('Sticky');
790
+
791
+ }(Kube));
792
+ /**
793
+ * @library Kube Toggleme
794
+ * @author Imperavi LLC
795
+ * @license MIT
796
+ */
797
+ (function(Kube)
798
+ {
799
+ Kube.Toggleme = function(element, options)
800
+ {
801
+ this.namespace = 'toggleme';
802
+ this.defaults = {
803
+ toggleEvent: 'click',
804
+ target: null,
805
+ text: '',
806
+ animationOpen: 'slideDown',
807
+ animationClose: 'slideUp',
808
+ callbacks: ['open', 'opened', 'close', 'closed']
809
+ };
810
+
811
+ // Parent Constructor
812
+ Kube.apply(this, arguments);
813
+
814
+ // Initialization
815
+ this.start();
816
+ };
817
+
818
+ // Functionality
819
+ Kube.Toggleme.prototype = {
820
+ start: function()
821
+ {
822
+ if (!this.hasTarget()) return;
823
+
824
+ this.$element.on(this.opts.toggleEvent + '.' + this.namespace, $.proxy(this.toggle, this));
825
+ },
826
+ stop: function()
827
+ {
828
+ this.$element.off('.' + this.namespace);
829
+ this.revertText();
830
+ },
831
+ toggle: function(e)
832
+ {
833
+ if (this.isOpened()) this.close(e);
834
+ else this.open(e);
835
+ },
836
+ open: function(e)
837
+ {
838
+ if (e) e.preventDefault();
839
+
840
+ if (!this.isOpened())
841
+ {
842
+ this.storeText();
843
+ this.callback('open');
844
+ this.$target.animation('slideDown', $.proxy(this.onOpened, this));
845
+
846
+ // changes the text of $element with a less delay to smooth
847
+ setTimeout($.proxy(this.replaceText, this), 100);
848
+ }
849
+ },
850
+ close: function(e)
851
+ {
852
+ if (e) e.preventDefault();
853
+
854
+ if (this.isOpened())
855
+ {
856
+ this.callback('close');
857
+ this.$target.animation('slideUp', $.proxy(this.onClosed, this));
858
+ }
859
+ },
860
+ isOpened: function()
861
+ {
862
+ return (this.$target.hasClass('open'));
863
+ },
864
+ onOpened: function()
865
+ {
866
+ this.$target.addClass('open');
867
+ this.callback('opened');
868
+ },
869
+ onClosed: function()
870
+ {
871
+ this.$target.removeClass('open');
872
+ this.revertText();
873
+ this.callback('closed');
874
+ },
875
+ storeText: function()
876
+ {
877
+ this.$element.data('replacement-text', this.$element.html());
878
+ },
879
+ revertText: function()
880
+ {
881
+ var text = this.$element.data('replacement-text');
882
+ if (text) this.$element.html(text);
883
+
884
+ this.$element.removeData('replacement-text');
885
+ },
886
+ replaceText: function()
887
+ {
888
+ if (this.opts.text !== '')
889
+ {
890
+ this.$element.html(this.opts.text);
891
+ }
892
+ }
893
+ };
894
+
895
+ // Inheritance
896
+ Kube.Toggleme.inherits(Kube);
897
+
898
+ // Plugin
899
+ Kube.Plugin.create('Toggleme');
900
+ Kube.Plugin.autoload('Toggleme');
901
+
902
+ }(Kube));
903
+ /**
904
+ * @library Kube Offcanvas
905
+ * @author Imperavi LLC
906
+ * @license MIT
907
+ */
908
+ (function(Kube)
909
+ {
910
+ Kube.Offcanvas = function(element, options)
911
+ {
912
+ this.namespace = 'offcanvas';
913
+ this.defaults = {
914
+ target: null, // selector
915
+ push: true, // boolean
916
+ width: '250px', // string
917
+ direction: 'left', // string: left or right
918
+ toggleEvent: 'click',
919
+ clickOutside: true, // boolean
920
+ animationOpen: 'slideInLeft',
921
+ animationClose: 'slideOutLeft',
922
+ callbacks: ['open', 'opened', 'close', 'closed']
923
+ };
924
+
925
+ // Parent Constructor
926
+ Kube.apply(this, arguments);
927
+
928
+ // Services
929
+ this.utils = new Kube.Utils();
930
+ this.detect = new Kube.Detect();
931
+
932
+ // Initialization
933
+ this.start();
934
+ };
935
+
936
+ // Functionality
937
+ Kube.Offcanvas.prototype = {
938
+ start: function()
939
+ {
940
+ if (!this.hasTarget()) return;
941
+
942
+ this.buildTargetWidth();
943
+ this.buildAnimationDirection();
944
+
945
+ this.$close = this.getCloseLink();
946
+ this.$element.on(this.opts.toggleEvent + '.' + this.namespace, $.proxy(this.toggle, this));
947
+ this.$target.addClass('offcanvas');
948
+ },
949
+ stop: function()
950
+ {
951
+ this.closeAll();
952
+
953
+ this.$element.off('.' + this.namespace);
954
+ this.$close.off('.' + this.namespace);
955
+ $(document).off('.' + this.namespace);
956
+ },
957
+ toggle: function(e)
958
+ {
959
+ if (this.isOpened()) this.close(e);
960
+ else this.open(e);
961
+ },
962
+ buildTargetWidth: function()
963
+ {
964
+ this.opts.width = ($(window).width() < parseInt(this.opts.width)) ? '100%' : this.opts.width;
965
+ },
966
+ buildAnimationDirection: function()
967
+ {
968
+ if (this.opts.direction === 'right')
969
+ {
970
+ this.opts.animationOpen = 'slideInRight';
971
+ this.opts.animationClose = 'slideOutRight';
972
+ }
973
+ },
974
+ getCloseLink: function()
975
+ {
976
+ return this.$target.find('.close');
977
+ },
978
+ open: function(e)
979
+ {
980
+ if (e) e.preventDefault();
981
+
982
+ if (!this.isOpened())
983
+ {
984
+ this.closeAll();
985
+ this.callback('open');
986
+
987
+ this.$target.addClass('offcanvas-' + this.opts.direction);
988
+ this.$target.css('width', this.opts.width);
989
+
990
+ this.pushBody();
991
+
992
+ this.$target.animation(this.opts.animationOpen, $.proxy(this.onOpened, this));
993
+ }
994
+ },
995
+ closeAll: function()
996
+ {
997
+ var $elms = $(document).find('.offcanvas');
998
+ if ($elms.length !== 0)
999
+ {
1000
+ $elms.each(function()
1001
+ {
1002
+ var $el = $(this);
1003
+
1004
+ if ($el.hasClass('open'))
1005
+ {
1006
+ $el.css('width', '').animation('hide');
1007
+ $el.removeClass('open offcanvas-left offcanvas-right');
1008
+ }
1009
+
1010
+ });
1011
+
1012
+ $(document).off('.' + this.namespace);
1013
+ $('body').css('left', '');
1014
+ }
1015
+ },
1016
+ close: function(e)
1017
+ {
1018
+ if (e)
1019
+ {
1020
+ var $el = $(e.target);
1021
+ var isTag = ($el[0].tagName === 'A' || $el[0].tagName === 'BUTTON');
1022
+ if (isTag && $el.closest('.offcanvas').length !== 0 && !$el.hasClass('close'))
1023
+ {
1024
+ return;
1025
+ }
1026
+
1027
+ e.preventDefault();
1028
+ }
1029
+
1030
+ if (this.isOpened())
1031
+ {
1032
+ this.utils.enableBodyScroll();
1033
+ this.callback('close');
1034
+ this.pullBody();
1035
+ this.$target.animation(this.opts.animationClose, $.proxy(this.onClosed, this));
1036
+ }
1037
+ },
1038
+ isOpened: function()
1039
+ {
1040
+ return (this.$target.hasClass('open'));
1041
+ },
1042
+ onOpened: function()
1043
+ {
1044
+ if (this.opts.clickOutside) $(document).on('click.' + this.namespace, $.proxy(this.close, this));
1045
+ if (this.detect.isMobileScreen()) $('html').addClass('no-scroll');
1046
+
1047
+ $(document).on('keyup.' + this.namespace, $.proxy(this.handleKeyboard, this));
1048
+ this.$close.on('click.' + this.namespace, $.proxy(this.close, this));
1049
+
1050
+ this.utils.disableBodyScroll();
1051
+ this.$target.addClass('open');
1052
+ this.callback('opened');
1053
+ },
1054
+ onClosed: function()
1055
+ {
1056
+ if (this.detect.isMobileScreen()) $('html').removeClass('no-scroll');
1057
+
1058
+ this.$target.css('width', '').removeClass('offcanvas-' + this.opts.direction);
1059
+
1060
+ this.$close.off('.' + this.namespace);
1061
+ $(document).off('.' + this.namespace);
1062
+
1063
+ this.$target.removeClass('open');
1064
+ this.callback('closed');
1065
+ },
1066
+ handleKeyboard: function(e)
1067
+ {
1068
+ if (e.which === 27) this.close();
1069
+ },
1070
+ pullBody: function()
1071
+ {
1072
+ if (this.opts.push)
1073
+ {
1074
+ $('body').animate({ left: 0 }, 350, function() { $(this).removeClass('offcanvas-push-body'); });
1075
+ }
1076
+ },
1077
+ pushBody: function()
1078
+ {
1079
+ if (this.opts.push)
1080
+ {
1081
+ var properties = (this.opts.direction === 'left') ? { 'left': this.opts.width } : { 'left': '-' + this.opts.width };
1082
+ $('body').addClass('offcanvas-push-body').animate(properties, 200);
1083
+ }
1084
+ }
1085
+ };
1086
+
1087
+ // Inheritance
1088
+ Kube.Offcanvas.inherits(Kube);
1089
+
1090
+ // Plugin
1091
+ Kube.Plugin.create('Offcanvas');
1092
+ Kube.Plugin.autoload('Offcanvas');
1093
+
1094
+ }(Kube));
1095
+ /**
1096
+ * @library Kube Collapse
1097
+ * @author Imperavi LLC
1098
+ * @license MIT
1099
+ */
1100
+ (function(Kube)
1101
+ {
1102
+ Kube.Collapse = function(element, options)
1103
+ {
1104
+ this.namespace = 'collapse';
1105
+ this.defaults = {
1106
+ target: null,
1107
+ toggle: true,
1108
+ active: false, // string (hash = tab id selector)
1109
+ toggleClass: 'collapse-toggle',
1110
+ boxClass: 'collapse-box',
1111
+ callbacks: ['open', 'opened', 'close', 'closed'],
1112
+
1113
+ // private
1114
+ hashes: [],
1115
+ currentHash: false,
1116
+ currentItem: false
1117
+ };
1118
+
1119
+ // Parent Constructor
1120
+ Kube.apply(this, arguments);
1121
+
1122
+ // Initialization
1123
+ this.start();
1124
+ };
1125
+
1126
+ // Functionality
1127
+ Kube.Collapse.prototype = {
1128
+ start: function()
1129
+ {
1130
+ // items
1131
+ this.$items = this.getItems();
1132
+ this.$items.each($.proxy(this.loadItems, this));
1133
+
1134
+ // boxes
1135
+ this.$boxes = this.getBoxes();
1136
+
1137
+ // active
1138
+ this.setActiveItem();
1139
+ },
1140
+ getItems: function()
1141
+ {
1142
+ return this.$element.find('.' + this.opts.toggleClass);
1143
+ },
1144
+ getBoxes: function()
1145
+ {
1146
+ return this.$element.find('.' + this.opts.boxClass);
1147
+ },
1148
+ loadItems: function(i, el)
1149
+ {
1150
+ var item = this.getItem(el);
1151
+
1152
+ // set item identificator
1153
+ item.$el.attr('rel', item.hash);
1154
+
1155
+ // active
1156
+ if (!$(item.hash).hasClass('hide'))
1157
+ {
1158
+ this.opts.currentItem = item;
1159
+ this.opts.active = item.hash;
1160
+
1161
+ item.$el.addClass('active');
1162
+ }
1163
+
1164
+ // event
1165
+ item.$el.on('click.collapse', $.proxy(this.toggle, this));
1166
+
1167
+ },
1168
+ setActiveItem: function()
1169
+ {
1170
+ if (this.opts.active !== false)
1171
+ {
1172
+ this.opts.currentItem = this.getItemBy(this.opts.active);
1173
+ this.opts.active = this.opts.currentItem.hash;
1174
+ }
1175
+
1176
+ if (this.opts.currentItem !== false)
1177
+ {
1178
+ this.addActive(this.opts.currentItem);
1179
+ this.opts.currentItem.$box.removeClass('hide');
1180
+ }
1181
+ },
1182
+ addActive: function(item)
1183
+ {
1184
+ item.$box.removeClass('hide').addClass('open');
1185
+ item.$el.addClass('active');
1186
+
1187
+ if (item.$caret !== false) item.$caret.removeClass('down').addClass('up');
1188
+ if (item.$parent !== false) item.$parent.addClass('active');
1189
+
1190
+ this.opts.currentItem = item;
1191
+ },
1192
+ removeActive: function(item)
1193
+ {
1194
+ item.$box.removeClass('open');
1195
+ item.$el.removeClass('active');
1196
+
1197
+ if (item.$caret !== false) item.$caret.addClass('down').removeClass('up');
1198
+ if (item.$parent !== false) item.$parent.removeClass('active');
1199
+
1200
+ this.opts.currentItem = false;
1201
+ },
1202
+ toggle: function(e)
1203
+ {
1204
+ if (e) e.preventDefault();
1205
+
1206
+ var target = $(e.target).closest('.' + this.opts.toggleClass).get(0) || e.target;
1207
+ var item = this.getItem(target);
1208
+
1209
+ if (this.isOpened(item.hash)) this.close(item.hash);
1210
+ else this.open(e)
1211
+ },
1212
+ openAll: function()
1213
+ {
1214
+ this.$items.addClass('active');
1215
+ this.$boxes.addClass('open').removeClass('hide');
1216
+ },
1217
+ open: function(e, push)
1218
+ {
1219
+ if (typeof e === 'undefined') return;
1220
+ if (typeof e === 'object') e.preventDefault();
1221
+
1222
+ var target = $(e.target).closest('.' + this.opts.toggleClass).get(0) || e.target;
1223
+ var item = (typeof e === 'object') ? this.getItem(target) : this.getItemBy(e);
1224
+
1225
+ if (item.$box.hasClass('open'))
1226
+ {
1227
+ return;
1228
+ }
1229
+
1230
+ if (this.opts.toggle) this.closeAll();
1231
+
1232
+ this.callback('open', item);
1233
+ this.addActive(item);
1234
+
1235
+ item.$box.animation('slideDown', $.proxy(this.onOpened, this));
1236
+ },
1237
+ onOpened: function()
1238
+ {
1239
+ this.callback('opened', this.opts.currentItem);
1240
+ },
1241
+ closeAll: function()
1242
+ {
1243
+ this.$items.removeClass('active').closest('li').removeClass('active');
1244
+ this.$boxes.removeClass('open').addClass('hide');
1245
+ },
1246
+ close: function(num)
1247
+ {
1248
+ var item = this.getItemBy(num);
1249
+
1250
+ this.callback('close', item);
1251
+
1252
+ this.opts.currentItem = item;
1253
+
1254
+ item.$box.animation('slideUp', $.proxy(this.onClosed, this));
1255
+ },
1256
+ onClosed: function()
1257
+ {
1258
+ var item = this.opts.currentItem;
1259
+
1260
+ this.removeActive(item);
1261
+ this.callback('closed', item);
1262
+ },
1263
+ isOpened: function(hash)
1264
+ {
1265
+ return $(hash).hasClass('open');
1266
+ },
1267
+ getItem: function(element)
1268
+ {
1269
+ var item = {};
1270
+
1271
+ item.$el = $(element);
1272
+ item.hash = item.$el.attr('href');
1273
+ item.$box = $(item.hash);
1274
+
1275
+ var $parent = item.$el.parent();
1276
+ item.$parent = ($parent[0].tagName === 'LI') ? $parent : false;
1277
+
1278
+ var $caret = item.$el.find('.caret');
1279
+ item.$caret = ($caret.length !== 0) ? $caret : false;
1280
+
1281
+ return item;
1282
+ },
1283
+ getItemBy: function(num)
1284
+ {
1285
+ var element = (typeof num === 'number') ? this.$items.eq(num-1) : this.$element.find('[rel="' + num + '"]');
1286
+
1287
+ return this.getItem(element);
1288
+ }
1289
+ };
1290
+
1291
+ // Inheritance
1292
+ Kube.Collapse.inherits(Kube);
1293
+
1294
+ // Plugin
1295
+ Kube.Plugin.create('Collapse');
1296
+ Kube.Plugin.autoload('Collapse');
1297
+
1298
+ }(Kube));
1299
+ /**
1300
+ * @library Kube Dropdown
1301
+ * @author Imperavi LLC
1302
+ * @license MIT
1303
+ */
1304
+ (function(Kube)
1305
+ {
1306
+ Kube.Dropdown = function(element, options)
1307
+ {
1308
+ this.namespace = 'dropdown';
1309
+ this.defaults = {
1310
+ target: null,
1311
+ toggleEvent: 'click',
1312
+ height: false, // integer
1313
+ width: false, // integer
1314
+ animationOpen: 'slideDown',
1315
+ animationClose: 'slideUp',
1316
+ caretUp: false,
1317
+ callbacks: ['open', 'opened', 'close', 'closed']
1318
+ };
1319
+
1320
+ // Parent Constructor
1321
+ Kube.apply(this, arguments);
1322
+
1323
+ // Services
1324
+ this.utils = new Kube.Utils();
1325
+ this.detect = new Kube.Detect();
1326
+
1327
+ // Initialization
1328
+ this.start();
1329
+ };
1330
+
1331
+ // Functionality
1332
+ Kube.Dropdown.prototype = {
1333
+ start: function()
1334
+ {
1335
+ this.buildClose();
1336
+ this.buildCaret();
1337
+
1338
+ if (this.detect.isMobile()) this.buildMobileAnimation();
1339
+
1340
+ this.$target.addClass('hide');
1341
+ this.$element.on(this.opts.toggleEvent + '.' + this.namespace, $.proxy(this.toggle, this));
1342
+
1343
+ },
1344
+ stop: function()
1345
+ {
1346
+ this.$element.off('.' + this.namespace);
1347
+ this.$target.removeClass('open').addClass('hide');
1348
+ this.disableEvents();
1349
+ },
1350
+ buildMobileAnimation: function()
1351
+ {
1352
+ this.opts.animationOpen = 'fadeIn';
1353
+ this.opts.animationClose = 'fadeOut';
1354
+ },
1355
+ buildClose: function()
1356
+ {
1357
+ this.$close = this.$target.find('.close');
1358
+ },
1359
+ buildCaret: function()
1360
+ {
1361
+ this.$caret = this.getCaret();
1362
+ this.buildCaretPosition();
1363
+ },
1364
+ buildCaretPosition: function()
1365
+ {
1366
+ var height = this.$element.offset().top + this.$element.innerHeight() + this.$target.innerHeight();
1367
+
1368
+ if ($(document).height() > height)
1369
+ {
1370
+ return;
1371
+ }
1372
+
1373
+ this.opts.caretUp = true;
1374
+ this.$caret.addClass('up');
1375
+ },
1376
+ getCaret: function()
1377
+ {
1378
+ return this.$element.find('.caret');
1379
+ },
1380
+ toggleCaretOpen: function()
1381
+ {
1382
+ if (this.opts.caretUp) this.$caret.removeClass('up').addClass('down');
1383
+ else this.$caret.removeClass('down').addClass('up');
1384
+ },
1385
+ toggleCaretClose: function()
1386
+ {
1387
+ if (this.opts.caretUp) this.$caret.removeClass('down').addClass('up');
1388
+ else this.$caret.removeClass('up').addClass('down');
1389
+ },
1390
+ toggle: function(e)
1391
+ {
1392
+ if (this.isOpened()) this.close(e);
1393
+ else this.open(e);
1394
+ },
1395
+ open: function(e)
1396
+ {
1397
+ if (e) e.preventDefault();
1398
+
1399
+ this.callback('open');
1400
+ $('.dropdown').removeClass('open').addClass('hide');
1401
+
1402
+ if (this.opts.height) this.$target.css('min-height', this.opts.height + 'px');
1403
+ if (this.opts.width) this.$target.width(this.opts.width);
1404
+
1405
+ this.setPosition();
1406
+ this.toggleCaretOpen();
1407
+
1408
+ this.$target.animation(this.opts.animationOpen, $.proxy(this.onOpened, this));
1409
+ },
1410
+ close: function(e)
1411
+ {
1412
+ if (!this.isOpened())
1413
+ {
1414
+ return;
1415
+ }
1416
+
1417
+ if (e)
1418
+ {
1419
+ if (this.shouldNotBeClosed(e.target))
1420
+ {
1421
+ return;
1422
+ }
1423
+
1424
+ e.preventDefault();
1425
+ }
1426
+
1427
+ this.utils.enableBodyScroll();
1428
+ this.callback('close');
1429
+ this.toggleCaretClose();
1430
+
1431
+ this.$target.animation(this.opts.animationClose, $.proxy(this.onClosed, this));
1432
+ },
1433
+ onClosed: function()
1434
+ {
1435
+ this.$target.removeClass('open');
1436
+ this.disableEvents();
1437
+ this.callback('closed');
1438
+ },
1439
+ onOpened: function()
1440
+ {
1441
+ this.$target.addClass('open');
1442
+ this.enableEvents();
1443
+ this.callback('opened');
1444
+ },
1445
+ isOpened: function()
1446
+ {
1447
+ return (this.$target.hasClass('open'));
1448
+ },
1449
+ enableEvents: function()
1450
+ {
1451
+ if (this.detect.isDesktop())
1452
+ {
1453
+ this.$target.on('mouseover.' + this.namespace, $.proxy(this.utils.disableBodyScroll, this.utils))
1454
+ .on('mouseout.' + this.namespace, $.proxy(this.utils.enableBodyScroll, this.utils));
1455
+ }
1456
+
1457
+ $(document).on('scroll.' + this.namespace, $.proxy(this.setPosition, this));
1458
+ $(window).on('resize.' + this.namespace, $.proxy(this.setPosition, this));
1459
+ $(document).on('click.' + this.namespace + ' touchstart.' + this.namespace, $.proxy(this.close, this));
1460
+ $(document).on('keydown.' + this.namespace, $.proxy(this.handleKeyboard, this));
1461
+ this.$target.find('[data-action="dropdown-close"]').on('click.' + this.namespace, $.proxy(this.close, this));
1462
+ },
1463
+ disableEvents: function()
1464
+ {
1465
+ this.$target.off('.' + this.namespace);
1466
+ $(document).off('.' + this.namespace);
1467
+ $(window).off('.' + this.namespace);
1468
+ },
1469
+ handleKeyboard: function(e)
1470
+ {
1471
+ if (e.which === 27) this.close(e);
1472
+ },
1473
+ shouldNotBeClosed: function(el)
1474
+ {
1475
+ if ($(el).attr('data-action') === 'dropdown-close' || el === this.$close[0])
1476
+ {
1477
+ return false;
1478
+ }
1479
+ else if ($(el).closest('.dropdown').length === 0)
1480
+ {
1481
+ return false;
1482
+ }
1483
+
1484
+ return true;
1485
+ },
1486
+ isNavigationFixed: function()
1487
+ {
1488
+ return (this.$element.closest('.fixed').length !== 0);
1489
+ },
1490
+ getPlacement: function(height)
1491
+ {
1492
+ return ($(document).height() < height) ? 'top' : 'bottom';
1493
+ },
1494
+ getOffset: function(position)
1495
+ {
1496
+ return (this.isNavigationFixed()) ? this.$element.position() : this.$element.offset();
1497
+ },
1498
+ getPosition: function()
1499
+ {
1500
+ return (this.isNavigationFixed()) ? 'fixed' : 'absolute';
1501
+ },
1502
+ setPosition: function()
1503
+ {
1504
+ if (this.detect.isMobile())
1505
+ {
1506
+ this.$target.addClass('dropdown-mobile');
1507
+ return;
1508
+ }
1509
+
1510
+ var position = this.getPosition();
1511
+ var coords = this.getOffset(position);
1512
+ var height = this.$target.innerHeight();
1513
+ var width = this.$target.innerWidth();
1514
+ var placement = this.getPlacement(coords.top + height + this.$element.innerHeight());
1515
+ var leftFix = ($(window).width() < (coords.left + width)) ? (width - this.$element.innerWidth()) : 0;
1516
+ var top, left = coords.left - leftFix;
1517
+
1518
+ if (placement === 'bottom')
1519
+ {
1520
+ if (!this.isOpened()) this.$caret.removeClass('up').addClass('down');
1521
+
1522
+ this.opts.caretUp = false;
1523
+ top = coords.top + this.$element.outerHeight() + 1;
1524
+ }
1525
+ else
1526
+ {
1527
+ this.opts.animationOpen = 'show';
1528
+ this.opts.animationClose = 'hide';
1529
+
1530
+ if (!this.isOpened()) this.$caret.addClass('up').removeClass('down');
1531
+
1532
+ this.opts.caretUp = true;
1533
+ top = coords.top - height - 1;
1534
+ }
1535
+
1536
+ this.$target.css({ position: position, top: top + 'px', left: left + 'px' });
1537
+ }
1538
+ };
1539
+
1540
+ // Inheritance
1541
+ Kube.Dropdown.inherits(Kube);
1542
+
1543
+ // Plugin
1544
+ Kube.Plugin.create('Dropdown');
1545
+ Kube.Plugin.autoload('Dropdown');
1546
+
1547
+ }(Kube));
1548
+ /**
1549
+ * @library Kube Tabs
1550
+ * @author Imperavi LLC
1551
+ * @license MIT
1552
+ */
1553
+ (function(Kube)
1554
+ {
1555
+ Kube.Tabs = function(element, options)
1556
+ {
1557
+ this.namespace = 'tabs';
1558
+ this.defaults = {
1559
+ equals: false,
1560
+ active: false, // string (hash = tab id selector)
1561
+ live: false, // class selector
1562
+ hash: true, //boolean
1563
+ callbacks: ['init', 'next', 'prev', 'open', 'opened', 'close', 'closed']
1564
+ };
1565
+
1566
+ // Parent Constructor
1567
+ Kube.apply(this, arguments);
1568
+
1569
+ // Initialization
1570
+ this.start();
1571
+ };
1572
+
1573
+ // Functionality
1574
+ Kube.Tabs.prototype = {
1575
+ start: function()
1576
+ {
1577
+ if (this.opts.live !== false) this.buildLiveTabs();
1578
+
1579
+ this.tabsCollection = [];
1580
+ this.hashesCollection = [];
1581
+ this.currentHash = [];
1582
+ this.currentItem = false;
1583
+
1584
+ // items
1585
+ this.$items = this.getItems();
1586
+ this.$items.each($.proxy(this.loadItems, this));
1587
+
1588
+ // tabs
1589
+ this.$tabs = this.getTabs();
1590
+
1591
+ // location hash
1592
+ this.currentHash = this.getLocationHash();
1593
+
1594
+ // close all
1595
+ this.closeAll();
1596
+
1597
+ // active & height
1598
+ this.setActiveItem();
1599
+ this.setItemHeight();
1600
+
1601
+ // callback
1602
+ this.callback('init');
1603
+
1604
+ },
1605
+ getTabs: function()
1606
+ {
1607
+ return $(this.tabsCollection).map(function()
1608
+ {
1609
+ return this.toArray();
1610
+ });
1611
+ },
1612
+ getItems: function()
1613
+ {
1614
+ return this.$element.find('a');
1615
+ },
1616
+ loadItems: function(i, el)
1617
+ {
1618
+ var item = this.getItem(el);
1619
+
1620
+ // set item identificator
1621
+ item.$el.attr('rel', item.hash);
1622
+
1623
+ // collect item
1624
+ this.collectItem(item);
1625
+
1626
+ // active
1627
+ if (item.$parent.hasClass('active'))
1628
+ {
1629
+ this.currentItem = item;
1630
+ this.opts.active = item.hash;
1631
+ }
1632
+
1633
+ // event
1634
+ item.$el.on('click.tabs', $.proxy(this.open, this));
1635
+
1636
+ },
1637
+ collectItem: function(item)
1638
+ {
1639
+ this.tabsCollection.push(item.$tab);
1640
+ this.hashesCollection.push(item.hash);
1641
+ },
1642
+ buildLiveTabs: function()
1643
+ {
1644
+ var $layers = $(this.opts.live);
1645
+
1646
+ if ($layers.length === 0)
1647
+ {
1648
+ return;
1649
+ }
1650
+
1651
+ this.$liveTabsList = $('<ul />');
1652
+ $layers.each($.proxy(this.buildLiveItem, this));
1653
+
1654
+ this.$element.html('').append(this.$liveTabsList);
1655
+
1656
+ },
1657
+ buildLiveItem: function(i, tab)
1658
+ {
1659
+ var $tab = $(tab);
1660
+ var $li = $('<li />');
1661
+ var $a = $('<a />');
1662
+ var index = i + 1;
1663
+
1664
+ $tab.attr('id', this.getLiveItemId($tab, index));
1665
+
1666
+ var hash = '#' + $tab.attr('id');
1667
+ var title = this.getLiveItemTitle($tab);
1668
+
1669
+ $a.attr('href', hash).attr('rel', hash).text(title);
1670
+ $li.append($a);
1671
+
1672
+ this.$liveTabsList.append($li);
1673
+ },
1674
+ getLiveItemId: function($tab, index)
1675
+ {
1676
+ return (typeof $tab.attr('id') === 'undefined') ? this.opts.live.replace('.', '') + index : $tab.attr('id');
1677
+ },
1678
+ getLiveItemTitle: function($tab)
1679
+ {
1680
+ return (typeof $tab.attr('data-title') === 'undefined') ? $tab.attr('id') : $tab.attr('data-title');
1681
+ },
1682
+ setActiveItem: function()
1683
+ {
1684
+ if (this.currentHash)
1685
+ {
1686
+ this.currentItem = this.getItemBy(this.currentHash);
1687
+ this.opts.active = this.currentHash;
1688
+ }
1689
+ else if (this.opts.active === false)
1690
+ {
1691
+ this.currentItem = this.getItem(this.$items.first());
1692
+ this.opts.active = this.currentItem.hash;
1693
+ }
1694
+
1695
+ this.addActive(this.currentItem);
1696
+ },
1697
+ addActive: function(item)
1698
+ {
1699
+ item.$parent.addClass('active');
1700
+ item.$tab.removeClass('hide').addClass('open');
1701
+
1702
+ this.currentItem = item;
1703
+ },
1704
+ removeActive: function(item)
1705
+ {
1706
+ item.$parent.removeClass('active');
1707
+ item.$tab.addClass('hide').removeClass('open');
1708
+
1709
+ this.currentItem = false;
1710
+ },
1711
+ next: function(e)
1712
+ {
1713
+ if (e) e.preventDefault();
1714
+
1715
+ var item = this.getItem(this.fetchElement('next'));
1716
+
1717
+ this.open(item.hash);
1718
+ this.callback('next', item);
1719
+
1720
+ },
1721
+ prev: function(e)
1722
+ {
1723
+ if (e) e.preventDefault();
1724
+
1725
+ var item = this.getItem(this.fetchElement('prev'));
1726
+
1727
+ this.open(item.hash);
1728
+ this.callback('prev', item);
1729
+ },
1730
+ fetchElement: function(type)
1731
+ {
1732
+ var element;
1733
+ if (this.currentItem !== false)
1734
+ {
1735
+ // prev or next
1736
+ element = this.currentItem.$parent[type]().find('a');
1737
+
1738
+ if (element.length === 0)
1739
+ {
1740
+ return;
1741
+ }
1742
+ }
1743
+ else
1744
+ {
1745
+ // first
1746
+ element = this.$items[0];
1747
+ }
1748
+
1749
+ return element;
1750
+ },
1751
+ open: function(e, push)
1752
+ {
1753
+ if (typeof e === 'undefined') return;
1754
+ if (typeof e === 'object') e.preventDefault();
1755
+
1756
+ var item = (typeof e === 'object') ? this.getItem(e.target) : this.getItemBy(e);
1757
+ this.closeAll();
1758
+
1759
+ this.callback('open', item);
1760
+ this.addActive(item);
1761
+
1762
+ // push state (doesn't need to push at the start)
1763
+ this.pushStateOpen(push, item);
1764
+ this.callback('opened', item);
1765
+ },
1766
+ pushStateOpen: function(push, item)
1767
+ {
1768
+ if (push !== false && this.opts.hash !== false)
1769
+ {
1770
+ history.pushState(false, false, item.hash);
1771
+ }
1772
+ },
1773
+ close: function(num)
1774
+ {
1775
+ var item = this.getItemBy(num);
1776
+
1777
+ if (!item.$parent.hasClass('active'))
1778
+ {
1779
+ return;
1780
+ }
1781
+
1782
+ this.callback('close', item);
1783
+ this.removeActive(item);
1784
+ this.pushStateClose();
1785
+ this.callback('closed', item);
1786
+
1787
+ },
1788
+ pushStateClose: function()
1789
+ {
1790
+ if (this.opts.hash !== false)
1791
+ {
1792
+ history.pushState(false, false, ' ');
1793
+ }
1794
+ },
1795
+ closeAll: function()
1796
+ {
1797
+ this.$tabs.removeClass('open').addClass('hide');
1798
+ this.$items.parent().removeClass('active');
1799
+ },
1800
+ getItem: function(element)
1801
+ {
1802
+ var item = {};
1803
+
1804
+ item.$el = $(element);
1805
+ item.hash = item.$el.attr('href');
1806
+ item.$parent = item.$el.parent();
1807
+ item.$tab = $(item.hash);
1808
+
1809
+ return item;
1810
+ },
1811
+ getItemBy: function(num)
1812
+ {
1813
+ var element = (typeof num === 'number') ? this.$items.eq(num-1) : this.$element.find('[rel="' + num + '"]');
1814
+
1815
+ return this.getItem(element);
1816
+ },
1817
+ getLocationHash: function()
1818
+ {
1819
+ if (this.opts.hash === false)
1820
+ {
1821
+ return false;
1822
+ }
1823
+
1824
+ return (this.isHash()) ? top.location.hash : false;
1825
+ },
1826
+ isHash: function()
1827
+ {
1828
+ return !(top.location.hash === '' || $.inArray(top.location.hash, this.hashesCollection) === -1);
1829
+ },
1830
+ setItemHeight: function()
1831
+ {
1832
+ if (this.opts.equals)
1833
+ {
1834
+ var minHeight = this.getItemMaxHeight() + 'px';
1835
+ this.$tabs.css('min-height', minHeight);
1836
+ }
1837
+ },
1838
+ getItemMaxHeight: function()
1839
+ {
1840
+ var max = 0;
1841
+ this.$tabs.each(function()
1842
+ {
1843
+ var h = $(this).height();
1844
+ max = h > max ? h : max;
1845
+ });
1846
+
1847
+ return max;
1848
+ }
1849
+ };
1850
+
1851
+ // Inheritance
1852
+ Kube.Tabs.inherits(Kube);
1853
+
1854
+ // Plugin
1855
+ Kube.Plugin.create('Tabs');
1856
+ Kube.Plugin.autoload('Tabs');
1857
+
1858
+ }(Kube));
1859
+ /**
1860
+ * @library Kube Modal
1861
+ * @author Imperavi LLC
1862
+ * @license MIT
1863
+ */
1864
+ (function($)
1865
+ {
1866
+ $.modalcurrent = null;
1867
+ $.modalwindow = function(options)
1868
+ {
1869
+ var opts = $.extend({}, options, { show: true });
1870
+ var $element = $('<span />');
1871
+
1872
+ $element.modal(opts);
1873
+ };
1874
+
1875
+ })(jQuery);
1876
+
1877
+ (function(Kube)
1878
+ {
1879
+ Kube.Modal = function(element, options)
1880
+ {
1881
+ this.namespace = 'modal';
1882
+ this.defaults = {
1883
+ target: null,
1884
+ show: false,
1885
+ url: false,
1886
+ header: false,
1887
+ width: '600px', // string
1888
+ height: false, // or string
1889
+ maxHeight: false,
1890
+ position: 'center', // top or center
1891
+ overlay: true,
1892
+ appendForms: false,
1893
+ appendFields: false,
1894
+ animationOpen: 'show',
1895
+ animationClose: 'hide',
1896
+ callbacks: ['open', 'opened', 'close', 'closed']
1897
+ };
1898
+
1899
+ // Parent Constructor
1900
+ Kube.apply(this, arguments);
1901
+
1902
+ // Services
1903
+ this.utils = new Kube.Utils();
1904
+ this.detect = new Kube.Detect();
1905
+
1906
+ // Initialization
1907
+ this.start();
1908
+ };
1909
+
1910
+ // Functionality
1911
+ Kube.Modal.prototype = {
1912
+ start: function()
1913
+ {
1914
+ if (!this.hasTarget())
1915
+ {
1916
+ return;
1917
+ }
1918
+
1919
+ if (this.opts.show) this.load();
1920
+ else this.$element.on('click.' + this.namespace, $.proxy(this.load, this));
1921
+ },
1922
+ buildModal: function()
1923
+ {
1924
+ this.$modal = this.$target.find('.modal');
1925
+ this.$header = this.$target.find('.modal-header');
1926
+ this.$close = this.$target.find('.close');
1927
+ this.$body = this.$target.find('.modal-body');
1928
+ },
1929
+ buildOverlay: function()
1930
+ {
1931
+ if (this.opts.overlay === false)
1932
+ {
1933
+ return;
1934
+ }
1935
+
1936
+ if ($('#modal-overlay').length !== 0)
1937
+ {
1938
+ this.$overlay = $('#modal-overlay');
1939
+ }
1940
+ else
1941
+ {
1942
+ this.$overlay = $('<div id="modal-overlay">').addClass('hide');
1943
+ $('body').prepend(this.$overlay);
1944
+ }
1945
+
1946
+ this.$overlay.addClass('overlay');
1947
+ },
1948
+ buildHeader: function()
1949
+ {
1950
+ if (this.opts.header) this.$header.html(this.opts.header);
1951
+ },
1952
+ load: function(e)
1953
+ {
1954
+ this.buildModal();
1955
+ this.buildOverlay();
1956
+ this.buildHeader();
1957
+
1958
+ if (this.opts.url) this.buildContent();
1959
+ else this.open(e);
1960
+ },
1961
+ open: function(e)
1962
+ {
1963
+ if (e) e.preventDefault();
1964
+
1965
+ if (this.isOpened())
1966
+ {
1967
+ return;
1968
+ }
1969
+
1970
+ if (this.detect.isMobile()) this.opts.width = '96%';
1971
+ if (this.opts.overlay) this.$overlay.removeClass('hide');
1972
+
1973
+ this.$target.removeClass('hide');
1974
+ this.$modal.removeClass('hide');
1975
+
1976
+ this.enableEvents();
1977
+ this.findActions();
1978
+
1979
+ this.resize();
1980
+ $(window).on('resize.' + this.namespace, $.proxy(this.resize, this));
1981
+
1982
+ if (this.detect.isDesktop()) this.utils.disableBodyScroll();
1983
+
1984
+ // enter
1985
+ this.$modal.find('input[type=text],input[type=url],input[type=email]').on('keydown.' + this.namespace, $.proxy(this.handleEnter, this));
1986
+
1987
+ this.callback('open');
1988
+ this.$modal.animation(this.opts.animationOpen, $.proxy(this.onOpened, this));
1989
+ },
1990
+ close: function(e)
1991
+ {
1992
+ if (!this.$modal || !this.isOpened())
1993
+ {
1994
+ return;
1995
+ }
1996
+
1997
+ if (e)
1998
+ {
1999
+ if (this.shouldNotBeClosed(e.target))
2000
+ {
2001
+ return;
2002
+ }
2003
+
2004
+ e.preventDefault();
2005
+ }
2006
+
2007
+ this.callback('close');
2008
+ this.disableEvents();
2009
+
2010
+ this.$modal.animation(this.opts.animationClose, $.proxy(this.onClosed, this));
2011
+
2012
+ if (this.opts.overlay) this.$overlay.animation(this.opts.animationClose);
2013
+ },
2014
+ onOpened: function()
2015
+ {
2016
+ this.$modal.addClass('open');
2017
+ this.callback('opened');
2018
+
2019
+ $.modalcurrent = this;
2020
+ },
2021
+ onClosed: function()
2022
+ {
2023
+ this.callback('closed');
2024
+
2025
+ this.$target.addClass('hide');
2026
+ this.$modal.removeClass('open');
2027
+
2028
+ if (this.detect.isDesktop()) this.utils.enableBodyScroll();
2029
+
2030
+ this.$body.css('height', '');
2031
+ $.modalcurrent = null;
2032
+ },
2033
+ isOpened: function()
2034
+ {
2035
+ return (this.$modal.hasClass('open'));
2036
+ },
2037
+ getData: function()
2038
+ {
2039
+ var formdata = new Kube.FormData(this);
2040
+ formdata.set('');
2041
+
2042
+ return formdata.get();
2043
+ },
2044
+ buildContent: function()
2045
+ {
2046
+ $.ajax({
2047
+ url: this.opts.url + '?' + new Date().getTime(),
2048
+ cache: false,
2049
+ type: 'post',
2050
+ data: this.getData(),
2051
+ success: $.proxy(function(data)
2052
+ {
2053
+ this.$body.html(data);
2054
+ this.open();
2055
+
2056
+ }, this)
2057
+ });
2058
+ },
2059
+ buildWidth: function()
2060
+ {
2061
+ var width = this.opts.width;
2062
+ var top = '2%';
2063
+ var bottom = '2%';
2064
+ var percent = width.match(/%$/);
2065
+
2066
+ if ((parseInt(this.opts.width) > $(window).width()) && !percent)
2067
+ {
2068
+ width = '96%';
2069
+ }
2070
+ else if (!percent)
2071
+ {
2072
+ top = '16px';
2073
+ bottom = '16px';
2074
+ }
2075
+
2076
+ this.$modal.css({ 'width': width, 'margin-top': top, 'margin-bottom': bottom });
2077
+
2078
+ },
2079
+ buildPosition: function()
2080
+ {
2081
+ if (this.opts.position !== 'center')
2082
+ {
2083
+ return;
2084
+ }
2085
+
2086
+ var windowHeight = $(window).height();
2087
+ var height = this.$modal.outerHeight();
2088
+ var top = (windowHeight/2 - height/2) + 'px';
2089
+
2090
+ if (this.detect.isMobile()) top = '2%';
2091
+ else if (height > windowHeight) top = '16px';
2092
+
2093
+ this.$modal.css('margin-top', top);
2094
+ },
2095
+ buildHeight: function()
2096
+ {
2097
+ var windowHeight = $(window).height();
2098
+
2099
+ if (this.opts.maxHeight)
2100
+ {
2101
+ var padding = parseInt(this.$body.css('padding-top')) + parseInt(this.$body.css('padding-bottom'));
2102
+ var margin = parseInt(this.$modal.css('margin-top')) + parseInt(this.$modal.css('margin-bottom'));
2103
+ var height = windowHeight - this.$header.innerHeight() - padding - margin;
2104
+
2105
+ this.$body.height(height);
2106
+ }
2107
+ else if (this.opts.height !== false)
2108
+ {
2109
+ this.$body.css('height', this.opts.height);
2110
+ }
2111
+
2112
+ var modalHeight = this.$modal.outerHeight();
2113
+ if (modalHeight > windowHeight)
2114
+ {
2115
+ this.opts.animationOpen = 'show';
2116
+ this.opts.animationClose = 'hide';
2117
+ }
2118
+ },
2119
+ resize: function()
2120
+ {
2121
+ this.buildWidth();
2122
+ this.buildPosition();
2123
+ this.buildHeight();
2124
+ },
2125
+ enableEvents: function()
2126
+ {
2127
+ this.$close.on('click.' + this.namespace, $.proxy(this.close, this));
2128
+ $(document).on('keyup.' + this.namespace, $.proxy(this.handleEscape, this));
2129
+ this.$target.on('click.' + this.namespace, $.proxy(this.close, this));
2130
+ },
2131
+ disableEvents: function()
2132
+ {
2133
+ this.$close.off('.' + this.namespace);
2134
+ $(document).off('.' + this.namespace);
2135
+ this.$target.off('.' + this.namespace);
2136
+ $(window).off('.' + this.namespace);
2137
+ },
2138
+ findActions: function()
2139
+ {
2140
+ this.$body.find('[data-action="modal-close"]').on('mousedown.' + this.namespace, $.proxy(this.close, this));
2141
+ },
2142
+ setHeader: function(header)
2143
+ {
2144
+ this.$header.html(header);
2145
+ },
2146
+ setContent: function(content)
2147
+ {
2148
+ this.$body.html(content);
2149
+ },
2150
+ setWidth: function(width)
2151
+ {
2152
+ this.opts.width = width;
2153
+ this.resize();
2154
+ },
2155
+ getModal: function()
2156
+ {
2157
+ return this.$modal;
2158
+ },
2159
+ getBody: function()
2160
+ {
2161
+ return this.$body;
2162
+ },
2163
+ getHeader: function()
2164
+ {
2165
+ return this.$header;
2166
+ },
2167
+ handleEnter: function(e)
2168
+ {
2169
+ if (e.which === 13)
2170
+ {
2171
+ e.preventDefault();
2172
+ this.close(false);
2173
+ }
2174
+ },
2175
+ handleEscape: function(e)
2176
+ {
2177
+ return (e.which === 27) ? this.close(false) : true;
2178
+ },
2179
+ shouldNotBeClosed: function(el)
2180
+ {
2181
+ if ($(el).attr('data-action') === 'modal-close' || el === this.$close[0])
2182
+ {
2183
+ return false;
2184
+ }
2185
+ else if ($(el).closest('.modal').length === 0)
2186
+ {
2187
+ return false;
2188
+ }
2189
+
2190
+ return true;
2191
+ }
2192
+ };
2193
+
2194
+ // Inheritance
2195
+ Kube.Modal.inherits(Kube);
2196
+
2197
+ // Plugin
2198
+ Kube.Plugin.create('Modal');
2199
+ Kube.Plugin.autoload('Modal');
2200
+
2201
+ }(Kube));