gumby 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,206 @@
1
+ /**
2
+ * Gumby Fixed
3
+ */
4
+ !function() {
5
+
6
+ 'use strict';
7
+
8
+ function Fixed($el) {
9
+ this.$el = $el;
10
+
11
+ this.fixedPoint = '';
12
+ this.pinPoint = false;
13
+ this.offset = 0;
14
+ this.pinOffset = 0;
15
+ this.top = 0;
16
+ this.constrainEl = true;
17
+ this.state = false;
18
+ this.measurements = {
19
+ left: 0,
20
+ width: 0
21
+ };
22
+
23
+ // set up module based on attributes
24
+ this.setup();
25
+
26
+ var scope = this;
27
+
28
+ // monitor scroll and update fixed elements accordingly
29
+ $(window).on('scroll load', function() {
30
+ scope.monitorScroll();
31
+ });
32
+
33
+ // reinitialize event listener
34
+ this.$el.on('gumby.initialize', function() {
35
+ scope.setup();
36
+ });
37
+ }
38
+
39
+ // set up module based on attributes
40
+ Fixed.prototype.setup = function() {
41
+ var scope = this;
42
+
43
+ this.fixedPoint = this.parseAttrValue(Gumby.selectAttr.apply(this.$el, ['fixed']));
44
+
45
+ // pin point is optional
46
+ this.pinPoint = Gumby.selectAttr.apply(this.$el, ['pin']) || false;
47
+
48
+ // offset from fixed point
49
+ this.offset = Number(Gumby.selectAttr.apply(this.$el, ['offset'])) || 0;
50
+
51
+ // offset from pin point
52
+ this.pinOffset = Number(Gumby.selectAttr.apply(this.$el, ['pinoffset'])) || 0;
53
+
54
+ // top position when fixed
55
+ this.top = Number(Gumby.selectAttr.apply(this.$el, ['top'])) || 0;
56
+
57
+ // constrain can be turned off
58
+ this.constrainEl = Gumby.selectAttr.apply(this.$el, ['constrain']) || true;
59
+ if(this.constrainEl === 'false') {
60
+ this.constrainEl = false;
61
+ }
62
+
63
+ // reference to the parent, row/column
64
+ this.$parent = this.$el.parents('.columns, .column, .row');
65
+ this.$parent = this.$parent.length ? this.$parent.first() : false;
66
+ this.parentRow = this.$parent ? !!this.$parent.hasClass('row') : false;
67
+
68
+ // if optional pin point set then parse now
69
+ if(this.pinPoint) {
70
+ this.pinPoint = this.parseAttrValue(this.pinPoint);
71
+ }
72
+
73
+ // if we have a parent constrain dimenions
74
+ if(this.$parent && this.constrainEl) {
75
+ // measure up
76
+ this.measure();
77
+ // and on resize reset measurement
78
+ $(window).resize(function() {
79
+ if(scope.state) {
80
+ scope.measure();
81
+ scope.constrain();
82
+ }
83
+ });
84
+ }
85
+ };
86
+
87
+ // monitor scroll and trigger changes based on position
88
+ Fixed.prototype.monitorScroll = function() {
89
+ var scrollAmount = $(window).scrollTop(),
90
+ // recalculate selector attributes as position may have changed
91
+ fixedPoint = this.fixedPoint instanceof jQuery ? this.fixedPoint.offset().top : this.fixedPoint,
92
+ pinPoint = false;
93
+
94
+ // if a pin point is set recalculate
95
+ if(this.pinPoint) {
96
+ pinPoint = this.pinPoint instanceof jQuery ? this.pinPoint.offset().top : this.pinPoint;
97
+ }
98
+
99
+ // apply offsets
100
+ if(this.offset) { fixedPoint -= this.offset; }
101
+ if(this.pinOffset) { pinPoint -= this.pinOffset; }
102
+
103
+ // fix it
104
+ if((scrollAmount >= fixedPoint) && this.state !== 'fixed') {
105
+ if(!pinPoint || scrollAmount < pinPoint) {
106
+ this.fix();
107
+ }
108
+ // unfix it
109
+ } else if(scrollAmount < fixedPoint && this.state === 'fixed') {
110
+ this.unfix();
111
+
112
+ // pin it
113
+ } else if(pinPoint && scrollAmount >= pinPoint && this.state !== 'pinned') {
114
+ this.pin();
115
+ }
116
+ };
117
+
118
+ // fix the element and update state
119
+ Fixed.prototype.fix = function() {
120
+ this.state = 'fixed';
121
+ this.$el.css({
122
+ 'top' : 0 + this.top
123
+ }).addClass('fixed').removeClass('unfixed pinned').trigger('gumby.onFixed');
124
+
125
+ // if we have a parent constrain dimenions
126
+ if(this.$parent) {
127
+ this.constrain();
128
+ }
129
+ };
130
+
131
+ // unfix the element and update state
132
+ Fixed.prototype.unfix = function() {
133
+ this.state = 'unfixed';
134
+ this.$el.addClass('unfixed').removeClass('fixed pinned').trigger('gumby.onUnfixed');
135
+ };
136
+
137
+ // pin the element in position
138
+ Fixed.prototype.pin = function() {
139
+ this.state = 'pinned';
140
+ this.$el.css({
141
+ 'top' : this.$el.offset().top
142
+ }).addClass('pinned fixed').removeClass('unfixed').trigger('gumby.onPinned');
143
+ };
144
+
145
+ // constrain elements dimensions to match width/height
146
+ Fixed.prototype.constrain = function() {
147
+ this.$el.css({
148
+ left: this.measurements.left,
149
+ width: this.measurements.width
150
+ });
151
+ };
152
+
153
+ // measure up the parent for constraining
154
+ Fixed.prototype.measure = function() {
155
+ var offsets = this.$parent.offset(), parentPadding;
156
+
157
+ this.measurements.left = offsets.left;
158
+ this.measurements.width = this.$parent.width();
159
+
160
+ // if element has a parent row then need to consider padding
161
+ if(this.parentRow) {
162
+ parentPadding = Number(this.$parent.css('paddingLeft').replace(/px/, ''));
163
+ if(parentPadding) {
164
+ this.measurements.left += parentPadding;
165
+ }
166
+ }
167
+ };
168
+
169
+ // parse attribute values, could be px, top, selector
170
+ Fixed.prototype.parseAttrValue = function(attr) {
171
+ // px value fixed point
172
+ if($.isNumeric(attr)) {
173
+ return Number(attr);
174
+ // 'top' string fixed point
175
+ } else if(attr === 'top') {
176
+ return this.$el.offset().top;
177
+ // selector specified
178
+ } else {
179
+ var $el = $(attr);
180
+ return $el;
181
+ }
182
+ };
183
+
184
+ // add initialisation
185
+ Gumby.addInitalisation('fixed', function() {
186
+ $('[data-fixed],[gumby-fixed],[fixed]').each(function() {
187
+ var $this = $(this);
188
+ // this element has already been initialized
189
+ if($this.data('isFixed')) {
190
+ return true;
191
+ }
192
+ // mark element as initialized
193
+ $this.data('isFixed', true);
194
+ new Fixed($this);
195
+ });
196
+ });
197
+
198
+ // register UI module
199
+ Gumby.UIModule({
200
+ module: 'fixed',
201
+ events: ['onFixed', 'onUnfixed'],
202
+ init: function() {
203
+ Gumby.initialize('fixed');
204
+ }
205
+ });
206
+ }();
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Gumby Navbar
3
+ */
4
+ !function() {
5
+
6
+ 'use strict';
7
+
8
+ var $html = Gumby.$dom.find('html');
9
+
10
+ // define and init module on touch enabled devices only
11
+ // when we are at tablet size or smaller
12
+ if(!Modernizr.touch || $(window).width() > Gumby.breakpoint) {
13
+
14
+ // add Gumby no touch class
15
+ $html.addClass('gumby-no-touch');
16
+ return;
17
+ }
18
+
19
+ // add Gumby touch class
20
+ $html.addClass('gumby-touch');
21
+
22
+ function Navbar($el) {
23
+ this.$el = $el;
24
+ this.$dropDowns = this.$el.find('li:has(.dropdown)');
25
+ var scope = this;
26
+
27
+ // when navbar items
28
+ this.$dropDowns
29
+ // are tapped hide/show dropdowns
30
+ .on('tap', this.toggleDropdown)
31
+ // are swiped right open link
32
+ .on('swiperight', this.openLink);
33
+
34
+ // if there's a link set
35
+ if(this.$dropDowns.children('a').attr('href') !== '#') {
36
+ // append an icon
37
+ this.$dropDowns.children('a').append('<i class="icon-popup"></i>').children('i')
38
+ // and bind to click event to open link
39
+ .on('tap', this.openLink);
40
+ }
41
+
42
+ // on mousemove and touchstart toggle modernizr classes and disable/enable this module
43
+ // workaround for Pixel and other multi input devices
44
+ $(window).on('mousemove touchstart', function(e) {
45
+ e.stopImmediatePropagation();
46
+ if(e.type === 'mousemove') {
47
+ scope.$dropDowns.on('mouseover mouseout', scope.toggleDropdown);
48
+ }
49
+ });
50
+ }
51
+
52
+ Navbar.prototype.toggleDropdown = function(e) {
53
+ // prevent click from triggering here too
54
+ e.stopImmediatePropagation();
55
+ e.preventDefault();
56
+
57
+ var $this = $(this);
58
+
59
+ if($this.hasClass('active')) {
60
+ $this.removeClass('active');
61
+ } else {
62
+ $this.addClass('active');
63
+ }
64
+ };
65
+
66
+ // handle opening list item link
67
+ Navbar.prototype.openLink = function(e) {
68
+ e.stopImmediatePropagation();
69
+ e.preventDefault();
70
+
71
+ var $this = $(this),
72
+ $el, href;
73
+
74
+ // tapped icon
75
+ if($this.is('i')) {
76
+ $el = $this.parent('a');
77
+ // swiped li
78
+ } else if($this.is('li')) {
79
+ $el = $this.children('a');
80
+ }
81
+
82
+ href = $el.attr('href');
83
+
84
+ // open in new window
85
+ if($el.attr('target') == 'blank') {
86
+ window.open(href);
87
+ // regular relocation
88
+ } else {
89
+ window.location = href;
90
+ }
91
+ };
92
+
93
+ // add initialisation
94
+ Gumby.addInitalisation('navbars', function() {
95
+ $('.navbar').each(function() {
96
+ var $this = $(this);
97
+ // this element has already been initialized
98
+ if($this.data('isNavbar')) {
99
+ return true;
100
+ }
101
+ // mark element as initialized
102
+ $this.data('isNavbar', true);
103
+ new Navbar($this);
104
+ });
105
+ });
106
+
107
+ // register UI module
108
+ Gumby.UIModule({
109
+ module: 'navbar',
110
+ events: [],
111
+ init: function() {
112
+ Gumby.initialize('navbars');
113
+ }
114
+ });
115
+ }();
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Gumby RadioBtn
3
+ */
4
+ !function() {
5
+
6
+ 'use strict';
7
+
8
+ function RadioBtn($el) {
9
+
10
+ this.$el = $el;
11
+ var scope = this;
12
+
13
+ // listen for click event and custom gumby check event
14
+ this.$el.on(Gumby.click, function(e) {
15
+ // prevent propagation
16
+ e.stopImmediatePropagation();
17
+
18
+ // prevent radio button checking, we'll do that manually
19
+ e.preventDefault();
20
+
21
+ // check radio button
22
+ scope.update();
23
+ }).on('gumby.check', function() {
24
+ scope.update();
25
+ });
26
+
27
+ // update any .checked checkboxes on load
28
+ if(scope.$el.hasClass('checked')) {
29
+ scope.update();
30
+ }
31
+ }
32
+
33
+ // check radio button, uncheck all others in name group
34
+ RadioBtn.prototype.update = function() {
35
+ var // this specific radio button
36
+ $input = this.$el.find('input[type=radio]'),
37
+ $span = this.$el.find('span'),
38
+ // the group of radio buttons
39
+ group = 'input[name="'+$input.attr('name')+'"]';
40
+
41
+ // uncheck radio buttons in same group - uncheck input, remove checked class, remove <i>
42
+ $('.radio').has(group).removeClass('checked')
43
+ .find('input').prop('checked', false).end()
44
+ .find('i').remove();
45
+
46
+ // check this radio button - check input, add checked class, append <i>
47
+ $input.prop('checked', true);
48
+ $span.append('<i class="icon-dot" />');
49
+ this.$el.addClass('checked').trigger('gumby.onChange');
50
+ };
51
+
52
+ // add initialisation
53
+ Gumby.addInitalisation('radiobtns', function() {
54
+ $('.radio').each(function() {
55
+ var $this = $(this);
56
+ // this element has already been initialized
57
+ if($this.data('isRadioBtn')) {
58
+ return true;
59
+ }
60
+ // mark element as initialized
61
+ $this.data('isRadioBtn', true);
62
+ new RadioBtn($this);
63
+ });
64
+ });
65
+
66
+ // register UI module
67
+ Gumby.UIModule({
68
+ module: 'radiobtn',
69
+ events: ['onChange', 'check'],
70
+ init: function() {
71
+ Gumby.initialize('radiobtns');
72
+ }
73
+ });
74
+ }();
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Gumby Retina
3
+ */
4
+ !function() {
5
+
6
+ 'use strict';
7
+
8
+ function Retina($el) {
9
+ this.$el = $el;
10
+ this.imageSrc = this.$el.attr('src');
11
+ this.retinaSrc = this.fetchRetinaImage();
12
+ this.$retinaImg = $(new Image());
13
+
14
+ var scope = this
15
+
16
+ // image src not valid
17
+ if(!this.retinaSrc) {
18
+ return false;
19
+ }
20
+
21
+ // load retina image
22
+ this.$retinaImg.attr('src', this.retinaSrc).load(function() {
23
+ scope.retinaImageLoaded();
24
+ });
25
+ }
26
+
27
+ // fetch retina src by appending '@2x' to image string before extension
28
+ Retina.prototype.fetchRetinaImage = function() {
29
+ var imgSrc = this.imageSrc,
30
+ index = this.imageSrc.search(/(\.|\/)(gif|jpe?g|png)$/i);
31
+
32
+ // image src is not valid
33
+ if(index < 0) {
34
+ return false;
35
+ }
36
+
37
+ // return retina src
38
+ return imgSrc.substr(0, index) + '@2x' + imgSrc.substr(index, imgSrc.length);
39
+ };
40
+
41
+ // once retina image loaded swap original src
42
+ Retina.prototype.retinaImageLoaded = function() {
43
+ this.$el.attr('src', this.$retinaImg.attr('src')).trigger('gumby.onRetina');
44
+ };
45
+
46
+ // add initialisation
47
+ Gumby.addInitalisation('retina', function() {
48
+
49
+ // this module is for retina devices only
50
+ if(!window.devicePixelRatio || window.devicePixelRatio <= 1) {
51
+ return;
52
+ }
53
+
54
+ $('img[data-retina],img[gumby-retina],img[retina]').each(function() {
55
+ var $this = $(this);
56
+ // this element has already been initialized
57
+ if($this.data('isRetina')) {
58
+ return true;
59
+ }
60
+ // mark element as initialized
61
+ $this.data('isRetina', true);
62
+ new Retina($this);
63
+ });
64
+ });
65
+
66
+ // register UI module
67
+ Gumby.UIModule({
68
+ module: 'retina',
69
+ events: ['onRetina'],
70
+ init: function() {
71
+ Gumby.initialize('retina');
72
+ }
73
+ });
74
+ }();