gumby-framework 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 +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
|
+
}();
|