1var boss_common_module = angular.module('bossApp'); 2 3function validateAddress(address, entityName) { 4 let errors = []; 5 6 if (!address) return errors; 7 8 if (address.address1 && address.address1.length > 70) errors.push(`${entityName} Address1 exceeds the maximum length of 70 characters.`); 9 if (address.address2 && address.address2.length > 70) errors.push(`${entityName} Address2 exceeds the maximum length of 70 characters.`); 10 if (address.city && address.city.length > 35) errors.push(`${entityName} City exceeds the maximum length of 35 characters.`); 11 if (address.state && address.state.length > 35) errors.push(`${entityName} State exceeds the maximum length of 35 characters.`); 12 if (address.isoCountryCode && address.isoCountryCode.length !== 2) errors.push(`${entityName} ISO Country Code must be exactly 2 characters long.`); 13 if (address.postalCode && address.postalCode.length > 16) errors.push(`${entityName} Postal Code exceeds the maximum length of 16 characters.`); 14 15 return errors; 16} 17 18function validateBank(bank, entityName) { 19 let errors = []; 20 21 if (!bank) return errors; 22 23 if (bank.institutionName && bank.institutionName.length > 140) errors.push(`${entityName} Name exceeds the maximum length of 140 characters.`); 24 if (bank.streetAddress1 && bank.streetAddress1.length > 70) errors.push(`${entityName} Street Address1 exceeds the maximum length of 70 characters.`); 25 if (bank.streetAddress2 && bank.streetAddress2.length > 70) errors.push(`${entityName} Street Address2 exceeds the maximum length of 70 characters.`); 26 if (bank.city && bank.city.length > 35) errors.push(`${entityName} City exceeds the maximum length of 35 characters.`); 27 if (bank.state && bank.state.length > 35) errors.push(`${entityName} State exceeds the maximum length of 35 characters.`); 28 if (bank.isoCountryCode && bank.isoCountryCode.length !== 2) errors.push(`${entityName} ISO Country Code must be exactly 2 characters long.`); 29 if (bank.zipCode && bank.zipCode.length > 16) errors.push(`${entityName} Zip Code exceeds the maximum length of 16 characters.`); 30 31 return errors; 32} 33 34// Formating numbers with comma and decimal 35app.directive('numberFormat', ['$filter', '$parse', '$rootScope', function ($filter, $parse, $rootScope) { 36 return { 37 require: 'ngModel', 38 link: function (scope, element, attrs, ngModelController) { 39 40 ngModelController.$formatters.push(function (data) { 41 //convert data from model format to view format while edit. 42 var decimals = $parse(attrs.decimals)(scope); 43 return $filter('number')(data, decimals); //converted 44 }); 45 46 element.bind('focus', function () { 47 element.val(ngModelController.$modelValue); 48 }); 49 50 element.bind('blur', function () { 51 var decimals = $parse(attrs.decimals)(scope); 52 var _num = ngModelController.$modelValue; 53 if(_num){ 54 var data = _num.toString(); 55 var clean = data.replace(/,/g,"").replace(/-/g,""); 56 var _lastChar = clean.charAt(clean.length - 1); 57 var sliced = clean.slice(0, -1); 58 var remainingStr = $filter('number')(sliced, decimals); 59 if(!isNaN(parseFloat(remainingStr))){ 60 let _decimalVal = (remainingStr.indexOf(".") != -1)?remainingStr.slice((remainingStr.indexOf(".")+1),(remainingStr.length+1)):undefined; 61 if(_decimalVal){ 62 let _div = (_decimalVal.length == 1)?10:(_decimalVal.length == 2)?100:100; 63 if("k" == _lastChar || "K" == _lastChar){ 64 clean = (parseInt(remainingStr) * 1000) + (parseInt(_decimalVal)/_div); 65 }else if("m" == _lastChar || "M" == _lastChar){ 66 clean = (parseInt(remainingStr) * 1000000) + (parseInt(_decimalVal)/_div); 67 } 68 } 69 } 70 var formatted = $filter('number')(clean, decimals); 71 if(formatted){ 72 if(formatted.replace(/,/g,"")) 73 ngModelController.$setViewValue(formatted.replace(/,/g,"")); 74 } 75 else 76 ngModelController.$setViewValue(undefined); 77 element.val(formatted); 78 } 79 }); 80 } 81 } 82}]); 83 84 85/**** 86* Capitalize all content. 87*/ 88boss_common_module.directive('capitalize', function() { 89 return { 90 require: 'ngModel', 91 link: function(scope, element, attrs, modelCtrl) { 92 var capitalize = function(inputValue) { 93 if(inputValue == undefined) inputValue = ''; 94 var capitalized = inputValue.toUpperCase(); 95 if(capitalized !== inputValue) { 96 modelCtrl.$setViewValue(capitalized); 97 modelCtrl.$render(); 98 } 99 return capitalized; 100 } 101 modelCtrl.$parsers.push(capitalize); 102 capitalize(scope[attrs.ngModel]); // capitalize initial value 103 } 104 }; 105}); 106/**** 107* TypeAhead on focus 108*/ 109boss_common_module.directive('typeaheadFocus', function () { 110 return { 111 require: 'ngModel', 112 link: function (scope, element, attr, ngModel) { 113 114 //trigger the popup on 'click' because 'focus' 115 //is also triggered after the item selection 116 element.bind('click', function () { 117 118 var viewValue = ngModel.$viewValue; 119 120 //restore to null value so that the typeahead can detect a change 121 if (ngModel.$viewValue == ' ') { 122 ngModel.$setViewValue(null); 123 } 124 125 //force trigger the popup 126 ngModel.$setViewValue(' '); 127 128 //set the actual value in case there was already a value in the input 129 ngModel.$setViewValue(viewValue || ' '); 130 }); 131 132 //compare function that treats the empty space as a match 133 scope.emptyOrMatch = function (actual, expected) { 134 if (expected == ' ') { 135 return true; 136 } 137 return actual.indexOf(expected) > -1; 138 }; 139 } 140 }; 141 }); 142 143 144 145/**** 146 * Allow only numbers. 147 */ 148boss_common_module.directive('numbersOnly', function () { 149 return { 150 require: 'ngModel', 151 link: function (scope, element, attr, ngModelCtrl) { 152 function fromUser(text) { 153 if (text) { 154 var transformedInput = text.replace(/[^0-9]/g, ''); 155 156 if (transformedInput !== text) { 157 ngModelCtrl.$setViewValue(transformedInput); 158 ngModelCtrl.$render(); 159 } 160 return transformedInput; 161 } 162 return undefined; 163 } 164 ngModelCtrl.$parsers.push(fromUser); 165 } 166 }; 167}); 168 169 170 171/**** 172 * Allow only numbers except ZERO. 173 */ 174boss_common_module.directive('positiveNumbersOnly', function () { 175 return { 176 require: 'ngModel', 177 link: function (scope, element, attr, ngModelCtrl) { 178 function fromUser(text) { 179 if (text) { 180 var transformedInput = text.replace(/[^0-9]/g, ''); 181 182 if (transformedInput !== text) { 183 ngModelCtrl.$setViewValue((transformedInput)?transformedInput
183:undefined); 184 ngModelCtrl.$render(); 185 } 186 return transformedInput; 187 } 188 return undefined; 189 } 190 ngModelCtrl.$parsers.push(fromUser); 191 } 192 }; 193}); 194 195 196boss_common_module.directive('noSpecialChar', function() { 197return { 198 require: 'ngModel', 199 restrict: 'A', 200 link: function(scope, element, attrs, modelCtrl) { 201 modelCtrl.$parsers.push(function(inputValue) { 202 if (inputValue == undefined) 203 return '' 204 cleanInputValue = inputValue.replace(/[^\w\d]/gi, ''); 205 if (cleanInputValue != inputValue) { 206 modelCtrl.$setViewValue(cleanInputValue); 207 modelCtrl.$render(); 208 } 209 return cleanInputValue; 210 }); 211 } 212}; 213}); 214 215 216 217boss_common_module.directive('numberInput', function() { 218 return { 219 require: 'ngModel', 220 restrict: 'A', 221 link: function(scope, element, attrs, modelCtrl) { 222 modelCtrl.$parsers.push(function(inputValue) { 223 if (inputValue == undefined) 224 return '' 225 cleanInputValue = inputValue.replace(/[^\d\s]/gi, ''); 226 if (cleanInputValue != inputValue) { 227 modelCtrl.$setViewValue(cleanInputValue); 228 modelCtrl.$render(); 229 } 230 return cleanInputValue; 231 }); 232 } 233 }; 234}); 235 236 237/****** 238 <input class="input-phone" type='text' phone-input ng-model="phoneVal"/> 239 ****/ 240boss_common_module.directive('phoneInput', function($filter, $browser) { 241 return { 242 require: 'ngModel', 243 link: function($scope, $element, $attrs, ngModelCtrl) { 244 var listener = function() { 245 var value = $element.val().replace(/[^0-9]/g, ''); 246 $element.val($filter('tel')(value, false)); 247 }; 248 249 // This runs when we update the text field 250 ngModelCtrl.$parsers.push(function(viewValue) { 251 return viewValue.replace(/[^0-9]/g, '').slice(0,10); 252 }); 253 254 // This runs when the model gets updated on the scope directly and keeps our view in sync 255 ngModelCtrl.$render = function() { 256 $element.val($filter('tel')(ngModelCtrl.$viewValue, false)); 257 }; 258 259 $element.bind('change', listener); 260 $element.bind('keydown', function(event) { 261 var key = event.keyCode; 262 // If the keys include the CTRL, SHIFT, ALT, or META keys, or the arrow keys, do nothing. 263 // This lets us support copy and paste too 264 if (key == 91 || (15 < key && key < 19) || (37 <= key && key <= 40)){ 265 return; 266 } 267 $browser.defer(listener); // Have to do this or changes don't get picked up properly 268 }); 269 270 $element.bind('paste cut', function() { 271 $browser.defer(listener); 272 }); 273 } 274 275 }; 276}); 277 278 279boss_common_module.directive('validateEmail', function() { 280 var EMAIL_REGEXP = /^[_A-Za-z0-9-+]+(\.[_A-Za-z0-9-+]+)*@[A-Za-z0-9-_+]+(\.[A-Za-z0-9-_+]+)*(\.[A-Za-z]+)$/; 281 282 function validateAll(ctrl, validatorName, value) { 283 var validity = ctrl.$isEmpty(value) || value.split(',').every(function (email) { 284 if (email && email.indexOf("@") != -1) { 285 let emailAt = email.split("@"); 286 let emailBeforeAt = emailAt[0] || undefined; 287 let emailAfterAt = emailAt[1] || undefined; 288 if (emailBeforeAt && (emailBeforeAt.length == 0 || emailBeforeAt.length > 64)) { 289 console.assert(false, "Invalid email in length before @. allowed max 64 characters"); 290 return false 291 } 292 if (emailAfterAt && (emailAfterAt.length == 0 || emailAfterAt.length > 255)) { 293 console.assert(false, "Invalid email in length after @. allowed max 255 characters"); 294 return false 295 } 296 } 297 return EMAIL_REGEXP.test(email.trim()); 298 }); 299 if (value) { 300 ctrl.$setTouched(); 301 } 302 ctrl.$setValidity(validatorName, validity); 303 return value; 304 } 305 return { 306 restrict: 'A', 307 require: 'ngModel', 308 link: function postLink(scope, elem, attrs, modelCtrl) { 309 function multipleEmailsValidator(value) { 310 return validateAll(modelCtrl, 'validateEmail', value); 311 }; 312 313 modelCtrl.$formatters.push(multipleEmailsValidator); 314 modelCtrl.$parsers.push(multipleEmailsValidator); 315 } 316 }; 317}); 318/****** 319 In this function we will allow (+) sign and (,) sign and does not allow (,) sign at the end 320 ****/ 321boss_common_module.directive('validatePhonenumber', function() { 322 var PHONE_NUMBER_REGEXP = /^[\d\+,]+(?<!,)$/; 323 324 function validatePhoneNumber(ctrl, validatorName, value) {
325 var validity = ctrl.$isEmpty(value) || PHONE_NUMBER_REGEXP.test(value); 326 ctrl.$setValidity(validatorName, validity); 327 return validity ? value : undefined; 328 } 329 return { 330 restrict: 'A', 331 require: 'ngModel', 332 link: function postLink(scope, elem, attrs, modelCtrl) { 333 function phoneNumberValidator(value) { 334 return validatePhoneNumber(modelCtrl, 'validatePhonenumber', value); 335 } 336 337 modelCtrl.$formatters.push(phoneNumberValidator); 338 modelCtrl.$parsers.push(phoneNumberValidator); 339 } 340 }; 341}); 342boss_common_module.directive('onlyNumbers', function () { 343 return { 344 restrict: 'A', 345 link: function (scope, elm, attrs, ctrl) { 346 elm.on('keydown', function (event) { 347 if(event.shiftKey){event.preventDefault(); return false;} 348 if ([8, 13, 27, 37, 38, 39, 40].indexOf(event.which) > -1) { 349 // backspace, enter, escape, arrows 350 return true; 351 } else if (event.which >= 48 && event.which <= 57) { 352 // numbers 0 to 9 353 return true; 354 } else if (event.which >= 96 && event.which <= 105) { 355 // numpad number 356 return true; 357 } 358 else { 359 event.preventDefault(); 360 return false; 361 } 362 }); 363 } 364 } 365}); 366 367 368/************************************************************** 369| swift char validation// false if invalid swift char present | 370**************************************************************/ 371 372boss_common_module.directive('swiftValidate', function($rootScope) { 373 return { 374 restrict: 'A', 375 require: 'ngModel', 376 link: function(scope, elem, attr, ctrl) { 377 378 // obtained from fxstar services's TransactionAcc Validator. 379 var regex = $rootScope.isSwiftMXMessage 380 ? new RegExp("^[0-9a-zA-Z\\/\\-\\?:\\(\\)\\.,'\\+ !#$%&\\*=^_`\\{\\|\\}~\";<>@\\[\\\\\\]\\r\\n]*$") 381 : new RegExp("^[(\r\n) A-Za-z0-9/?:().,'+ -]*$"); 382 ctrl.$parsers.unshift(function(value) { 383 var valid = regex.test(value); 384 ctrl.$setValidity('swiftValidate', valid); 385 return valid ? value : undefined; 386 }); 387 ctrl.$formatters.unshift(function(value) { 388 valid = regex.test(value); 389 ctrl.$setValidity('swiftValidate', valid); 390 ctrl.$setValidity('required', !valid); 391 // return the value or nothing will be written to the DOM. 392 return value; 393 }); 394 } 395 }; 396}); 397 398/************************************************************** 399| swift MX char validation// false if invalid swift char present | 400**************************************************************/ 401 402boss_common_module.directive('swiftMxValidate', function ($rootScope) { 403 function getSwiftValidationRegex(isSwiftMXMessage) { 404 return new RegExp( 405 isSwiftMXMessage ? "^[0-9a-zA-Z/\\-\\?:().,'+ !#$%&*=^_`{}|~\";<>@\\[\\\\\\]\\r\\n]*$" : "^[(\r\n) A-Za-z0-9/?:().,'+ -]*$" 406 ); 407 } 408 return { 409 restrict: 'A', 410 require: 'ngModel', 411 link: function (scope, elem, attr, ctrl) { 412 var regex = getSwiftValidationRegex($rootScope.isSwiftMXMessage); 413 ctrl.$parsers.unshift(function (value) { 414 var valid = regex.test(value); 415 ctrl.$setValidity('swiftMxValidate', valid); 416 return valid ? value : undefined; 417 }); 418 ctrl.$formatters.unshift(function (value) { 419 valid = regex.test(value); 420 ctrl.$setValidity('swiftMxValidate', valid); 421 ctrl.$setValidity('required', !valid); 422 // return the value or nothing will be written to the DOM. 423 return value; 424 }); 425 } 426 }; 427}); 428 429/*********************************************** 430| Swift char validation error Message template | 431***********************************************/ 432 433boss_common_module.directive("swiftErrorMsg",function(){ 434 return { 435 template : "Invalid Swift Char entered. Allowed CharSet is : A-Za-z0-9/?:().,'+ - CrLf Space" 436 }; 437}); 438 439boss_common_module.directive("swiftMxErrorMsg", function ($rootScope) { 440 return { 441 template: function () { 442 if ($rootScope.isSwiftMXMessage) { 443 return 'Invalid Swift Char entered. Allowed CharSet is : A-Za-z0-9/\\-?:().,\'+ !#$%&*=^_`{|}~";<>@[] CrLf Space'; 444 } else { 445 return "Invalid Swift Char entered. Allowed CharSet is : A-Za-z0-9/?:().,'+ - CrLf Space"; 446 } 447 } 448 }; 449}); 450 451boss_common_module.directive("swiftLenErrMsg", function ($rootScope) { 452 return { 453 scope: { 454 maxLenMx: "@", 455 maxLenNonMx: "@" 456 }, 457 link: function (scope, element, attrs) { 458 var inputEl = element.closest('.form-group').find('input'); 459 scope.$watch(function () { 460 return inputEl.val(); 461 }, function (newVal) { 462 var maxLen = $rootScope.isSwiftMXMessage ? parseInt(scope.maxLenMx) : parseInt(scope.maxLenNonMx); 463 if (newVal && newVal.length > maxLen) { 464 inputEl.addClass('txtbxReq'); 465 } else { 466 inputEl.removeClass('txtbxReq'); 467 } 468 }); 469 }, 470 template: function (element, attrs) { 471 var maxLenMx = attrs.maxLenMx || 70; 472 var maxLenNMt = attrs.maxLenNonMx || 35; 473 if ($rootScope.isSwiftMXMessage) {
474 return "Exceeds the Maximum Allowed Length " + maxLenMx + " characters."; 475 } 476 if (maxLenNMt && !$rootScope.isSwiftMXMessage) { 477 return "Exceeds the Maximum Allowed Length " + maxLenNMt + " Characters."; 478 } 479 } 480 }; 481}); 482 483/*** 484* Directive to allow only number including decimal. USAGE: is-number allow-decimal-number 485*/ 486boss_common_module.directive('allowDecimalNumber', function () { 487 return { 488 restrict: 'A', 489 link: function (scope, elm, attrs, ctrl) { 490 elm.on('keydown', function (event) { 491 var $input = $(this); 492 var value = $input.val(); 493 value = value.replace(/[^0-9.]/g, ''); 494 var findsDot = new RegExp(/\./g) 495 var containsDot = value.match(findsDot) 496 if (containsDot != null && ([46, 110, 190].indexOf(event.which) > -1)) { 497 event.preventDefault(); 498 return false; 499 } 500 $input.val(value); 501 if (event.which == 64 || event.which == 16) { 502 // numbers 503 return false; 504 } if ([8, 13, 27, 37, 38, 39, 40, 110].indexOf(event.which) > -1) { 505 // backspace, enter, escape, arrows 506 return true; 507 } else if (event.which >= 48 && event.which <= 57) { 508 // numbers 509 return true; 510 } else if (event.which >= 96 && event.which <= 105) { 511 // numpad number 512 return true; 513 } else if ([46, 110, 190].indexOf(event.which) > -1) { 514 // dot and numpad dot 515 return true; 516 } else { 517 event.preventDefault(); 518 return false; 519 } 520 }); 521 } 522 } 523}); 524 525/**** 526 * Allow only numbers and negative symbol 527 * USAGE: numbers-with-negative 528 */ 529 530boss_common_module.directive('numbersWithNegative',['$filter', '$parse', function ($filter, $parse) { 531 return { 532 require: 'ngModel', 533 link: function (scope, element, attrs, ngModelController) { 534 535 var decimals = $parse(attrs.decimals)(scope); 536 537 ngModelController.$formatters.push(function (data) { 538 //convert data from model format to view format while edit. 539 return $filter('number')(data, decimals); //converted 540 }); 541 542 element.bind('focus', function () { 543 element.val(ngModelController.$modelValue); 544 }); 545 546 element.bind('blur', function () { 547 var _num = ngModelController.$modelValue; 548 if(_num){ 549 var data = _num.toString(); 550 var clean = data.replace(/,/g,""); 551 var _lastChar = clean.charAt(clean.length - 1); 552 var sliced = clean.slice(0, -1); 553 var remainingStr = $filter('number')(sliced, decimals); 554 if(!isNaN(parseFloat(remainingStr))){ 555 let _decimalVal = (remainingStr.indexOf(".") != -1)?remainingStr.slice((remainingStr.indexOf(".")+1),(remainingStr.length+1)):undefined; 556 if(_decimalVal){ 557 let _div = (_decimalVal.length == 1)?10:(_decimalVal.length == 2)?100:100; 558 if("k" == _lastChar || "K" == _lastChar){ 559 clean = (parseInt(remainingStr) * 1000) + (parseInt(_decimalVal)/_div); 560 }else if("m" == _lastChar || "M" == _lastChar){ 561 clean = (parseInt(remainingStr) * 1000000) + (parseInt(_decimalVal)/_div); 562 } 563 } 564 } 565 var formatted = $filter('number')(clean, decimals); 566 if(formatted){ 567 if(formatted.replace(/,/g,"")) 568 ngModelController.$setViewValue(formatted.replace(/,/g,"")); 569 } 570 else 571 ngModelController.$setViewValue(undefined); 572 element.val(formatted); 573 } 574 }); 575 } 576 } 577}]); 578 579/*jslint browser: true, plusplus: true, indent: 2 */ 580 581//This will be removed by uglify, along with the DEBUG code 582if (typeof DEBUG === 'undefined') { 583DEBUG = true; 584} 585 586//Logic and fallbacks based on the following SO answers: 587//- Getting caret position cross browser: http://stackoverflow.com/a/9370239/147507 588//- Selection API on non input-text fields: http://stackoverflow.com/a/24247942/147507 589//- Set cursor position on input text: http://stackoverflow.com/q/5755826/14750
5897 590 591boss_common_module.directive('ngPatternRestrict', ['$log', function ($log) { 592 'use strict'; 593 594 function showDebugInfo() { 595 $log.debug("[ngPatternRestrict] " + Array.prototype.join.call(arguments, ' ')); 596 } 597 598 return { 599 restrict: 'A', 600 require: "?ngModel", 601 compile: function uiPatternRestrictCompile() { 602 DEBUG && showDebugInfo("Loaded"); 603 604 return function ngPatternRestrictLinking(scope, iElement, iAttrs, ngModelController) { 605 var regex, // validation regex object 606 oldValue, // keeping track of the previous value of the element 607 caretPosition, // keeping track of where the caret is at to avoid jumpiness 608 // housekeeping 609 initialized = false, // have we initialized our directive yet? 610 eventsBound = false, // have we bound our events yet? 611 // functions 612 getCaretPosition, // function to get the caret position, set in detectGetCaretPositionMethods 613 setCaretPosition; // function to set the caret position, set in detectSetCaretPositionMethods 614 615 //------------------------------------------------------------------- 616 // caret position 617 function getCaretPositionWithInputSelectionStart() { 618 return iElement[0].selectionStart; // we need to go under jqlite 619 } 620 621 function getCaretPositionWithDocumentSelection() { 622 // create a selection range from where we are to the beggining 623 // and measure how much we moved 624 var range = document.selection.createRange(); 625 range.moveStart('character', -iElement.val().length); 626 return range.text.length; 627 } 628 629 function getCaretPositionWithWindowSelection() { 630 var s = window.getSelection(), 631 originalSelectionLength = String(s).length, 632 selectionLength, 633 didReachZero = false, 634 detectedCaretPosition, 635 restorePositionCounter; 636 637 do { 638 selectionLength = String(s).length; 639 s.modify('extend', 'backward', 'character'); 640 // we're undoing a selection, and starting a new one towards the beggining of the string 641 if (String(s).length === 0) { 642 didReachZero = true; 643 } 644 } while (selectionLength !== String(s).length); 645 646 detectedCaretPosition = didReachZero ? selectionLength : selectionLength - originalSelectionLength; 647 s.collapseToStart(); 648 649 restorePositionCounter = detectedCaretPosition; 650 while (restorePositionCounter-- > 0) { 651 s.modify('move', 'forward', 'character'); 652 } 653 while (originalSelectionLength-- > 0) { 654 s.modify('extend', 'forward', 'character'); 655 } 656 657 return detectedCaretPosition; 658 } 659 660 function setCaretPositionWithSetSelectionRange(position) { 661 iElement[0].setSelectionRange(position, position); 662 } 663 664 function setCaretPositionWithCreateTextRange(position) { 665 var textRange = iElement[0].createTextRange(); 666 textRange.collapse(true); 667 textRange.moveEnd('character', position); 668 textRange.moveStart('character', position); 669 textRange.select(); 670 } 671 672 function setCaretPositionWithWindowSelection(position) { 673 var s = window.getSelection(), 674 selectionLength; 675 676 do { 677 selectionLength = String(s).length; 678 s.modify('extend', 'backward', 'line'); 679 } while (selectionLength !== String(s).length); 680 s.collapseToStart(); 681 682 while (position--) { 683 s.modify('move', 'forward', 'character'); 684 } 685 } 686 687 // HACK: Opera 12 won't give us a wrong validity status although the input is invalid 688 // we can select the whole text and check the selection size 689 // Congratulations to IE 11 for doing the same but not returning the selection. 690 function getValueLengthThroughSelection(input) { 691 // only do this on opera, since it'll mess up the caret position 692 // and break Firefox functionality 693 if (!/Opera/i.test(navigator.userAgent)) { 694 return 0; 695 } 696 697 input.focus(); 698 document.execCommand("selectAll"); 699 var focusNode = window.getSelection().focusNode; 700 return (focusNode || {}).selectionStart || 0; 701 } 702 703 //------------------------------------------------------------------- 704 // event handlers 705 function revertToPreviousValue() { 706 if (ngModelController) { 707 scope.$apply(function () { 708 ngModelController.$setViewValue(oldValue); 709 }); 710 } 711 iElement.val(oldValue); 712 713 if (!angular.isUndefined(caretPosition)) { 714 setCaretPosition(caretPosition); 715 } 716 } 717 718 function updateCurrentValue(newValue) { 719 oldValue = newValue; 720 caretPosition = getCaretPosition(); 721 } 722 723 function genericEventHandler(evt) { 724 DEBUG && showDebugInfo("Reacting to event:", evt.type); 725 726 //HACK Chrome returns an empty string as value if user inputs a non-numeric string into a
726number type input 727 // and this may happen with other non-text inputs soon enough. As such, if getting the string only gives us an 728 // empty string, we don't have the chance of validating it against a regex. All we can do is assume it's wrong, 729 // since the browser is rejecting it either way. 730 var newValue = iElement.val(), 731 inputValidity = iElement.prop("validity"); 732 if (newValue === "" && iElement.attr("type") !== "text" && inputValidity && inputValidity.badInput) { 733 DEBUG && showDebugInfo("Value cannot be verified. Should be invalid. Reverting back to:", oldValue); 734 evt.preventDefault(); 735 revertToPreviousValue(); 736 } else if (newValue === "" && getValueLengthThroughSelection(iElement[0]) !== 0) { 737 DEBUG && showDebugInfo("Invalid input. Reverting back to:", oldValue); 738 evt.preventDefault(); 739 revertToPreviousValue(); 740 } else if (regex.test(newValue)) { 741 DEBUG && showDebugInfo("New value passed validation against", regex, newValue); 742 updateCurrentValue(newValue); 743 } else { 744 DEBUG && showDebugInfo("New value did NOT pass validation against", regex, newValue, "Reverting back to:", oldValue); 745 evt.preventDefault(); 746 revertToPreviousValue(); 747 } 748 } 749 750 //------------------------------------------------------------------- 751 // setup based on attributes 752 function tryParseRegex(regexString) { 753 try { 754 regex = new RegExp(regexString); 755 } catch (e) { 756 throw "Invalid RegEx string parsed for ngPatternRestrict: " + regexString; 757 } 758 } 759 760 //------------------------------------------------------------------- 761 // setup events 762 function bindListeners() { 763 if (eventsBound) { 764 return; 765 } 766 767 iElement.bind('input keyup click', genericEventHandler); 768 769 DEBUG && showDebugInfo("Bound events: input, keyup, click"); 770 } 771 772 function unbindListeners() { 773 if (!eventsBound) { 774 return; 775 } 776 777 iElement.unbind('input', genericEventHandler); 778 //input: HTML5 spec, changes in content 779 780 iElement.unbind('keyup', genericEventHandler); 781 //keyup: DOM L3 spec, key released (possibly changing content) 782 783 iElement.unbind('click', genericEventHandler); 784 //click: DOM L3 spec, mouse clicked and released (possibly changing content) 785 786 DEBUG && showDebugInfo("Unbound events: input, keyup, click"); 787 788 eventsBound = false; 789 } 790 791 //------------------------------------------------------------------- 792 // initialization 793 function readPattern() { 794 var entryRegex = !!iAttrs.ngPatternRestrict ? iAttrs.ngPatternRestrict : iAttrs.pattern; 795 DEBUG && showDebugInfo("RegEx to use:", entryRegex); 796 tryParseRegex(entryRegex); 797 } 798 799 function notThrows(testFn, shouldReturnTruthy) { 800 try { 801 return testFn() || !shouldReturnTruthy; 802 } catch (e) { 803 return false; 804 } 805 } 806 807 function detectGetCaretPositionMethods() { 808 var input = iElement[0]; 809 810 // Chrome will throw on input.selectionStart of input type=number 811 // See http://stackoverflow.com/a/21959157/147507 812 if (notThrows(function () { return input.selectionStart; })) { 813 getCaretPosition = getCaretPositionWithInputSelectionStart; 814 } else { 815 // IE 9- will use document.selection 816 // TODO support IE 11+ with document.getSelection() 817 if (notThrows(function () { return document.selection; }, true)) { 818 getCaretPosition = getCaretPositionWithDocumentSelection; 819 } else { 820 getCaretPosition = getCaretPositionWithWindowSelection; 821 } 822 } 823 } 824 825 function detectSetCaretPositionMethods() { 826 var input = iElement[0]; 827 if (typeof input.setSelectionRange === 'function') { 828 setCaretPosition = setCaretPositionWithSetSelectionRange; 829 } else if (typeof input.createTextRange === 'function') { 830 setCaretPosition = setCaretPositionWithCreateTextRange; 831 } else { 832 setCaretPosition = setCaretPositionWithWindowSelection; 833 } 834 } 835 836 function initialize() { 837 if (initialized) { 838 return; 839 } 840 DEBUG && showDebugInfo("Initializing"); 841 842 readPattern(); 843 844 oldValue = iElement.val(); 845 if (!oldValue) { 846 oldValue = ""; 847 } 848 DEBUG && showDebugInfo("Original value:", oldValue); 849 850 bindListeners(); 851 852 detectGetCaretPositionMethods(); 853 detectSetCaretPositionMethods(); 854 855 initialized = true; 856 } 857 858 function uninitialize() { 859 DEBUG && showDebugInfo("Uninitializing"); 860 unbindListeners(); 861 } 862 863 iAttrs.$observe("ngPatternRestrict", readPattern); 864 iAttrs.$observe("pattern", readPattern); 865 866 scope.$on("$destroy", uninitialize); 867 868 initialize(); 869 }; 870 } 871 }; 872}]); 873 874app 875.provider('ngIntlTelInput', function () { 876 var me = this; 877 var props = {}; 878 var setFn = function (obj) { 879 if (typeof obj === 'object') { 880 for (var key in obj) { 881 props[key] = obj[key]; 882 } 883 } 884 }; 885 me.set = setFn; 886 887 me.$get = ['$log', function ($log) { 888 return Object.create(me, { 889 init: { 890 value: function (elm) { 891 if (!window.intlTelInputUtils) { 892 $log.warn('intlTelInputUtils is not defined. Formatting and validation will not work.'); 893 } 894 // elm.intlTelInput(props); 895 } 896 }, 897 }); 898 }]; 899}); 900app 901.directive('ngIntlTelInput', ['ngIntlTelInput', '$log', '$timeout','$window', '$parse', 902 function (ngIntlTelInput, $log, $timeout ,$window, $parse) { 903 return { 904 restrict: 'A', 905 require: 'ngModel', 906 link: function (scope, elm, attr, ctrl) { 907 // Warning for bad directive usage. 908 if ((!!attr.type && (attr.type !== 'text' && attr.type !== 'tel')) || elm[0].tagName !== 'INPUT') { 909 $log.warn('ng-intl-tel-input can only be applied to a *text* or *tel* input'); 910 return; 911 } 912 //Timeout added to load country Flags and correct place holders 913 $timeout (function() { 914 var formname=$("#"+attr.id).closest("form").attr("name"); 915 var input = document.querySelector("#"+attr.id); 916 var iti = window.intlTelInput(input, { 917 utilsScript: "app/assets/intl/intl-utils.js", 918 }); 919 var reset = function() { 920 scope[formname][attr.id].$setValidity(attr.id, true); 921 }; 922 923 input.addEventListener("countrychange", function() { 924 input.value=""; 925 }); 926 927 input.addEventListener("valuechanged", function() { 928 iti.setCountry(iti.getSelectedCountryData().iso2); 929 iti._updateFlagFromNumber(input.value); 930 }); 931 932 // Validate PhoneNumber 933 input.addEventListener('keyup', function() { 934 reset(); 935 var dialCode=iti.selectedCountryData.dialCode; 936 console.log("dialCode::"+dialCode); 937 938 if (input.value.trim()) { 939 if (input.value) { 940 input.value = input.value.trim().replace(/\D/g, ""); 941 } 942 if (iti.isValidNumber()) { 943 scope[formname][attr.id].$setValidity(attr.id, true); 944 if(input.value.indexOf("+")==-1 && input.value.startsWith(dialCode,0)){ 945 input.value="+"+input.value; 946 }else if(!input.value.startsWith("+",0)){ 947 input.value="+"+dialCode+input.value; 948 } 949 } else { 950 scope[formname][attr.id].$setValidity(attr.id, false); 951 } 952 scope.$apply(); 953 } 954 }); 955 956 }, 1000); 957 } 958 }; 959 }]); 960 961/** 962 * This directive helps - Disallow space in between characters what you enter in the text field. 963 * It can be used as attribute or element 964 */ 965function showErrorMsg(eleName){ 966 let noSpace = $("<div />", { id: eleName + "noSpace", style : "color:#ff5252;text-decoration:none;font-family:Arial;", text:"Space not allowed" });
967 $("[name=" + eleName + "]").after(noSpace); 968} 969app.directive('noSpace', function() { 970return { 971 restrict: 'AE', 972 link: function($scope, $element) { 973 $element.bind('keydown', function(e) { 974 if( $element[0].name ) $("#" + $element[0].name + "noSpace").remove(); 975 if( e.which === 32 ) { 976 if( $element[0].name ){ 977 showErrorMsg( $element[0].name ); 978 } 979 e.preventDefault(); 980 return; 981 } 982 }); 983 // checking space in string on blur 984 $element.bind('blur', function(e) { 985 if( $element[0].name ) $("#" + $element[0].name + "noSpace").remove(); 986 if( /\s/g.test( $element[0].value ) ) { 987 if( $element[0].name ){ 988 showErrorMsg( $element[0].name ); 989 } 990 return; 991 } 992 }); 993 } 994} 995}); 996 997app.directive('loading', ['$timeout', '$http', function($timeout, $http) { 998 return { 999 restrict: 'A', 1000 link: function(scope, elm, attrs) { 1001 scope.isLoading = function() { 1002 return $http.pendingRequests.length > 0; 1003 }; 1004 1005 scope.$watch(scope.isLoading, function(isLoading) { 1006 var showLoader = true; 1007 if (sessionStorage.currentState) { 1008 showLoader = sessionStorage.currentState.indexOf("internationalPayee") == -1; 1009 } 1010 if ($http.pendingRequests.length > 0 && $http.pendingRequests && ($http.pendingRequests[0].url.includes("payment/request_rate_poll") || $http.pendingRequests[0].url.includes("static/searchBanks"))) { 1011 showLoader = false;
1012 } 1013 if (isLoading && showLoader) { 1014 elm.show(); 1015 $("body").css('pointer-events', 'none'); 1016 1017 } else { 1018 elm.hide(); 1019 $("body").css('pointer-events', ''); 1020 } 1021 }); 1022 } 1023 }; 1024}]); 1025 1026window.addEventListener("beforeunload", (event) => { 1027 $("body").css('pointer-events', 'none'); 1028 $(".loading-spiner-holder").show(); 1029});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.