gumby2-rails 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.
Files changed (72) hide show
  1. data/.gitignore +17 -0
  2. data/Gemfile +4 -0
  3. data/LICENSE.txt +22 -0
  4. data/README.md +29 -0
  5. data/Rakefile +1 -0
  6. data/gumby2-rails.gemspec +19 -0
  7. data/lib/gumby2-rails/version.rb +5 -0
  8. data/lib/gumby2-rails.rb +9 -0
  9. data/vendor/assets/.DS_Store +0 -0
  10. data/vendor/assets/fonts/icons/entypo.eot +0 -0
  11. data/vendor/assets/fonts/icons/entypo.ttf +0 -0
  12. data/vendor/assets/fonts/icons/entypo.woff +0 -0
  13. data/vendor/assets/js/libs/gumby.init.js +27 -0
  14. data/vendor/assets/js/libs/gumby.js +150 -0
  15. data/vendor/assets/js/libs/gumby.min.js +1 -0
  16. data/vendor/assets/js/libs/jquery-1.10.1.min.js +6 -0
  17. data/vendor/assets/js/libs/jquery-2.0.2.min.js +6 -0
  18. data/vendor/assets/js/libs/jquery.mobile.custom.min.js +3 -0
  19. data/vendor/assets/js/libs/modernizr-2.6.2.min.js +4 -0
  20. data/vendor/assets/js/libs/ui/gumby.checkbox.js +90 -0
  21. data/vendor/assets/js/libs/ui/gumby.fittext.js +107 -0
  22. data/vendor/assets/js/libs/ui/gumby.fixed.js +206 -0
  23. data/vendor/assets/js/libs/ui/gumby.navbar.js +115 -0
  24. data/vendor/assets/js/libs/ui/gumby.radiobtn.js +79 -0
  25. data/vendor/assets/js/libs/ui/gumby.retina.js +74 -0
  26. data/vendor/assets/js/libs/ui/gumby.skiplink.js +145 -0
  27. data/vendor/assets/js/libs/ui/gumby.tabs.js +71 -0
  28. data/vendor/assets/js/libs/ui/gumby.toggleswitch.js +203 -0
  29. data/vendor/assets/js/libs/ui/jquery.validation.js +138 -0
  30. data/vendor/assets/js/main.js +25 -0
  31. data/vendor/assets/js/plugins.js +8 -0
  32. data/vendor/assets/stylesheets/.DS_Store +0 -0
  33. data/vendor/assets/stylesheets/gumby.css +1876 -0
  34. data/vendor/assets/stylesheets/sass/_base.scss +71 -0
  35. data/vendor/assets/stylesheets/sass/_custom.scss +1 -0
  36. data/vendor/assets/stylesheets/sass/_fonts.scss +28 -0
  37. data/vendor/assets/stylesheets/sass/_grid.scss +273 -0
  38. data/vendor/assets/stylesheets/sass/_typography.scss +274 -0
  39. data/vendor/assets/stylesheets/sass/extensions/modular-scale/lib/modular-scale.rb +129 -0
  40. data/vendor/assets/stylesheets/sass/extensions/modular-scale/stylesheets/_modular-scale.scss +310 -0
  41. data/vendor/assets/stylesheets/sass/extensions/sassy-math/lib/sassy-math.rb +159 -0
  42. data/vendor/assets/stylesheets/sass/extensions/sassy-math/stylesheets/_math.scss +310 -0
  43. data/vendor/assets/stylesheets/sass/functions/_all.scss +15 -0
  44. data/vendor/assets/stylesheets/sass/functions/_breakpoints.scss +11 -0
  45. data/vendor/assets/stylesheets/sass/functions/_buttons.scss +44 -0
  46. data/vendor/assets/stylesheets/sass/functions/_clearfix.scss +25 -0
  47. data/vendor/assets/stylesheets/sass/functions/_forms.scss +18 -0
  48. data/vendor/assets/stylesheets/sass/functions/_grid-calc.scss +59 -0
  49. data/vendor/assets/stylesheets/sass/functions/_height-calc.scss +6 -0
  50. data/vendor/assets/stylesheets/sass/functions/_line-and-height.scss +7 -0
  51. data/vendor/assets/stylesheets/sass/functions/_responsivity.scss +34 -0
  52. data/vendor/assets/stylesheets/sass/functions/_semantic-grid.scss +187 -0
  53. data/vendor/assets/stylesheets/sass/functions/_strip-units.scss +5 -0
  54. data/vendor/assets/stylesheets/sass/functions/_typography.scss +15 -0
  55. data/vendor/assets/stylesheets/sass/functions/_visibility.scss +17 -0
  56. data/vendor/assets/stylesheets/sass/gumby.scss +37 -0
  57. data/vendor/assets/stylesheets/sass/ui/_all.scss +10 -0
  58. data/vendor/assets/stylesheets/sass/ui/_buttons.scss +151 -0
  59. data/vendor/assets/stylesheets/sass/ui/_forms.scss +379 -0
  60. data/vendor/assets/stylesheets/sass/ui/_icons.scss +37 -0
  61. data/vendor/assets/stylesheets/sass/ui/_images.scss +21 -0
  62. data/vendor/assets/stylesheets/sass/ui/_labels.scss +86 -0
  63. data/vendor/assets/stylesheets/sass/ui/_navbar.scss +417 -0
  64. data/vendor/assets/stylesheets/sass/ui/_tables.scss +87 -0
  65. data/vendor/assets/stylesheets/sass/ui/_tabs.scss +109 -0
  66. data/vendor/assets/stylesheets/sass/ui/_toggles.scss +69 -0
  67. data/vendor/assets/stylesheets/sass/ui/_video.scss +22 -0
  68. data/vendor/assets/stylesheets/sass/var/_lists.scss +20 -0
  69. data/vendor/assets/stylesheets/sass/var/_settings.scss +149 -0
  70. data/vendor/assets/stylesheets/sass/var/icons/_entypo-icon-list.scss +286 -0
  71. data/vendor/assets/stylesheets/sass/var/icons/_entypo.scss +294 -0
  72. metadata +116 -0
@@ -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,79 @@
1
+ /**
2
+ * Gumby RadioBtn
3
+ */
4
+ !function() {
5
+
6
+ 'use strict';
7
+
8
+ function RadioBtn($el) {
9
+
10
+ this.$el = $el;
11
+ this.$input = this.$el.find('input[type=radio]');
12
+
13
+ var scope = this;
14
+
15
+ // listen for click event and custom gumby check event
16
+ this.$el.on(Gumby.click, function(e) {
17
+ // prevent propagation
18
+ e.stopImmediatePropagation();
19
+
20
+ // prevent radio button checking, we'll do that manually
21
+ e.preventDefault();
22
+
23
+ // do nothing if radio is disabled
24
+ if (scope.$input.is('[disabled]')) {
25
+ return;
26
+ }
27
+
28
+ // check radio button
29
+ scope.update();
30
+ }).on('gumby.check', function() {
31
+ scope.update();
32
+ });
33
+
34
+ // update any .checked checkboxes on load
35
+ if(scope.$el.hasClass('checked')) {
36
+ scope.update();
37
+ }
38
+ }
39
+
40
+ // check radio button, uncheck all others in name group
41
+ RadioBtn.prototype.update = function() {
42
+ var $span = this.$el.find('span'),
43
+ // the group of radio buttons
44
+ group = 'input[name="'+this.$input.attr('name')+'"]';
45
+
46
+ // uncheck radio buttons in same group - uncheck input, remove checked class, remove <i>
47
+ $('.radio').has(group).removeClass('checked')
48
+ .find('input').prop('checked', false).end()
49
+ .find('i').remove();
50
+
51
+ // check this radio button - check input, add checked class, append <i>
52
+ this.$input.prop('checked', true);
53
+ $span.append('<i class="icon-dot" />');
54
+ this.$el.addClass('checked').trigger('gumby.onChange');
55
+ };
56
+
57
+ // add initialisation
58
+ Gumby.addInitalisation('radiobtns', function() {
59
+ $('.radio').each(function() {
60
+ var $this = $(this);
61
+ // this element has already been initialized
62
+ if($this.data('isRadioBtn')) {
63
+ return true;
64
+ }
65
+ // mark element as initialized
66
+ $this.data('isRadioBtn', true);
67
+ new RadioBtn($this);
68
+ });
69
+ });
70
+
71
+ // register UI module
72
+ Gumby.UIModule({
73
+ module: 'radiobtn',
74
+ events: ['onChange', 'check'],
75
+ init: function() {
76
+ Gumby.initialize('radiobtns');
77
+ }
78
+ });
79
+ }();
@@ -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
+ }();
@@ -0,0 +1,145 @@
1
+ /**
2
+ * Gumby SkipLink
3
+ */
4
+ !function() {
5
+
6
+ 'use strict';
7
+
8
+ function SkipLink($el) {
9
+ this.$el = $el;
10
+ this.targetPos = 0;
11
+ this.duration = 0;
12
+ this.offset = false;
13
+ this.easing = '';
14
+ this.update = false;
15
+
16
+ // set up module based on attributes
17
+ this.setup();
18
+
19
+ var scope = this;
20
+
21
+ // skip to target element on click or trigger of gumby.skipTo event
22
+ this.$el.on(Gumby.click+' gumby.skip', function(e) {
23
+
24
+ e.stopImmediatePropagation();
25
+ e.preventDefault();
26
+
27
+ // calculate target on each click if update var set to true
28
+ if(scope.update) {
29
+ scope.calculateTarget(scope.skipTo);
30
+
31
+ // skip straight to target
32
+ } else {
33
+ scope.skipTo();
34
+ }
35
+ }).on('gumby.initialize', function() {
36
+ scope.setup();
37
+ });
38
+ }
39
+
40
+ // set up module based on attributes
41
+ SkipLink.prototype.setup = function() {
42
+ this.duration = Number(Gumby.selectAttr.apply(this.$el, ['duration'])) || 200;
43
+ this.offset = Gumby.selectAttr.apply(this.$el, ['offset']) || false;
44
+ this.easing = Gumby.selectAttr.apply(this.$el, ['easing']) || 'swing';
45
+ this.update = Gumby.selectAttr.apply(this.$el, ['update']) ? true : false;
46
+
47
+ this.calculateTarget();
48
+ };
49
+
50
+ // calculate target px point to skip to
51
+ SkipLink.prototype.calculateTarget = function(cb) {
52
+
53
+ var scope = this,
54
+ target = Gumby.selectAttr.apply(this.$el, ['goto']),
55
+ $target;
56
+
57
+ // 'top' specified so target is 0px
58
+ if(target == 'top') {
59
+ this.targetPos = 0;
60
+
61
+ // px point specified
62
+ } else if($.isNumeric(target)) {
63
+ this.targetPos = Number(target);
64
+ } else {
65
+
66
+ // check for element with target as selector
67
+ $target = $(target);
68
+
69
+ // target does not exist, we need a target
70
+ if(!$target) {
71
+ return false;
72
+ }
73
+
74
+ this.targetPos = $target.offset().top;
75
+ }
76
+
77
+ if(cb) {
78
+ cb.apply(this);
79
+ }
80
+ };
81
+
82
+ // animate body, html scrollTop value to target px point
83
+ SkipLink.prototype.skipTo = function() {
84
+ var scope = this;
85
+
86
+ // slide to position of target
87
+ $('html,body').animate({
88
+ 'scrollTop' : this.calculateOffset()
89
+ }, this.duration, this.easing).promise().done(function() {
90
+ scope.$el.trigger('gumby.onComplete');
91
+ });
92
+ };
93
+
94
+ // calculate offset with current target point
95
+ SkipLink.prototype.calculateOffset = function() {
96
+ // no offset so return target here
97
+ if(!this.offset) {
98
+ return this.targetPos;
99
+ }
100
+
101
+ // negative / positive
102
+ var op = this.offset.substr(0, 1),
103
+ off = Number(this.offset.substr(1, this.offset.length));
104
+
105
+ // subtract offset from target position
106
+ if(op === '-') {
107
+ return this.targetPos - off;
108
+ // add offset to target position
109
+ } else if(op === '+') {
110
+ return this.targetPos + off;
111
+ }
112
+ };
113
+
114
+ // add initialisation
115
+ Gumby.addInitalisation('skiplinks', function(all) {
116
+ $('.skiplink > a, .skip').each(function() {
117
+ var $this = $(this);
118
+
119
+ // this element has already been initialized
120
+ // and we're only initializing new modules
121
+ if($this.data('isSkipLink') && !all) {
122
+ return true;
123
+
124
+ // this element has already been initialized
125
+ // and we need to reinitialize it
126
+ } else if($this.data('isSkipLink') && all) {
127
+ $this.trigger('gumby.initialize');
128
+ return true;
129
+ }
130
+
131
+ // mark element as initialized
132
+ $this.data('isSkipLink', true);
133
+ new SkipLink($this);
134
+ });
135
+ });
136
+
137
+ // register UI module
138
+ Gumby.UIModule({
139
+ module: 'skiplink',
140
+ events: ['onComplete', 'skip'],
141
+ init: function() {
142
+ Gumby.initialize('skiplinks');
143
+ }
144
+ });
145
+ }();
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Gumby Tabs
3
+ */
4
+ !function() {
5
+
6
+ 'use strict';
7
+
8
+ function Tabs($el) {
9
+
10
+ this.$el = $el;
11
+ this.$nav = this.$el.find('ul.tab-nav > li');
12
+ this.$content = this.$el.find('.tab-content');
13
+
14
+ var scope = this;
15
+
16
+ // listen for click event on tab nav and custom gumby set event
17
+ this.$nav.children('a').on(Gumby.click, function(e) {
18
+ e.stopImmediatePropagation();
19
+ e.preventDefault();
20
+ scope.click($(this));
21
+ });
22
+
23
+ // listen for gumby.set value for dynamically set tabs
24
+ this.$el.on('gumby.set', function(e, index) {
25
+ scope.set(e, index);
26
+ });
27
+ }
28
+
29
+ // handle tab nav click event
30
+ Tabs.prototype.click = function($this) {
31
+ // index of item to activate
32
+ var index = $this.parent().index();
33
+
34
+ // deactivate other tab navigation and content
35
+ this.$nav.add(this.$content).removeClass('active');
36
+
37
+ // activate this tab nav link and content
38
+ this.$nav.eq(index).add(this.$content.eq(index)).addClass('active');
39
+
40
+ // trigger gumby.change event and pass current active tab index
41
+ this.$el.trigger('gumby.onChange', index);
42
+ };
43
+
44
+ // set specific tab
45
+ Tabs.prototype.set = function(e, index) {
46
+ this.$nav.eq(index).find('a').trigger(Gumby.click);
47
+ };
48
+
49
+ // add initialisation
50
+ Gumby.addInitalisation('tabs', function() {
51
+ $('.tabs').each(function() {
52
+ var $this = $(this);
53
+ // this element has already been initialized
54
+ if($this.data('isTabs')) {
55
+ return true;
56
+ }
57
+ // mark element as initialized
58
+ $this.data('isTabs', true);
59
+ new Tabs($this);
60
+ });
61
+ });
62
+
63
+ // register UI module
64
+ Gumby.UIModule({
65
+ module: 'tabs',
66
+ events: ['onChange', 'set'],
67
+ init: function() {
68
+ Gumby.initialize('tabs');
69
+ }
70
+ });
71
+ }();