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.
- data/.gitignore +3 -0
- data/LICENSE.txt +22 -0
- data/README.md +73 -0
- data/Rakefile +1 -0
- data/gumby.gemspec +20 -0
- data/lib/gumby.rb +8 -0
- data/lib/gumby/version.rb +5 -0
- data/vendor/assets/fonts/icons/entypo.eot +0 -0
- data/vendor/assets/fonts/icons/entypo.ttf +0 -0
- data/vendor/assets/fonts/icons/entypo.woff +0 -0
- data/vendor/assets/javascripts/gumby.js +150 -0
- data/vendor/assets/javascripts/gumby.min.js +1 -0
- data/vendor/assets/javascripts/ui/gumby.checkbox.js +84 -0
- data/vendor/assets/javascripts/ui/gumby.fittext.js +107 -0
- data/vendor/assets/javascripts/ui/gumby.fixed.js +206 -0
- data/vendor/assets/javascripts/ui/gumby.navbar.js +115 -0
- data/vendor/assets/javascripts/ui/gumby.radiobtn.js +74 -0
- data/vendor/assets/javascripts/ui/gumby.retina.js +74 -0
- data/vendor/assets/javascripts/ui/gumby.skiplink.js +145 -0
- data/vendor/assets/javascripts/ui/gumby.tabs.js +71 -0
- data/vendor/assets/javascripts/ui/gumby.toggleswitch.js +203 -0
- data/vendor/assets/javascripts/ui/jquery.validation.js +138 -0
- data/vendor/assets/stylesheets/gumby.css +1876 -0
- metadata +101 -0
@@ -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);
|