bendrucker/angular-credit-cards

View on GitHub
src/expiration.js

Summary

Maintainability
F
4 days
Test Coverage
'use strict'

var expiration = require('creditcards').expiration
var month = expiration.month
var year = expiration.year
var ap = require('ap')

exports = module.exports = function ccExp () {
  return {
    restrict: 'AE',
    require: 'ccExp',
    controller: CcExpController,
    link: function (scope, element, attributes, ccExp) {
      ccExp.$watch()
    }
  }
}

CcExpController.$inject = ['$scope', '$element']
function CcExpController ($scope, $element) {
  var nullFormCtrl = {
    $setValidity: noop
  }
  var parentForm = $element.inheritedData('$formController') || nullFormCtrl
  var ngModel = {
    year: {},
    month: {}
  }

  this.setMonth = function (monthCtrl) {
    ngModel.month = monthCtrl
  }
  this.setYear = function (yearCtrl) {
    ngModel.year = yearCtrl
  }

  function setValidity (exp) {
    var expMonth = exp.month
    var expYear = exp.year
    var valid = (expMonth == null && expYear == null) || !!expMonth && !!expYear && !expiration.isPast(expMonth, expYear)
    parentForm.$setValidity('ccExp', valid, $element)
  }

  this.$watch = function $watchExp () {
    $scope.$watch(function watchExp () {
      return {
        month: ngModel.month.$modelValue,
        year: ngModel.year.$modelValue
      }
    }, setValidity, true)
  }
}

var nullCcExp = {
  setMonth: noop,
  setYear: noop
}

exports.month = function ccExpMonth () {
  return {
    restrict: 'A',
    require: ['ngModel', '^?ccExp'],
    compile: function (element, attributes) {
      attributes.$set('maxlength', 2)
      attributes.$set('pattern', '[0-9]*')
      attributes.$set('xAutocompletetype', 'cc-exp-month')

      return function (scope, element, attributes, controllers) {
        var ngModel = controllers[0]
        var ccExp = controllers[1] || nullCcExp

        ccExp.setMonth(ngModel)
        ngModel.$parsers.unshift(month.parse)
        ngModel.$validators.ccExpMonth = function validateExpMonth (value) {
          return ngModel.$isEmpty(ngModel.$viewValue) || month.isValid(value)
        }
      }
    }
  }
}

exports.year = function ccExpYear () {
  return {
    restrict: 'A',
    require: ['ngModel', '^?ccExp'],
    compile: function (element, attributes) {
      var fullYear = attributes.fullYear !== undefined

      attributes.$set('maxlength', fullYear ? 4 : 2)
      attributes.$set('pattern', '[0-9]*')
      attributes.$set('xAutocompletetype', 'cc-exp-year')

      return function (scope, element, attributes, controllers) {
        var ngModel = controllers[0]
        var ccExp = controllers[1] || nullCcExp

        ccExp.setYear(ngModel)

        ngModel.$parsers.unshift(ap.partialRight(year.parse, !fullYear))

        ngModel.$formatters.unshift(function formatExpYear (value) {
          return value ? year.format(value, !fullYear) : ''
        })

        ngModel.$validators.ccExpYear = function validateExpYear (value) {
          return ngModel.$isEmpty(ngModel.$viewValue) || (year.isValid(value) && !year.isPast(value))
        }
      }
    }
  }
}

function noop () {}