gumby-rails 1.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 +30 -0
- data/Rakefile +1 -0
- data/gumby-rails.gemspec +22 -0
- data/lib/gumby-rails.rb +8 -0
- data/lib/gumby-rails/version.rb +5 -0
- data/vendor/assets/javascripts/gumby.js +361 -0
- data/vendor/assets/stylesheets/gumby-hybrid.css +4 -0
- data/vendor/assets/stylesheets/gumby/12col.css +441 -0
- data/vendor/assets/stylesheets/gumby/16col.css +459 -0
- data/vendor/assets/stylesheets/gumby/hybrid.css +543 -0
- data/vendor/assets/stylesheets/gumby/style.css +9 -0
- data/vendor/assets/stylesheets/gumby/text.css +50 -0
- data/vendor/assets/stylesheets/gumby/ui.css +1613 -0
- data/vendor/assets/stylesheets/gumby12.css +4 -0
- data/vendor/assets/stylesheets/gumby16.css +4 -0
- metadata +96 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Fábio Luiz Nery de Miranda
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# Gumby::Rails
|
2
|
+
|
3
|
+
A rails gem for http://gumbyframework.com/ assets.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'gumby-rails'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install gumby-rails
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
|
22
|
+
|
23
|
+
|
24
|
+
## Contributing
|
25
|
+
|
26
|
+
1. Fork it
|
27
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
28
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
29
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
30
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/gumby-rails.gemspec
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'gumby-rails/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "gumby-rails"
|
8
|
+
gem.version = Gumby::Rails::VERSION
|
9
|
+
gem.authors = ["Fábio Luiz Nery de Miranda"]
|
10
|
+
gem.email = ["fabio@miranti.net.br"]
|
11
|
+
gem.description = %q{A rails gem for http://gumbyframework.com assets}
|
12
|
+
gem.summary = %q{}
|
13
|
+
gem.homepage = "https://github.com/fabiolnm/gumby-rails"
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = ["lib"]
|
19
|
+
|
20
|
+
gem.add_development_dependency "jquery-rails"
|
21
|
+
gem.add_development_dependency "modernizr-rails"
|
22
|
+
end
|
data/lib/gumby-rails.rb
ADDED
@@ -0,0 +1,361 @@
|
|
1
|
+
/* Gumby JS */
|
2
|
+
|
3
|
+
(function ($) {
|
4
|
+
|
5
|
+
var Gumby = function () {
|
6
|
+
|
7
|
+
// Gumby data object for storing simpleUI classes and handlers
|
8
|
+
var gumbyData = {},
|
9
|
+
|
10
|
+
setGumbyData = function (key, value) {
|
11
|
+
return gumbyData[key] = value;
|
12
|
+
},
|
13
|
+
|
14
|
+
getGumbyData = function (key) {
|
15
|
+
return gumbyData[key] || false;
|
16
|
+
},
|
17
|
+
|
18
|
+
/**
|
19
|
+
* Simple UI Elements
|
20
|
+
* ------------------
|
21
|
+
* UI elements that bind to an event, toggle
|
22
|
+
* a class with possibility to run simple logic
|
23
|
+
* on completion and test for specific conditions
|
24
|
+
*/
|
25
|
+
simpleUI = {
|
26
|
+
|
27
|
+
// simple UI elements holder object
|
28
|
+
ui: [
|
29
|
+
|
30
|
+
// checkbox - check/uncheck (including hidden input) on click
|
31
|
+
{
|
32
|
+
selector: '.checkbox',
|
33
|
+
onEvent: 'click',
|
34
|
+
className: 'checked',
|
35
|
+
target: false,
|
36
|
+
condition: false,
|
37
|
+
// check/uncheck hidden checkbox input
|
38
|
+
complete: function ($e) {
|
39
|
+
var checked = $e.hasClass('checked');
|
40
|
+
$e.children('input').attr('checked', checked).change();
|
41
|
+
}
|
42
|
+
},
|
43
|
+
|
44
|
+
// radio - check/uncheck (including hidden input) on click
|
45
|
+
// also uncheck all others with same name
|
46
|
+
{
|
47
|
+
selector: '.radio',
|
48
|
+
onEvent: 'click',
|
49
|
+
className: 'checked',
|
50
|
+
target: false,
|
51
|
+
condition: false,
|
52
|
+
// check hidden radio input and uncheck others
|
53
|
+
complete: function ($e) {
|
54
|
+
var $input = $e.children('input'),
|
55
|
+
// radio buttons with matching names in the same group
|
56
|
+
$otherInputs = $('input[name="' + $input.attr('name') + '"]');
|
57
|
+
|
58
|
+
// uncheck other radio buttons that are currently checked
|
59
|
+
// loop round so we can trigger change on required elements
|
60
|
+
$otherInputs.each(function() {
|
61
|
+
var $this = $(this);
|
62
|
+
|
63
|
+
// uncheck select radio buttons in group
|
64
|
+
$this.attr('checked', false).parent().removeClass('checked');
|
65
|
+
});
|
66
|
+
|
67
|
+
// check this one and trigger change on it
|
68
|
+
$input.attr('checked', true).change().parent().addClass('checked')
|
69
|
+
}
|
70
|
+
},
|
71
|
+
|
72
|
+
// validation - add/remove error class dependent on value being present
|
73
|
+
// conditional method used to check for value
|
74
|
+
{
|
75
|
+
selector: 'form[data-form="validate"] .field',
|
76
|
+
onEvent: 'blur',
|
77
|
+
className: 'error',
|
78
|
+
target: false,
|
79
|
+
// check input is required and if so add/remove error class based on present value
|
80
|
+
condition: function ($e) {
|
81
|
+
var $child = $e.find('input, textarea').first(),
|
82
|
+
val = $child.val(),
|
83
|
+
req = $child.attr('data-form');
|
84
|
+
|
85
|
+
if(!req || req !== 'required') {
|
86
|
+
return false;
|
87
|
+
}
|
88
|
+
|
89
|
+
// email/regular validation
|
90
|
+
if (($child.attr('type') === 'email' && !val.match(/^[\w.%&=+$#!-']+@[\w.-]+\.[a-zA-Z]{2,4}$/)) || !val.length) {
|
91
|
+
$e.addClass('error');
|
92
|
+
return false;
|
93
|
+
}
|
94
|
+
|
95
|
+
$e.removeClass('error');
|
96
|
+
},
|
97
|
+
complete: false
|
98
|
+
},
|
99
|
+
|
100
|
+
// toggles - toggle active class on itself and selector in data-for
|
101
|
+
// on click
|
102
|
+
{
|
103
|
+
selector: '.toggle:not([data-on]), .toggle[data-on="click"]',
|
104
|
+
onEvent: 'click',
|
105
|
+
className: 'active',
|
106
|
+
target: function($e) {
|
107
|
+
return $e.add($($e.attr('data-for')));
|
108
|
+
},
|
109
|
+
condition: false,
|
110
|
+
complete: false
|
111
|
+
},
|
112
|
+
|
113
|
+
// on mouseover (will always add class) and mouseout (will always remove class)
|
114
|
+
{
|
115
|
+
selector: '.toggle[data-on="hover"]',
|
116
|
+
onEvent: 'mouseover mouseout',
|
117
|
+
className: 'active',
|
118
|
+
target: function($e) {
|
119
|
+
return $e.add($($e.attr('data-for')));
|
120
|
+
},
|
121
|
+
condition: false,
|
122
|
+
complete: false
|
123
|
+
}
|
124
|
+
],
|
125
|
+
|
126
|
+
// initialize simple UI
|
127
|
+
init: function () {
|
128
|
+
|
129
|
+
var x, ui, $e, callBack, conditionalCallBack, activeClass, targetName;
|
130
|
+
|
131
|
+
// loop round gumby UI elements applying active/inactive class logic
|
132
|
+
for(x = 0; x < simpleUI.ui.length; x++) {
|
133
|
+
|
134
|
+
ui = simpleUI.ui[x];
|
135
|
+
$e = $(ui.selector);
|
136
|
+
// complete call back
|
137
|
+
callBack = ui.complete && typeof ui.complete === 'function' ? ui.complete : false;
|
138
|
+
// conditional callback
|
139
|
+
conditionalCallBack = ui.condition && typeof ui.condition === 'function' ? ui.condition : false;
|
140
|
+
targetName = ui.target && typeof ui.target === 'function' ? ui.target : false;
|
141
|
+
activeClass = ui.className || false;
|
142
|
+
|
143
|
+
// store UI data
|
144
|
+
// replace spaces with dashes for GumbyData object reference
|
145
|
+
setGumbyData(ui.selector.replace(' ', '-'), {
|
146
|
+
'GumbyCallback' : callBack,
|
147
|
+
'GumbyConditionalCallBack' : conditionalCallBack,
|
148
|
+
'GumbyActiveClass' : activeClass,
|
149
|
+
'GumbyTarget' : targetName
|
150
|
+
});
|
151
|
+
|
152
|
+
// bind it all!
|
153
|
+
$(document).on(ui.onEvent, ui.selector, function (e) {
|
154
|
+
e.preventDefault();
|
155
|
+
|
156
|
+
var $this = $(this),
|
157
|
+
$target = $(this),
|
158
|
+
gumbyData = getGumbyData(e.handleObj.selector.replace(' ', '-')),
|
159
|
+
condition = true;
|
160
|
+
|
161
|
+
// if there is a conditional function test it here
|
162
|
+
// leaving if it returns false
|
163
|
+
if(gumbyData.GumbyConditionalCallBack) {
|
164
|
+
return condition = gumbyData.GumbyConditionalCallBack($this);
|
165
|
+
}
|
166
|
+
|
167
|
+
// no conditional or it passed so toggle class
|
168
|
+
if (gumbyData.GumbyActiveClass) {
|
169
|
+
// check for sepcified target
|
170
|
+
if(gumbyData.GumbyTarget) {
|
171
|
+
$target = gumbyData.GumbyTarget($this);
|
172
|
+
}
|
173
|
+
$target.toggleClass(gumbyData.GumbyActiveClass);
|
174
|
+
}
|
175
|
+
|
176
|
+
// if complete call back present call it here
|
177
|
+
if (gumbyData.GumbyCallback) {
|
178
|
+
gumbyData.GumbyCallback($this);
|
179
|
+
}
|
180
|
+
});
|
181
|
+
}
|
182
|
+
}
|
183
|
+
},
|
184
|
+
|
185
|
+
/**
|
186
|
+
* Complex UI Elements
|
187
|
+
* ------------------
|
188
|
+
* UI elements that require logic passed the
|
189
|
+
* capabilities of simple add/remove class.
|
190
|
+
*/
|
191
|
+
complexUI = {
|
192
|
+
|
193
|
+
// init separate complexUI elements
|
194
|
+
init: function () {
|
195
|
+
complexUI.pickers();
|
196
|
+
complexUI.skipLinks();
|
197
|
+
complexUI.tabs();
|
198
|
+
},
|
199
|
+
|
200
|
+
// pickers - open picker on click and update <select> and picker label when option chosen
|
201
|
+
pickers: function() {
|
202
|
+
|
203
|
+
// open picker on click
|
204
|
+
$(document).on('click', '.picker', function (e) {
|
205
|
+
e.preventDefault();
|
206
|
+
|
207
|
+
var $this = $(this),
|
208
|
+
openTimer = null;
|
209
|
+
|
210
|
+
// custom .picker style are removed on handheld devices using :after to insert hidden content and inform JS
|
211
|
+
if (window.getComputedStyle && window.getComputedStyle($this.get(0), ':after').getPropertyValue('content') === 'handheld') {
|
212
|
+
return false;
|
213
|
+
}
|
214
|
+
|
215
|
+
// mouseout for > 500ms will close picker
|
216
|
+
$this.hover(function () {
|
217
|
+
clearTimeout(openTimer);
|
218
|
+
}, function () {
|
219
|
+
var $this = $(this);
|
220
|
+
openTimer = setTimeout(function () {
|
221
|
+
$this.removeClass('open');
|
222
|
+
}, 500);
|
223
|
+
});
|
224
|
+
|
225
|
+
$this.toggleClass('open');
|
226
|
+
});
|
227
|
+
|
228
|
+
// clicking children elements should update hidden <select> and .picker active label
|
229
|
+
$(document).on('click', '.picker > ul > li', function (e) {
|
230
|
+
e.preventDefault();
|
231
|
+
|
232
|
+
var $this = $(this),
|
233
|
+
$parent = $this.parents('.picker'),
|
234
|
+
val = $this.children('a').html();
|
235
|
+
|
236
|
+
// update label
|
237
|
+
$parent.children('.toggle').html(val + '<span class="caret"></span>');
|
238
|
+
|
239
|
+
// update hidden select and trigger change event
|
240
|
+
$parent.find('option').attr('selected', false).eq($this.index() + 1)
|
241
|
+
.attr('selected', true).parent('select').change();
|
242
|
+
});
|
243
|
+
},
|
244
|
+
|
245
|
+
// skiplinks - slide to data-type content area on click of skiplink and on window load if hash present
|
246
|
+
skipLinks: function () {
|
247
|
+
var skip = function () {
|
248
|
+
|
249
|
+
var skipTypeParts,
|
250
|
+
skipType,
|
251
|
+
$skipTos = $('[data-type]'),
|
252
|
+
$skipTo = false,
|
253
|
+
onWin = false,
|
254
|
+
$this = $(this);
|
255
|
+
|
256
|
+
if ($this.get(0) === window && !window.location.hash) {
|
257
|
+
return false;
|
258
|
+
}
|
259
|
+
|
260
|
+
// initial load skip
|
261
|
+
if ($this.get(0) === window && window.location.hash) {
|
262
|
+
skipType = window.location.hash.replace('#', '');
|
263
|
+
onWin = true;
|
264
|
+
} else {
|
265
|
+
skipTypeParts = $this.attr('href').split('#');
|
266
|
+
skipType = skipTypeParts[skipTypeParts.length - 1];
|
267
|
+
}
|
268
|
+
|
269
|
+
// loop round potential data-type matches
|
270
|
+
$skipTos.each(function () {
|
271
|
+
// data-type can be multiple space separated values
|
272
|
+
var typeParts = $(this).attr('data-type').split(' '), x;
|
273
|
+
|
274
|
+
// find first match and break the each
|
275
|
+
for (x in typeParts) {
|
276
|
+
if (typeParts[x] === skipType) {
|
277
|
+
$skipTo = $(this);
|
278
|
+
return false;
|
279
|
+
}
|
280
|
+
}
|
281
|
+
});
|
282
|
+
|
283
|
+
if (!$skipTo.length) {
|
284
|
+
return false;
|
285
|
+
}
|
286
|
+
|
287
|
+
// scroll to skiplink
|
288
|
+
$('body,html').animate({
|
289
|
+
'scrollTop' : $skipTo.offset().top
|
290
|
+
}, 350);
|
291
|
+
|
292
|
+
// update hash if not an initial hash load
|
293
|
+
if (onWin) {
|
294
|
+
window.location.hash = skipType;
|
295
|
+
}
|
296
|
+
|
297
|
+
};
|
298
|
+
|
299
|
+
// bind to skip links and window load
|
300
|
+
$(document).on('click', '.skiplink a, .skipnav ul li a, .skip', skip);
|
301
|
+
$(window).load(skip);
|
302
|
+
},
|
303
|
+
|
304
|
+
// tabs - activate tab and tab content on click as well as on window load if hash present
|
305
|
+
tabs: function () {
|
306
|
+
|
307
|
+
var activateTab = function ($tab) {
|
308
|
+
var // this links tabs set
|
309
|
+
$tabs = $tab.parents('.tabs'),
|
310
|
+
// currently active tab
|
311
|
+
activeTab = {
|
312
|
+
'tab' : $tabs.find('ul').children('li.active'),
|
313
|
+
'content' : $tabs.find('div[data-tab].active')
|
314
|
+
},
|
315
|
+
// newly clicked tab
|
316
|
+
newTab = {
|
317
|
+
'tab' : $tab.parent('li'),
|
318
|
+
'content' : $tabs.find('[data-tab=' + $tab.attr('href').replace('#', '') + ']')
|
319
|
+
},
|
320
|
+
x, y;
|
321
|
+
|
322
|
+
// remove active class from tab and content
|
323
|
+
for (x in activeTab) {
|
324
|
+
activeTab[x].removeClass('active');
|
325
|
+
}
|
326
|
+
|
327
|
+
// add active class to tab and content
|
328
|
+
for (y in newTab) {
|
329
|
+
newTab[y].addClass('active');
|
330
|
+
}
|
331
|
+
}
|
332
|
+
|
333
|
+
// hook up tab links
|
334
|
+
$(document).on('click', '.tabs > ul > li > a', function(e) {
|
335
|
+
activateTab($(this));
|
336
|
+
});
|
337
|
+
|
338
|
+
// hook up initial load active tab
|
339
|
+
if (window.location.hash) {
|
340
|
+
var $activeTab = $('a[href="' + window.location.hash + '"]');
|
341
|
+
if ($activeTab.length && $activeTab.parents('.tabs').length) {
|
342
|
+
activateTab($activeTab);
|
343
|
+
}
|
344
|
+
}
|
345
|
+
}
|
346
|
+
},
|
347
|
+
|
348
|
+
// initialize Gumby
|
349
|
+
init = function () {
|
350
|
+
simpleUI.init();
|
351
|
+
complexUI.init();
|
352
|
+
};
|
353
|
+
|
354
|
+
// return public methods
|
355
|
+
return {
|
356
|
+
i: init
|
357
|
+
}
|
358
|
+
}().i();
|
359
|
+
|
360
|
+
})(window.jQuery);
|
361
|
+
|