PageSourceSearch

https://almacen.ahac.gob.hn/dashboard/_lib/lib/js/jquery.scInput2.js

js ahac.gob.hn collected 2026-10-03 22:25:01 UTC 42,556 bytes, 1,458 lines download raw bytes

1/**
2 * Scriptcase input plugin
3 */
4$.widget('scriptcase.scInput', {
5
6	/**
7	 * Default options
8	 */
9	options: {
10		// General
11		datatype        : 'text',
12		maxLength       : 0,
13		alignment       : '',
14		alignRight      : false,
15		enterTab        : false,
16		enterSubmit     : false,
17		selectOnFocus   : true,
18		lettersCase     : '',
19		// Mask
20		mask            : '',
21		maskChars       : '(){}[].,;:-+/ ',
22		maskList        : '',
23		maskOrientation : 'right',
24        maskZeroValue   : '',
25		allowedChars    : '',
26		decimalSep      : '.',
27		thousandsSep    : ',',
28		precision       : 2,
29		dateFormat      : 'mdy',
30		dateSep         : '/',
31		timeFormat      : 'his',
32		timeSep         : ':',
33		currencySymbol  : '',
34		currencyPosition: 'left',
35		allowNegative   : true,
36		onlyNegative    : false,
37		negativePos     : 'prefix',
38		manualDecimals  : false,
39		thousandsFormat : 1,
40		// Auto tab
41		autoTab         : false,
42		// Watermark
43		watermark       : '',
44		watermarkClass  : '',
45		// Internal
46		$clone          : null,
47		completedZero   : false,
48		invalidCount    : 0,
49		inputFocusValue : '',
50		isNegative      : false,
51		isNumeric       : false,
52        isZero          : false,
53		hasDecimalSep   : false,
54		pressedMinus    : false,
55		originalMask    : '',
56		forceMask       : false,
57		forceDecimalPos : false,
58		longestMask     : 0
59	},
60
61	/**
62	 * List of predefined masks
63	 */
64	masks: {
65		'cep' : '99.999-999',
66		'cpf' : '999.999.999-99',
67		'cnpj': '**.***.***/****-**',
68		'ssn' : '999-99-9999',
69		'cc'  : '9999 9999 9999 9999'
70	}, // masks
71
72	/**
73	 * List of special keys
74	 */
75	specialKeys: {
76		8  : 'backspace',
77		9  : 'tab',
78		13 : 'enter',
79		16 : 'shift',
80		17 : 'control',
81		18 : 'alt',
82		27 : 'esc',
83		33 : 'page up',
84		34 : 'page down',
85		35 : 'end',
86		36 : 'home',
87		37 : 'left',
88		38 : 'up',
89		39 : 'right',
90		40 : 'down',
91		45 : 'insert',
92		46 : 'delete',
93		93 : 'menu',
94		116: 'f5',
95		123: 'f12',
96		224: 'command'
97	}, // specialKeys
98
99	//------------------------------------------------------------------------------------------------------------------
100	// constructor method
101
102	/**
103	 * Plugin instance creator
104	 */
105	_create: function() {
106		this._loadOptions();
107		this._initializeSettings();
108		this._bindEvents();
109		this._createWatermark();
110	},
111
112	//------------------------------------------------------------------------------------------------------------------
113	// public method
114
115	/**
116	 * Format the current value on the input
117	 */
118	formatValue: function() {
119		this._getNewValue();
120		this._getRange();
121		this._maskValue();
122		this._setNewValue();
123		this._autoTab();
124	}, // formatValue
125
126	//------------------------------------------------------------------------------------------------------------------
127	// event handling method
128
129	/**
130	 * Bind the input element events
131	 */
132	_bindEvents: function() {
133		this._on(this.element, {
134			'focus':    '_onFocus',
135			'keypress': '_onKeyPress',
136			'input':    '_onInput',
137			'blur':     '_onBlur'
138		});
139	}, // _bindEvents
140
141	/**
142	 * Handle the focus event
143	 */
144	_onFocus: function() {
145		this.options.hasChanged = false;
146
147        this.options.isZero = this._hasOnlyZeros($(this.element).val());
148
149		if (this.options.selectOnFocus) {
150			$(this.element).select();
151		}
152	}, // _onFocus
153
154	/**
155	 * Handle the keypress event
156	 */
157	_onKeyPress: function(e) {
158		this._getNewValue();
159		this._getRange();
160		this._getPressedKey(e);
161		this._checkForNegative();
162
163		if (this._isSpecialEnterTab()) {
164			var prevDef = this._goToNextElement();
165
166			if (prevDef) {
167				e.preventDefault();
168			}
169
170			return true;
171		}
172
173		if (this._isNotText(this.element[0])) {
174			return true;
175		}
176
177		if (this.options.isSpecial) {
178			if (this._isEnterSubmit('enter')) {
179				if (typeof nm_submit_form == 'function') { // para filtro da consulta
180					nm_submit_form();
181				}
182				else {
183					document.F1.submit();
184				}
185			}
186			else if (this._isEnterTab('enter')) {
187				var prevDef = this._goToNextElement();
188
189				if (prevDef) {
190					e.preventDefault();
191				}
192			}
193			else if (13 == this.options.pressedKey && 'textarea' != this.element[0].type) {
194				e.preventDefault();
195			}
196
197			return true;
198		}
199
200		this._checkDecimalsPress();
201	}, // _onKeyPress
202
203	/**
204	 * Handle the input event
205	 */
206	_onInput: function() {
207		if (!this._isNotText(this.element[0])) {
208			this._getNewValue();
209			this._getRange();
210			this._maskValue();
211			this._setNewValue();
212		}
213		this._autoTab();
214	}, // _onInput
215
216	/**
217	 * Handle the blur event
218	 */
219	_onBlur: function() {
220		if (typeof _scCalculatorControl !== 'undefined') {
221			if (_scCalculatorControl[$(this.element).attr('id')]) {
222				return;
223			}
224		}
225
226		if (this.options.isNumeric) {
227            var testValue;
228
229			testValue = this._removeCurrencySymbol($(this.element).val());
230			testValue = this._removeNegativeSymbol(testValue);
231
232			if ('' == testValue) {
233				$(this.element).val('');
234			}
235            else if (this.options.isZero) {
236                $(this.element).val(this._removeNegativeSymbol($(this.element).val()));
237            }
238		}
239
240		if ('decimal' == this.options.datatype || 'currency' == this.options.datatype) {
241			this._completeDecimal();
242		}
243
244		if (typeof _scBrowser != undefined && ('msie' == _scBrowser || 'safari' == _scBrowser) && this.options.hasChanged) {
245			$(this.element).trigger('change');
246		}
247	}, // _onBlur
248
249	//------------------------------------------------------------------------------------------------------------------
250	// range methods
251
252	/**
253	 * Get the cursor position on the input
254	 */
255	_getRange: function() {
256		this.options.range = {start: 0, end: 0};
257
258		if (!$.browser.msie) {
259			this.options.range.start = this.element[0].selectionStart;
260			this.options.range.end   = this.element[0].selectionEnd;
261		}
262		else {
263			if ('textarea' == this.element[0].type) {
264				var inputRange = $(this.element).getSelection();
265
266				this.options.range.start = inputRange.start;
267				this.options.range.end   = inputRange.end;
268			}
269			else {
270				var inputRange = document.selection.createRange();
271
272				this.options.range.start = 0 - inputRange.duplicate().moveStart('character', -100000);
273				this.options.range.end   = oPos.start + inputRange.text.length;
274			}
275		}
276
277		this.options.charsFromRight = this.options.newValue.length - this.options.range.end;
278	}, // _getRange
279
280	/**
281	 * Set the cursor position on the input
282	 */
283	_setRange: function(startPos, endPos) {
284		if ('undefined' == typeof endPos) {
285			endPos = startPos;
286		}
287
288		if (this.element[0].setSelectionRange) {
289			this.element[0].setSelectionRange(startPos, endPos);
290		}
291		else {
292			var inputRange = this.element[0].createTextRange();
293
294			inputRange.collapse();
295			inputRange.moveStart('character', startPos);
296			inputRange.moveEnd('character', endPos - startPos);
297			inputRange.select();
298		}
299	}, // _setRange
300
301	//------------------------------------------------------------------------------------------------------------------
302	// processing methods
303
304	/**
305	 * Get the new value after user input
306	 */
307	_getNewValue: function() {
308		this.options.newValue = $(this.element).val();
309	}, // _getNewValue
310
311	/**
312	 * Check if the value has changed. If yes, set the new value on the input
313	 */
314	_setNewValue: function() {
315		if (this.options.newValue != this.options.maskedValue) {
316			$(this.element).val(this.options.maskedValue);
317
318			var negativePosFix = 0;
319
320			if ('suffix' == this.options.negativePos) {
321				if (this.options.isNegative) {
322					negativePosFix = 1;
323				}
324				else if (this.options.pressedMinus) {
325					negativePosFix = -1;
326				}
327			}
328
329			this._setRange(this.options.maskedValue.length - this.options.charsFromRight - negativePosFix);
330
331			this.options.hasChanged = true;
332		}
333	}, // _setNewValue
334
335	/**
336	 * Get the pressed key and char
337	 */
338	_getPressedKey: function(e) {
339		this.options.pressedKey  = e.charCode || e.keyCode || e.which;
340		this.options.pressedChar = String.fromCharCode(this.options.pressedKey);
341		this.options.isSpecial   = (null != this.specialKeys[this.options.pressedKey]) || e.ctrlKey || e.metaKey || e.altKey;
342
343		if (this.options.isSpecial && ((46 == e.charCode && 0 == e.keyCode && 46 == e.which) || (46 == e.charCode && 46 == e.keyCode && 46 == e.which))) {
344			this.options.isSpecial = false;
345		}
346		/*console.log(e.charCode + " - " + e.keyCode + " - " + e.which);*/
347	}, // _getPressedKey
348
349	/**
350	 * Check if the negative sign was pressed on a numeric input
351	 */
352	_checkForNegative: function() {
353		if (!this.options.isNumeric || !this.options.allowNegative) {
354			return;
355		}
356
357		var hasMinus = false, newValue = this.options.newValue;
358
359		while (-1 != (minusPos = newValue.indexOf('-'))) {
360			newValue = newValue.substr(0, minusPos) + newValue.substr(minusPos + 1);
361			hasMinus = !hasMinus;
362		}
363
364		if (this.options.onlyNegative) {
365			this.options.isNegative = true;
366		}
367		else if (!hasMinus && '-' == this.options.pressedChar) {
368			this.options.pressedMinus = true;
369			this.options.isNegative = true;
370		}
371		else if (hasMinus && '-' == this.options.pressedChar) {
372			this.options.pressedMinus = true;
373			this.options.isNegative = false;
374		}
375		else if (!hasMinus && '+' == this.options.pressedChar) {
376			this.options.isNegative = false;
377		}
378		else if (hasMinus && '+' == this.options.pressedChar) {
379			this.options.isNegative = false;
380		}
381		else {
382			this.options.isNegative = hasMinus;
383		}
384	}, // _checkForNegative
385
386	//------------------------------------------------------------------------------------------------------------------
387	// configuration methods
388
389	/**
390	 * Load any values set on the 'alt' attribute into the plugin options
391	 */
392	_loadOptions: function() {
393		var userOptions = {};
394
395		if ($(this.element).attr('alt')) {
396			eval('userOptions = ' + $(this.element).attr('alt') + ';');
397		}
398
399		this.options = $.extend(this.options, userOptions);
400	},
401
402	/**
403	 * Initialize the instance settings according to its type
404	 */
405	_initializeSettings: function() {
406		if ('currency' == this.options.datatype && '' == this.options.currencySymbol) {
407			this.options.datatype = 'decimal';
408		}
409
410		if (('currency' == this.options.datatype || 'decimal' == this.options.datatype) && 0 == this.options.precision) {
411			this.options.datatype = 'integer';
412		}
413
414		if ('currency' != this.options.datatype && 'decimal' != this.options.datatype) {
415			this.options.manualDecimals = false;
416		}
417
418		switch (this.options.datatype) {
419			case 'integer':
420				if ('left' != this.options.alignment && 'center' != this.options.alignment && 'justify' != this.options.alignment) {
421					this.options.alignRight = true;
422				}
423				this.options.isNumeric       = true;
424				this.options.maskList        = this._createIntegerMask(this.options.maxLength, this.options.thousandsFormat, this.options.thousandsSep);
425				this.options.maskOrientation = 'left';
426				this.options.maskChars       = this.options.thousandsSep;
427				this.options.originalMask    = this.options.maskList;
428				this.options.precision       = 0;
429				break;
430
431			case 'decimal':
432				if ('left' != this.options.alignment && 'center' != this.options.alignment && 'justify' != this.options.alignment) {
433					this.options.alignRight = true;
434				}
435				this.options.isNumeric       = true;
436				this.options.maskList        = this._createDecimalMask(this.options.maxLength, this.options.thousandsFormat, this.options.decimalSep, this.options.thousandsSep, this.options.precision);
437				this.options.maskZeroValue   = this._createDecimalZeroValueMask(this.options.decimalSep, this.options.precision);
438				this.options.maskOrientation = 'left';
439				this.options.maskChars       = this.options.decimalSep + this.options.thousandsSep;
440				this.options.originalMask    = this.options.maskList;
441				break;
442
443			case 'currency':
444				if ('left' != this.options.alignment && 'center' != this.options.alignment && 'justify' != this.options.alignment) {
445					this.options.alignRight = true;
446				}
447				this.options.isNumeric       = true;
448				this.options.maskList        = this._createDecimalMask(this.options.maxLength, this.options.thousandsFormat, this.options.decimalSep, this.options.thousandsSep, this.options.precision);
449				this.options.maskZeroValue   = this._createDecimalZeroValueMask(this.options.decimalSep, this.options.precision);
450				this.options.maskOrientation = 'left';
451				this.options.maskChars       = this.options.decimalSep + this.options.thousandsSep + this.options.currencySymbol + ' ';
452				this.options.originalMask    = this.options.maskList;
453				break;
454
455			case 'datetime':
456				this.options.allowNegative = false;
457				this.options.maskList      = this._createDateTimeMask(this.options.dateFormat, this.options.dateSep, this.options.timeSep);
458				this.options.maskChars     = this.options.dateSep + this.options.timeSep + ' ';
459				this.options.originalMask  = this.options.maskList;
460				break;
461
462			case 'date':
463				this.options.allowNegative = false;
464				this.options.maskList      = this._createDateMask(this.options.dateFormat, this.options.dateSep);
465				this.options.maskChars     = this.options.dateSep;
466				this.options.originalMask  = this.options.maskList;
467				break;
468
469			case 'time':
470				this.options.allowNegative = false;
471				this.options.maskList      = this._createTimeMask(this.options.timeFormat, this.options.timeSep);
472				this.options.maskChars     = this.options.timeSep;
473				this.options.originalMask  = this.options.maskList;
474				break;
475
476			case 'mask':
477				this.options.allowNegative = false;
478				this.options.maskList      = this.options.maskList;
479				this.options.longestMask   = this._getLongestMaskSize(this.options.maskList, this.options.maskChars);
480				this.options.originalMask  = this.options.maskList;
481				break;
482
483			case 'text':
484				this.options.allowedChars = this.options.allowedChars.toLowerCase();
485				if(this.options.allowedChars != '')
486				{
487					this.options.allowedChars += "\r\n";
488				}
489				this.options.maskChars    = '';
490				break;
491
492			default:
493				this.options.allowNegative = false;
494				this.options.maskList      = this.masks[this.options.datatype] ? this.masks[this.options.datatype] : '';
495				this.options.originalMask  = this.options.maskList;
496				break;
497		}
498
499		if ('' != this.options.maskList) {
500			this.options.maskListArray = this.options.maskList.split(';');
501		}
502		else {
503			this.options.maskListArray = new Array();
504		}
505
506		this.options.originalLength = this.options.maxLength;
507		this.options.maxLength      = this._getMaxLength();
508		this.options.maskCharsArray = this.options.maskChars.split('');
509
510		$(this.element).attr('maxlength', this.options.maxLength);
511	},
512
513	//------------------------------------------------------------------------------------------------------------------
514	// masking methods
515
516	/**
517	 * Mask a value according to its configuration
518	 */
519	_maskValue: function() {
520		var cleanValue = this._getCleanValue();
521
522		if (this.options.isNumeric && 0 < this.options.precision && this.options.manualDecimals) {
523			this.options.hasDecimalSep = -1 < this.options.newValue.indexOf(this.options.decimalSep) || this.options.pressedChar == this.options.decimalSep;
524		}
525
526		if ('' == cleanValue) {
527			this.options.maskedValue = '';
528			this._addNegativeSymbol();
529			return;
530		}
531
532		this.options.maskedValue = 'text' == this.options.datatype
533		                         ? this._filterUnallowedChars(cleanValue)
534		                         : this._applyMask(cleanValue);
535
536		this._addNegativeSymbol();
537		this._addCurrencySymbol();
538	}, // _maskValue
539
540	/**
541	 * Remove unallowed characters from the value
542	 */
543	_filterUnallowedChars: function(cleanValue) {
544		if ('' == this.options.allowedChars) {
545			return this._matchCase(cleanValue);
546		}
547
548		var filtered = '';
549
550		for (var i = 0; i < cleanValue.length; i++) {
551			if (-1 < this.options.allowedChars.indexOf(cleanValue.charAt(i).toLowerCase())) {
552				filtered += cleanValue.charAt(i);
553			}
554		}
555
556		return this._matchCase(filtered);
557	}, // _filterUnallowedChars
558
559	/**
560	 * Apply the current mask to a clean value
561	 */
562	_applyMask: function(cleanValue) {
563		var cleanArray, maskedValue, maskArray;
564
565		if ('left' == this.options.maskOrientation && (!this.options.isNumeric || !this.options.isZero || this.options.precision == 0)) {
566			cleanValue = this._checkMaxLength(cleanValue);
567		}
568
569		cleanArray  = cleanValue.split('');
570		maskedValue = '';
571        if (this.options.isNumeric && this.options.isZero && this.options.precision > 0) { // allow deletion of decimals whose value is zero
572            maskArray = this.options.maskZeroValue.split('');
573        }
574        else {
575            maskArray = this._getMaskArray(cleanValue.length);
576        }
577
578		if ('left' == this.options.maskOrientation && (!this.options.isNumeric || !this.options.isZero || this.options.precision == 0)) {
579			maskArray.reverse();
580			cleanArray.reverse();
581		}
582
583		this.options.invalidCount = 0;
584
585		for (var i = 0; i < maskArray.length; i++) {
586			if (-1 < $.inArray(maskArray[i], this.options.maskCharsArray)) {
587				maskedValue += maskArray[i];
588			}
589			else {
590				getChar = true;
591
592				while (getChar) {
593					thisChar = cleanArray.shift();
594
595					if (this._testChar(thisChar, maskArray[i])) {
596						getChar = false;
597					}
598					else {
599						this.options.invalidCount++;
600						thisChar = '';
601					}
602
603					if (0 == cleanArray.length) {
604						getChar = false;
605					}
606				}
607
608				maskedValue += thisChar;
609			}
610
611			if (0 == cleanArray.length) {
612				break;
613			}
614		}
615
616		if ('left' == this.options.maskOrientation && (!this.options.isNumeric || !this.options.isZero || this.options.precision == 0)) {
617			maskedValue = this._strReverse(maskedValue);
618		}
619
620		if (this.options.isNumeric && this.options.isZero && this.options.precision && this.options.pressedChar == this.options.decimalSep) {
621			maskedValue += this.options.decimalSep;
622		}
623
624		return this._matchCase(maskedValue);
625	}, // _applyMask
626
627	/**
628	 * Get the mask array to be used to format the input value
629	 */
630	_getMaskArray: function(valueLength) {
631		this.options.mask = '';
632
633		if (1 == this.options.maskListArray.length) {
634			this.options.mask = this.options.maskListArray[0];
635		}
636		else if (1 < this.options.maskListArray.length) {
637			for (var i = 0; i < this.options.maskListArray.length; i++) {
638				cleanMask  = this._removeMaskChars(this.options.mask            , this.options.maskCharsArray);
639				cleanMaskI = this._removeMaskChars(this.options.maskListArray[i], this.options.maskCharsArray);
640
641				if ('' == this.options.mask) {
642					this.options.mask = this.options.maskListArray[i];
643				}
644				else if (cleanMask.length < cleanMaskI.length && cleanMask.length < valueLength) {
645					this.options.mask = this.options.maskListArray[i];
646				}
647			}
648		}
649
650		// removes decimal part of the mask when using manual decimals if the input
651		// length is less than than the integer length part configured for this field
652		if (this.options.isNumeric && 0 < this.options.precision && this.options.manualDecimals && !this.options.hasDecimalSep) {
653			var maskParts = this.options.mask.split(this.options.decimalSep);
654			var cleanIntegerPart = this._removeMaskChars(maskParts[0], this.options.maskCharsArray);
655
656			if (valueLength <= cleanIntegerPart.length) {
657				this.options.mask = maskParts[0];
658			}
659		}
660
661		return this.options.mask.split('');
662	}, // _getMaskArray
663
664	/**
665	 * Adds the currency symbol of a value
666	 */
667	_addCurrencySymbol: function() {
668		if ('' == this.options.maskedValue) {
669			return;
670		}
671		else if ('currency' != this.options.datatype) {
672			return;
673		}
674
675		this.options.maskedValue = ('left' == this.options.currencyPosition)
676		                         ? this.options.currencySymbol + ' ' + this.options.maskedValue
677		                         : this.options.maskedValue + ' ' + this.options.currencySymbol;
678	}, // _addCurrencySymbol
679
680	/**
681	 * Removes the currency symbol of a value
682	 */
683	_removeCurrencySymbol: function(numValue) {
684		if ('currency' != this.options.datatype) {
685			return numValue;
686		}
687
688		if ('left' == this.options.currencyPosition) {
689			if (numValue.substr(0, this.options.currencySymbol.length + 1) == this.options.currencySymbol + ' ') {
690				return numValue.substr(this.options.currencySymbol.length + 1);
691			}
692			else if (numValue.substr(0, this.options.currencySymbol.length) == this.options.currencySymbol) {
693				return numValue.substr(this.options.currencySymbol.length);
694			}
695		}
696		else if ('right' == this.options.currencyPosition) {
697			var curStr = numValue.substr(numValue.length - this.options.currencySymbol.length - 2),
698			    curPos = curStr.indexOf('-');
699			if (-1 < curPos) {
700				numValue = numValue.substr(0, numValue.length - this.options.currencySymbol.length - 2) + '-'
701						+ curStr.substr(0, curPos) + curStr.substr(curPos + 1);
702			}
703
704			if (numValue.substr(numValue.length - this.options.currencySymbol.length - 1) == this.options.currencySymbol + ' ') {
705				return numValue.substr(0, numValue.length - this.options.currencySymbol.length - 2);
706			}
707			else if (numValue.substr(numValue.length - this.options.currencySymbol.length) == this.options.currencySymbol) {
708				return numValue.substr(0, numValue.length - this.options.currencySymbol.length - 1);
709			}
710		}
711
712		var valArray  = numValue.split(''),
713		    curSymbol = this.options.currencySymbol + ' ',
714		    arrSymbol = curSymbol.split('');
715		    newValue  = '';
716
717		for (var i = 0; i < valArray.length; i++) {
718			if (-1 == $.inArray(numValue.charAt(i), arrSymbol)) {
719				newValue += numValue.charAt(i);
720			}
721		}
722
723		return newValue;
724	}, // _removeCurrencySymbol
725
726	/**
727	 * Adds the negative symbol to a value
728	 */
729	_addNegativeSymbol: function() {
730		if (!this.options.isNumeric || !this.options.allowNegative) {
731			return;
732		}
733
734		var maxLength = this.options.maxLength;
735
736		// allow typing of decimal separator for manual decimals
737		// when precision is 1 less than number size
738		if (this.options.isNumeric && this.options.precision > 0) {
739			maxLength++;
740
741			if ('' != this.options.currencySymbol) {
742				maxLength += this.options.currencySymbol.length + 1;
743			}
744		}
745
746		if (this.options.isNegative) {
747			$(this.element).attr('maxlength', maxLength + 1);
748			if ('prefix' == this.options.negativePos) {
749				this.options.maskedValue = '-' + this.options.maskedValue;
750			}
751			else {
752				this.options.maskedValue = this.options.maskedValue + '-';
753			}
754		}
755		else {
756			$(this.element).attr('maxlength', maxLength);
757		}
758	}, // _addNegativeSymbol
759
760	/**
761	 * Removes the negative symbol of a value
762	 */
763	_removeNegativeSymbol: function(numValue) {
764		if (!this.options.isNumeric) {
765			return;
766		}
767
768		var hasMinus = false;
769
770		while (-1 != (minusPos = numValue.indexOf('-'))) {
771			numValue = numValue.substr(0, minusPos) + numValue.substr(minusPos + 1);
772			hasMinus = !hasMinus;
773		}
774
775        if (!this.options.allowNegative) {
776			this.options.isNegative = false;
777        }
778		else if (this.options.onlyNegative) {
779			this.options.isNegative = true;
780		}
781		else {
782			this.options.isNegative = hasMinus;
783		}
784
785		return numValue;
786	}, // _removeNegativeSymbol
787
788	/**
789	 * Complete a decimal value with trailing zeros
790	 */
791	_completeDecimal: function() {
792		if (1 > this.options.precision) {
793			return;
794		}
795
796		var newValue = $(this.element).val();
797
798		newValue = this._removeCurrencySymbol(newValue);
799
800		if ('' != newValue) {
801			if (-1 == newValue.indexOf(this.options.decimalSep)) {
802				newValue += this.options.decimalSep + this._strRepeat('0', this.options.precision)
803			}
804			else {
805				var valueParts = newValue.split(this.options.decimalSep);
806
807				if (valueParts[1].length < this.options.precision) {
808					valueParts[1] += this._strRepeat('0', this.options.precision - valueParts[1].length);
809					newValue       = valueParts.join(this.options.decimalSep);
810				}
811			}
812		}
813
814		this.options.maskedValue = newValue;
815
816		this._addCurrencySymbol();
817
818		$(this.element).val(this.options.maskedValue);
819	}, // _completeDecimal
820
821	/**
822	 * Check if the input value exceeds the lenght of the mask when formatting to the left. If it does, remove last
823	 * character
824	 */
825	_checkMaxLength: function(cleanValue) {
826		if (this.options.isNumeric && cleanValue.length > this.options.originalLength) {
827			cleanValue = cleanValue.substr(0, cleanValue.length - 1);
828		}
829
830		return cleanValue;
831	}, // _checkMaxLength
832
833	/**
834	 * Test if a character 'thisChar' is valid
835	 */
836	_testChar: function(thisChar, charType) {
837        var regExpression;
838
839		if ('9' == charType) {
840			regExpression = new RegExp('[0-9]');
841			return regExpression.test(thisChar);
842		}
843		else if ('a' == charType) {
844			regExpression = new RegExp('[a-zA-Z]');
845			return regExpression.test(thisChar);
846		}
847		else if ('*' == charType) {
848			regExpression = new RegExp('[0-9a-zA-Z]');
849			if (regExpression.test(thisChar)) {
850				return true;
851			}
852
853			// http://kourge.net/projects/regexp-unicode-block
854			/*regExpression = /[\u0600-\u06FF\u0750-\u077F]/;
855			if (regExpression.test(thisChar)) {
856				return true;
857			}*/
858
859			return false;
860		}
861
862		return thisChar == charType;
863	}, // _testChar
864
865	/**
866	 * Transform the text according to the character case configuration
867	 */
868	_matchCase: function(oldValue) {
869		if ('' == oldValue || '' == this.options.lettersCase) {
870			return oldValue;
871		}
872
873		var newValue = '';
874
875		if ('first' == this.options.lettersCase) {
876			var pos = 0;
877
878			while (pos < oldValue.length && ' ' == oldValue.charAt(pos)) {
879				newValue += oldValue.charAt(pos++);
880			}
881			if (pos < oldValue.length) {
882				newValue += oldValue.charAt(pos).toUpperCase() + oldValue.substr(pos + 1);
883			}
884		}
885		else if ('upper' == this.options.lettersCase || 'lower' == this.options.lettersCase) {
886			for (var i = 0; i < oldValue.length; i++) {
887				newValue += ('upper' == this.options.lettersCase)
888				          ? oldValue.charAt(i).toUpperCase()
889				          : oldValue.charAt(i).toLowerCase();
890			}
891		}
892		else if ('words' == this.options.lettersCase) {
893			var words = oldValue.split(' ');
894
895			for (var i = 0; i < words.length; i++) {
896				if (0 < words[i].length) {
897					words[i] = words[i].charAt(0).toUpperCase() + words[i].substr(1);
898				}
899			}
900			newValue = words.join(' ');
901		}
902
903		return newValue;
904	}, // _matchCase
905
906	/**
907	 * Check if the value has a decimal separator when using manual decimals
908	 */
909	_checkDecimalsPress: function() {
910		if (!this.options.manualDecimals) {
911			return;
912		}
913
914		var decimalPos   = this.options.newValue.indexOf(this.options.decimalSep),
915		    isDecimalKey = this.options.pressedChar == this.options.decimalSep,
916		    isNumberKey  = 48 <= this.options.pressedKey && 57 >= this.options.pressedKey,
917		    maksParts    = this.options.originalMask.split(this.options.decimalSep);
918
919		if (isNumberKey && -1 == decimalPos && !this.options.manualDecimals) {
920			this.options.maskList = maksParts[0];
921		}
922		else if (isDecimalKey && ((-1 == decimalPos) || (decimalPos >= this.options.range.start && decimalPos <= this.options.range.end))) {
923			var decimalSize = this.options.newValue.length - this.options.range.end;
924
925			this.options.forceMask       = true;
926			this.options.forceDecimalPos = true;
927
928			if (0 == decimalSize) {
929				this.options.maskList = maksParts[0] + this.options.decimalSep;
930			}
931			else if (decimalSize < this.options.precision) {
932				this.options.maskList = maksParts[0] + this.options.decimalSep + maksParts[1].substr(0, decimalSize);
933			}
934			else {
935				this.options.maskList = this.options.originalMask;
936			}
937		}
938		else if (isNumberKey && this.options.range.start == this.options.range.end && this.options.range.end > decimalPos) {
939			var decimalSize = this.options.newValue.length - decimalPos;
940
941			this.options.forceMask = true;
942
943			if (this.options.precision == decimalSize) {
944				this.options.maskList = this.options.originalMask;
945			}
946			else {
947				this.options.maskList = maksParts[0] + this.options.decimalSep + maksParts[1].substr(0, decimalSize);
948			}
949		}
950		else if (isNumberKey && this.options.range.start == this.options.range.end && this.options.range.end <= decimalPos) {
951			var decimalSize = this.options.newValue.length - decimalPos;
952
953			this.options.forceMask = true;
954
955			if (this.options.precision == decimalSize - 1) {
956				this.options.maskList = this.options.originalMask;
957			}
958			else {
959				this.options.maskList = maksParts[0] + this.options.decimalSep + maksParts[1].substr(0, decimalSize - 1);
960			}
961		}
962		else if (!isNumberKey && -1 < decimalPos) {
963			var decimalSize = this.options.newValue.length - decimalPos;
964
965			this.options.forceMask = true;
966
967			if (this.options.precision == decimalSize) {
968				this.options.maskList = this.options.originalMask;
969			}
970			else {
971				this.options.maskList = maksParts[0] + this.options.decimalSep + maksParts[1].substr(0, decimalSize);
972			}
973		}
974
975		this.options.maskListArray = this.options.maskList.split(';');
976		this.options.maxLength     = this.options.maskList.length;
977	}, // _checkDecimalsPress
978
979	/**
980	 * Get the longest size of the mask list
981	 */
982	_getLongestMaskSize: function(maskList, charList) {
983		var charArray = charList.split(''),
984			maskArray = maskList.split(';'),
985			maxLength = 0;
986
987		for (var i = 0; i < maskArray.length; i++) {
988			maxLength = Math.max(maxLength, this._removeMaskChars(maskArray[i], charArray).length);
989		}
990
991		return maxLength;
992	}, // _getLongestMaskSize
993
994	//------------------------------------------------------------------------------------------------------------------
995	// cleaning methods
996
997	/**
998	 * Get the value without any mask characters
999	 */
1000	_getCleanValue: function() {
1001		var cleanValue = this._removeMaskChars(this.options.newValue, this.options.maskCharsArray);
1002
1003		if ('currency' == this.options.datatype) {
1004			cleanValue = this._removeCurrencySymbol(cleanValue);
1005		}
1006		if (this.options.isNumeric) {
1007			cleanValue = this._removeNegativeSymbol(cleanValue);
1008		}
1009
1010        if (this.options.isNumeric) {
1011            if (0 == parseInt(cleanValue)) {
1012                this.options.isZero = true;
1013
1014                if (this.options.precision > 0) { // allow deletion of decimals whose value is zero
1015                    return cleanValue;
1016                }
1017            }
1018            else {
1019                this.options.isZero = false;
1020            }
1021        }
1022
1023		if ('integer' == this.options.datatype) {
1024			cleanValue = this._removeZeros(cleanValue, 0);
1025		}
1026		else if ('decimal' == this.options.datatype || 'currency' == this.options.datatype) {
1027			cleanValue = this._removeZeros(cleanValue, this.options.precision);
1028		}
1029
1030		return cleanValue;
1031	}, // _getCleanValue
1032
1033	/**
1034	 * Remove all mask characters leaving only the clean value
1035	 */
1036	_removeMaskChars: function(originalValue, maskCharsArray) {
1037		var unmaskedValue = '';
1038
1039		for (var i = 0; i < originalValue.length; i++) {
1040			if (-1 == $.inArray(originalValue.charAt(i), maskCharsArray)) {
1041				unmaskedValue += originalValue.charAt(i);
1042			}
1043		}
1044
1045		return unmaskedValue;
1046	}, // _removeMaskChars
1047
1048	/**
1049	 * Remove the extra zeros on the left for numerical values
1050	 */
1051	_removeZeros: function(numValue, numPrecision) {
1052		if ('' == numValue) {
1053			return numValue;
1054		}
1055
1056		while ('0' == numValue.substr(0, 1) && numPrecision + 1 < numValue.length) {
1057			numValue = numValue.substr(1);
1058		}
1059
1060		this.options.completedZero = false;
1061		if (!this.options.manualDecimals && 0 < numPrecision && numPrecision + 1 > numValue.length) {
1062			numValue                   = this._strRepeat('0', numPrecision + 1 - numValue.length) + numValue;
1063			this.options.completedZero = true;
1064		}
1065
1066		return numValue;
1067	}, // _removeZeros
1068
1069	//------------------------------------------------------------------------------------------------------------------
1070	// mask creation methods
1071
1072	/**
1073	 * Create an integer mask based on the input length 'numLength' and the thousands separator 'thousandSep' according
1074	 * to a given format
1075	 *
1076	 * numFormat = 1:  9,999,999,999
1077	 * numFormat = 2:    9999999,999
1078	 * numFormat = 3: 9,99,99,99,999
1079	 */
1080	_createIntegerMask: function(numLength, numFormat, thousandSep) {
1081		var numMask = new Array();
1082
1083		if (1 == numFormat) {
1084			var iRepeat   = Math.floor(numLength / 3),
1085			    iComplete = numLength % 3;
1086
1087			if (0 != iComplete) {
1088				numMask.push(this._strRepeat('9', iComplete));
1089			}
1090			for (var i = 0; i < iRepeat; i++) {
1091				numMask.push('999');
1092			}
1093		}
1094		else if (2 == numFormat) {
1095			if (4 > numLength) {
1096				numMask.push(this._strRepeat('9', numLength));
1097			}
1098			else {
1099				numMask.push(this._strRepeat('9', numLength - 3));
1100				numMask.push(this._strRepeat('9', 3));
1101			}
1102		}
1103		else if (3 == numFormat) {
1104			if (4 > numLength) {
1105				numMask.push(this._strRepeat('9', numLength));
1106			}
1107			else {
1108				var iRepeat   = Math.floor((numLength - 3) / 2),
1109				    iComplete = (numLength - 3) % 2;
1110
1111				if (0 != iComplete) {
1112					numMask.push(this._strRepeat('9', iComplete));
1113				}
1114				for (var i = 0; i < iRepeat; i++) {
1115					numMask.push('99');
1116				}
1117				numMask.push(this._strRepeat('9', 3));
1118			}
1119		}
1120
1121		return numMask.join(thousandSep);
1122	}, // _createIntegerMask
1123
1124	/**
1125	 * Create a decimal mask based on the input length 'numLength', the decimal separator 'decimalSep', the thousands
1126	 * separator 'thousandSep' and the precision 'numPrecision'
1127	 */
1128	_createDecimalMask: function(numLength, numFormat, decimalSep, thousandSep, numPrecision) {
1129		var decimals = '';
1130
1131		if (0 < numPrecision) {
1132			numLength -= numPrecision;
1133			decimals   = decimalSep + this._strRepeat('9', numPrecision)
1134		}
1135
1136		return this._createIntegerMask(numLength, numFormat, thousandSep) + decimals;
1137	}, // _createDecimalMask
1138
1139    /**
1140     * Create a mask for zero values.
1141     */
1142    _createDecimalZeroValueMask: function(decimalSep, numPrecision) {
1143		var decimals = '';
1144
1145		if (0 < numPrecision) {
1146			decimals = decimalSep + this._strRepeat('9', numPrecision)
1147		}
1148
1149		return '9' + decimals;
1150    }, // _createDecimalZeroValueMask
1151
1152	/**
1153	 * Create a date mask based on the input format 'dateFormat' and the date separator 'dateSep'
1154	 */
1155	_createDateMask: function(dateFormat, dateSep) {
1156		var dateMask = new Array();
1157
1158		dateFormat = dateFormat.replace(/dd/i,   'd')
1159		                       .replace(/mm/i,   'm')
1160		                       .replace(/yyyy/i, 'y')
1161		                       .replace(/aaaa/i, 'y');
1162
1163		for (var i = 0; i < dateFormat.length; i++) {
1164			switch (dateFormat.charAt(i)) {
1165				case 'd':
1166				case 'm':
1167					dateMask.push('99');
1168					break;
1169
1170				case 'y':
1171					dateMask.push('9999');
1172					break;
1173			}
1174		}
1175
1176		return dateMask.join(dateSep);
1177	}, // _createDateMask
1178
1179	/**
1180	 * Create a time mask based on the input format 'timeFormat' and the time separator 'timeSep'
1181	 */
1182	_createTimeMask: function(timeFormat, timeSep) {
1183		var timeMask = new Array();
1184
1185		timeFormat = timeFormat.replace(/hh/i,  'h')
1186		                       .replace(/ii/i,  'i')
1187		                       .replace(/sss/i, 'm')
1188		                       .replace(/ss/i,  's');
1189
1190		for (var i = 0; i < timeFormat.length; i++) {
1191			switch (timeFormat.charAt(i)) {
1192				case 'h':
1193				case 'i':
1194				case 's':
1195					timeMask.push('99');
1196					break;
1197				case 'm':
1198					timeMask.push('999');
1199					break;
1200			}
1201		}
1202
1203		return timeMask.join(timeSep);
1204	}, // _createTimeMask
1205
1206	/**
1207	 * Create a date & time mask based on the input format 'dateTimeFormat', the date separator 'dateSep' and time
1208	 * separator 'timeSep'
1209	 */
1210	_createDateTimeMask: function(dateTimeFormat, dateSep, timeSep) {
1211		var formatParts = dateTimeFormat.split(';');
1212
1213		return this._createDateMask(formatParts[0], dateSep) +
1214		       ' ' +
1215		       this._createTimeMask(formatParts[1], timeSep);
1216	}, // _createDateTimeMask
1217
1218	//------------------------------------------------------------------------------------------------------------------
1219	// auto tabbing methods
1220
1221	/**
1222	 * Auto tab to the next form element
1223	 */
1224	_autoTab: function() {
1225		if (!this.options.autoTab) {
1226			return;
1227		}
1228		else if (this.options.isSpecial || 16 == this.options.pressedKey) {
1229			return;
1230		}
1231		else if ('decimal' == this.options.datatype || 'currency' == this.options.datatype) {
1232			var sepPos = this.options.maskedValue.indexOf(this.options.decimalSep);
1233
1234			if (-1 == sepPos) {
1235				return;
1236			}
1237			else if (this.options.maskedValue.substr(sepPos + 1).length < this.options.precision) {
1238				return;
1239			}
1240		}
1241
1242		if ('mask' == this.options.datatype && this.options.longestMask <= this._removeMaskChars(this.options.maskedValue, this.options.maskChars.split('')).length) {
1243			this._goToNextElement();
1244		}
1245		else if ('mask' != this.options.datatype && !this.options.isNegative && this.options.maskedValue.length >= this.options.maxLength) {
1246			this._goToNextElement();
1247		}
1248		else if ('mask' != this.options.datatype && this.options.isNegative && (this.options.maskedValue.length - 1) >= this.options.maxLength) {
1249			this._goToNextElement();
1250		}
1251	}, // _autoTab
1252
1253	/**
1254	 * Get the next form element if it exists
1255	 */
1256	_getNextElement: function() {
1257		var elementList = this.element[0].form.elements,
1258		    inputIndex  = $.inArray(this.element[0], elementList) + 1,
1259		    testInput;
1260
1261		for (var i = inputIndex; i < elementList.length; i++) {
1262			testInput = $(elementList[i]);
1263
1264			if (this._isValidInput(testInput)) {
1265				return testInput;
1266			}
1267		}
1268
1269		var formList  = document.forms,
1270		    formIndex = $.inArray(this.element[0].form, formList) + 1;
1271
1272		for (var j = formIndex; j < formList.length; j++) {
1273			elementList = formList[j].elements;
1274
1275			for (i = 0; i < elementList.length; i++) {
1276				testInput = $(elementList[i]);
1277
1278				if (this._isValidInput(testInput)) {
1279					return testInput;
1280				}
1281			}
1282		}
1283
1284		return null;
1285	}, // _getNextElement
1286
1287	/**
1288	 * Move the focus to the next form element
1289	 */
1290	_goToNextElement: function() {
1291		if ('textarea' == this.element[0].type) {
1292			return false;
1293		}
1294
1295		nextElement = this._getNextElement();
1296
1297		if (nextElement) {
1298			nextElement.focus();
1299
1300			return this._isNotText(this.element[0]);
1301		}
1302
1303		return false;
1304	}, // _goToNextElement
1305
1306	/**
1307	 * Test if an input is a valid one to focus to
1308	 */
1309	_isValidInput: function(testInput) {
1310		var inputElement = testInput.get(0);
1311
1312		if (0 >= inputElement.offsetHeight || 0 >= inputElement.offsetWidth || inputElement.disabled) {
1313			return false;
1314		}
1315
1316		if ('file' == inputElement.type) {
1317			return false;
1318		}
1319
1320		return true;
1321	}, // _isValidInput
1322
1323	//------------------------------------------------------------------------------------------------------------------
1324	// watermark methods
1325
1326	/**
1327	 * Set the watermark for the input
1328	 */
1329	_createWatermark: function() {
1330		if ('' == this.options.watermark) {
1331			return;
1332		}
1333
1334		$(this.element).attr('placeholder', this.options.watermark);
1335	}, // _createWatermark
1336
1337	//------------------------------------------------------------------------------------------------------------------
1338	// auxiliary methods
1339
1340	/**
1341	 * Get the maximum length of an input element
1342	 */
1343	_getMaxLength: function() {
1344		var maxLength = 0;
1345
1346		if ('' != this.options.maskList) {
1347			for (var i = 0; i < this.options.maskListArray.length; i++) {
1348				maxLength = Math.max(maxLength, this.options.maskListArray[i].length);
1349			}
1350		}
1351
1352		if (0 == maxLength) {
1353			if (0 < this.options.maxLength) {
1354				if (this.options.isNumeric && 0 < this.options.precision) {
1355					return this.options.maxLength + 1;
1356				} else {
1357					return this.options.maxLength;
1358				}
1359			}
1360
1361			var thisElement = $(this.element);
1362
1363			if (thisElement.attr('maxlength') && 0 < thisElement.attr('maxlength')) {
1364				return thisElement.attr('maxlength');
1365			}
1366			if (thisElement.attr('size') && 0 < thisElement.attr('size')) {
1367				return thisElement.attr('size');
1368			}
1369		}
1370
1371		if ('currency' == this.options.datatype) {
1372			maxLength += this.options.currencySymbol.length + 1;
1373		}
1374
1375		if (this.options.isNumeric && 0 < this.options.precision) {
1376			return maxLength + 1;
1377		} else {
1378			return maxLength;
1379		}
1380	}, // _getMaxLength
1381
1382    /**
1383     * Check if the string only has '0' as numbers
1384     */
1385    _hasOnlyZeros: function(testValue) {
1386        if (!this.options.isNumeric) {
1387            return false;
1388        }
1389
1390        var regExpression = new RegExp('[1-9]'), i;
1391
1392        for (i =0; i < testValue.length; i++) {
1393            if (regExpression.test(testValue[i])) {
1394                return false;
1395            }
1396        }
1397
1398        return true;
1399    }, // _hasOnlyZeros
1400
1401	/**
1402	 * Check if the 'enter' tab option is enabled and which key was pressed
1403	 */
1404	_isEnterTab: function(pressedKey) {
1405		if (!this.options.enterTab) {
1406			return false;
1407		}
1408
1409		if ('enter' == pressedKey) {
1410			return 13 == this.options.pressedKey;
1411		}
1412		else {
1413			return 9 == this.options.pressedKey;
1414		}
1415	}, // _isEnterTab
1416
1417	/**
1418	 * Check if the 'enter' submit option is enabled and which key was pressed
1419	 */
1420	_isEnterSubmit: function(pressedKey) {
1421		if (!this.options.enterSubmit) {
1422			return false;
1423		}
1424
1425		if ('enter' == pressedKey) {
1426			return 13 == this.options.pressedKey;
1427		}
1428		else {
1429			return 9 == this.options.pressedKey;
1430		}
1431	}, // _isEnterSubmit
1432
1433	/**
1434	 * Check if the input is not text
1435	 */
1436	_isNotText: function(thisElement) {
1437		return ('select' == thisElement.type || 'select-one' == thisElement.type || 'select-multiple' == thisElement.type || 'checkbox' == thisElement.type || 'radio' == thisElement.type);
1438	}, // _isNotText
1439
1440	_isSpecialEnterTab: function() {
1441		return this._isEnterTab('enter') && this._isNotText(this.element[0]);
1442	}, // _isSpecialEnterTab
1443
1444	/**
1445	 * Repeat a string 's' for 'n' times
1446	 */
1447	_strRepeat: function(s, n) {
1448		return new Array(n + 1).join(s);
1449	}, // _strRepeat
1450
1451	/**
1452	 * Reverse a string 's'
1453	 */
1454	_strReverse: function(s) {
1455		return s.split('').reverse().join('');
1456	} // _strReverse
1457
1458});

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.