gumby 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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);
|