Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Test fix for jQuery masked input

  • Loading branch information...
commit 06ef498374e8e3b980aa82598931d1e84c0c9c81 1 parent dfbc44d
@mhoran authored
View
1  .gitignore
@@ -14,3 +14,4 @@
/log/*.log
/tmp
*.swp
+.rvmrc
View
4 Gemfile
@@ -6,7 +6,9 @@ gem 'json'
group :test do
gem 'cucumber-rails'
- gem 'capybara-webkit'
+ gem 'capybara-webkit', github: 'thoughtbot/capybara-webkit'
+ gem 'capybara', '2.1.0.beta1'
+ gem 'selenium-webdriver'
end
group :test, :development do
View
38 Gemfile.lock
@@ -1,3 +1,11 @@
+GIT
+ remote: git://github.com/thoughtbot/capybara-webkit.git
+ revision: f8731b692a030a8f83f0375ae7127f44c9a97ef4
+ specs:
+ capybara-webkit (0.14.1)
+ capybara (~> 2.0, >= 2.0.2)
+ json
+
GEM
remote: https://rubygems.org/
specs:
@@ -28,21 +36,16 @@ GEM
activesupport (3.2.11)
i18n (~> 0.6)
multi_json (~> 1.0)
- addressable (2.3.2)
arel (3.0.2)
builder (3.0.4)
- capybara (2.0.2)
+ capybara (2.1.0.beta1)
mime-types (>= 1.16)
nokogiri (>= 1.3.3)
rack (>= 1.0.0)
rack-test (>= 0.5.4)
- selenium-webdriver (~> 2.0)
- xpath (~> 1.0.0)
- capybara-webkit (0.14.1)
- capybara (~> 2.0, >= 2.0.2)
- json
- childprocess (0.3.6)
- ffi (~> 1.0, >= 1.0.6)
+ xpath (>= 2.0.0.beta1)
+ childprocess (0.3.9)
+ ffi (~> 1.0, >= 1.0.11)
cucumber (1.1.9)
builder (>= 2.1.2)
diff-lcs (>= 1.1.2)
@@ -55,7 +58,7 @@ GEM
nokogiri (>= 1.5.0)
diff-lcs (1.1.3)
erubis (2.7.0)
- ffi (1.3.1)
+ ffi (1.4.0)
gherkin (2.9.0)
json (>= 1.4.6)
hike (1.2.1)
@@ -65,9 +68,6 @@ GEM
railties (>= 3.2.0, < 5.0)
thor (~> 0.14)
json (1.7.6)
- libwebsocket (0.1.7.1)
- addressable
- websocket
mail (2.4.4)
i18n (>= 0.4.0)
mime-types (~> 1.16)
@@ -115,11 +115,11 @@ GEM
railties (>= 3.0)
rspec (~> 2.8.0)
rubyzip (0.9.9)
- selenium-webdriver (2.27.2)
+ selenium-webdriver (2.31.0)
childprocess (>= 0.2.5)
- libwebsocket (~> 0.1.3)
multi_json (~> 1.0)
rubyzip
+ websocket (~> 1.0.4)
sprockets (2.2.2)
hike (~> 1.2)
multi_json (~> 1.0)
@@ -132,17 +132,19 @@ GEM
polyglot
polyglot (>= 0.3.1)
tzinfo (0.3.35)
- websocket (1.0.6)
- xpath (1.0.0)
+ websocket (1.0.7)
+ xpath (2.0.0.beta1)
nokogiri (~> 1.3)
PLATFORMS
ruby
DEPENDENCIES
- capybara-webkit
+ capybara (= 2.1.0.beta1)
+ capybara-webkit!
cucumber-rails
jquery-rails
json
rails
rspec-rails
+ selenium-webdriver
View
338 app/assets/javascripts/jquery.maskedinput.js
@@ -0,0 +1,338 @@
+/*
+ Masked Input plugin for jQuery
+ Copyright (c) 2007-2013 Josh Bush (digitalbush.com)
+ Licensed under the MIT license (http://digitalbush.com/projects/masked-input-plugin/#license)
+ Version: 1.3.1
+*/
+(function($) {
+ function getPasteEvent() {
+ var el = document.createElement('input'),
+ name = 'onpaste';
+ el.setAttribute(name, '');
+ return (typeof el[name] === 'function')?'paste':'input';
+}
+
+var pasteEventName = getPasteEvent() + ".mask",
+ ua = navigator.userAgent,
+ iPhone = /iphone/i.test(ua),
+ android=/android/i.test(ua),
+ caretTimeoutId;
+
+$.mask = {
+ //Predefined character definitions
+ definitions: {
+ '9': "[0-9]",
+ 'a': "[A-Za-z]",
+ '*': "[A-Za-z0-9]"
+ },
+ dataName: "rawMaskFn",
+ placeholder: '_',
+};
+
+$.fn.extend({
+ //Helper Function for Caret positioning
+ caret: function(begin, end) {
+ var range;
+
+ if (this.length === 0 || this.is(":hidden")) {
+ return;
+ }
+
+ if (typeof begin == 'number') {
+ end = (typeof end === 'number') ? end : begin;
+ return this.each(function() {
+ if (this.setSelectionRange) {
+ this.setSelectionRange(begin, end);
+ } else if (this.createTextRange) {
+ range = this.createTextRange();
+ range.collapse(true);
+ range.moveEnd('character', end);
+ range.moveStart('character', begin);
+ range.select();
+ }
+ });
+ } else {
+ if (this[0].setSelectionRange) {
+ begin = this[0].selectionStart;
+ end = this[0].selectionEnd;
+ } else if (document.selection && document.selection.createRange) {
+ range = document.selection.createRange();
+ begin = 0 - range.duplicate().moveStart('character', -100000);
+ end = begin + range.text.length;
+ }
+ return { begin: begin, end: end };
+ }
+ },
+ unmask: function() {
+ return this.trigger("unmask");
+ },
+ mask: function(mask, settings) {
+ var input,
+ defs,
+ tests,
+ partialPosition,
+ firstNonMaskPos,
+ len;
+
+ if (!mask && this.length > 0) {
+ input = $(this[0]);
+ return input.data($.mask.dataName)();
+ }
+ settings = $.extend({
+ placeholder: $.mask.placeholder, // Load default placeholder
+ completed: null
+ }, settings);
+
+
+ defs = $.mask.definitions;
+ tests = [];
+ partialPosition = len = mask.length;
+ firstNonMaskPos = null;
+
+ $.each(mask.split(""), function(i, c) {
+ if (c == '?') {
+ len--;
+ partialPosition = i;
+ } else if (defs[c]) {
+ tests.push(new RegExp(defs[c]));
+ if (firstNonMaskPos === null) {
+ firstNonMaskPos = tests.length - 1;
+ }
+ } else {
+ tests.push(null);
+ }
+ });
+
+ return this.trigger("unmask").each(function() {
+ var input = $(this),
+ buffer = $.map(
+ mask.split(""),
+ function(c, i) {
+ if (c != '?') {
+ return defs[c] ? settings.placeholder : c;
+ }
+ }),
+ focusText = input.val();
+
+ function seekNext(pos) {
+ while (++pos < len && !tests[pos]);
+ return pos;
+ }
+
+ function seekPrev(pos) {
+ while (--pos >= 0 && !tests[pos]);
+ return pos;
+ }
+
+ function shiftL(begin,end) {
+ var i,
+ j;
+
+ if (begin<0) {
+ return;
+ }
+
+ for (i = begin, j = seekNext(end); i < len; i++) {
+ if (tests[i]) {
+ if (j < len && tests[i].test(buffer[j])) {
+ buffer[i] = buffer[j];
+ buffer[j] = settings.placeholder;
+ } else {
+ break;
+ }
+
+ j = seekNext(j);
+ }
+ }
+ writeBuffer();
+ input.caret(Math.max(firstNonMaskPos, begin));
+ }
+
+ function shiftR(pos) {
+ var i,
+ c,
+ j,
+ t;
+
+ for (i = pos, c = settings.placeholder; i < len; i++) {
+ if (tests[i]) {
+ j = seekNext(i);
+ t = buffer[i];
+ buffer[i] = c;
+ if (j < len && tests[j].test(t)) {
+ c = t;
+ } else {
+ break;
+ }
+ }
+ }
+ }
+
+ function keydownEvent(e) {
+ var k = e.which,
+ pos,
+ begin,
+ end;
+
+ //backspace, delete, and escape get special treatment
+ if (k === 8 || k === 46 || (iPhone && k === 127)) {
+ pos = input.caret();
+ begin = pos.begin;
+ end = pos.end;
+
+ if (end - begin === 0) {
+ begin=k!==46?seekPrev(begin):(end=seekNext(begin-1));
+ end=k===46?seekNext(end):end;
+ }
+ clearBuffer(begin, end);
+ shiftL(begin, end - 1);
+
+ e.preventDefault();
+ } else if (k == 27) {//escape
+ input.val(focusText);
+ input.caret(0, checkVal());
+ e.preventDefault();
+ }
+ }
+
+ function keypressEvent(e) {
+ var k = e.which,
+ pos = input.caret(),
+ p,
+ c,
+ next;
+
+ if (e.ctrlKey || e.altKey || e.metaKey || k < 32) {//Ignore
+ return;
+ } else if (k) {
+ if (pos.end - pos.begin !== 0){
+ clearBuffer(pos.begin, pos.end);
+ shiftL(pos.begin, pos.end-1);
+ }
+
+ p = seekNext(pos.begin - 1);
+ if (p < len) {
+ c = String.fromCharCode(k);
+ if (tests[p].test(c)) {
+ shiftR(p);
+
+ buffer[p] = c;
+ writeBuffer();
+ next = seekNext(p);
+
+ if(android){
+ setTimeout($.proxy($.fn.caret,input,next),0);
+ }else{
+ input.caret(next);
+ }
+
+ if (settings.completed && next >= len) {
+ settings.completed.call(input);
+ }
+ }
+ }
+ e.preventDefault();
+ }
+ }
+
+ function clearBuffer(start, end) {
+ var i;
+ for (i = start; i < end && i < len; i++) {
+ if (tests[i]) {
+ buffer[i] = settings.placeholder;
+ }
+ }
+ }
+
+ function writeBuffer() { input.val(buffer.join('')); }
+
+ function checkVal(allow) {
+ //try to place characters where they belong
+ var test = input.val(),
+ lastMatch = -1,
+ i,
+ c;
+
+ for (i = 0, pos = 0; i < len; i++) {
+ if (tests[i]) {
+ buffer[i] = settings.placeholder;
+ while (pos++ < test.length) {
+ c = test.charAt(pos - 1);
+ if (tests[i].test(c)) {
+ buffer[i] = c;
+ lastMatch = i;
+ break;
+ }
+ }
+ if (pos > test.length) {
+ break;
+ }
+ } else if (buffer[i] === test.charAt(pos) && i !== partialPosition) {
+ pos++;
+ lastMatch = i;
+ }
+ }
+ if (allow) {
+ writeBuffer();
+ } else if (lastMatch + 1 < partialPosition) {
+ input.val("");
+ clearBuffer(0, len);
+ } else {
+ writeBuffer();
+ input.val(input.val().substring(0, lastMatch + 1));
+ }
+ return (partialPosition ? i : firstNonMaskPos);
+ }
+
+ input.data($.mask.dataName,function(){
+ return $.map(buffer, function(c, i) {
+ return tests[i]&&c!=settings.placeholder ? c : null;
+ }).join('');
+ });
+
+ if (!input.attr("readonly"))
+ input
+ .one("unmask", function() {
+ input
+ .unbind(".mask")
+ .removeData($.mask.dataName);
+ })
+ .bind("focus.mask", function() {
+ clearTimeout(caretTimeoutId);
+ var pos,
+ moveCaret;
+
+ focusText = input.val();
+ pos = checkVal();
+
+ caretTimeoutId = setTimeout(function(){
+ writeBuffer();
+ if (pos == mask.length) {
+ input.caret(0, pos);
+ } else {
+ input.caret(pos);
+ }
+ }, 10);
+ })
+ .bind("blur.mask", function() {
+ checkVal();
+ if (input.val() != focusText)
+ input.change();
+ })
+ .bind("keydown.mask", keydownEvent)
+ .bind("keypress.mask", keypressEvent)
+ .bind(pasteEventName, function() {
+ setTimeout(function() {
+ var pos=checkVal(true);
+ input.caret(pos);
+ if (settings.completed && pos == input.val().length)
+ settings.completed.call(input);
+ }, 0);
+ });
+ checkVal(); //Perform initial check for existing values
+ });
+ }
+});
+
+
+})(jQuery);
View
7 features/inputmask.feature
@@ -0,0 +1,7 @@
+Feature: Testing jQuery inputmask
+
+ @javascript
+ Scenario:
+ Given I am on a page with an inputmask
+ When I fill out the masked input
+ Then I should see the proper value
View
11 features/step_definitions/intputmask_steps.rb
@@ -0,0 +1,11 @@
+Given /^I am on a page with an inputmask$/ do
+ visit '/test.html'
+end
+
+When /^I fill out the masked input$/ do
+ fill_in 'Input', with: '2011'
+end
+
+Then /^I should see the proper value$/ do
+ page.find_field('Input').value.should == '2011'
+end
View
2  features/step_definitions/popup_steps.rb
@@ -5,7 +5,7 @@
When /^I sign in via Facebook$/ do
click_link 'Login'
- within_window('Log In | Facebook') do
+ within_window('Facebook') do
fill_in 'Email', :with => 'test_xmefjnz_user@tfbnw.net'
fill_in 'Password', :with => '1292562059'
click_button 'Log In'
View
20 public/test.html
@@ -0,0 +1,20 @@
+<html>
+ <head>
+ <script src="/assets/jquery.js"></script>
+ <script src="/assets/jquery.maskedinput.js"></script>
+ <script>
+ (function ($) {
+ $('input[data-mask]').live('focus', function () {
+ var input = $(this);
+
+ input.mask(input.attr("data-mask")).trigger('focus.mask');
+ });
+ })(jQuery);
+ </script>
+ </head>
+ <body>
+ <form>
+ <label>Input <input type="text" data-mask="9999" value="2012" /></label>
+ </form>
+ </body>
+</html>
Please sign in to comment.
Something went wrong with that request. Please try again.