PageSourceSearch

https://fxboss.firstcitizens.com/app/components/common/common_directives.js?v=31082026-1758

js firstcitizens.com collected 2026-09-24 21:51:27 UTC 36,142 bytes, 1,029 lines download raw bytes

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.