formtastic_masked_input 0.1.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.
- data/MIT-LICENSE +20 -0
- data/README.textile +60 -0
- data/Rakefile +27 -0
- data/VERSION +1 -0
- data/generators/formtastic_masked_input/USAGE +9 -0
- data/generators/formtastic_masked_input/formtastic_masked_input_generator.rb +8 -0
- data/generators/formtastic_masked_input/templates/masked_input.js +312 -0
- data/init.rb +1 -0
- data/lib/formtastic_masked_input.rb +15 -0
- data/tasks/formtastic_masked_input_tasks.rake +4 -0
- metadata +64 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010 Gabriel Sobrinho
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.textile
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
h1. formtastic_masked_input
|
2
|
+
|
3
|
+
Sometimes you want to mask your fields like phones, zipcodes or something like that.
|
4
|
+
|
5
|
+
This plugin will do it for you if you are using formtastic.
|
6
|
+
|
7
|
+
Note: the javascript file depends on Prototype 1.6.1, just update your prototype.js. Rails 2 uses Prototype version 1.6.0.3
|
8
|
+
|
9
|
+
h2. Usage
|
10
|
+
|
11
|
+
<pre>$ ruby script/plugin install git://github.com/sobrinho/formtastic_masked_input.git
|
12
|
+
$ ruby script/generate formtastic_masked_input</pre>
|
13
|
+
|
14
|
+
Include prototype.js and masked_input.js into layout:
|
15
|
+
|
16
|
+
<pre><%= javascript_include_tag 'prototype', 'masked_input' %></pre>
|
17
|
+
|
18
|
+
And update your form field:
|
19
|
+
|
20
|
+
<pre><% semantic_form_for @person do |f| %>
|
21
|
+
<% f.inputs do %>
|
22
|
+
<%= f.input :name %>
|
23
|
+
<%= f.input :phone, :as => :masked, :mask => :phone %>
|
24
|
+
<% end %>
|
25
|
+
|
26
|
+
<%= f.buttons %>
|
27
|
+
<% end %></pre>
|
28
|
+
|
29
|
+
h2. Masks
|
30
|
+
|
31
|
+
The available masks are made for Brazil:
|
32
|
+
|
33
|
+
* phone: (99) 9999-9999
|
34
|
+
* cpf: 999.999.999-99
|
35
|
+
* cnpj: 99.999.999/9999-99
|
36
|
+
* date: 99/99/9999
|
37
|
+
* cep: 99999-999
|
38
|
+
* time: 99:99
|
39
|
+
|
40
|
+
If you want to add a custom mask, you can edit masked_input.js around line 301 (preferred) or add directly into your layout:
|
41
|
+
|
42
|
+
<pre><%= javascript_include_tag 'prototype', 'masked_input' %>
|
43
|
+
<script type="text/javascript">
|
44
|
+
//<![CDATA[
|
45
|
+
Object.extend(MaskedInput.masks, {
|
46
|
+
'version': '9.9.9'
|
47
|
+
});
|
48
|
+
//]]>
|
49
|
+
</script></pre>
|
50
|
+
|
51
|
+
h2. Credits
|
52
|
+
|
53
|
+
Special thanks to Justin French for formtastic and Bjarte K. Vebjørnsen for MaskedInput port for Prototype.
|
54
|
+
|
55
|
+
h2. TODO
|
56
|
+
|
57
|
+
* Make tests for plugin
|
58
|
+
* Make tests for MaskedInput
|
59
|
+
|
60
|
+
Copyright (c) 2010 Gabriel Sobrinho, released under the MIT license
|
data/Rakefile
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
|
5
|
+
begin
|
6
|
+
require 'jeweler'
|
7
|
+
Jeweler::Tasks.new do |gemspec|
|
8
|
+
gemspec.name = "formtastic_masked_input"
|
9
|
+
gemspec.summary = "MaskedInput for formtastic"
|
10
|
+
gemspec.email = "gabriel.sobrinho@gmail.com"
|
11
|
+
gemspec.homepage = "http://github.com/sobrinho/formtastic_masked_input"
|
12
|
+
gemspec.authors = ["Gabriel Sobrinho"]
|
13
|
+
end
|
14
|
+
|
15
|
+
Jeweler::GemcutterTasks.new
|
16
|
+
rescue LoadError
|
17
|
+
puts "Jeweler not available. Install it with: gem install jeweler"
|
18
|
+
end
|
19
|
+
|
20
|
+
desc 'Generate documentation for the formtastic_masked_input plugin.'
|
21
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
22
|
+
rdoc.rdoc_dir = 'rdoc'
|
23
|
+
rdoc.title = 'FormtasticMaskedInput'
|
24
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
25
|
+
rdoc.rdoc_files.include('README')
|
26
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
27
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
@@ -0,0 +1,9 @@
|
|
1
|
+
Description:
|
2
|
+
The formtastic_masked_input generator creates a javascript file called
|
3
|
+
masked_input.js to the public path which will be used on formtastic.
|
4
|
+
|
5
|
+
Example:
|
6
|
+
./script/generate formtastic_masked_input
|
7
|
+
|
8
|
+
This will create:
|
9
|
+
public/javascripts/masked_input.js
|
@@ -0,0 +1,312 @@
|
|
1
|
+
/*
|
2
|
+
Masked Input plugin for prototype ported from jQuery
|
3
|
+
Bjarte K. Vebjørnsen <bjartekv at gmail dot com>
|
4
|
+
|
5
|
+
Note that the onchange event isn't fired for masked inputs. It won't fire unless event.simulate.js is available.
|
6
|
+
|
7
|
+
Requires: Prototype >= 1.6.1
|
8
|
+
Optional: event.simulate.js from http://github.com/kangax/protolicious to trigger native change event.
|
9
|
+
|
10
|
+
Tested on windows IE6, IE7, IE8, Opera 9.6, Chrome 3, FireFox 3, Safari 3
|
11
|
+
|
12
|
+
Masked Input plugin for jQuery
|
13
|
+
Copyright (c) 2007-2009 Josh Bush (digitalbush.com)
|
14
|
+
Licensed under the MIT license (http://digitalbush.com/projects/masked-input-plugin/#license)
|
15
|
+
Version: 1.2.2 (03/09/2009 22:39:06)
|
16
|
+
*/
|
17
|
+
|
18
|
+
(function() {
|
19
|
+
var pasteEventName = (Prototype.Browser.IE ? 'paste' : 'input'),
|
20
|
+
iPhone = (window.orientation != undefined);
|
21
|
+
|
22
|
+
if(typeof(Prototype) == "undefined")
|
23
|
+
throw "MaskedInput requires Prototype to be loaded.";
|
24
|
+
|
25
|
+
if(Prototype.Version < '1.6.1')
|
26
|
+
throw "MaskedInput requires Prototype 1.6.1 or greater.";
|
27
|
+
|
28
|
+
Element.addMethods({
|
29
|
+
caret: function(element, begin, end) {
|
30
|
+
if (element.length == 0) return;
|
31
|
+
if (typeof begin == 'number') {
|
32
|
+
end = (typeof end == 'number') ? end : begin;
|
33
|
+
if (element.setSelectionRange) {
|
34
|
+
element.focus();
|
35
|
+
element.setSelectionRange(begin, end);
|
36
|
+
} else if (element.createTextRange) {
|
37
|
+
var range = element.createTextRange();
|
38
|
+
range.collapse(true);
|
39
|
+
range.moveEnd('character', end);
|
40
|
+
range.moveStart('character', begin);
|
41
|
+
range.select();
|
42
|
+
}
|
43
|
+
} else {
|
44
|
+
if (element.setSelectionRange) {
|
45
|
+
begin = element.selectionStart;
|
46
|
+
end = element.selectionEnd;
|
47
|
+
} else if (document.selection && document.selection.createRange) {
|
48
|
+
var range = document.selection.createRange();
|
49
|
+
begin = 0 - range.duplicate().moveStart('character', -100000);
|
50
|
+
end = begin + range.text.length;
|
51
|
+
}
|
52
|
+
return { begin: begin, end: end };
|
53
|
+
}
|
54
|
+
}
|
55
|
+
});
|
56
|
+
|
57
|
+
MaskedInput = Class.create({
|
58
|
+
initialize: function(selector, mask, settings) {
|
59
|
+
this.elements = $$(selector);
|
60
|
+
this.mask(mask, settings);
|
61
|
+
},
|
62
|
+
unmask: function() {
|
63
|
+
this.elements.each(function(el) {
|
64
|
+
el.fire("mask:unmask");
|
65
|
+
});
|
66
|
+
return this;
|
67
|
+
},
|
68
|
+
mask: function (mask, settings) {
|
69
|
+
if (!mask && this.elements.length > 0) {
|
70
|
+
var input = $(this.elements[0]);
|
71
|
+
var tests = input.retrieve("tests");
|
72
|
+
return $A(input.retrieve("buffer")).map(function(c, i) {
|
73
|
+
return tests[i] ? c : null;
|
74
|
+
}).join('');
|
75
|
+
}
|
76
|
+
settings = Object.extend({
|
77
|
+
placeholder: "_",
|
78
|
+
completed: null
|
79
|
+
}, settings || {});
|
80
|
+
|
81
|
+
var defs = MaskedInput.definitions;
|
82
|
+
var tests = [];
|
83
|
+
var partialPosition = mask.length;
|
84
|
+
var firstNonMaskPos = null;
|
85
|
+
var len = mask.length;
|
86
|
+
|
87
|
+
$A(mask.split("")).each(function(c, i) {
|
88
|
+
if (c == '?') {
|
89
|
+
len--;
|
90
|
+
partialPosition = i;
|
91
|
+
} else if (defs[c]) {
|
92
|
+
tests.push(new RegExp(defs[c]));
|
93
|
+
if(firstNonMaskPos==null)
|
94
|
+
firstNonMaskPos = tests.length - 1;
|
95
|
+
} else {
|
96
|
+
tests.push(null);
|
97
|
+
}
|
98
|
+
});
|
99
|
+
|
100
|
+
this.elements.each(function(el) {
|
101
|
+
|
102
|
+
var input = $(el);
|
103
|
+
|
104
|
+
var buffer = $A(mask.split("")).map( function(c, i) { if (c != '?') return defs[c] ? settings.placeholder : c });
|
105
|
+
|
106
|
+
var ignore = false; //Variable for ignoring control keys
|
107
|
+
var focusText = input.getValue();
|
108
|
+
|
109
|
+
input.store("buffer", buffer).store("tests", tests);
|
110
|
+
|
111
|
+
function seekNext(pos) {
|
112
|
+
while (++pos < len && !tests[pos]);
|
113
|
+
return pos;
|
114
|
+
};
|
115
|
+
|
116
|
+
function shiftL(pos) {
|
117
|
+
while (!tests[pos] && --pos >= 0);
|
118
|
+
for (var i = pos; i < len; i++) {
|
119
|
+
if (tests[i]) {
|
120
|
+
buffer[i] = settings.placeholder;
|
121
|
+
var j = seekNext(i);
|
122
|
+
if (j < len && tests[i].test(buffer[j])) {
|
123
|
+
buffer[i] = buffer[j];
|
124
|
+
} else
|
125
|
+
break;
|
126
|
+
}
|
127
|
+
}
|
128
|
+
writeBuffer();
|
129
|
+
input.caret(Math.max(firstNonMaskPos, pos));
|
130
|
+
};
|
131
|
+
|
132
|
+
function shiftR(pos) {
|
133
|
+
for (var i = pos, c = settings.placeholder; i < len; i++) {
|
134
|
+
if (tests[i]) {
|
135
|
+
var j = seekNext(i);
|
136
|
+
var t = buffer[i];
|
137
|
+
buffer[i] = c;
|
138
|
+
if (j < len && tests[j].test(t))
|
139
|
+
c = t;
|
140
|
+
else
|
141
|
+
break;
|
142
|
+
}
|
143
|
+
}
|
144
|
+
};
|
145
|
+
|
146
|
+
function keydownEvent(e) {
|
147
|
+
var pos = input.caret();
|
148
|
+
var k = e.keyCode;
|
149
|
+
ignore = (k < 16 || (k > 16 && k < 32) || (k > 32 && k < 41));
|
150
|
+
//delete selection before proceeding
|
151
|
+
if ((pos.begin - pos.end) != 0 && (!ignore || k == 8 || k == 46))
|
152
|
+
clearBuffer(pos.begin, pos.end);
|
153
|
+
|
154
|
+
//backspace, delete, and escape get special treatment
|
155
|
+
if (k == 8 || k == 46 || (iPhone && k == 127)) {//backspace/delete
|
156
|
+
shiftL(pos.begin + (k == 46 ? 0 : -1));
|
157
|
+
e.stop();
|
158
|
+
} else if (k == 27) {//escape
|
159
|
+
input.setValue(focusText);
|
160
|
+
input.caret(0, checkVal());
|
161
|
+
e.stop();
|
162
|
+
}
|
163
|
+
};
|
164
|
+
|
165
|
+
function keypressEvent(e) {
|
166
|
+
if (ignore) {
|
167
|
+
ignore = false;
|
168
|
+
//Fixes Mac FF bug on backspace
|
169
|
+
return (e.keyCode == 8) ? false : null;
|
170
|
+
}
|
171
|
+
e = e || window.event;
|
172
|
+
var k = e.charCode || e.keyCode || e.which;
|
173
|
+
var pos = input.caret();
|
174
|
+
if (e.ctrlKey || e.altKey || e.metaKey) {//Ignore
|
175
|
+
return true;
|
176
|
+
} else if ((k >= 32 && k <= 125) || k > 186) {//typeable characters
|
177
|
+
var p = seekNext(pos.begin - 1);
|
178
|
+
if (p < len) {
|
179
|
+
var c = String.fromCharCode(k);
|
180
|
+
if (tests[p].test(c)) {
|
181
|
+
shiftR(p);
|
182
|
+
buffer[p] = c;
|
183
|
+
writeBuffer();
|
184
|
+
var next = seekNext(p);
|
185
|
+
input.caret(next);
|
186
|
+
if (settings.completed && next == len)
|
187
|
+
settings.completed.call(input);
|
188
|
+
}
|
189
|
+
}
|
190
|
+
}
|
191
|
+
e.stop();
|
192
|
+
};
|
193
|
+
|
194
|
+
function blurEvent(e) {
|
195
|
+
checkVal();
|
196
|
+
if (input.getValue() != focusText) {
|
197
|
+
// since the native change event doesn't fire we have to fire it ourselves
|
198
|
+
// since Event.fire doesn't support native events we're using Event.simulate if available
|
199
|
+
if (window.Event.simulate) {
|
200
|
+
input.simulate('change');
|
201
|
+
}
|
202
|
+
}
|
203
|
+
};
|
204
|
+
|
205
|
+
function focusEvent(e) {
|
206
|
+
focusText = input.getValue();
|
207
|
+
var pos = checkVal();
|
208
|
+
writeBuffer();
|
209
|
+
|
210
|
+
setTimeout(function() {
|
211
|
+
if (pos == mask.length)
|
212
|
+
input.caret(0, pos);
|
213
|
+
else
|
214
|
+
input.caret(pos);
|
215
|
+
}, 0);
|
216
|
+
};
|
217
|
+
|
218
|
+
function pasteEvent(e) {
|
219
|
+
setTimeout(function() { input.caret(checkVal(true)); }, 0);
|
220
|
+
};
|
221
|
+
|
222
|
+
function clearBuffer(start, end) {
|
223
|
+
for (var i = start; i < end && i < len; i++) {
|
224
|
+
if (tests[i])
|
225
|
+
buffer[i] = settings.placeholder;
|
226
|
+
}
|
227
|
+
};
|
228
|
+
|
229
|
+
function writeBuffer() { return input.setValue(buffer.join('')).getValue(); };
|
230
|
+
|
231
|
+
function checkVal(allow) {
|
232
|
+
//try to place characters where they belong
|
233
|
+
var test = input.getValue();
|
234
|
+
var lastMatch = -1;
|
235
|
+
for (var i = 0, pos = 0; i < len; i++) {
|
236
|
+
if (tests[i]) {
|
237
|
+
buffer[i] = settings.placeholder;
|
238
|
+
while (pos++ < test.length) {
|
239
|
+
var c = test.charAt(pos - 1);
|
240
|
+
if (tests[i].test(c)) {
|
241
|
+
buffer[i] = c;
|
242
|
+
lastMatch = i;
|
243
|
+
break;
|
244
|
+
}
|
245
|
+
}
|
246
|
+
if (pos > test.length)
|
247
|
+
break;
|
248
|
+
} else if (buffer[i] == test[pos] && i!=partialPosition) {
|
249
|
+
pos++;
|
250
|
+
lastMatch = i;
|
251
|
+
}
|
252
|
+
}
|
253
|
+
if (!allow && lastMatch + 1 < partialPosition) {
|
254
|
+
input.setValue("");
|
255
|
+
clearBuffer(0, len);
|
256
|
+
} else if (allow || lastMatch + 1 >= partialPosition) {
|
257
|
+
writeBuffer();
|
258
|
+
if (!allow) input.setValue(input.getValue().substring(0, lastMatch + 1));
|
259
|
+
}
|
260
|
+
return (partialPosition ? i : firstNonMaskPos);
|
261
|
+
};
|
262
|
+
|
263
|
+
if (!input.readAttribute("readonly"))
|
264
|
+
input
|
265
|
+
.observe("mask:unmask", function() {
|
266
|
+
input
|
267
|
+
.store("buffer",undefined)
|
268
|
+
.store("tests",undefined)
|
269
|
+
.stopObserving("mask:unmask")
|
270
|
+
.stopObserving("focus", focusEvent)
|
271
|
+
.stopObserving("blur", blurEvent)
|
272
|
+
.stopObserving("keydown", keydownEvent)
|
273
|
+
.stopObserving("keypress", keypressEvent)
|
274
|
+
.stopObserving(pasteEventName, pasteEvent);
|
275
|
+
})
|
276
|
+
.observe("focus", focusEvent)
|
277
|
+
.observe("blur", blurEvent)
|
278
|
+
.observe("keydown", keydownEvent)
|
279
|
+
.observe("keypress", keypressEvent)
|
280
|
+
.observe(pasteEventName, pasteEvent);
|
281
|
+
|
282
|
+
checkVal(); //Perform initial check for existing values
|
283
|
+
});
|
284
|
+
return this;
|
285
|
+
}
|
286
|
+
});
|
287
|
+
|
288
|
+
Object.extend(MaskedInput,{
|
289
|
+
definitions: {
|
290
|
+
'9': "[0-9]",
|
291
|
+
'a': "[A-Za-z]",
|
292
|
+
'*': "[A-Za-z0-9]"
|
293
|
+
},
|
294
|
+
|
295
|
+
masks: {
|
296
|
+
'phone': '(99) 9999-9999',
|
297
|
+
'cpf' : '999.999.999-99',
|
298
|
+
'cnpj' : '99.999.999/9999-99',
|
299
|
+
'date' : '99/99/9999',
|
300
|
+
'cep' : '99999-999',
|
301
|
+
'time' : '99:99'
|
302
|
+
},
|
303
|
+
|
304
|
+
apply: function () {
|
305
|
+
Object.keys(MaskedInput.masks).each(function (name) {
|
306
|
+
new MaskedInput('input.mask.' + name, MaskedInput.masks[name]);
|
307
|
+
});
|
308
|
+
}
|
309
|
+
});
|
310
|
+
|
311
|
+
$(document).observe('dom:loaded', MaskedInput.apply.bind(MaskedInput));
|
312
|
+
})();
|
data/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'formtastic_masked_input'
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module FormtasticMaskedInput
|
2
|
+
def masked_input(method, options)
|
3
|
+
mask = options.delete(:mask)
|
4
|
+
|
5
|
+
raise ArgumentError, 'you must specify a mask' unless mask
|
6
|
+
|
7
|
+
options[:input_html] ||= {}
|
8
|
+
options[:input_html][:class] ||= ''
|
9
|
+
options[:input_html][:class] = "#{options[:input_html][:class]} mask #{mask}".strip
|
10
|
+
|
11
|
+
string_input(method, options)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
Formtastic::SemanticFormBuilder.send(:include, FormtasticMaskedInput)
|
metadata
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: formtastic_masked_input
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Gabriel Sobrinho
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2010-02-04 00:00:00 -02:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description:
|
17
|
+
email: gabriel.sobrinho@gmail.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- README.textile
|
24
|
+
files:
|
25
|
+
- MIT-LICENSE
|
26
|
+
- README.textile
|
27
|
+
- Rakefile
|
28
|
+
- VERSION
|
29
|
+
- generators/formtastic_masked_input/USAGE
|
30
|
+
- generators/formtastic_masked_input/formtastic_masked_input_generator.rb
|
31
|
+
- generators/formtastic_masked_input/templates/masked_input.js
|
32
|
+
- init.rb
|
33
|
+
- lib/formtastic_masked_input.rb
|
34
|
+
- tasks/formtastic_masked_input_tasks.rake
|
35
|
+
has_rdoc: true
|
36
|
+
homepage: http://github.com/sobrinho/formtastic_masked_input
|
37
|
+
licenses: []
|
38
|
+
|
39
|
+
post_install_message:
|
40
|
+
rdoc_options:
|
41
|
+
- --charset=UTF-8
|
42
|
+
require_paths:
|
43
|
+
- lib
|
44
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: "0"
|
49
|
+
version:
|
50
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: "0"
|
55
|
+
version:
|
56
|
+
requirements: []
|
57
|
+
|
58
|
+
rubyforge_project:
|
59
|
+
rubygems_version: 1.3.5
|
60
|
+
signing_key:
|
61
|
+
specification_version: 3
|
62
|
+
summary: MaskedInput for formtastic
|
63
|
+
test_files: []
|
64
|
+
|