andy_rails_toolbox 0.0.1 → 1.0.0
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.
- checksums.yaml +4 -4
- data/{LICENSE.txt → MIT-LICENSE} +1 -3
- data/README.md +178 -1
- data/Rakefile +22 -1
- data/app/assets/javascripts/jquery.timeago.js +214 -0
- data/app/assets/javascripts/jquery.timeago.load.coffee +3 -0
- data/app/assets/javascripts/jquery.timeago.zh-TW.js +20 -0
- data/app/helpers/bootstrap_helper.rb +211 -0
- data/app/helpers/font_awesome_helper.rb +94 -0
- data/app/helpers/hash_helper.rb +25 -0
- data/app/helpers/markdown_helper.rb +25 -0
- data/app/helpers/qrcode_helper.rb +21 -0
- data/app/helpers/timeago_helper.rb +7 -0
- data/lib/andy_rails_toolbox/version.rb +1 -1
- data/lib/andy_rails_toolbox.rb +6 -3
- metadata +24 -18
- data/.gitignore +0 -14
- data/Gemfile +0 -4
- data/andy_rails_toolbox.gemspec +0 -23
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1f80bf87e2fb9ba3f445312d86e45efe5c892a68
|
4
|
+
data.tar.gz: 116cd8015e92c1cddb2cae0492c5ea1ad22d694e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 55612b107b794647de97be8b31cdd648ab96c360a1d150d390f2f208c021fa765d4e40a7dfa3b8874d167b3a6b96dfb4281fa203da168fc10b55cf842b449cd0
|
7
|
+
data.tar.gz: d3ac2b27b5f8d49df9497957fc0c782c74904c75f6df0ee641d21bf1e49e207a6f2e787072172285984f0c4ca7555ab4c7a37c27f0a65e21b28870ffc5564aa2
|
data/{LICENSE.txt → MIT-LICENSE}
RENAMED
data/README.md
CHANGED
@@ -20,7 +20,184 @@ Or install it yourself as:
|
|
20
20
|
|
21
21
|
## Usage
|
22
22
|
|
23
|
-
|
23
|
+
#### BootstrapHelper
|
24
|
+
|
25
|
+
Bootstrap Homepage: <a href="http://getbootstrap.com/" target="_blank">http://getbootstrap.com/</a>
|
26
|
+
|
27
|
+
|
28
|
+
Add below codes to layout `app/views/layout/application.html.erb`
|
29
|
+
|
30
|
+
``` erb
|
31
|
+
...
|
32
|
+
<%= stylesheet_link_tag '//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css' %>
|
33
|
+
...
|
34
|
+
<%= javascript_include_tag '//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js' %>
|
35
|
+
...
|
36
|
+
```
|
37
|
+
|
38
|
+
Examples
|
39
|
+
|
40
|
+
ICONS
|
41
|
+
|
42
|
+
``` rb
|
43
|
+
bs_icon 'user'
|
44
|
+
# => <span class="glyphicon glyphicon-user"></span>
|
45
|
+
```
|
46
|
+
|
47
|
+
BUTTONS
|
48
|
+
|
49
|
+
``` rb
|
50
|
+
html_button 'button'
|
51
|
+
# => <button name="button" type="button" class="btn btn-default">button</button>
|
52
|
+
html_button 'button', color: 'primary'
|
53
|
+
# => <button name="button" type="button" class="btn btn-primary">button</button>
|
54
|
+
html_button 'button', size: 'sm'
|
55
|
+
# => <button name="button" type="button" class="btn btn-default btn-sm">button</button>
|
56
|
+
html_button 'button', block: true
|
57
|
+
# => <button name="button" type="button" class="btn btn-default btn-block">button</button>
|
58
|
+
html_button 'button', icon: 'user'
|
59
|
+
# => <button name="button" type="button" class="btn btn-default"><i class="fa fa-user"></i> button</button>
|
60
|
+
html_button 'button', active: true
|
61
|
+
# => <button name="button" type="button" class="btn btn-default active">button</button>
|
62
|
+
submit_button 'submit'
|
63
|
+
# => <button type="submit" class="btn btn-default">submit</button>
|
64
|
+
reset_button 'reset'
|
65
|
+
# => <button type="reset" class="btn btn-default">reset</button>
|
66
|
+
link_button 'link', url: root_path
|
67
|
+
# => <a class="btn btn-default" role="button" href="/">link</a>
|
68
|
+
input_button 'input button'
|
69
|
+
# => <input class="btn btn-default" value="input button" type="button" />
|
70
|
+
input_submit 'input button'
|
71
|
+
# => <input type="submit" name="commit" value="input button" class="btn btn-default" />
|
72
|
+
```
|
73
|
+
|
74
|
+
IMAGES
|
75
|
+
|
76
|
+
``` rb
|
77
|
+
image_responsive 'pic.png'
|
78
|
+
# => <img class="img-responsive" src="/images/pic.png" alt="Pic" />
|
79
|
+
image_rounded 'pic.png'
|
80
|
+
# => <img class="img-rounded" src="/images/pic.png" alt="Pic" />
|
81
|
+
image_circle 'pic.png'
|
82
|
+
# => <img class="img-circle" src="/images/pic.png" alt="Pic" />
|
83
|
+
image_thumbnail 'pic.png'
|
84
|
+
# => <img class="img-thumbnail" src="/images/pic.png" alt="Pic" />
|
85
|
+
```
|
86
|
+
|
87
|
+
#### MarkdownHelper
|
88
|
+
|
89
|
+
New a css erb file `app/assets/stylesheets/pygments.css.erb` for pygments color style
|
90
|
+
|
91
|
+
``` erb
|
92
|
+
<%= Pygments.css(style: "igor") %>
|
93
|
+
```
|
94
|
+
|
95
|
+
All styles:
|
96
|
+
|
97
|
+
``` sh
|
98
|
+
$ rails c
|
99
|
+
# => Loading development environment (Rails 4.2.0)
|
100
|
+
irb(main):001:0> require 'pygments.rb'
|
101
|
+
# => true
|
102
|
+
irb(main):002:0> Pygments.styles
|
103
|
+
# => ["manni", "igor", "xcode", "vim", "autumn", "vs", "rrt", "native", "perldoc", "borland", "tango", "emacs", "friendly", "monokai", "paraiso-dark", "colorful", "murphy", "bw", "pastie", "paraiso-light", "trac", "default", "fruity"]
|
104
|
+
```
|
105
|
+
|
106
|
+
Examples
|
107
|
+
|
108
|
+
``` rb
|
109
|
+
markdown '# h1'
|
110
|
+
# => <h1>h1</h1>
|
111
|
+
markdown '## h2'
|
112
|
+
# => <h2>h2</h2>
|
113
|
+
markdown '[an example](http://example.com/)'
|
114
|
+
# => <p><a href="http://example.com/">an example</a></p>
|
115
|
+
markdown @post.content
|
116
|
+
# => transform markdown code to html codes and payments highlighter
|
117
|
+
```
|
118
|
+
|
119
|
+
#### QrcodeHelper Examples
|
120
|
+
|
121
|
+
``` rb
|
122
|
+
qrcode 'Hello world!'
|
123
|
+
```
|
124
|
+
|
125
|
+
<img alt="Hello world!" src="https://chart.googleapis.com/chart?cht=qr&chl=Hello world!&chs=200x200" />
|
126
|
+
|
127
|
+
QRCode options parameters: <a href="https://google-developers.appspot.com/chart/infographics/docs/qr_codes#overview" target="_blank">Here</a>
|
128
|
+
|
129
|
+
``` rb
|
130
|
+
qrcode 'Hello world!', width: '300', output_encoding: 'Shift_JIS', error_correction_level: 'H', margin: '10'
|
131
|
+
```
|
132
|
+
|
133
|
+
#### FontAwesomeHelper
|
134
|
+
|
135
|
+
Font Awesome icons Homepage: <a href="http://fortawesome.github.io/Font-Awesome/" target="_blank">http://fortawesome.github.io/Font-Awesome/</a>
|
136
|
+
|
137
|
+
Add below codes to layout `app/views/layout/application.html.erb`
|
138
|
+
|
139
|
+
``` erb
|
140
|
+
...
|
141
|
+
<%= stylesheet_link_tag '//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css' %>
|
142
|
+
...
|
143
|
+
```
|
144
|
+
|
145
|
+
Examples
|
146
|
+
|
147
|
+
``` rb
|
148
|
+
fa_icon "user"
|
149
|
+
# => <i class="fa fa-user"></i>
|
150
|
+
|
151
|
+
fa_icon "user", text: "Login"
|
152
|
+
# => <i class="fa fa-user"></i> Login
|
153
|
+
|
154
|
+
fa_icon "user", text: "Login", right: true
|
155
|
+
# => Login <i class="fa fa-user"></i>
|
156
|
+
|
157
|
+
fa_icon "user 4x"
|
158
|
+
# => <i class="fa fa-user fa-4x"></i>
|
159
|
+
```
|
160
|
+
|
161
|
+
#### HashHelper Examples
|
162
|
+
|
163
|
+
``` rb
|
164
|
+
options = { a: '1', b: '2', c: '3' }
|
165
|
+
|
166
|
+
get_value :a, options
|
167
|
+
# => '1'
|
168
|
+
get_value :d, options
|
169
|
+
# => nil
|
170
|
+
get_value :d, options, '4'
|
171
|
+
# => '4'
|
172
|
+
|
173
|
+
pop_value :a, options
|
174
|
+
# => '1'
|
175
|
+
# options = { b: '2', c: '3' }
|
176
|
+
pop_value :d, options
|
177
|
+
# => nil
|
178
|
+
pop_value :d, options, '4'
|
179
|
+
# => '4'
|
180
|
+
# options = { a: '1', b: '2', c: '3' }
|
181
|
+
```
|
182
|
+
|
183
|
+
#### TimeagoHelper
|
184
|
+
|
185
|
+
Add below codes to file `app/assets/javascripts/application.js`
|
186
|
+
|
187
|
+
``` js
|
188
|
+
...
|
189
|
+
//= require jquery.timeago
|
190
|
+
//= require jquery.timeago.zh-TW
|
191
|
+
//= require jquery.timeago.load
|
192
|
+
...
|
193
|
+
```
|
194
|
+
|
195
|
+
Use in View
|
196
|
+
|
197
|
+
``` rb
|
198
|
+
timeago '2014-11-21 09:38:27.256503'
|
199
|
+
# => '2個月之前'
|
200
|
+
```
|
24
201
|
|
25
202
|
## Contributing
|
26
203
|
|
data/Rakefile
CHANGED
@@ -1,2 +1,23 @@
|
|
1
|
-
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'rdoc/task'
|
8
|
+
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
11
|
+
rdoc.title = 'AndyRailsToolbox'
|
12
|
+
rdoc.options << '--line-numbers'
|
13
|
+
rdoc.rdoc_files.include('README.rdoc')
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
|
20
|
+
|
21
|
+
|
22
|
+
Bundler::GemHelper.install_tasks
|
2
23
|
|
@@ -0,0 +1,214 @@
|
|
1
|
+
/**
|
2
|
+
* Timeago is a jQuery plugin that makes it easy to support automatically
|
3
|
+
* updating fuzzy timestamps (e.g. "4 minutes ago" or "about 1 day ago").
|
4
|
+
*
|
5
|
+
* @name timeago
|
6
|
+
* @version 1.4.1
|
7
|
+
* @requires jQuery v1.2.3+
|
8
|
+
* @author Ryan McGeary
|
9
|
+
* @license MIT License - http://www.opensource.org/licenses/mit-license.php
|
10
|
+
*
|
11
|
+
* For usage and examples, visit:
|
12
|
+
* http://timeago.yarp.com/
|
13
|
+
*
|
14
|
+
* Copyright (c) 2008-2013, Ryan McGeary (ryan -[at]- mcgeary [*dot*] org)
|
15
|
+
*/
|
16
|
+
|
17
|
+
(function (factory) {
|
18
|
+
if (typeof define === 'function' && define.amd) {
|
19
|
+
// AMD. Register as an anonymous module.
|
20
|
+
define(['jquery'], factory);
|
21
|
+
} else {
|
22
|
+
// Browser globals
|
23
|
+
factory(jQuery);
|
24
|
+
}
|
25
|
+
}(function ($) {
|
26
|
+
$.timeago = function(timestamp) {
|
27
|
+
if (timestamp instanceof Date) {
|
28
|
+
return inWords(timestamp);
|
29
|
+
} else if (typeof timestamp === "string") {
|
30
|
+
return inWords($.timeago.parse(timestamp));
|
31
|
+
} else if (typeof timestamp === "number") {
|
32
|
+
return inWords(new Date(timestamp));
|
33
|
+
} else {
|
34
|
+
return inWords($.timeago.datetime(timestamp));
|
35
|
+
}
|
36
|
+
};
|
37
|
+
var $t = $.timeago;
|
38
|
+
|
39
|
+
$.extend($.timeago, {
|
40
|
+
settings: {
|
41
|
+
refreshMillis: 60000,
|
42
|
+
allowPast: true,
|
43
|
+
allowFuture: false,
|
44
|
+
localeTitle: false,
|
45
|
+
cutoff: 0,
|
46
|
+
strings: {
|
47
|
+
prefixAgo: null,
|
48
|
+
prefixFromNow: null,
|
49
|
+
suffixAgo: "ago",
|
50
|
+
suffixFromNow: "from now",
|
51
|
+
inPast: 'any moment now',
|
52
|
+
seconds: "less than a minute",
|
53
|
+
minute: "about a minute",
|
54
|
+
minutes: "%d minutes",
|
55
|
+
hour: "about an hour",
|
56
|
+
hours: "about %d hours",
|
57
|
+
day: "a day",
|
58
|
+
days: "%d days",
|
59
|
+
month: "about a month",
|
60
|
+
months: "%d months",
|
61
|
+
year: "about a year",
|
62
|
+
years: "%d years",
|
63
|
+
wordSeparator: " ",
|
64
|
+
numbers: []
|
65
|
+
}
|
66
|
+
},
|
67
|
+
|
68
|
+
inWords: function(distanceMillis) {
|
69
|
+
if(!this.settings.allowPast && ! this.settings.allowFuture) {
|
70
|
+
throw 'timeago allowPast and allowFuture settings can not both be set to false.';
|
71
|
+
}
|
72
|
+
|
73
|
+
var $l = this.settings.strings;
|
74
|
+
var prefix = $l.prefixAgo;
|
75
|
+
var suffix = $l.suffixAgo;
|
76
|
+
if (this.settings.allowFuture) {
|
77
|
+
if (distanceMillis < 0) {
|
78
|
+
prefix = $l.prefixFromNow;
|
79
|
+
suffix = $l.suffixFromNow;
|
80
|
+
}
|
81
|
+
}
|
82
|
+
|
83
|
+
if(!this.settings.allowPast && distanceMillis >= 0) {
|
84
|
+
return this.settings.strings.inPast;
|
85
|
+
}
|
86
|
+
|
87
|
+
var seconds = Math.abs(distanceMillis) / 1000;
|
88
|
+
var minutes = seconds / 60;
|
89
|
+
var hours = minutes / 60;
|
90
|
+
var days = hours / 24;
|
91
|
+
var years = days / 365;
|
92
|
+
|
93
|
+
function substitute(stringOrFunction, number) {
|
94
|
+
var string = $.isFunction(stringOrFunction) ? stringOrFunction(number, distanceMillis) : stringOrFunction;
|
95
|
+
var value = ($l.numbers && $l.numbers[number]) || number;
|
96
|
+
return string.replace(/%d/i, value);
|
97
|
+
}
|
98
|
+
|
99
|
+
var words = seconds < 45 && substitute($l.seconds, Math.round(seconds)) ||
|
100
|
+
seconds < 90 && substitute($l.minute, 1) ||
|
101
|
+
minutes < 45 && substitute($l.minutes, Math.round(minutes)) ||
|
102
|
+
minutes < 90 && substitute($l.hour, 1) ||
|
103
|
+
hours < 24 && substitute($l.hours, Math.round(hours)) ||
|
104
|
+
hours < 42 && substitute($l.day, 1) ||
|
105
|
+
days < 30 && substitute($l.days, Math.round(days)) ||
|
106
|
+
days < 45 && substitute($l.month, 1) ||
|
107
|
+
days < 365 && substitute($l.months, Math.round(days / 30)) ||
|
108
|
+
years < 1.5 && substitute($l.year, 1) ||
|
109
|
+
substitute($l.years, Math.round(years));
|
110
|
+
|
111
|
+
var separator = $l.wordSeparator || "";
|
112
|
+
if ($l.wordSeparator === undefined) { separator = " "; }
|
113
|
+
return $.trim([prefix, words, suffix].join(separator));
|
114
|
+
},
|
115
|
+
|
116
|
+
parse: function(iso8601) {
|
117
|
+
var s = $.trim(iso8601);
|
118
|
+
s = s.replace(/\.\d+/,""); // remove milliseconds
|
119
|
+
s = s.replace(/-/,"/").replace(/-/,"/");
|
120
|
+
s = s.replace(/T/," ").replace(/Z/," UTC");
|
121
|
+
s = s.replace(/([\+\-]\d\d)\:?(\d\d)/," $1$2"); // -04:00 -> -0400
|
122
|
+
s = s.replace(/([\+\-]\d\d)$/," $100"); // +09 -> +0900
|
123
|
+
return new Date(s);
|
124
|
+
},
|
125
|
+
datetime: function(elem) {
|
126
|
+
var iso8601 = $t.isTime(elem) ? $(elem).attr("datetime") : $(elem).attr("title");
|
127
|
+
return $t.parse(iso8601);
|
128
|
+
},
|
129
|
+
isTime: function(elem) {
|
130
|
+
// jQuery's `is()` doesn't play well with HTML5 in IE
|
131
|
+
return $(elem).get(0).tagName.toLowerCase() === "time"; // $(elem).is("time");
|
132
|
+
}
|
133
|
+
});
|
134
|
+
|
135
|
+
// functions that can be called via $(el).timeago('action')
|
136
|
+
// init is default when no action is given
|
137
|
+
// functions are called with context of a single element
|
138
|
+
var functions = {
|
139
|
+
init: function(){
|
140
|
+
var refresh_el = $.proxy(refresh, this);
|
141
|
+
refresh_el();
|
142
|
+
var $s = $t.settings;
|
143
|
+
if ($s.refreshMillis > 0) {
|
144
|
+
this._timeagoInterval = setInterval(refresh_el, $s.refreshMillis);
|
145
|
+
}
|
146
|
+
},
|
147
|
+
update: function(time){
|
148
|
+
var parsedTime = $t.parse(time);
|
149
|
+
$(this).data('timeago', { datetime: parsedTime });
|
150
|
+
if($t.settings.localeTitle) $(this).attr("title", parsedTime.toLocaleString());
|
151
|
+
refresh.apply(this);
|
152
|
+
},
|
153
|
+
updateFromDOM: function(){
|
154
|
+
$(this).data('timeago', { datetime: $t.parse( $t.isTime(this) ? $(this).attr("datetime") : $(this).attr("title") ) });
|
155
|
+
refresh.apply(this);
|
156
|
+
},
|
157
|
+
dispose: function () {
|
158
|
+
if (this._timeagoInterval) {
|
159
|
+
window.clearInterval(this._timeagoInterval);
|
160
|
+
this._timeagoInterval = null;
|
161
|
+
}
|
162
|
+
}
|
163
|
+
};
|
164
|
+
|
165
|
+
$.fn.timeago = function(action, options) {
|
166
|
+
var fn = action ? functions[action] : functions.init;
|
167
|
+
if(!fn){
|
168
|
+
throw new Error("Unknown function name '"+ action +"' for timeago");
|
169
|
+
}
|
170
|
+
// each over objects here and call the requested function
|
171
|
+
this.each(function(){
|
172
|
+
fn.call(this, options);
|
173
|
+
});
|
174
|
+
return this;
|
175
|
+
};
|
176
|
+
|
177
|
+
function refresh() {
|
178
|
+
var data = prepareData(this);
|
179
|
+
var $s = $t.settings;
|
180
|
+
|
181
|
+
if (!isNaN(data.datetime)) {
|
182
|
+
if ( $s.cutoff == 0 || Math.abs(distance(data.datetime)) < $s.cutoff) {
|
183
|
+
$(this).text(inWords(data.datetime));
|
184
|
+
}
|
185
|
+
}
|
186
|
+
return this;
|
187
|
+
}
|
188
|
+
|
189
|
+
function prepareData(element) {
|
190
|
+
element = $(element);
|
191
|
+
if (!element.data("timeago")) {
|
192
|
+
element.data("timeago", { datetime: $t.datetime(element) });
|
193
|
+
var text = $.trim(element.text());
|
194
|
+
if ($t.settings.localeTitle) {
|
195
|
+
element.attr("title", element.data('timeago').datetime.toLocaleString());
|
196
|
+
} else if (text.length > 0 && !($t.isTime(element) && element.attr("title"))) {
|
197
|
+
element.attr("title", text);
|
198
|
+
}
|
199
|
+
}
|
200
|
+
return element.data("timeago");
|
201
|
+
}
|
202
|
+
|
203
|
+
function inWords(date) {
|
204
|
+
return $t.inWords(distance(date));
|
205
|
+
}
|
206
|
+
|
207
|
+
function distance(date) {
|
208
|
+
return (new Date().getTime() - date.getTime());
|
209
|
+
}
|
210
|
+
|
211
|
+
// fix for IE6 suckage
|
212
|
+
document.createElement("abbr");
|
213
|
+
document.createElement("time");
|
214
|
+
}));
|
@@ -0,0 +1,20 @@
|
|
1
|
+
// Traditional Chinese, zh-tw
|
2
|
+
jQuery.timeago.settings.strings = {
|
3
|
+
prefixAgo: null,
|
4
|
+
prefixFromNow: "從現在開始",
|
5
|
+
suffixAgo: "之前",
|
6
|
+
suffixFromNow: null,
|
7
|
+
seconds: "不到1分鐘",
|
8
|
+
minute: "大約1分鐘",
|
9
|
+
minutes: "%d分鐘",
|
10
|
+
hour: "大約1小時",
|
11
|
+
hours: "%d小時",
|
12
|
+
day: "大約1天",
|
13
|
+
days: "%d天",
|
14
|
+
month: "大約1個月",
|
15
|
+
months: "%d個月",
|
16
|
+
year: "大約1年",
|
17
|
+
years: "%d年",
|
18
|
+
numbers: [],
|
19
|
+
wordSeparator: ""
|
20
|
+
};
|
@@ -0,0 +1,211 @@
|
|
1
|
+
module BootstrapHelper
|
2
|
+
#############
|
3
|
+
### ICONS ###
|
4
|
+
#############
|
5
|
+
|
6
|
+
# Generates an icon.
|
7
|
+
def bs_icon(icon, options = {})
|
8
|
+
icon = %(glyphicon glyphicon-#{icon})
|
9
|
+
add_css_class icon, options
|
10
|
+
tag = pop_value :tag, options, :span
|
11
|
+
content_tag tag, '', options
|
12
|
+
end
|
13
|
+
|
14
|
+
###############
|
15
|
+
### BUTTONS ###
|
16
|
+
###############
|
17
|
+
|
18
|
+
# Generates a button.
|
19
|
+
def button(label = 'Button', options = {})
|
20
|
+
html_button label, options
|
21
|
+
end
|
22
|
+
|
23
|
+
# Generates a html submit button.
|
24
|
+
def html_button(label = 'Button', options = {})
|
25
|
+
btn :html_button, label, options
|
26
|
+
end
|
27
|
+
|
28
|
+
# Generates a submit button.
|
29
|
+
def submit_button(label = 'Submit', options = {})
|
30
|
+
btn :submit_button, label, options
|
31
|
+
end
|
32
|
+
|
33
|
+
# Generates a reset button.
|
34
|
+
def reset_button(label = 'Reset', options = {})
|
35
|
+
btn :reset_button, label, options
|
36
|
+
end
|
37
|
+
|
38
|
+
# Generates a link submit button.
|
39
|
+
def link_button(label = 'Submit', options = {})
|
40
|
+
btn :link_button, label, options
|
41
|
+
end
|
42
|
+
|
43
|
+
# Generates a input button.
|
44
|
+
def input_button(label = 'Button', options = {})
|
45
|
+
btn :input_button, label, options
|
46
|
+
end
|
47
|
+
|
48
|
+
# Generates a input submit button.
|
49
|
+
def input_submit(label = 'Submit', options = {})
|
50
|
+
btn :input_submit, label, options
|
51
|
+
end
|
52
|
+
|
53
|
+
# Generates a button.
|
54
|
+
def btn(type, label, options = {})
|
55
|
+
add_css_class 'btn', options
|
56
|
+
|
57
|
+
color = pop_value :color, options, 'default'
|
58
|
+
add_css_class(%(btn-#{color}), options) if color
|
59
|
+
|
60
|
+
size = pop_value :size, options
|
61
|
+
add_css_class(%(btn-#{size}), options) if size
|
62
|
+
|
63
|
+
block = pop_value :block, options
|
64
|
+
add_css_class('btn-block', options) if block
|
65
|
+
|
66
|
+
add_active_class options
|
67
|
+
|
68
|
+
icon = pop_value :icon, options
|
69
|
+
unless type.to_s.include? 'input'
|
70
|
+
if icon
|
71
|
+
label = fa_icon(icon) + ' ' + label
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
create_button type, label, options
|
76
|
+
end
|
77
|
+
|
78
|
+
def create_button(type, label, options)
|
79
|
+
url = pop_value :url, options, '#'
|
80
|
+
case type
|
81
|
+
when :html_button
|
82
|
+
options[:type] = :button unless options[:type]
|
83
|
+
button_tag label, options
|
84
|
+
when :submit_button
|
85
|
+
options[:name] = nil
|
86
|
+
options[:type] = :submit
|
87
|
+
button_tag label, options
|
88
|
+
when :reset_button
|
89
|
+
options[:name] = nil
|
90
|
+
options[:type] = :reset
|
91
|
+
button_tag label, options
|
92
|
+
when :link_button
|
93
|
+
options[:role] = :button
|
94
|
+
link_to label, url, options
|
95
|
+
when :input_button
|
96
|
+
options[:value] = label
|
97
|
+
options[:type] = :button
|
98
|
+
tag 'input', options
|
99
|
+
when :input_submit
|
100
|
+
submit_tag label, options
|
101
|
+
else
|
102
|
+
# type code here
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
##############
|
107
|
+
### IMAGES ###
|
108
|
+
##############
|
109
|
+
|
110
|
+
# Generates a responsive-friendly image tag
|
111
|
+
def image_responsive(source, options = {})
|
112
|
+
add_css_class 'img-responsive', options
|
113
|
+
image_tag source, options
|
114
|
+
end
|
115
|
+
|
116
|
+
# Generates an image tag with rounded corners.
|
117
|
+
def image_rounded(source, options = {})
|
118
|
+
add_css_class 'img-rounded', options
|
119
|
+
image_tag source, options
|
120
|
+
end
|
121
|
+
|
122
|
+
# Generates an image tag with circle.
|
123
|
+
def image_circle(source, options = {})
|
124
|
+
add_css_class 'img-circle', options
|
125
|
+
image_tag source, options
|
126
|
+
end
|
127
|
+
|
128
|
+
# Generates an image tag within thumbnail.
|
129
|
+
def image_thumbnail(source, options = {})
|
130
|
+
add_css_class 'img-thumbnail', options
|
131
|
+
image_tag source, options
|
132
|
+
end
|
133
|
+
|
134
|
+
#################
|
135
|
+
### UTILITIES ###
|
136
|
+
#################
|
137
|
+
|
138
|
+
# Appends new class names to the given options.
|
139
|
+
def add_css_class(class_names, options)
|
140
|
+
class_names = class_names.to_s if class_names.is_a? Symbol
|
141
|
+
class_names = class_names.split if class_names.is_a? String
|
142
|
+
if symbolize_keys(options).key? :class
|
143
|
+
options_class_names = options[:class].split
|
144
|
+
class_names.each do |value|
|
145
|
+
options_class_names << %(#{value.strip}) unless options_class_names.include? value
|
146
|
+
end
|
147
|
+
class_names = options_class_names
|
148
|
+
end
|
149
|
+
options[:class] = %(#{class_names * ' '})
|
150
|
+
end
|
151
|
+
|
152
|
+
# Adds the pull class to the given options is applicable.
|
153
|
+
def add_pull_class(options)
|
154
|
+
pull = pop_value :pull, options
|
155
|
+
add_css_class(%(pull-#{pull}), options) if pull
|
156
|
+
end
|
157
|
+
|
158
|
+
# Adds the text align class to the given options if applicable.
|
159
|
+
def add_align_class(options)
|
160
|
+
align = pop_value :align, options
|
161
|
+
add_css_class(%(text-#{align}), options) if align
|
162
|
+
end
|
163
|
+
|
164
|
+
# Adds the text transform class to the given options if applicable.
|
165
|
+
def add_transform_class(options)
|
166
|
+
transform = pop_value :transform, options
|
167
|
+
add_css_class(%(text-#{transform}), options) if transform
|
168
|
+
end
|
169
|
+
|
170
|
+
# Adds the color to the given options if applicable.
|
171
|
+
def add_color_class(options)
|
172
|
+
color = pop_value :color, options
|
173
|
+
add_css_class(%(text-#{color}), options) if color
|
174
|
+
end
|
175
|
+
|
176
|
+
# Adds the bgcolor to the given options if applicable.
|
177
|
+
def add_bgcolor_class(options)
|
178
|
+
bgcolor = pop_value :bgcolor, options
|
179
|
+
add_css_class(%(bg-#{bgcolor}), options) if bgcolor
|
180
|
+
end
|
181
|
+
|
182
|
+
# Adds the active to the given options if applicable.
|
183
|
+
def add_active_class(options)
|
184
|
+
active = pop_value :active, options
|
185
|
+
add_css_class('active', options) if active
|
186
|
+
end
|
187
|
+
|
188
|
+
def normalize_typography_options(options)
|
189
|
+
add_pull_class options
|
190
|
+
add_align_class options
|
191
|
+
add_transform_class options
|
192
|
+
add_color_class options
|
193
|
+
add_bgcolor_class options
|
194
|
+
end
|
195
|
+
|
196
|
+
################
|
197
|
+
### OVERRIDE ###
|
198
|
+
################
|
199
|
+
|
200
|
+
# override rails helper: content_tag
|
201
|
+
def content_tag(name, content_or_options_with_block = nil, options = nil, escape = true, &block)
|
202
|
+
if block_given?
|
203
|
+
options = content_or_options_with_block if content_or_options_with_block.is_a? Hash
|
204
|
+
normalize_typography_options(options) unless options.nil?
|
205
|
+
content_tag_string name, capture(&block), options, escape
|
206
|
+
else
|
207
|
+
normalize_typography_options(options) unless options.nil?
|
208
|
+
content_tag_string name, content_or_options_with_block, options, escape
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module FontAwesomeHelper
|
2
|
+
# Creates an icon tag given an icon name and possible icon
|
3
|
+
# modifiers.
|
4
|
+
#
|
5
|
+
# Examples
|
6
|
+
#
|
7
|
+
# fa_icon "camera-retro"
|
8
|
+
# # => <i class="fa fa-camera-retro"></i>
|
9
|
+
#
|
10
|
+
# fa_icon "camera-retro", text: "Take a photo"
|
11
|
+
# # => <i class="fa fa-camera-retro"></i> Take a photo
|
12
|
+
# fa_icon "chevron-right", text: "Get started", right: true
|
13
|
+
# # => Get started <i class="fa fa-chevron-right"></i>
|
14
|
+
#
|
15
|
+
# fa_icon "camera-retro 2x"
|
16
|
+
# # => <i class="fa fa-camera-retro fa-2x"></i>
|
17
|
+
# fa_icon ["camera-retro", "4x"]
|
18
|
+
# # => <i class="fa fa-camera-retro fa-4x"></i>
|
19
|
+
# fa_icon "spinner spin lg"
|
20
|
+
# # => <i class="fa fa-spinner fa-spin fa-lg">
|
21
|
+
#
|
22
|
+
# fa_icon "quote-left 4x", class: "pull-left"
|
23
|
+
# # => <i class="fa fa-quote-left fa-4x pull-left"></i>
|
24
|
+
#
|
25
|
+
# fa_icon "user", data: { id: 123 }
|
26
|
+
# # => <i class="fa fa-user" data-id="123"></i>
|
27
|
+
#
|
28
|
+
# content_tag(:li, fa_icon("check li", text: "Bulleted list item"))
|
29
|
+
# # => <li><i class="fa fa-check fa-li"></i> Bulleted list item</li>
|
30
|
+
def fa_icon(names = 'flag', options = {})
|
31
|
+
classes = ['fa']
|
32
|
+
classes.concat Private.icon_names(names)
|
33
|
+
classes.concat Array(options.delete(:class))
|
34
|
+
text = options.delete(:text)
|
35
|
+
right_icon = options.delete(:right)
|
36
|
+
icon = content_tag(:i, nil, options.merge(class: classes))
|
37
|
+
Private.icon_join(icon, text, right_icon)
|
38
|
+
end
|
39
|
+
|
40
|
+
# Creates an stack set of icon tags given a base icon name, a main icon
|
41
|
+
# name, and possible icon modifiers.
|
42
|
+
#
|
43
|
+
# Examples
|
44
|
+
#
|
45
|
+
# fa_stacked_icon "twitter", base: "square-o"
|
46
|
+
# # => <span class="fa-stack">
|
47
|
+
# # => <i class="fa fa-square-o fa-stack-2x"></i>
|
48
|
+
# # => <i class="fa fa-twitter fa-stack-1x"></i>
|
49
|
+
# # => </span>
|
50
|
+
#
|
51
|
+
# fa_stacked_icon "terminal inverse", base: "square", class: "pull-right", text: "Hi!"
|
52
|
+
# # => <span class="fa-stack pull-right">
|
53
|
+
# # => <i class="fa fa-square fa-stack-2x"></i>
|
54
|
+
# # => <i class="fa fa-terminal fa-inverse fa-stack-1x"></i>
|
55
|
+
# # => </span> Hi!
|
56
|
+
#
|
57
|
+
# fa_stacked_icon "camera", base: "ban-circle", reverse: true
|
58
|
+
# # => <span class="fa-stack">
|
59
|
+
# # => <i class="fa fa-camera fa-stack-1x"></i>
|
60
|
+
# # => <i class="fa fa-ban-circle fa-stack-2x"></i>
|
61
|
+
# # => </span>
|
62
|
+
def fa_stacked_icon(names = 'flag', options = {})
|
63
|
+
classes = Private.icon_names('stack').concat(Array(options.delete(:class)))
|
64
|
+
base_names = Private.array_value(options.delete(:base) || 'square-o').push('stack-2x')
|
65
|
+
names = Private.array_value(names).push('stack-1x')
|
66
|
+
base = fa_icon(base_names, options.delete(:base_options) || {})
|
67
|
+
icon = fa_icon(names, options.delete(:icon_options) || {})
|
68
|
+
icons = [base, icon]
|
69
|
+
icons.reverse! if options.delete(:reverse)
|
70
|
+
text = options.delete(:text)
|
71
|
+
right_icon = options.delete(:right)
|
72
|
+
stacked_icon = content_tag(:span, safe_join(icons), options.merge(class: classes))
|
73
|
+
Private.icon_join(stacked_icon, text, right_icon)
|
74
|
+
end
|
75
|
+
|
76
|
+
module Private
|
77
|
+
extend ActionView::Helpers::OutputSafetyHelper
|
78
|
+
|
79
|
+
def self.icon_join(icon, text, reverse_order = false)
|
80
|
+
return icon if text.blank?
|
81
|
+
elements = [icon, ERB::Util.html_escape(text)]
|
82
|
+
elements.reverse! if reverse_order
|
83
|
+
safe_join(elements, ' ')
|
84
|
+
end
|
85
|
+
|
86
|
+
def self.icon_names(names = [])
|
87
|
+
array_value(names).map { |n| "fa-#{n}" }
|
88
|
+
end
|
89
|
+
|
90
|
+
def self.array_value(value = [])
|
91
|
+
value.is_a?(Array) ? value : value.to_s.split(/\s+/)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module HashHelper
|
2
|
+
############
|
3
|
+
### Hash ###
|
4
|
+
############
|
5
|
+
|
6
|
+
# Returns a specific value from the given hash (or the default value if not set).
|
7
|
+
def get_value(key, hash, default_value = nil)
|
8
|
+
value = hash.delete key
|
9
|
+
value = default_value if value.nil? and !default_value.nil?
|
10
|
+
value
|
11
|
+
end
|
12
|
+
|
13
|
+
# Removes and returns a specific value from the given hash (or the default value if not set).
|
14
|
+
def pop_value(key, hash, default_value = nil)
|
15
|
+
symbolize_keys hash unless hash.empty?
|
16
|
+
get_value key.to_sym, hash, default_value
|
17
|
+
end
|
18
|
+
|
19
|
+
# all keys of the given hash symbolize.
|
20
|
+
def symbolize_keys(hash)
|
21
|
+
result = {}
|
22
|
+
hash.each { |key, value| result[key.to_sym] = value }
|
23
|
+
hash.replace result
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'redcarpet'
|
2
|
+
|
3
|
+
module MarkdownHelper
|
4
|
+
class HTMLWithPygments < Redcarpet::Render::HTML
|
5
|
+
def block_code(code, language)
|
6
|
+
sha = Digest::SHA1.hexdigest(code)
|
7
|
+
Rails.cache.fetch ["code", language, sha].join('-') do
|
8
|
+
Pygments.highlight(code, lexer: language)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def markdown(text)
|
14
|
+
renderer = HTMLWithPygments.new(hard_wrap: true, filter_html: true)
|
15
|
+
options = {
|
16
|
+
autolink: true,
|
17
|
+
no_intra_emphasis: true,
|
18
|
+
fenced_code_blocks: true,
|
19
|
+
lax_html_blocks: true,
|
20
|
+
strikethrough: true,
|
21
|
+
superscript: true
|
22
|
+
}
|
23
|
+
Redcarpet::Markdown.new(renderer, options).render(text).html_safe
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module QrcodeHelper
|
2
|
+
def qrcode(data='', options = {})
|
3
|
+
# Google API: https://google-developers.appspot.com/chart/infographics/docs/qr_codes
|
4
|
+
width = pop_value :width, options, '200'
|
5
|
+
output_encoding = pop_value :output_encoding, options
|
6
|
+
error_correction_level = pop_value :error_correction_level, options
|
7
|
+
margin = pop_value :margin, options
|
8
|
+
|
9
|
+
qrcode_url = 'https://chart.googleapis.com/chart?cht=qr'
|
10
|
+
qrcode_url += "&chl=#{data}"
|
11
|
+
qrcode_url += "&chs=#{width}x#{width}"
|
12
|
+
qrcode_url += "&choe=#{output_encoding}" unless output_encoding.nil?
|
13
|
+
if error_correction_level.nil? or margin.nil?
|
14
|
+
qrcode_url += "&chld=#{error_correction_level}" unless error_correction_level.nil?
|
15
|
+
qrcode_url += "&chld=|#{margin}" unless margin.nil?
|
16
|
+
else
|
17
|
+
qrcode_url += "&chld=#{error_correction_level}|#{margin}"
|
18
|
+
end
|
19
|
+
image_tag qrcode_url, alt: data
|
20
|
+
end
|
21
|
+
end
|
data/lib/andy_rails_toolbox.rb
CHANGED
metadata
CHANGED
@@ -1,43 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: andy_rails_toolbox
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ChouAndy
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-01-
|
11
|
+
date: 2015-01-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: redcarpet
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
20
|
-
type: :
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: pygments.rb
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
34
|
-
type: :
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '0'
|
41
41
|
description: Andy Rails Toolbox includes many useful helpers for rails development.
|
42
42
|
email:
|
43
43
|
- chouandy625@gmail.com
|
@@ -45,12 +45,18 @@ executables: []
|
|
45
45
|
extensions: []
|
46
46
|
extra_rdoc_files: []
|
47
47
|
files:
|
48
|
-
-
|
49
|
-
- Gemfile
|
50
|
-
- LICENSE.txt
|
48
|
+
- MIT-LICENSE
|
51
49
|
- README.md
|
52
50
|
- Rakefile
|
53
|
-
-
|
51
|
+
- app/assets/javascripts/jquery.timeago.js
|
52
|
+
- app/assets/javascripts/jquery.timeago.load.coffee
|
53
|
+
- app/assets/javascripts/jquery.timeago.zh-TW.js
|
54
|
+
- app/helpers/bootstrap_helper.rb
|
55
|
+
- app/helpers/font_awesome_helper.rb
|
56
|
+
- app/helpers/hash_helper.rb
|
57
|
+
- app/helpers/markdown_helper.rb
|
58
|
+
- app/helpers/qrcode_helper.rb
|
59
|
+
- app/helpers/timeago_helper.rb
|
54
60
|
- lib/andy_rails_toolbox.rb
|
55
61
|
- lib/andy_rails_toolbox/version.rb
|
56
62
|
homepage: https://github.com/ChouAndy/andy_rails_toolbox
|
data/.gitignore
DELETED
data/Gemfile
DELETED
data/andy_rails_toolbox.gemspec
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
lib = File.expand_path('../lib', __FILE__)
|
3
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require 'andy_rails_toolbox/version'
|
5
|
-
|
6
|
-
Gem::Specification.new do |spec|
|
7
|
-
spec.name = "andy_rails_toolbox"
|
8
|
-
spec.version = AndyRailsToolbox::VERSION
|
9
|
-
spec.authors = ["ChouAndy"]
|
10
|
-
spec.email = ["chouandy625@gmail.com"]
|
11
|
-
spec.summary = %q{Includes many useful helpers for rails development.}
|
12
|
-
spec.description = %q{Andy Rails Toolbox includes many useful helpers for rails development.}
|
13
|
-
spec.homepage = "https://github.com/ChouAndy/andy_rails_toolbox"
|
14
|
-
spec.license = "MIT"
|
15
|
-
|
16
|
-
spec.files = `git ls-files -z`.split("\x0")
|
17
|
-
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
-
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
-
spec.require_paths = ["lib"]
|
20
|
-
|
21
|
-
spec.add_development_dependency "bundler", "~> 1.7"
|
22
|
-
spec.add_development_dependency "rake", "~> 10.0"
|
23
|
-
end
|