mirror of
				https://github.com/yiisoft/yii2.git
				synced 2025-11-04 22:57:40 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			338 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			338 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
/*
 | 
						|
	Masked Input plugin for jQuery
 | 
						|
	Copyright (c) 2007-2013 Josh Bush (digitalbush.com)
 | 
						|
	Licensed under the MIT license (http://digitalbush.com/projects/masked-input-plugin/#license)
 | 
						|
	Version: 1.3.1
 | 
						|
*/
 | 
						|
(function($) {
 | 
						|
	function getPasteEvent() {
 | 
						|
    var el = document.createElement('input'),
 | 
						|
        name = 'onpaste';
 | 
						|
    el.setAttribute(name, '');
 | 
						|
    return (typeof el[name] === 'function')?'paste':'input';
 | 
						|
}
 | 
						|
 | 
						|
var pasteEventName = getPasteEvent() + ".mask",
 | 
						|
	ua = navigator.userAgent,
 | 
						|
	iPhone = /iphone/i.test(ua),
 | 
						|
	android=/android/i.test(ua),
 | 
						|
	caretTimeoutId;
 | 
						|
 | 
						|
$.mask = {
 | 
						|
	//Predefined character definitions
 | 
						|
	definitions: {
 | 
						|
		'9': "[0-9]",
 | 
						|
		'a': "[A-Za-z]",
 | 
						|
		'*': "[A-Za-z0-9]"
 | 
						|
	},
 | 
						|
	dataName: "rawMaskFn",
 | 
						|
	placeholder: '_',
 | 
						|
};
 | 
						|
 | 
						|
$.fn.extend({
 | 
						|
	//Helper Function for Caret positioning
 | 
						|
	caret: function(begin, end) {
 | 
						|
		var range;
 | 
						|
 | 
						|
		if (this.length === 0 || this.is(":hidden")) {
 | 
						|
			return;
 | 
						|
		}
 | 
						|
 | 
						|
		if (typeof begin == 'number') {
 | 
						|
			end = (typeof end === 'number') ? end : begin;
 | 
						|
			return this.each(function() {
 | 
						|
				if (this.setSelectionRange) {
 | 
						|
					this.setSelectionRange(begin, end);
 | 
						|
				} else if (this.createTextRange) {
 | 
						|
					range = this.createTextRange();
 | 
						|
					range.collapse(true);
 | 
						|
					range.moveEnd('character', end);
 | 
						|
					range.moveStart('character', begin);
 | 
						|
					range.select();
 | 
						|
				}
 | 
						|
			});
 | 
						|
		} else {
 | 
						|
			if (this[0].setSelectionRange) {
 | 
						|
				begin = this[0].selectionStart;
 | 
						|
				end = this[0].selectionEnd;
 | 
						|
			} else if (document.selection && document.selection.createRange) {
 | 
						|
				range = document.selection.createRange();
 | 
						|
				begin = 0 - range.duplicate().moveStart('character', -100000);
 | 
						|
				end = begin + range.text.length;
 | 
						|
			}
 | 
						|
			return { begin: begin, end: end };
 | 
						|
		}
 | 
						|
	},
 | 
						|
	unmask: function() {
 | 
						|
		return this.trigger("unmask");
 | 
						|
	},
 | 
						|
	mask: function(mask, settings) {
 | 
						|
		var input,
 | 
						|
			defs,
 | 
						|
			tests,
 | 
						|
			partialPosition,
 | 
						|
			firstNonMaskPos,
 | 
						|
			len;
 | 
						|
 | 
						|
		if (!mask && this.length > 0) {
 | 
						|
			input = $(this[0]);
 | 
						|
			return input.data($.mask.dataName)();
 | 
						|
		}
 | 
						|
		settings = $.extend({
 | 
						|
			placeholder: $.mask.placeholder, // Load default placeholder
 | 
						|
			completed: null
 | 
						|
		}, settings);
 | 
						|
 | 
						|
 | 
						|
		defs = $.mask.definitions;
 | 
						|
		tests = [];
 | 
						|
		partialPosition = len = mask.length;
 | 
						|
		firstNonMaskPos = null;
 | 
						|
 | 
						|
		$.each(mask.split(""), function(i, c) {
 | 
						|
			if (c == '?') {
 | 
						|
				len--;
 | 
						|
				partialPosition = i;
 | 
						|
			} else if (defs[c]) {
 | 
						|
				tests.push(new RegExp(defs[c]));
 | 
						|
				if (firstNonMaskPos === null) {
 | 
						|
					firstNonMaskPos = tests.length - 1;
 | 
						|
				}
 | 
						|
			} else {
 | 
						|
				tests.push(null);
 | 
						|
			}
 | 
						|
		});
 | 
						|
 | 
						|
		return this.trigger("unmask").each(function() {
 | 
						|
			var input = $(this),
 | 
						|
				buffer = $.map(
 | 
						|
				mask.split(""),
 | 
						|
				function(c, i) {
 | 
						|
					if (c != '?') {
 | 
						|
						return defs[c] ? settings.placeholder : c;
 | 
						|
					}
 | 
						|
				}),
 | 
						|
				focusText = input.val();
 | 
						|
 | 
						|
			function seekNext(pos) {
 | 
						|
				while (++pos < len && !tests[pos]);
 | 
						|
				return pos;
 | 
						|
			}
 | 
						|
 | 
						|
			function seekPrev(pos) {
 | 
						|
				while (--pos >= 0 && !tests[pos]);
 | 
						|
				return pos;
 | 
						|
			}
 | 
						|
 | 
						|
			function shiftL(begin,end) {
 | 
						|
				var i,
 | 
						|
					j;
 | 
						|
 | 
						|
				if (begin<0) {
 | 
						|
					return;
 | 
						|
				}
 | 
						|
 | 
						|
				for (i = begin, j = seekNext(end); i < len; i++) {
 | 
						|
					if (tests[i]) {
 | 
						|
						if (j < len && tests[i].test(buffer[j])) {
 | 
						|
							buffer[i] = buffer[j];
 | 
						|
							buffer[j] = settings.placeholder;
 | 
						|
						} else {
 | 
						|
							break;
 | 
						|
						}
 | 
						|
 | 
						|
						j = seekNext(j);
 | 
						|
					}
 | 
						|
				}
 | 
						|
				writeBuffer();
 | 
						|
				input.caret(Math.max(firstNonMaskPos, begin));
 | 
						|
			}
 | 
						|
 | 
						|
			function shiftR(pos) {
 | 
						|
				var i,
 | 
						|
					c,
 | 
						|
					j,
 | 
						|
					t;
 | 
						|
 | 
						|
				for (i = pos, c = settings.placeholder; i < len; i++) {
 | 
						|
					if (tests[i]) {
 | 
						|
						j = seekNext(i);
 | 
						|
						t = buffer[i];
 | 
						|
						buffer[i] = c;
 | 
						|
						if (j < len && tests[j].test(t)) {
 | 
						|
							c = t;
 | 
						|
						} else {
 | 
						|
							break;
 | 
						|
						}
 | 
						|
					}
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			function keydownEvent(e) {
 | 
						|
				var k = e.which,
 | 
						|
					pos,
 | 
						|
					begin,
 | 
						|
					end;
 | 
						|
 | 
						|
				//backspace, delete, and escape get special treatment
 | 
						|
				if (k === 8 || k === 46 || (iPhone && k === 127)) {
 | 
						|
					pos = input.caret();
 | 
						|
					begin = pos.begin;
 | 
						|
					end = pos.end;
 | 
						|
 | 
						|
					if (end - begin === 0) {
 | 
						|
						begin=k!==46?seekPrev(begin):(end=seekNext(begin-1));
 | 
						|
						end=k===46?seekNext(end):end;
 | 
						|
					}
 | 
						|
					clearBuffer(begin, end);
 | 
						|
					shiftL(begin, end - 1);
 | 
						|
 | 
						|
					e.preventDefault();
 | 
						|
				} else if (k == 27) {//escape
 | 
						|
					input.val(focusText);
 | 
						|
					input.caret(0, checkVal());
 | 
						|
					e.preventDefault();
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			function keypressEvent(e) {
 | 
						|
				var k = e.which,
 | 
						|
					pos = input.caret(),
 | 
						|
					p,
 | 
						|
					c,
 | 
						|
					next;
 | 
						|
 | 
						|
				if (e.ctrlKey || e.altKey || e.metaKey || k < 32) {//Ignore
 | 
						|
					return;
 | 
						|
				} else if (k) {
 | 
						|
					if (pos.end - pos.begin !== 0){
 | 
						|
						clearBuffer(pos.begin, pos.end);
 | 
						|
						shiftL(pos.begin, pos.end-1);
 | 
						|
					}
 | 
						|
 | 
						|
					p = seekNext(pos.begin - 1);
 | 
						|
					if (p < len) {
 | 
						|
						c = String.fromCharCode(k);
 | 
						|
						if (tests[p].test(c)) {
 | 
						|
							shiftR(p);
 | 
						|
 | 
						|
							buffer[p] = c;
 | 
						|
							writeBuffer();
 | 
						|
							next = seekNext(p);
 | 
						|
 | 
						|
							if(android){
 | 
						|
								setTimeout($.proxy($.fn.caret,input,next),0);
 | 
						|
							}else{
 | 
						|
								input.caret(next);
 | 
						|
							}
 | 
						|
 | 
						|
							if (settings.completed && next >= len) {
 | 
						|
								settings.completed.call(input);
 | 
						|
							}
 | 
						|
						}
 | 
						|
					}
 | 
						|
					e.preventDefault();
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			function clearBuffer(start, end) {
 | 
						|
				var i;
 | 
						|
				for (i = start; i < end && i < len; i++) {
 | 
						|
					if (tests[i]) {
 | 
						|
						buffer[i] = settings.placeholder;
 | 
						|
					}
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			function writeBuffer() { input.val(buffer.join('')); }
 | 
						|
 | 
						|
			function checkVal(allow) {
 | 
						|
				//try to place characters where they belong
 | 
						|
				var test = input.val(),
 | 
						|
					lastMatch = -1,
 | 
						|
					i,
 | 
						|
					c;
 | 
						|
 | 
						|
				for (i = 0, pos = 0; i < len; i++) {
 | 
						|
					if (tests[i]) {
 | 
						|
						buffer[i] = settings.placeholder;
 | 
						|
						while (pos++ < test.length) {
 | 
						|
							c = test.charAt(pos - 1);
 | 
						|
							if (tests[i].test(c)) {
 | 
						|
								buffer[i] = c;
 | 
						|
								lastMatch = i;
 | 
						|
								break;
 | 
						|
							}
 | 
						|
						}
 | 
						|
						if (pos > test.length) {
 | 
						|
							break;
 | 
						|
						}
 | 
						|
					} else if (buffer[i] === test.charAt(pos) && i !== partialPosition) {
 | 
						|
						pos++;
 | 
						|
						lastMatch = i;
 | 
						|
					}
 | 
						|
				}
 | 
						|
				if (allow) {
 | 
						|
					writeBuffer();
 | 
						|
				} else if (lastMatch + 1 < partialPosition) {
 | 
						|
					input.val("");
 | 
						|
					clearBuffer(0, len);
 | 
						|
				} else {
 | 
						|
					writeBuffer();
 | 
						|
					input.val(input.val().substring(0, lastMatch + 1));
 | 
						|
				}
 | 
						|
				return (partialPosition ? i : firstNonMaskPos);
 | 
						|
			}
 | 
						|
 | 
						|
			input.data($.mask.dataName,function(){
 | 
						|
				return $.map(buffer, function(c, i) {
 | 
						|
					return tests[i]&&c!=settings.placeholder ? c : null;
 | 
						|
				}).join('');
 | 
						|
			});
 | 
						|
 | 
						|
			if (!input.attr("readonly"))
 | 
						|
				input
 | 
						|
				.one("unmask", function() {
 | 
						|
					input
 | 
						|
						.unbind(".mask")
 | 
						|
						.removeData($.mask.dataName);
 | 
						|
				})
 | 
						|
				.bind("focus.mask", function() {
 | 
						|
					clearTimeout(caretTimeoutId);
 | 
						|
					var pos,
 | 
						|
						moveCaret;
 | 
						|
 | 
						|
					focusText = input.val();
 | 
						|
					pos = checkVal();
 | 
						|
					
 | 
						|
					caretTimeoutId = setTimeout(function(){
 | 
						|
						writeBuffer();
 | 
						|
						if (pos == mask.length) {
 | 
						|
							input.caret(0, pos);
 | 
						|
						} else {
 | 
						|
							input.caret(pos);
 | 
						|
						}
 | 
						|
					}, 10);
 | 
						|
				})
 | 
						|
				.bind("blur.mask", function() {
 | 
						|
					checkVal();
 | 
						|
					if (input.val() != focusText)
 | 
						|
						input.change();
 | 
						|
				})
 | 
						|
				.bind("keydown.mask", keydownEvent)
 | 
						|
				.bind("keypress.mask", keypressEvent)
 | 
						|
				.bind(pasteEventName, function() {
 | 
						|
					setTimeout(function() {
 | 
						|
						var pos=checkVal(true);
 | 
						|
						input.caret(pos);
 | 
						|
						if (settings.completed && pos == input.val().length)
 | 
						|
							settings.completed.call(input);
 | 
						|
					}, 0);
 | 
						|
				});
 | 
						|
			checkVal(); //Perform initial check for existing values
 | 
						|
		});
 | 
						|
	}
 | 
						|
});
 | 
						|
 | 
						|
 | 
						|
})(jQuery); |