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,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
+ }();
@@ -0,0 +1,203 @@
1
+ /**
2
+ * Gumby Toggles/Switches
3
+ */
4
+ !function() {
5
+
6
+ 'use strict';
7
+
8
+ // Toggle constructor
9
+ function Toggle($el) {
10
+ this.$el = $($el);
11
+ this.targets = [];
12
+ this.on = '';
13
+
14
+ if(this.$el.length) {
15
+ this.init();
16
+ }
17
+ }
18
+
19
+ // Switch constructor
20
+ function Switch($el) {
21
+ this.$el = $($el);
22
+ this.targets = [];
23
+ this.on = '';
24
+
25
+ if(this.$el.length) {
26
+ this.init();
27
+ }
28
+ }
29
+
30
+ // intialise toggles, switches will inherit method
31
+ Toggle.prototype.init = function() {
32
+ var scope = this;
33
+
34
+ // set up module based on attributes
35
+ this.setup();
36
+
37
+ // bind to specified event and trigger
38
+ this.$el.on(this.on, function(e) {
39
+ // stop propagation
40
+ e.stopImmediatePropagation();
41
+
42
+ // only disable default if <a>
43
+ if($(this).prop('tagName') === 'A') {
44
+ e.preventDefault();
45
+ }
46
+
47
+ scope.trigger(scope.triggered);
48
+
49
+ // listen for gumby.trigger to dynamically trigger toggle/switch
50
+ }).on('gumby.trigger', function() {
51
+ scope.trigger(scope.triggered);
52
+ // re-initialize module
53
+ }).on('gumby.initialize', function() {
54
+ scope.setup();
55
+ });
56
+ };
57
+
58
+ // set up module based on attributes
59
+ Toggle.prototype.setup = function() {
60
+ this.targets = this.parseTargets();
61
+ this.on = Gumby.selectAttr.apply(this.$el, ['on']) || Gumby.click;
62
+ this.className = Gumby.selectAttr.apply(this.$el, ['classname']) || 'active';
63
+ };
64
+
65
+ // parse data-for attribute, switches will inherit method
66
+ Toggle.prototype.parseTargets = function() {
67
+ var targetStr = Gumby.selectAttr.apply(this.$el, ['trigger']),
68
+ secondaryTargets = 0,
69
+ targets = [];
70
+
71
+ // no targets so return false
72
+ if(!targetStr) {
73
+ return false;
74
+ }
75
+
76
+ secondaryTargets = targetStr.indexOf('|');
77
+
78
+ // no secondary targets specified so return single target
79
+ if(secondaryTargets === -1) {
80
+ return [$(targetStr)];
81
+ }
82
+
83
+ // return array of both targets, split and return 0, 1
84
+ targets = targetStr.split('|');
85
+ return targets.length > 1 ? [$(targets[0]), $(targets[1])] : [$(targets[0])];
86
+ };
87
+
88
+ // call triggered event and pass target data
89
+ Toggle.prototype.triggered = function() {
90
+ // trigger gumby.onTrigger event and pass array of target status data
91
+ this.$el.trigger('gumby.onTrigger', [this.$el.hasClass(this.className)]);
92
+ };
93
+
94
+ // Switch object inherits from Toggle
95
+ Switch.prototype = new Toggle();
96
+
97
+ // Toggle specific trigger method
98
+ Toggle.prototype.trigger = function(cb) {
99
+ // no targets just toggle active class on toggle
100
+ if(!this.targets) {
101
+ this.$el.toggleClass(this.className);
102
+
103
+ // combine single target with toggle and toggle active class
104
+ } else if(this.targets.length == 1) {
105
+ this.$el.add(this.targets[0]).toggleClass(this.className);
106
+
107
+ // if two targets check active state of first
108
+ // always combine toggle and first target
109
+ } else if(this.targets.length > 1) {
110
+ if(this.targets[0].hasClass(this.className)) {
111
+ this.$el.add(this.targets[0]).removeClass(this.className);
112
+ this.targets[1].addClass(this.className);
113
+ } else {
114
+ this.targets[1].removeClass(this.className);
115
+ this.$el.add(this.targets[0]).addClass(this.className);
116
+ }
117
+ }
118
+
119
+ // call event handler here, applying scope of object Switch/Toggle
120
+ if(cb && typeof cb === 'function') {
121
+ cb.apply(this);
122
+ }
123
+ };
124
+
125
+ // Switch specific trigger method
126
+ Switch.prototype.trigger = function(cb) {
127
+ // no targets just add active class to switch
128
+ if(!this.targets) {
129
+ this.$el.addClass(this.className);
130
+
131
+ // combine single target with switch and add active class
132
+ } else if(this.targets.length == 1) {
133
+ this.$el.add(this.targets[0]).addClass(this.className);
134
+
135
+ // if two targets check active state of first
136
+ // always combine switch and first target
137
+ } else if(this.targets.length > 1) {
138
+ this.$el.add(this.targets[0]).addClass(this.className);
139
+ this.targets[1].removeClass(this.className);
140
+ }
141
+
142
+ // call event handler here, applying scope of object Switch/Toggle
143
+ if(cb && typeof cb === 'function') {
144
+ cb.apply(this);
145
+ }
146
+ };
147
+
148
+ // add toggle initialisation
149
+ Gumby.addInitalisation('toggles', function(all) {
150
+ $('.toggle').each(function() {
151
+ var $this = $(this);
152
+
153
+ // this element has already been initialized
154
+ // and we're only initializing new modules
155
+ if($this.data('isToggle') && !all) {
156
+ return true;
157
+
158
+ // this element has already been initialized
159
+ // and we need to reinitialize it
160
+ } else if($this.data('isToggle') && all) {
161
+ $this.trigger('gumby.initialize');
162
+ }
163
+
164
+ // mark element as initialized
165
+ $this.data('isToggle', true);
166
+ new Toggle($this);
167
+ });
168
+ });
169
+
170
+ // add switches initialisation
171
+ Gumby.addInitalisation('switches', function(all) {
172
+ $('.switch').each(function() {
173
+ var $this = $(this);
174
+
175
+ // this element has already been initialized
176
+ // and we're only initializing new modules
177
+ if($this.data('isSwitch') && !all) {
178
+ return true;
179
+
180
+ // this element has already been initialized
181
+ // and we need to reinitialize it
182
+ } else if($this.data('isSwitch') && all) {
183
+ $this.trigger('gumby.initialize');
184
+ return true;
185
+ }
186
+
187
+ // mark element as initialized
188
+ $this.data('isSwitch', true);
189
+ new Switch($this);
190
+ });
191
+ });
192
+
193
+ // register UI module
194
+ Gumby.UIModule({
195
+ module: 'toggleswitch',
196
+ events: ['trigger', 'onTrigger'],
197
+ init: function() {
198
+ // Run initialize methods
199
+ Gumby.initialize('switches');
200
+ Gumby.initialize('toggles');
201
+ }
202
+ });
203
+ }();
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Gumby jQuery Validation Plugin
3
+ */
4
+ !function($) {
5
+
6
+ 'use strict';
7
+
8
+ function Validation($this, req) {
9
+
10
+ // input and holder .field
11
+ this.$this = $this;
12
+ this.$field = this.$this.parents('.field');
13
+
14
+ // supplied validation function with default length check
15
+ this.req = req || function() {
16
+ return !!this.$this.val().length;
17
+ };
18
+
19
+ // reference to this class
20
+ var scope = this;
21
+
22
+ // checkboxes and radio buttons use gumby.onChange event to validate
23
+ if(this.$this.is('[type=checkbox], [type=radio]')) {
24
+ this.$field = this.$this.parent('label');
25
+ this.$field.on('gumby.onChange', function() {
26
+ scope.validate();
27
+ });
28
+
29
+ // selects validate on change
30
+ } else if(this.$this.is('select')) {
31
+ this.$field = this.$this.parents('.picker');
32
+ this.$field.on('change', function() {
33
+ scope.validate();
34
+ });
35
+
36
+ // others (text input, textarea) use blur
37
+ } else {
38
+ this.$this.on('blur', function(e) {
39
+ // ignore tab
40
+ if(e.which !== 9) {
41
+ scope.validate();
42
+ }
43
+ });
44
+ }
45
+ }
46
+
47
+ // validate field
48
+ Validation.prototype.validate = function() {
49
+
50
+ var result = this.req(this.$this);
51
+
52
+ // failed
53
+ if(!result) {
54
+ this.$field.removeClass('success').addClass('danger');
55
+
56
+ // passed
57
+ } else {
58
+ //} else if(this.$field.hasClass('danger')) {
59
+ this.$field.removeClass('danger').addClass('success');
60
+ }
61
+
62
+ return result;
63
+ };
64
+
65
+ // jQuery plugin definition
66
+ $.fn.validation = function(options) {
67
+
68
+ var // extend params with defaults
69
+ settings = $.extend({
70
+ submit : false,
71
+ fail: false,
72
+ required : []
73
+ }, options),
74
+ // store validation objects
75
+ validations = [];
76
+
77
+ // init each form plugin is called on
78
+ return this.each(function() {
79
+
80
+ // no required fields so plugin is pointless
81
+ if(!settings.required.length) {
82
+ return false;
83
+ }
84
+
85
+ var $this = $(this),
86
+ reqLength = settings.required.length,
87
+ i;
88
+
89
+ // loop round each required field and instantiate new validation object
90
+ for(i = 0; i < reqLength; i++) {
91
+ validations.push(new Validation(
92
+ $this.find('[name="'+settings.required[i].name+'"]'),
93
+ settings.required[i].validate || false
94
+ ));
95
+ }
96
+
97
+ // hijack submit event
98
+ $this.on('submit', function(e) {
99
+
100
+ // reference to whole form pass/fail
101
+ var failed = false;
102
+
103
+ // if no passed attribute found we should halt form submit
104
+ if(!$this.data('passed')) {
105
+ e.preventDefault();
106
+
107
+ // loop round validation objects and validate each
108
+ var reqLength = validations.length, i;
109
+ for(i = 0; i < reqLength; i++) {
110
+ if(!validations[i].validate()) {
111
+ failed = true;
112
+ }
113
+ }
114
+
115
+ // passed
116
+ if(!failed) {
117
+ // if submit method present call that otherwise submit form
118
+ if(settings.submit && typeof settings.submit === 'function') {
119
+ settings.submit($this.serializeArray());
120
+ return;
121
+ }
122
+
123
+ // store passed bool and re-submit
124
+ $this.data('passed', true).submit();
125
+
126
+ // failed
127
+ } else {
128
+ // call fail method if present
129
+ if(settings.fail && typeof settings.fail === 'function') {
130
+ settings.fail();
131
+ return;
132
+ }
133
+ }
134
+ }
135
+ });
136
+ });
137
+ };
138
+ }(jQuery);