diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000..c13c5f6 --- /dev/null +++ b/.babelrc @@ -0,0 +1,3 @@ +{ + "presets": ["es2015"] +} diff --git a/dist/js/DatPayment.js b/dist/js/DatPayment.js index 3a6da27..2ac0cc7 100644 --- a/dist/js/DatPayment.js +++ b/dist/js/DatPayment.js @@ -1,3 +1,242 @@ +'use strict'; + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var DatPayment = function () { + function DatPayment(options) { + _classCallCheck(this, DatPayment); + + this.options = options; + + this.form = document.querySelector(this.options.form_selector); + + this.input_number = document.querySelector(this.options.number_selector); + this.input_expiry = document.querySelector(this.options.date_selector); + this.input_cvc = document.querySelector(this.options.cvc_selector); + this.input_name = document.querySelector(this.options.name_selector); + + this.submit_button = document.querySelector(this.options.submit_button_selector); + this.form_locked = false; + + this.validators = this.options.validators; + + this.card = null; + + this.validation_class = { + 'success': 'dpf-row-valid', + 'error': 'dpf-row-invalid' + }; + + this.initForm(); + this.initCard(); + this.initEvents(); + } + + _createClass(DatPayment, [{ + key: 'initForm', + value: function initForm() { + this.input_number.placeholder = this.options.placeholders.number; + this.input_expiry.placeholder = this.options.placeholders.expiry; + this.input_cvc.placeholder = this.options.placeholders.cvc; + this.input_name.placeholder = this.options.placeholders.name; + } + }, { + key: 'getFormData', + value: function getFormData() { + return { + number: this.getValue('number'), + expiry: this.getValue('expiry'), + expiry_month: this.getValue('expiry_month'), + expiry_year: this.getValue('expiry_year'), + cvc: this.getValue('cvc'), + name: this.getValue('name') + }; + } + }, { + key: 'initEvents', + value: function initEvents() { + var _this = this; + + this.form.addEventListener('submit', function (e) { + _this.onSubmit(e); + }); + + var inputs = this.form.querySelectorAll("input"); + [].forEach.call(inputs, function (input) { + var type = input.getAttribute('data-type'); + if (null !== type) { + input.addEventListener('focus', function (e) { + _this.form.dispatchEvent(new CustomEvent('payment_form:field_validation_reset', { 'detail': input })); + }); + input.addEventListener('blur', function (e) { + _this.validateField(e.target.getAttribute('data-type'), e.target.value); + }); + } + }); + + this.form.addEventListener('payment_form:field_validation_reset', function (e) { + var input_row = _this.findRowFromInput(e.detail); + if (input_row.classList.contains(_this.validation_class.success)) { + input_row.classList.remove(_this.validation_class.success); + } + + if (input_row.classList.contains(_this.validation_class.error)) { + input_row.classList.remove(_this.validation_class.error); + } + }); + + this.form.addEventListener('payment_form:field_validation_failed', function (e) { + var input_row = _this.findRowFromInput(e.detail); + if (input_row.classList.contains(_this.validation_class.success)) { + input_row.classList.remove(_this.validation_class.success); + } + + if (!input_row.classList.contains(_this.validation_class.error)) { + input_row.classList.add(_this.validation_class.error); + } + }); + + this.form.addEventListener('payment_form:field_validation_success', function (e) { + var input_row = _this.findRowFromInput(e.detail); + + if (input_row.classList.contains(_this.validation_class.error)) { + input_row.classList.remove(_this.validation_class.error); + } + + if (!input_row.classList.contains(_this.validation_class.success)) { + input_row.classList.add(_this.validation_class.success); + } + }); + } + }, { + key: 'findRowFromInput', + value: function findRowFromInput(input) { + var nb_try = 0; + do { + nb_try++; + var parent = input.parentNode; + } while (!parent.classList.contains('dpf-input-container') || nb_try <= 4); + + return parent; + } + }, { + key: 'getValue', + value: function getValue(field_name) { + switch (field_name) { + case 'number': + case 'name': + case 'cvc': + case 'expiry': + return this['input_' + field_name + ''].value; + break; + + case 'expiry_month': + case 'expiry_year': + var expiry = this.input_expiry.value.split(' / '); + return expiry[field_name == "expiry_month" ? 0 : 1] || ''; + break; + } + } + }, { + key: 'validateForm', + value: function validateForm() { + var values = this.getFormData(); + var is_valid = true; + for (var field_name in values) { + if ("undefined" !== typeof this.validators[field_name]) { + is_valid &= this.validateField(field_name, values[field_name]); + } + } + return is_valid; + } + }, { + key: 'validateField', + value: function validateField(field_name, field_value) { + var is_valid = true; + if ('undefined' !== typeof this.validators[field_name]) { + is_valid = this.validators[field_name](field_value); + } + + if (!is_valid) { + this.form.dispatchEvent(new CustomEvent('payment_form:field_validation_failed', { 'detail': this['input_' + field_name] })); + } else { + this.form.dispatchEvent(new CustomEvent('payment_form:field_validation_success', { 'detail': this['input_' + field_name] })); + } + + return is_valid; + } + }, { + key: 'onSubmit', + value: function onSubmit(e) { + e.preventDefault(); + e.stopPropagation(); + + if (!this.form_locked) { + this.lockForm(); + + var form_is_valid = this.validateForm(); + if (form_is_valid) { + this.form.dispatchEvent(new CustomEvent('payment_form:submit', { 'detail': this.getFormData() })); + } else { + this.unlockForm(); + } + } + return false; + } + }, { + key: 'unlockForm', + value: function unlockForm() { + if (this.submit_button.classList.contains('loading')) { + this.submit_button.classList.remove('loading'); + } + + this.form_locked = false; + } + }, { + key: 'lockForm', + value: function lockForm() { + this.submit_button.classList.add('loading'); + + this.form_locked = true; + } + }, { + key: 'initCard', + value: function initCard() { + + this.card = new Card({ + form: this.options.form_selector, + container: this.options.card_container_selector, + + formSelectors: { + numberInput: this.options.number_selector, + expiryInput: this.options.date_selector, + cvcInput: this.options.cvc_selector, + nameInput: this.options.name_selector + }, + + width: 300, + formatting: true, + + messages: { + validDate: 'valid\ndate', + monthYear: 'mm/yy' + }, + + placeholders: { + number: this.options.placeholders.number, + expiry: this.options.placeholders.expiry, + cvc: this.options.placeholders.cvc, + name: this.options.placeholders.name + }, + debug: false + }); + } + }]); + + return DatPayment; +}(); var card = /******/ (function(modules) { // webpackBootstrap /******/ // The module cache @@ -43,9 +282,10 @@ var card = /************************************************************************/ /******/ ([ /* 0 */ -/***/ function(module, exports, __webpack_require__) { +/***/ (function(module, exports, __webpack_require__) { - /* WEBPACK VAR INJECTION */(function(global) {var Card, QJ, extend, payment; + /* WEBPACK VAR INJECTION */(function(global) {var Card, QJ, extend, payment, + bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; __webpack_require__(1); @@ -60,7 +300,7 @@ var card = Card.prototype.initializedDataAttr = "data-jp-card-initialized"; - Card.prototype.cardTemplate = '' + '
' + '
' + '' + '' + '
' + '
'; + Card.prototype.cardTemplate = '' + '
' + '
' + '' + '' + '
' + '
'; Card.prototype.template = function(tpl, data) { return tpl.replace(/\{\{(.*?)\}\}/g, function(match, key, str) { @@ -96,6 +336,9 @@ var card = expiry: '••/••', name: 'Full Name' }, + masks: { + cardNumber: false + }, classes: { valid: 'jp-card-valid', invalid: 'jp-card-invalid' @@ -104,6 +347,7 @@ var card = }; function Card(opts) { + this.maskCardNumber = bind(this.maskCardNumber, this); var toInitialize; this.options = extend(true, this.defaults, opts); if (!this.options.form) { @@ -151,7 +395,7 @@ var card = } if (this.options.width) { $cardContainer = QJ(this.options.cardSelectors.cardContainer)[0]; - baseWidth = parseInt($cardContainer.clientWidth); + baseWidth = parseInt($cardContainer.clientWidth || window.getComputedStyle($cardContainer).width); $cardContainer.style.transform = "scale(" + (this.options.width / baseWidth) + ")"; } if (typeof navigator !== "undefined" && navigator !== null ? navigator.userAgent : void 0) { @@ -169,10 +413,14 @@ var card = }; Card.prototype.attachHandlers = function() { - var expiryFilters; + var expiryFilters, numberInputFilters; + numberInputFilters = [this.validToggler('cardNumber')]; + if (this.options.masks.cardNumber) { + numberInputFilters.push(this.maskCardNumber); + } bindVal(this.$numberInput, this.$numberDisplay, { fill: false, - filters: this.validToggler('cardNumber') + filters: numberInputFilters }); QJ.on(this.$numberInput, 'payment.cardType', this.handle('setCardType')); expiryFilters = [ @@ -272,6 +520,22 @@ var card = return QJ.toggleClass(el, this.options.classes.invalid, !test); }; + Card.prototype.maskCardNumber = function(val, el, out) { + var mask, numbers; + mask = this.options.masks.cardNumber; + numbers = val.split(' '); + if (numbers.length >= 3) { + numbers.forEach(function(item, idx) { + if (idx !== numbers.length - 1) { + return numbers[idx] = numbers[idx].replace(/\d/g, mask); + } + }); + return numbers.join(' '); + } else { + return val.replace(/\d/g, mask); + } + }; + Card.prototype.handlers = { setCardType: function($el, e) { var cardType; @@ -370,9 +634,9 @@ var card = /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()))) -/***/ }, +/***/ }), /* 1 */ -/***/ function(module, exports, __webpack_require__) { +/***/ (function(module, exports, __webpack_require__) { // style-loader: Adds some css to the DOM by adding a