diff --git a/core/vendor/assets/javascripts/jquery.payment.js b/core/vendor/assets/javascripts/jquery.payment.js index 5bc7ef0adb6..f17cef97c01 100644 --- a/core/vendor/assets/javascripts/jquery.payment.js +++ b/core/vendor/assets/javascripts/jquery.payment.js @@ -1,11 +1,11 @@ -// Generated by CoffeeScript 1.4.0 +// jQuery.payment v1.3.2 +// Generated by CoffeeScript 1.7.1 (function() { - var $, cardFromNumber, cardFromType, cards, defaultFormat, formatBackCardNumber, formatBackExpiry, formatCardNumber, formatExpiry, formatForwardExpiry, formatForwardSlash, hasTextSelected, luhnCheck, reFormatCardNumber, restrictCVC, restrictCardNumber, restrictExpiry, restrictNumeric, setCardType, + var $, cardFromNumber, cardFromType, cards, defaultFormat, formatBackCardNumber, formatBackExpiry, formatCardNumber, formatExpiry, formatForwardExpiry, formatForwardSlashAndSpace, hasTextSelected, luhnCheck, reFormatCVC, reFormatCardNumber, reFormatExpiry, reFormatNumeric, replaceFullWidthChars, restrictCVC, restrictCardNumber, restrictExpiry, restrictNumeric, safeVal, setCardType, __slice = [].slice, - __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }, - _this = this; + __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; - $ = jQuery; + $ = window.jQuery || window.Zepto || window.$; $.payment = {}; @@ -19,80 +19,99 @@ defaultFormat = /(\d{1,4})/g; - cards = [ + $.payment.cards = cards = [ { - type: 'maestro', - pattern: /^(5018|5020|5038|6304|6759|676[1-3])/, + type: 'visaelectron', + patterns: [4026, 417500, 4405, 4508, 4844, 4913, 4917], format: defaultFormat, - length: [12, 13, 14, 15, 16, 17, 18, 19], + length: [16], cvcLength: [3], luhn: true }, { - type: 'dinersclub', - pattern: /^(36|38|30[0-5])/, + type: 'maestro', + patterns: [5018, 502, 503, 56, 58, 639, 6220, 67], format: defaultFormat, - length: [14], + length: [12, 13, 14, 15, 16, 17, 18, 19], cvcLength: [3], luhn: true }, { - type: 'laser', - pattern: /^(6706|6771|6709)/, + type: 'forbrugsforeningen', + patterns: [600], format: defaultFormat, - length: [16, 17, 18, 19], + length: [16], cvcLength: [3], luhn: true }, { - type: 'jcb', - pattern: /^35/, + type: 'dankort', + patterns: [5019], format: defaultFormat, length: [16], cvcLength: [3], luhn: true }, { - type: 'unionpay', - pattern: /^62/, - format: defaultFormat, - length: [16, 17, 18, 19], - cvcLength: [3], - luhn: false - }, { - type: 'discover', - pattern: /^(6011|65|64[4-9]|622)/, + type: 'visa', + patterns: [4], format: defaultFormat, - length: [16], + length: [13, 16], cvcLength: [3], luhn: true }, { type: 'mastercard', - pattern: /^5[1-5]/, + patterns: [51, 52, 53, 54, 55, 22, 23, 24, 25, 26, 27], format: defaultFormat, length: [16], cvcLength: [3], luhn: true }, { type: 'amex', - pattern: /^3[47]/, + patterns: [34, 37], format: /(\d{1,4})(\d{1,6})?(\d{1,5})?/, length: [15], cvcLength: [3, 4], luhn: true }, { - type: 'visa', - pattern: /^4/, + type: 'dinersclub', + patterns: [30, 36, 38, 39], + format: /(\d{1,4})(\d{1,6})?(\d{1,4})?/, + length: [14], + cvcLength: [3], + luhn: true + }, { + type: 'discover', + patterns: [60, 64, 65, 622], + format: defaultFormat, + length: [16], + cvcLength: [3], + luhn: true + }, { + type: 'unionpay', + patterns: [62, 88], + format: defaultFormat, + length: [16, 17, 18, 19], + cvcLength: [3], + luhn: false + }, { + type: 'jcb', + patterns: [35], format: defaultFormat, - length: [13, 14, 15, 16], + length: [16], cvcLength: [3], luhn: true } ]; cardFromNumber = function(num) { - var card, _i, _len; + var card, p, pattern, _i, _j, _len, _len1, _ref; num = (num + '').replace(/\D/g, ''); for (_i = 0, _len = cards.length; _i < _len; _i++) { card = cards[_i]; - if (card.pattern.test(num)) { - return card; + _ref = card.patterns; + for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) { + pattern = _ref[_j]; + p = pattern + ''; + if (num.substr(0, p.length) === p) { + return card; + } } } }; @@ -131,20 +150,72 @@ if (($target.prop('selectionStart') != null) && $target.prop('selectionStart') !== $target.prop('selectionEnd')) { return true; } - if (typeof document !== "undefined" && document !== null ? (_ref = document.selection) != null ? typeof _ref.createRange === "function" ? _ref.createRange().text : void 0 : void 0 : void 0) { - return true; + if ((typeof document !== "undefined" && document !== null ? (_ref = document.selection) != null ? _ref.createRange : void 0 : void 0) != null) { + if (document.selection.createRange().text) { + return true; + } } return false; }; + safeVal = function(value, $target) { + var cursor, error, last; + try { + cursor = $target.prop('selectionStart'); + } catch (_error) { + error = _error; + cursor = null; + } + last = $target.val(); + $target.val(value); + if (cursor !== null && $target.is(":focus")) { + if (cursor === last.length) { + cursor = value.length; + } + $target.prop('selectionStart', cursor); + return $target.prop('selectionEnd', cursor); + } + }; + + replaceFullWidthChars = function(str) { + var chars, chr, fullWidth, halfWidth, idx, value, _i, _len; + if (str == null) { + str = ''; + } + fullWidth = '\uff10\uff11\uff12\uff13\uff14\uff15\uff16\uff17\uff18\uff19'; + halfWidth = '0123456789'; + value = ''; + chars = str.split(''); + for (_i = 0, _len = chars.length; _i < _len; _i++) { + chr = chars[_i]; + idx = fullWidth.indexOf(chr); + if (idx > -1) { + chr = halfWidth[idx]; + } + value += chr; + } + return value; + }; + + reFormatNumeric = function(e) { + return setTimeout(function() { + var $target, value; + $target = $(e.currentTarget); + value = $target.val(); + value = replaceFullWidthChars(value); + value = value.replace(/\D/g, ''); + return safeVal(value, $target); + }); + }; + reFormatCardNumber = function(e) { - var _this = this; return setTimeout(function() { var $target, value; $target = $(e.currentTarget); value = $target.val(); + value = replaceFullWidthChars(value); value = $.payment.formatCardNumber(value); - return $target.val(value); + return safeVal(value, $target); }); }; @@ -175,10 +246,14 @@ } if (re.test(value)) { e.preventDefault(); - return $target.val(value + ' ' + digit); + return setTimeout(function() { + return $target.val(value + ' ' + digit); + }); } else if (re.test(value + digit)) { e.preventDefault(); - return $target.val(value + digit + ' '); + return setTimeout(function() { + return $target.val(value + digit + ' '); + }); } }; @@ -186,9 +261,6 @@ var $target, value; $target = $(e.currentTarget); value = $target.val(); - if (e.meta) { - return; - } if (e.which !== 8) { return; } @@ -197,13 +269,28 @@ } if (/\d\s$/.test(value)) { e.preventDefault(); - return $target.val(value.replace(/\d\s$/, '')); + return setTimeout(function() { + return $target.val(value.replace(/\d\s$/, '')); + }); } else if (/\s\d?$/.test(value)) { e.preventDefault(); - return $target.val(value.replace(/\s\d?$/, '')); + return setTimeout(function() { + return $target.val(value.replace(/\d$/, '')); + }); } }; + reFormatExpiry = function(e) { + return setTimeout(function() { + var $target, value; + $target = $(e.currentTarget); + value = $target.val(); + value = replaceFullWidthChars(value); + value = $.payment.formatExpiry(value); + return safeVal(value, $target); + }); + }; + formatExpiry = function(e) { var $target, digit, val; digit = String.fromCharCode(e.which); @@ -214,10 +301,21 @@ val = $target.val() + digit; if (/^\d$/.test(val) && (val !== '0' && val !== '1')) { e.preventDefault(); - return $target.val("0" + val + " / "); + return setTimeout(function() { + return $target.val("0" + val + " / "); + }); } else if (/^\d\d$/.test(val)) { e.preventDefault(); - return $target.val("" + val + " / "); + return setTimeout(function() { + var m1, m2; + m1 = parseInt(val[0], 10); + m2 = parseInt(val[1], 10); + if (m2 > 2 && m1 !== 0) { + return $target.val("0" + m1 + " / " + m2); + } else { + return $target.val("" + val + " / "); + } + }); } }; @@ -234,10 +332,10 @@ } }; - formatForwardSlash = function(e) { - var $target, slash, val; - slash = String.fromCharCode(e.which); - if (slash !== '/') { + formatForwardSlashAndSpace = function(e) { + var $target, val, which; + which = String.fromCharCode(e.which); + if (!(which === '/' || which === ' ')) { return; } $target = $(e.currentTarget); @@ -249,9 +347,6 @@ formatBackExpiry = function(e) { var $target, value; - if (e.meta) { - return; - } $target = $(e.currentTarget); value = $target.val(); if (e.which !== 8) { @@ -260,15 +355,25 @@ if (($target.prop('selectionStart') != null) && $target.prop('selectionStart') !== value.length) { return; } - if (/\d(\s|\/)+$/.test(value)) { - e.preventDefault(); - return $target.val(value.replace(/\d(\s|\/)*$/, '')); - } else if (/\s\/\s?\d?$/.test(value)) { + if (/\d\s\/\s$/.test(value)) { e.preventDefault(); - return $target.val(value.replace(/\s\/\s?\d?$/, '')); + return setTimeout(function() { + return $target.val(value.replace(/\d\s\/\s$/, '')); + }); } }; + reFormatCVC = function(e) { + return setTimeout(function() { + var $target, value; + $target = $(e.currentTarget); + value = $target.val(); + value = replaceFullWidthChars(value); + value = value.replace(/\D/g, '').slice(0, 4); + return safeVal(value, $target); + }); + }; + restrictNumeric = function(e) { var input; if (e.metaKey || e.ctrlKey) { @@ -330,6 +435,9 @@ if (!/^\d+$/.test(digit)) { return; } + if (hasTextSelected($target)) { + return; + } val = $target.val() + digit; return val.length <= 4; }; @@ -358,33 +466,44 @@ }; $.payment.fn.formatCardCVC = function() { - this.payment('restrictNumeric'); + this.on('keypress', restrictNumeric); this.on('keypress', restrictCVC); + this.on('paste', reFormatCVC); + this.on('change', reFormatCVC); + this.on('input', reFormatCVC); return this; }; $.payment.fn.formatCardExpiry = function() { - this.payment('restrictNumeric'); + this.on('keypress', restrictNumeric); this.on('keypress', restrictExpiry); this.on('keypress', formatExpiry); - this.on('keypress', formatForwardSlash); + this.on('keypress', formatForwardSlashAndSpace); this.on('keypress', formatForwardExpiry); this.on('keydown', formatBackExpiry); + this.on('change', reFormatExpiry); + this.on('input', reFormatExpiry); return this; }; $.payment.fn.formatCardNumber = function() { - this.payment('restrictNumeric'); + this.on('keypress', restrictNumeric); this.on('keypress', restrictCardNumber); this.on('keypress', formatCardNumber); this.on('keydown', formatBackCardNumber); this.on('keyup', setCardType); this.on('paste', reFormatCardNumber); + this.on('change', reFormatCardNumber); + this.on('input', reFormatCardNumber); + this.on('input', setCardType); return this; }; $.payment.fn.restrictNumeric = function() { this.on('keypress', restrictNumeric); + this.on('paste', reFormatNumeric); + this.on('change', reFormatNumeric); + this.on('input', reFormatNumeric); return this; }; @@ -394,8 +513,7 @@ $.payment.cardExpiryVal = function(value) { var month, prefix, year, _ref; - value = value.replace(/\s/g, ''); - _ref = value.split('/', 2), month = _ref[0], year = _ref[1]; + _ref = value.split(/[\s\/]+/, 2), month = _ref[0], year = _ref[1]; if ((year != null ? year.length : void 0) === 2 && /^\d+$/.test(year)) { prefix = (new Date).getFullYear(); prefix = prefix.toString().slice(0, 2); @@ -423,7 +541,7 @@ }; $.payment.validateCardExpiry = function(month, year) { - var currentTime, expiry, prefix, _ref; + var currentTime, expiry, _ref; if (typeof month === 'object' && 'month' in month) { _ref = month, month = _ref.month, year = _ref.year; } @@ -438,13 +556,18 @@ if (!/^\d+$/.test(year)) { return false; } - if (!(parseInt(month, 10) <= 12)) { + if (!((1 <= month && month <= 12))) { return false; } if (year.length === 2) { - prefix = (new Date).getFullYear(); - prefix = prefix.toString().slice(0, 2); - year = prefix + year; + if (year < 70) { + year = "20" + year; + } else { + year = "19" + year; + } + } + if (year.length !== 4) { + return false; } expiry = new Date(year, month); currentTime = new Date; @@ -454,13 +577,14 @@ }; $.payment.validateCardCVC = function(cvc, type) { - var _ref, _ref1; + var card, _ref; cvc = $.trim(cvc); if (!/^\d+$/.test(cvc)) { return false; } - if (type) { - return _ref = cvc.length, __indexOf.call((_ref1 = cardFromType(type)) != null ? _ref1.cvcLength : void 0, _ref) >= 0; + card = cardFromType(type); + if (card != null) { + return _ref = cvc.length, __indexOf.call(card.cvcLength, _ref) >= 0; } else { return cvc.length >= 3 && cvc.length <= 4; } @@ -476,22 +600,49 @@ $.payment.formatCardNumber = function(num) { var card, groups, upperLength, _ref; + num = num.replace(/\D/g, ''); card = cardFromNumber(num); if (!card) { return num; } upperLength = card.length[card.length.length - 1]; - num = num.replace(/\D/g, ''); - num = num.slice(0, +upperLength + 1 || 9e9); + num = num.slice(0, upperLength); if (card.format.global) { return (_ref = num.match(card.format)) != null ? _ref.join(' ') : void 0; } else { groups = card.format.exec(num); - if (groups != null) { - groups.shift(); + if (groups == null) { + return; } - return groups != null ? groups.join(' ') : void 0; + groups.shift(); + groups = $.grep(groups, function(n) { + return n; + }); + return groups.join(' '); } }; -}).call(this); \ No newline at end of file + $.payment.formatExpiry = function(expiry) { + var mon, parts, sep, year; + parts = expiry.match(/^\D*(\d{1,2})(\D+)?(\d{1,4})?/); + if (!parts) { + return ''; + } + mon = parts[1] || ''; + sep = parts[2] || ''; + year = parts[3] || ''; + if (year.length > 0) { + sep = ' / '; + } else if (sep === ' /') { + mon = mon.substring(0, 1); + sep = ''; + } else if (mon.length === 2 || sep.length > 0) { + sep = ' / '; + } else if (mon.length === 1 && (mon !== '0' && mon !== '1')) { + mon = "0" + mon; + sep = ' / '; + } + return mon + sep + year; + }; + +}).call(this); diff --git a/frontend/app/views/spree/checkout/payment/_gateway.html.erb b/frontend/app/views/spree/checkout/payment/_gateway.html.erb index 0db075079bd..0ca77357839 100644 --- a/frontend/app/views/spree/checkout/payment/_gateway.html.erb +++ b/frontend/app/views/spree/checkout/payment/_gateway.html.erb @@ -3,13 +3,12 @@
<%= label_tag "name_on_card_#{payment_method.id}", Spree.t(:name_on_card) %>*
- <%= text_field_tag "#{param_prefix}[name]", "#{@order.billing_firstname} #{@order.billing_lastname}", { id: "name_on_card_#{payment_method.id}"} %>
+ <%= text_field_tag "#{param_prefix}[name]", "#{@order.billing_firstname} #{@order.billing_lastname}", { id: "name_on_card_#{payment_method.id}", :autocomplete => "cc-name" } %>
<%= label_tag "card_number", Spree.t(:card_number) %>*
- <% options_hash = Rails.env.production? ? {:autocomplete => 'off'} : {} %>
- <%= text_field_tag "#{param_prefix}[number]", '', options_hash.merge(:id => 'card_number', :class => 'required cardNumber', :size => 19, :maxlength => 19, :autocomplete => "off") %>
+ <%= text_field_tag "#{param_prefix}[number]", '', {:id => 'card_number', :class => 'required cardNumber', :size => 19, :maxlength => 19, :autocomplete => "cc-number", type: "tel"} %>