gumby-framework 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +71 -0
- data/Rakefile +1 -0
- data/gumby-framework.gemspec +22 -0
- data/lib/gumby-framework.rb +8 -0
- data/lib/gumby-framework/version.rb +5 -0
- data/vendor/assets/fonts/humans.txt +47 -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 +171 -0
- data/vendor/assets/javascripts/ui/gumby.checkbox.js +86 -0
- data/vendor/assets/javascripts/ui/gumby.fixed.js +111 -0
- data/vendor/assets/javascripts/ui/gumby.radiobtn.js +81 -0
- data/vendor/assets/javascripts/ui/gumby.retina.js +74 -0
- data/vendor/assets/javascripts/ui/gumby.skiplink.js +113 -0
- data/vendor/assets/javascripts/ui/gumby.tabs.js +70 -0
- data/vendor/assets/javascripts/ui/gumby.toggleswitch.js +187 -0
- data/vendor/assets/javascripts/ui/jquery.validation.js +138 -0
- data/vendor/assets/stylesheets/gumby.css +1820 -0
- metadata +100 -0
@@ -0,0 +1,111 @@
|
|
1
|
+
/**
|
2
|
+
* Gumby Fixed
|
3
|
+
*/
|
4
|
+
!function() {
|
5
|
+
|
6
|
+
'use strict';
|
7
|
+
|
8
|
+
function Fixed($el) {
|
9
|
+
this.$el = $el;
|
10
|
+
this.$holder = Gumby.selectAttr.apply(this.$el, ['holder']);
|
11
|
+
this.fixedPoint = Gumby.selectAttr.apply(this.$el, ['fixed']);
|
12
|
+
this.unfixPoint = false;
|
13
|
+
|
14
|
+
// if holder attr set then create jQuery object
|
15
|
+
// otherwise use window for scrolling cals
|
16
|
+
if(this.$holder) {
|
17
|
+
this.$holder = $(this.$holder);
|
18
|
+
} else {
|
19
|
+
this.$holder = $(window);
|
20
|
+
}
|
21
|
+
|
22
|
+
// fix/unfix points specified
|
23
|
+
if(this.fixedPoint.indexOf('|') > -1) {
|
24
|
+
var points = this.fixedPoint.split('|');
|
25
|
+
this.fixedPoint = points[0];
|
26
|
+
this.unfixPoint = points[1];
|
27
|
+
}
|
28
|
+
|
29
|
+
// parse possible parameters
|
30
|
+
this.fixedPoint = this.parseAttrValue(this.fixedPoint);
|
31
|
+
if(this.unfixPoint) {
|
32
|
+
this.unfixPoint = this.parseAttrValue(this.unfixPoint);
|
33
|
+
}
|
34
|
+
|
35
|
+
var scope = this;
|
36
|
+
this.$holder.scroll(function() {
|
37
|
+
scope.scroll();
|
38
|
+
});
|
39
|
+
}
|
40
|
+
|
41
|
+
// handle scroll event on window/specified holder
|
42
|
+
Fixed.prototype.scroll = function() {
|
43
|
+
var offset = this.$holder.scrollTop(),
|
44
|
+
fixedPoint = this.fixedPoint,
|
45
|
+
unfixPoint = this.unfixPoint,
|
46
|
+
endPoint = this.endPoint;
|
47
|
+
|
48
|
+
// if fixed point, unfix point or end point are DOM fragements
|
49
|
+
// then re-calculate values as could have been updated
|
50
|
+
fixedPoint = fixedPoint instanceof jQuery ? this.fixedPoint.offset().top : this.fixedPoint;
|
51
|
+
unfixPoint = unfixPoint instanceof jQuery ? this.unfixPoint.offset().top : this.unfixPoint;
|
52
|
+
|
53
|
+
// ensure unfix point is never reached if not set
|
54
|
+
if(!unfixPoint) {
|
55
|
+
unfixPoint = offset * 2;
|
56
|
+
}
|
57
|
+
|
58
|
+
// scrolled past fixed point and no fixed class present
|
59
|
+
if((offset >= fixedPoint) && (offset < unfixPoint) && !this.$el.hasClass('fixed')) {
|
60
|
+
this.$el.addClass('fixed').trigger('gumby.onFixed');
|
61
|
+
|
62
|
+
// before fixed point, pass 0 to onUnfixed event
|
63
|
+
} else if((offset <= fixedPoint) && this.$el.hasClass('fixed')) {
|
64
|
+
this.$el.removeClass('fixed').trigger('gumby.onUnfixed', 0);
|
65
|
+
}
|
66
|
+
|
67
|
+
// after unfix point, pass 1 to onUnfixed event
|
68
|
+
// separate conditional as should override
|
69
|
+
if(unfixPoint && (offset >= unfixPoint) && this.$el.hasClass('fixed')) {
|
70
|
+
this.$el.removeClass('fixed').trigger('gumby.onUnfixed', 1);
|
71
|
+
}
|
72
|
+
};
|
73
|
+
|
74
|
+
// parse attribute values, could be px, top, selector
|
75
|
+
Fixed.prototype.parseAttrValue = function(attr) {
|
76
|
+
// px value fixed point
|
77
|
+
if($.isNumeric(attr)) {
|
78
|
+
return Number(attr);
|
79
|
+
// 'top' string fixed point
|
80
|
+
} else if(attr === 'top') {
|
81
|
+
return this.$el.offset().top;
|
82
|
+
// selector specified
|
83
|
+
} else {
|
84
|
+
var $el = $(attr);
|
85
|
+
return $el.length ? $el : false;
|
86
|
+
}
|
87
|
+
};
|
88
|
+
|
89
|
+
// add initialisation
|
90
|
+
Gumby.addInitalisation('fixed', function() {
|
91
|
+
$('[data-fixed],[gumby-fixed],[fixed]').each(function() {
|
92
|
+
var $this = $(this);
|
93
|
+
// this element has already been initialized
|
94
|
+
if($this.data('isFixed')) {
|
95
|
+
return true;
|
96
|
+
}
|
97
|
+
// mark element as initialized
|
98
|
+
$this.data('isFixed', true);
|
99
|
+
new Fixed($this);
|
100
|
+
});
|
101
|
+
});
|
102
|
+
|
103
|
+
// register UI module
|
104
|
+
Gumby.UIModule({
|
105
|
+
module: 'fixed',
|
106
|
+
events: ['onFixed', 'onUnfixed'],
|
107
|
+
init: function() {
|
108
|
+
Gumby.initialize('fixed');
|
109
|
+
}
|
110
|
+
});
|
111
|
+
}();
|
@@ -0,0 +1,81 @@
|
|
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
|
+
scope.click(e);
|
16
|
+
}).on('gumby.check', function() {
|
17
|
+
scope.update();
|
18
|
+
});
|
19
|
+
|
20
|
+
// update any .checked checkboxes on load
|
21
|
+
if(scope.$el.hasClass('checked')) {
|
22
|
+
scope.update();
|
23
|
+
}
|
24
|
+
}
|
25
|
+
|
26
|
+
// handle radio button click event
|
27
|
+
RadioBtn.prototype.click = function(e) {
|
28
|
+
|
29
|
+
// element responsible for event trigger
|
30
|
+
var $target = $(e.target);
|
31
|
+
|
32
|
+
// prevent propagation
|
33
|
+
e.stopPropagation();
|
34
|
+
|
35
|
+
// prevent radio button checking, we'll do that manually
|
36
|
+
e.preventDefault();
|
37
|
+
|
38
|
+
// check radio button
|
39
|
+
this.update();
|
40
|
+
};
|
41
|
+
|
42
|
+
// check radio button, uncheck all others in name group
|
43
|
+
RadioBtn.prototype.update = function() {
|
44
|
+
var // this specific radio button
|
45
|
+
$input = this.$el.find('input[type=radio]'),
|
46
|
+
// the group of radio buttons
|
47
|
+
group = 'input[name="'+$input.attr('name')+'"]';
|
48
|
+
|
49
|
+
// uncheck radio buttons in same group - uncheck input, remove checked class, remove <i>
|
50
|
+
$('.radio').has(group).removeClass('checked')
|
51
|
+
.find('input').attr('checked', false).end()
|
52
|
+
.find('i').remove();
|
53
|
+
|
54
|
+
// check this radio button - check input, add checked class, append <i>
|
55
|
+
$input.attr('checked', true);
|
56
|
+
this.$el.append('<i class="icon-dot" />').addClass('checked').trigger('gumby.onChange');
|
57
|
+
};
|
58
|
+
|
59
|
+
// add initialisation
|
60
|
+
Gumby.addInitalisation('radiobtns', function() {
|
61
|
+
$('.radio').each(function() {
|
62
|
+
var $this = $(this);
|
63
|
+
// this element has already been initialized
|
64
|
+
if($this.data('isRadioBtn')) {
|
65
|
+
return true;
|
66
|
+
}
|
67
|
+
// mark element as initialized
|
68
|
+
$this.data('isRadioBtn', true);
|
69
|
+
new RadioBtn($this);
|
70
|
+
});
|
71
|
+
});
|
72
|
+
|
73
|
+
// register UI module
|
74
|
+
Gumby.UIModule({
|
75
|
+
module: 'radiobtn',
|
76
|
+
events: ['onChange', 'check'],
|
77
|
+
init: function() {
|
78
|
+
Gumby.initialize('radiobtns');
|
79
|
+
}
|
80
|
+
});
|
81
|
+
}();
|
@@ -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,113 @@
|
|
1
|
+
/**
|
2
|
+
* Gumby SkipLink
|
3
|
+
*/
|
4
|
+
!function() {
|
5
|
+
|
6
|
+
'use strict';
|
7
|
+
|
8
|
+
function SkipLink($el) {
|
9
|
+
|
10
|
+
this.$el = $el;
|
11
|
+
this.animateElement = $.browser.webkit ? 'body' : 'html';
|
12
|
+
this.targetPos = 0;
|
13
|
+
this.duration = Number(Gumby.selectAttr.apply(this.$el, ['duration'])) || 200;
|
14
|
+
this.offset = Gumby.selectAttr.apply(this.$el, ['offset']) || false;
|
15
|
+
this.easing = Gumby.selectAttr.apply(this.$el, ['easing']) || 'swing';
|
16
|
+
|
17
|
+
var scope = this;
|
18
|
+
|
19
|
+
// skip to target element on click or trigger of gumby.skipTo event
|
20
|
+
this.$el.on(Gumby.click+' gumby.skip', function(e) {
|
21
|
+
e.preventDefault();
|
22
|
+
// calculate target on each click
|
23
|
+
// other UI interactions could effect this
|
24
|
+
scope.calculateTarget();
|
25
|
+
});
|
26
|
+
}
|
27
|
+
|
28
|
+
// calculate target px point to skip to
|
29
|
+
SkipLink.prototype.calculateTarget = function() {
|
30
|
+
|
31
|
+
var scope = this,
|
32
|
+
target = Gumby.selectAttr.apply(this.$el, ['goto']),
|
33
|
+
$target;
|
34
|
+
|
35
|
+
// 'top' specified so target is 0px
|
36
|
+
if(target == 'top') {
|
37
|
+
this.targetPos = 0;
|
38
|
+
|
39
|
+
// px point specified
|
40
|
+
} else if($.isNumeric(target)) {
|
41
|
+
this.targetPos = Number(target);
|
42
|
+
} else {
|
43
|
+
|
44
|
+
// check for element with target as selector
|
45
|
+
$target = $(target);
|
46
|
+
|
47
|
+
// target does not exist, we need a target
|
48
|
+
if(!$target) {
|
49
|
+
return false;
|
50
|
+
}
|
51
|
+
|
52
|
+
this.targetPos = $target.offset().top;
|
53
|
+
}
|
54
|
+
|
55
|
+
// skip to target
|
56
|
+
this.skipTo();
|
57
|
+
};
|
58
|
+
|
59
|
+
// animate body, html scrollTop value to target px point
|
60
|
+
SkipLink.prototype.skipTo = function() {
|
61
|
+
var scope = this;
|
62
|
+
|
63
|
+
// slide to position of target
|
64
|
+
$(scope.animateElement).animate({
|
65
|
+
'scrollTop' : this.calculateOffset()
|
66
|
+
}, this.duration, this.easing, function() {
|
67
|
+
scope.$el.trigger('gumby.onComplete');
|
68
|
+
});
|
69
|
+
};
|
70
|
+
|
71
|
+
// calculate offset with current target point
|
72
|
+
SkipLink.prototype.calculateOffset = function() {
|
73
|
+
// no offset so return target here
|
74
|
+
if(!this.offset) {
|
75
|
+
return this.targetPos;
|
76
|
+
}
|
77
|
+
|
78
|
+
// negative / positive
|
79
|
+
var op = this.offset.substr(0, 1),
|
80
|
+
off = Number(this.offset.substr(1, this.offset.length));
|
81
|
+
|
82
|
+
// subtract offset from target position
|
83
|
+
if(op === '-') {
|
84
|
+
return this.targetPos - off;
|
85
|
+
// add offset to target position
|
86
|
+
} else if(op === '+') {
|
87
|
+
return this.targetPos + off;
|
88
|
+
}
|
89
|
+
};
|
90
|
+
|
91
|
+
// add initialisation
|
92
|
+
Gumby.addInitalisation('skiplinks', function() {
|
93
|
+
$('.skiplink > a, .skip').each(function() {
|
94
|
+
var $this = $(this);
|
95
|
+
// this element has already been initialized
|
96
|
+
if($this.data('isSkipLink')) {
|
97
|
+
return true;
|
98
|
+
}
|
99
|
+
// mark element as initialized
|
100
|
+
$this.data('isSkipLink', true);
|
101
|
+
new SkipLink($this);
|
102
|
+
});
|
103
|
+
});
|
104
|
+
|
105
|
+
// register UI module
|
106
|
+
Gumby.UIModule({
|
107
|
+
module: 'skiplink',
|
108
|
+
events: ['onComplete', 'skip'],
|
109
|
+
init: function() {
|
110
|
+
Gumby.initialize('skiplinks');
|
111
|
+
}
|
112
|
+
});
|
113
|
+
}();
|
@@ -0,0 +1,70 @@
|
|
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.preventDefault();
|
19
|
+
scope.click($(this));
|
20
|
+
});
|
21
|
+
|
22
|
+
// listen for gumby.set value for dynamically set tabs
|
23
|
+
this.$el.on('gumby.set', function(e, index) {
|
24
|
+
scope.set(e, index);
|
25
|
+
});
|
26
|
+
}
|
27
|
+
|
28
|
+
// handle tab nav click event
|
29
|
+
Tabs.prototype.click = function($this) {
|
30
|
+
// index of item to activate
|
31
|
+
var index = $this.parent().index();
|
32
|
+
|
33
|
+
// deactivate other tab navigation and content
|
34
|
+
this.$nav.add(this.$content).removeClass('active');
|
35
|
+
|
36
|
+
// activate this tab nav link and content
|
37
|
+
this.$nav.eq(index).add(this.$content.eq(index)).addClass('active');
|
38
|
+
|
39
|
+
// trigger gumby.change event and pass current active tab index
|
40
|
+
this.$el.trigger('gumby.onChange', index);
|
41
|
+
};
|
42
|
+
|
43
|
+
// set specific tab
|
44
|
+
Tabs.prototype.set = function(e, index) {
|
45
|
+
this.$nav.eq(index).find('a').trigger(Gumby.click);
|
46
|
+
};
|
47
|
+
|
48
|
+
// add initialisation
|
49
|
+
Gumby.addInitalisation('tabs', function() {
|
50
|
+
$('.tabs').each(function() {
|
51
|
+
var $this = $(this);
|
52
|
+
// this element has already been initialized
|
53
|
+
if($this.data('isTabs')) {
|
54
|
+
return true;
|
55
|
+
}
|
56
|
+
// mark element as initialized
|
57
|
+
$this.data('isTabs', true);
|
58
|
+
new Tabs($this);
|
59
|
+
});
|
60
|
+
});
|
61
|
+
|
62
|
+
// register UI module
|
63
|
+
Gumby.UIModule({
|
64
|
+
module: 'tabs',
|
65
|
+
events: ['onChange', 'set'],
|
66
|
+
init: function() {
|
67
|
+
Gumby.initialize('tabs');
|
68
|
+
}
|
69
|
+
});
|
70
|
+
}();
|