PageSourceSearch

https://gigas.su/bitrix/js/main/masked_input.js?175628928015294

js gigas.su collected 2026-10-08 00:04:20 UTC 15,294 bytes, 832 lines download raw bytes

1;(function()
2{
3	if (BX.MaskedInput)
4		return;
5
6	var defaultDefinitions = {
7		"cypher": {
8			"char": "9",
9			"rule": "[0-9]"
10		},
11		"hexrgb": {
12			"char": "h",
13			"rule": "[A-Fa-f0-9]"
14		},
15		"lang_en": {
16			"char": "a",
17			"rule": "[a-zA-Z]"
18		}
19	};
20
21	/**
22	 * @param {object} params
23	 * @constructor
24	 */
25	BX.MaskedInput = function (params)
26	{
27		this.mask = params.mask || '';
28		this.placeholder = (params.placeholder || '_').substring(0, 1);
29		this.definitions = this.prepareDefinitions(params.definitions || ['cypher', 'lang_en']);
30		this.stopChangeEvent = false;
31
32		this.initInput(params);
33	};
34
35	BX.MaskedInput.prototype.initInput = function (params)
36	{
37		if (params.input.tagName == 'INPUT')
38		{
39			this.input = new BX.MaskedInputElement({node: params.input});
40		}
41		else
42		{
43			this.input = new BX.MaskedTextElement({node: params.input});
44		}
45
46		this.dataInput = params.dataInput || null;
47		this.isDataInputClean = params.isDataInputClean || false;
48		this.isHoldOverInputValueInit = params.isHoldOverInputValueInit || false;
49		this.enableCheckingValue = params.enableCheckingValue || false;
50		this.onDataInputChange = params.onDataInputChange || null;
51		this.onDataInputInitValue = params.onDataInputInitValue || null;
52
53		BX.addCustomEvent(this.input, 'change', BX.proxy(this.onInputChange, this));
54		BX.addCustomEvent(this.input, 'paste', BX.proxy(this.onInputPaste, this));
55		BX.addCustomEvent(this.input, 'delete', BX.proxy(this.onInputDelete, this));
56
57		BX.bind(this.input.node, 'focus', BX.proxy(function ()
58		{
59			if (this.getFirstEmptyPosition() === null)
60			{
61				return;
62			}
63
64			setTimeout(BX.proxy(function ()
65			{
66				this.moveCaret(this.getFirstEmptyPosition());
67			}, this), 50);
68		}, this));
69
70		if (!this.isHoldOverInputValueInit && !this.test(this.input.val()))
71		{
72			this.input.val(this.getMaskedPlaceholder());
73		}
74
75		if (this.dataInput)
76		{
77			var dataInputVal = this.dataInput.value;
78			if (BX.type.isFunction(this.onDataInputInitValue))
79			{
80				dataInputVal = this.onDataInputInitValue.apply(this, [dataInputVal]);
81			}
82			if (BX.type.isString(dataInputVal) && dataInputVal.length > 0)
83			{
84				this.setValue(dataInputVal);
85			}
86
87			BX.addCustomEvent(this, 'change', BX.proxy(function ()
88			{
89				var inputVal = '';
90				if (BX.type.isFunction(this.onDataInputChange))
91				{
92					inputVal = this.onDataInputChange.apply(this, [this.getValueClean(), this.getValue()]);
93				}
94				else if (this.isDataInputClean)
95				{
96					inputVal = this.getValueClean();
97				}
98				else
99				{
100					inputVal = this.getValue();
101				}
102
103				if (!BX.type.isString(inputVal))
104				{
105					inputVal = '';
106				}
107
108				if (this.enableCheckingValue && !this.checkValue())
109				{
110					inputVal = '';
111				}
112
113				this.dataInput.value = inputVal;
114
115			}, this));
116
117		}
118	};
119
120	BX.MaskedInput.prototype.setMask = function (mask)
121	{
122		if (this.mask == mask)
123		{
124			return;
125		}
126
127		var val = this.getValueClean();
128		this.mask = mask;
129
130		this.setChangeEventFiring(false);
131		this.setValue(val);
132		this.setChangeEventFiring(true);
133	};
134
135	BX.MaskedInput.prototype.getMask = function ()
136	{
137		return this.mask;
138	};
139
140	BX.MaskedInput.prototype.setValue = function (val)
141	{
142		if (!this.mask)
143		{
144			this.input.val(val);
145			this.fireChangeEvent();
146			return;
147		}
148
149		var lastCaretPosition = this.input.getSelectionStart();
150		this.moveCaret(0);
151
152		this.input.val(this.mask);
153
154		var j = 0;
155		for (var i = 0; i < this.mask.length; i++)
156		{
157			if (!this.isMaskCharReplaceable(i))
158			{
159				this.replaceChar(i, this.mask.charAt(i));
160				continue;
161			}
162
163			while (true)
164			{
165				var char = val.charAt(j);
166				if (!char)
167				{
168					char = this.placeholder;
169					break;
170				}
171
172				if (char == this.placeholder)
173				{
174					break;
175				}
176
177				if (this.testChar(i, char))
178				{
179					break;
180				}
181
182				j++;
183			}
184
185			this.replaceChar(i, char);
186			j++;
187		}
188
189		this.moveCaret(lastCaretPosition);
190		//this.moveCaret(this.getFirstEmptyPosition());
191		this.fireChangeEvent();
192	};
193
194	BX.MaskedInput.prototype.getValue = function ()
195	{
196		return this.input.val();
197	};
198
199	BX.MaskedInput.prototype.getFirstEmptyPosition = function ()
200	{
201		var val = this.getValue();
202		for (var i = 0; i < val.length; i++)
203		{
204			if (!this.isMaskCharReplaceable(i))
205			{
206				continue;
207			}
208
209			var char = val.charAt(i);
210			if (char == this.placeholder)
211			{
212				return i;
213			}
214		}
215
216		return null;
217	};
218
219	BX.MaskedInput.prototype.getValueClean = function ()
220	{
221		var returnValue = '';
222		var val = this.getValue();
223		if (!this.mask)
224		{
225			return val;
226		}
227
228		for (var i = 0; i < val.length; i++)
229		{
230			if (!this.isMaskCharReplaceable(i))
231			{
232				continue;
233			}
234
235			var char = val.charAt(i);
236			returnValue += char == this.placeholder ? '' : char;
237		}
238
239		return returnValue;
240	};
241
242	BX.MaskedInput.prototype.checkValue = function ()
243	{
244		var val = this.getValue();
245		if (!this.mask)
246		{
247			return val;
248		}
249
250		for (var i = 0; i < val.length; i++)
251		{
252			if (!this.isMaskCharReplaceable(i))
253			{
254				continue;
255			}
256
257			if (val.charAt(i) == this.placeholder)
258			{
259				return false;
260			}
261		}
262
263		return true;
264	};
265
266	BX.MaskedInput.prototype.onInputDelete = function (directionLeft)
267	{
268		if (this.deleteSelection())
269		{
270			this.fireChangeEvent();
271			return;
272		}
273
274		var pos = this.input.getSelectionStart();
275		if (directionLeft)
276		{
277			if (pos === this.mask.length)
278			{
279				this.replaceChar(pos - 1, this.placeholder);
280			}
281			else
282			{
283				this.shift(pos, pos - 1);
284			}
285			this.moveCaret(pos - 1);
286		}
287		else
288		{
289			if (pos === this.mask.length - 1)
290			{
291				this.replaceChar(pos, this.placeholder);
292			}
293			else if (pos < this.mask.length - 1)
294			{
295				this.shift(pos + 1, pos);
296			}
297
298			this.moveCaret(pos);
299		}
300		this.fireChangeEvent();
301	};
302
303	BX.MaskedInput.prototype.onInputPaste = function (pastedData)
304	{
305		this.deleteSelection();
306		for (var i = 0; i < pastedData.length; i++)
307		{
308			this.setCharOnCaret(pastedData.charAt(i));
309		}
310		this.fireChangeEvent();
311	};
312
313	BX.MaskedInput.prototype.onInputChange = function (char)
314	{
315		if (this.input.val() == '' && this.mask)
316		{
317			this.input.val(this.getMaskedPlaceholder());
318			this.input.setCaretPosition(0);
319		}
320
321		this.deleteSelection();
322		this.setCharOnCaret(char);
323		this.fireChangeEvent();
324	};
325
326	BX.MaskedInput.prototype.moveCaret = function (pos)
327	{
328		if (pos > this.mask.length)
329		{
330			pos = this.mask.length;
331		}
332		else if (pos < 0)
333		{
334			pos = 0;
335		}
336		else if (pos === null)
337		{
338			return this.input.getSelectionStart();
339		}
340
341		this.input.setCaretPosition(pos);
342		return pos;
343	};
344
345	BX.MaskedInput.prototype.findClosestAllowPosition = function (pos, char, directionLeft)
346	{
347		if (typeof pos === 'undefined')
348		{
349			pos = 0;
350		}
351		if (typeof char === 'undefined')
352		{
353			char = null;
354		}
355		if (typeof directionLeft === 'undefined')
356		{
357			directionLeft = false;
358		}
359
360		while (true)
361		{
362			if (!directionLeft && pos >= this.mask.length)
363			{
364				return null;
365			}
366			else if (directionLeft && pos <= 0)
367			{
368				return 0;
369			}
370
371			if (this.isMaskCharReplaceable(pos))
372			{
373				break;
374			}
375
376			if (!directionLeft)
377			{
378				pos++;
379			}
380			else
381			{
382				pos--;
383			}
384		}
385
386		if (!this.isMaskCharReplaceable(pos))
387		{
388			return null;
389		}
390		if (char && !this.testChar(pos, char))
391		{
392			return null;
393		}
394
395		return pos;
396	};
397
398	BX.MaskedInput.prototype.setCharOnCaret = function (char)
399	{
400		var pos = this.input.getSelectionStart();
401		pos = this.findClosestAllowPosition(pos, char);
402		if (pos === null)
403		{
404			return;
405		}
406
407		this.shift(pos, pos + 1);
408		pos = this.replaceChar(pos, char);
409
410		if (pos === null)
411		{
412			return;
413		}
414
415		pos = this.findClosestAllowPosition(pos + 1);
416
417		this.moveCaret(pos);
418
419		if (BX.browser.IsAndroid() && BX.browser.DetectAndroidVersion() < 7)
420		{
421			var _this = this;
422			setTimeout(function ()
423			{
424				_this.moveCaret(pos);
425			}, 50);
426		}
427
428		/*
429		 var pos = this.getFirstEmptyPosition();
430		 if(pos)
431		 {
432		 this.moveCaret(pos);
433		 }
434		 */
435	};
436
437	BX.MaskedInput.prototype.shift = function (start, target)
438	{
439		var i, char = null;
440		var buffer = [];
441
442		for (i = start; i < this.mask.length; i++)
443		{
444			if (!this.isMaskCharReplaceable(i)) continue;
445			var val = this.input.val();
446			buffer.push(val.charAt(i));
447			this.replaceChar(i, this.placeholder);
448		}
449
450		buffer.reverse();
451		for (i = target; i < this.mask.length; i++)
452		{
453			if (!this.isMaskCharReplaceable(i)) continue;
454			if (buffer.length > 0)
455			{
456				char = buffer.pop();
457			}
458			else
459			{
460				char = this.placeholder;
461			}
462
463			this.replaceChar(i, char);
464		}
465	};
466
467	BX.MaskedInput.prototype.deleteSelection = function ()
468	{
469		var posStart = this.input.getSelectionStart();
470		var posEnd = this.input.getSelectionEnd();
471		if (posStart == posEnd)
472		{
473			return false;
474		}
475
476		// delete
477		for (var i = posStart; i < posEnd; i++)
478		{
479			if (!this.isMaskCharReplaceable(i))
480			{
481				continue;
482			}
483
484			this.replaceChar(i, this.placeholder);
485		}
486
487		this.shift(posEnd, posStart);
488		this.moveCaret(posStart);
489
490		return true;
491	};
492
493	BX.MaskedInput.prototype.setChangeEventFiring = function (start)
494	{
495		this.stopChangeEvent = !start;
496	};
497
498	BX.MaskedInput.prototype.fireChangeEvent = function ()
499	{
500		if (!this.stopChangeEvent)
501		{
502			BX.onCustomEvent(this, 'change', [this.getValueClean(), this.getValue()]);
503		}
504	};
505
506	BX.MaskedInput.prototype.replaceChar = function (pos, char)
507	{
508		if (isNaN(pos))
509		{
510			return null;
511		}
512
513		var val = this.input.val();
514		var valTml = val.substring(0, pos) + char;
515		valTml += (pos >= val.length) ? '' : val.substring((pos + 1));
516		val = valTml;
517
518		this.input.val(val);
519
520		return pos;
521	};
522	BX.MaskedInput.prototype.isMaskCharReplaceable = function (pos)
523	{
524		var char = this.mask.charAt(pos);
525		if (!char)
526		{
527			return false;
528		}
529
530		return !!this.definitions[char];
531	};
532
533	BX.MaskedInput.prototype.getMaskedPlaceholder = function ()
534	{
535		var val = '';
536		for (var i = 0; i < this.mask.length; i++)
537		{
538			var char = this.mask[i];
539			if (this.definitions[char])
540			{
541				char = this.placeholder;
542			}
543
544			val += char;
545		}
546
547		return val;
548	};
549
550	BX.MaskedInput.prototype.prepareDefinitions = function (definitions)
551	{
552		var result = {};
553
554		definitions.forEach(function (definition)
555		{
556			if (BX.type.isString(definition) && defaultDefinitions[definition])
557			{
558				definition = defaultDefinitions[definition];
559			}
560
561			if (BX.type.isPlainObject(definition))
562			{
563				var def = {
564					"rule": definition.rule,
565					"isFunction": false
566				};
567				if (BX.type.isFunction(definition.rule))
568				{
569					def.isFunction = true;
570				}
571				else
572				{
573					def.regexp = new RegExp(definition.rule);
574				}
575
576				result[definition.char] = def;
577			}
578		}, this);
579		return result;
580	};
581
582	BX.MaskedInput.prototype.test = function (string)
583	{
584		for (var i = 0; i < string.length; i++)
585		{
586			var r = this.testChar(i, string[i]);
587			if (!r)
588			{
589				return false;
590			}
591		}
592
593		return true;
594	};
595
596	BX.MaskedInput.prototype.testChar = function (pos, char)
597	{
598		var maskChar = this.mask[pos];
599
600		if (!this.definitions[maskChar])
601		{
602			return char === maskChar;
603		}
604
605		var isSuccess = true;
606		if (this.definitions[maskChar].isFunction)
607		{
608			isSuccess = !!this.definitions[maskChar].func.apply(this, [char]);
609		}
610		else
611		{
612			isSuccess = this.definitions[maskChar].regexp.test(char);
613		}
614
615		return isSuccess;
616	};
617
618	BX.MaskedInputElement = function (params)
619	{
620		this.node = params.node;
621		this.skipTextInputEvent = false;
622
623		BX.bind(this.node, 'paste', BX.proxy(this.onChange, this));
624		BX.bind(this.node, 'keypress', BX.proxy(this.onChange, this));
625
626		if (BX.browser.IsAndroid() && BX.browser.DetectAndroidVersion() < 7)
627		{
628			BX.bind(this.node, 'textInput', BX.proxy(this.onAndroidInput, this));
629			BX.bind(this.node, 'keydown', BX.proxy(this.onAndroidInput, this));
630		}
631		else
632		{
633			BX.bind(this.node, 'keydown', BX.proxy(this.onChange, this));
634		}
635	};
636
637	BX.MaskedInputElement.prototype.val = function (value)
638	{
639		if (typeof value != 'undefined')
640		{
641			this.node.value = value;
642		}
643
644		return this.node.value;
645	};
646
647	BX.MaskedInputElement.prototype.onAndroidInput = function (e)
648	{
649		var kc = 0;
650		if (e.type == 'keydown')
651		{
652			kc = (typeof e.which == "number") ? e.which : e.keyCode;
653			if (kc != 8)
654			{
655				if (e.key == "Unidentified") // if keydown has wrong key, use textInput with right key
656				{
657					this.skipTextInputEvent = false;
658					BX.PreventDefault(e);
659					return false;
660				}
661				else
662				{
663					this.skipTextInputEvent = true;
664				}
665			}
666		}
667		else
668		{
669			if (this.skipTextInputEvent)
670			{
671				BX.PreventDefault(e);
672				return false;
673			}
674
675			kc = e.data.toUpperCase().charCodeAt(0);
676		}
677
678		var eventObject = {
679			keyCode: kc,
680			which: kc,
681			type: 'keydown'
682		};
683
684		return this.onChange(eventObject, e);
685	};
686
687	BX.MaskedInputElement.prototype.onChange = function (e, eReal)
688	{
689		var isCatch = true;
690		var kc = (typeof e.which == "number") ? e.which : e.keyCode;
691
692		if (kc <= 0)
693		{
694			return;
695		}
696
697		switch (e.type)
698		{
699			case 'keydown':
700
701				isCatch = (
702					(!e.ctrlKey && !e.altKey && !e.metaKey)
703					&&
704					(
705						kc
706						&&
707						(
708							(kc > 46 && kc <= 90) // chars
709							||
710							kc > 145
711							||
712							kc === 13 // Carriage return
713							||
714							kc === 8 // [backspace] key
715							||
716							kc === 46 // [Del] key
717							||
718							(BX.browser.IsIOS() && kc === 127) // iOS [delete] key
719						)
720					)
721				);
722				break;
723			case 'keypress':
724				break;
725		}
726
727		if (!isCatch)
728		{
729			return;
730		}
731
732		BX.PreventDefault(eReal || e);
733		if (e.type == 'paste')
734		{
735			var clipboardData = e.clipboardData || window.clipboardData;
736			var pastedData = clipboardData.getData('Text');
737			BX.onCustomEvent(this, 'paste', [pastedData]);
738		}
739		else if (kc === 8 || kc === 46 || (BX.browser.IsIOS() && kc === 127))
740		{
741			var directionLeft = kc === 8;
742			BX.onCustomEvent(this, 'delete', [directionLeft]);
743		}
744		else
745		{
746			var char = String.fromCharCode(kc);
747			BX.onCustomEvent(this, 'change', [char]);
748		}
749	};
750
751	BX.MaskedInputElement.prototype.setCaretPosition = function (pos)
752	{
753		this.node.setSelectionRange(pos, pos);
754	};
755
756	BX.MaskedInputElement.prototype.getSelectionStart = function ()
757	{
758		if (this.node.selectionStart)
759		{
760			return this.node.selectionStart;
761		}
762		else if (this.node.createTextRange)
763		{
764			var range = this.node.createTextRange().duplicate();
765			range.moveEnd('character', this.node.value.length);
766			if (range.text == '')
767			{
768				return this.node.value.length;
769			}
770			else
771			{
772				return this.node.value.lastIndexOf(range.text);
773			}
774		}
775		else
776		{
777			return 0;
778		}
779	};
780
781	BX.MaskedInputElement.prototype.getSelectionEnd = function ()
782	{
783		if (this.node.selectionEnd)
784		{
785			return this.node.selectionEnd;
786		}
787		else if (this.node.createTextRange)
788		{
789			var range = this.node.createTextRange().duplicate();
790			range.moveStart('character', -this.node.value.length);
791			return range.text.length;
792		}
793		else
794		{
795			return 0;
796		}
797	};
798
799	BX.MaskedTextElement = function (params)
800	{
801		this.node = params.node;
802	};
803
804
805	BX.MaskedTextElement.prototype.val = function (value)
806	{
807		if (typeof value != 'undefined')
808		{
809			this.node.innerText = value;
810		}
811
812		return this.node.innerText;
813	};
814
815	BX.MaskedTextElement.prototype.onChange = function (e)
816	{
817	};
818
819	BX.MaskedTextElement.prototype.setCaretPosition = function (pos)
820	{
821	};
822
823	BX.MaskedTextElement.prototype.getSelectionStart = function ()
824	{
825		return 0;
826	};
827
828	BX.MaskedTextElement.prototype.getSelectionEnd = function ()
829	{
830		return 0;
831	};
832})();

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.