jsbeans

jsbeans  1.0.0

jsbeans > jsbeans > SmartInsert.js (source view)
Search:
 
Filters
/*!
 * Copyright (c) 2009 Francesco Mele jsbeans@francescomele.com
 *
 * This Software is licenced under the LGPL Licence (GNU Lesser General 
 * Public License).
 * In addition to the LGPL Licence the Software is subject to the 
 * following conditions:
 * 
 * 	i	every modification must be public and comunicated to the Author
 * 	ii	every "jsbean" added to this library must be self consistent 
 * 		except for the dependence from jsbeans-x.x.x.js
 * 	iii	copyright notice and this permission notice shall be included 
 * 		in all copies or substantial portions of the Software
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

/**
 * A collection of utilities for inputs autocompletion
 * @namespace jsbeans
 * @class SmartInsert
 * @static
 * @author Francesco Mele
 * @credits Antonio Guerra for original inspiration
 */
jsbeans.SmartInsert = {
	/**
	 * Prevents the 'enter', useful in you don't want an accindental enter over an {@param} <code class="param">input</code>
	 * @method noReturn
	 * @param event {event}
	 * @param input {DOM} an input of type text or password
	 * */
	noReturn: function(event, obj) {
		var kc = this._getKeyCode(event);
		var status = true;
		if (kc == 13) {
			status = false;
		}
		this._returnValue(event, status);
	},
	/**
	 * Avoids entering characters other than integers
	 * @method int
	 * @param event {event}
	 * @param input {DOM} an input of type text
	 * */
	"int": function(event,obj) {
		var kc = this._getKeyCode(event);
		var status = true;
		if (!this._isSpecialKey(event)) {
			var chrCode = String.fromCharCode(kc);
			var re = /[0-9]/;
			if (chrCode.search(re) == -1) {
				status = false;
			}
		}
		this._returnValue(event, status);
	},
	/**
	 * Avoids entering characters other than floats, optionally indicating precision.
	 * @method float
	 * @param event {event}
	 * @param input {DOM} an input of type text
	 * @param [options] {JSON} 
	 * <pre>
	 * precision: string // precision, optional with default "99999999999999999999.9999999999"
	 * </pre>
	 * */
	"float": function(event,obj) {
		var kc = this._getKeyCode(event);
		var status = true;
		var args = arguments[2] || {};
		if (!this._isSpecialKey(event)) {
			var chrCode = String.fromCharCode(kc);
			var re = /[0-9]/;
			if (obj.value.length == 0 && chrCode.search(re) == -1) {
				status = false;
			} 
			else if (obj.value.length > 0) {
				var sp = obj.value.split(".");
				var spLen = sp.length;
				if (spLen >= 2 && chrCode == ".") {
					status = false;
				} 
				else if (chrCode != "." && chrCode.search(re) == -1) {
					status = false;
				} 
				else {
					var precision = args.precision || "99999999999999999999.9999999999";
					var fullLen = parseInt(precision.split(".")[0]);
					var decimalLen = parseInt(precision.split(".")[1]);
					if (chrCode == "." && decimalLen <= 0) {
						status = false;
					}
					if (spLen == 2 && sp[1].length == decimalLen) {
						status = false;
					}
					if (sp[0].length == fullLen - decimalLen) {
						if (spLen == 1 && chrCode != "." && decimalLen > 0) {
							status = false;
						}
					}
				}
			}
		}
		this._returnValue(event, status);
	},
	/**
	 * Autocompletion for date.
	 * @method date
	 * @param event {event}
	 * @param input {DOM} an input of type text
	 * @param [pattern] {String} one among "dd/MM/yyyy", "dd-MM-yyyy", "MM/dd/yyyy" and "MM-dd-yyyy". Default "MM/dd/yyyy".
	 * */
	date: function(event, obj) {
		var dateFormat = null;
		if (arguments.length == 3) {
			var supportedFormats = ["dd/MM/yyyy", "dd-MM-yyyy", "MM/dd/yyyy", "MM-dd-yyyy"];
			var isSupported = false;
			for (var i = 0; i < supportedFormats.length; i++) {
				if (arguments[2] == supportedFormats[i]) {
					dateFormat = arguments[2];
					isSupported = true;
					break;
				}
			}
			if (!isSupported) {
				return;
			}
		}
		if (dateFormat == null) {
			var getDefaultFormat = function() {
			    var res = "dd/MM/yyyy";
			    var lang = null;
			    if (typeof navigator.userLanguage != "undefined") {
			        lang = navigator.userLanguage.toUpperCase();
			    } 
			    else if (typeof navigator.language != "undefined") {
			        lang = navigator.language.toUpperCase();
			    }
			    if (lang != null && lang.indexOf("IT") != -1) {
			    	res = "dd/MM/yyyy";
			    } 
			    else {
					res = "MM/dd/yyyy";
			    }
			    return res;
			};
			dateFormat = getDefaultFormat();
		}
		var separator = dateFormat.indexOf("/") != -1 ? "/" : "-";
		var format = function(obj, chrCode) {
			var append = false;
			var status = true;
			var dPart = obj.value.split(separator);
			if (dateFormat.indexOf("d") == 0) {
				switch (dPart.length) {
		          case 1 :
		          			var day = dPart[0];
		                  	if (day.length == 1) {
			                  	if (chrCode == separator) {
			                  		obj.value = '0' + obj.value;
			                  	} 
			                  	else if (day.charAt(0) > '3') {
			                  		obj.value = '0' + obj.value;
			                  		append = true;
			                  	} 
			                  	else if (day.charAt(0) == '3' && chrCode > '1') {
									obj.value = '0' + obj.value;
									append = true;
			                  	}
			                } 
		                  	else if (day.length == 2) {
			                  	if (chrCode != separator){
			                  		append = true;
			                  	}
			                }
			                break;
		          case 2 :
		                  	var day = dPart[0];
		                  	var month = dPart[1];
						  	if (day.length == 1) {
		                  		obj.value = '0' + obj.value;
		                  	}
		                  	if (chrCode == separator) {
		                  		if (month.length == 1) {
		                  			obj.value = obj.value.substring(0, obj.value.indexOf(separator) + 1) + '0' + obj.value.substring(obj.value.indexOf(separator) + 1, obj.value.length);
		                  		}
		                  	} 
		                  	else if (month.length == 2) {
		                  		if (chrCode != separator) {
		                  			append = true;
		                  		}
		                  	} 
		                  	else if (month.length == 1) {
		                  		if (month.charAt(0) > '1' || (month.charAt(0) == '1' && chrCode > '2')) {
		                  			obj.value = obj.value.substring(0, obj.value.lastIndexOf(separator) + 1) + '0' + obj.value.substring(obj.value.lastIndexOf(separator) + 1, obj.value.length);
		                  			append = true;
		                  		} 
		                  	}
		                  	break;
				}
			} 
			else {
				switch (dPart.length) {
		          case 1 :
		          		var month = dPart[0];
		          		if (month.length == 1) {
		          			if (chrCode == separator) {
		          				obj.value = '0' + obj.value;
		          			} 
		          			else if (month.charAt(0) > '1') {
		          				obj.value = '0' + obj.value;
		          				append = true;
		          			} 
		          			else if (month.charAt(0) == '1' && chrCode>'2') {
		          				obj.value = '0' + obj.value;
		          				append = true;
		          			}
		          		} 
		          		else if (month.length == 2) {
		          			if (chrCode != separator) {
		          				append = true;
		          			}
		          		}
		          		break;
		          case 2 :
						var month = dPart[0];
		                var day = dPart[1];
						if (month.length == 1) {
							obj.value = '0' + obj.value;
						}
						if (chrCode == separator) {
							if (day.length == 1) {
								obj.value = obj.value.substring(0, obj.value.indexOf(separator) + 1) + '0' + obj.value.substring(obj.value.indexOf(separator) + 1, obj.value.length);
		                  	}
						} 
						else if (day.length == 2) {
							if (chrCode != separator) {
								append = true;
							}
						} 
						else if (day.length == 1) {
							if (day.charAt(0) > '3' || (day.charAt(0) == '3' && chrCode > '1')) {
								obj.value = obj.value.substring(0, obj.value.lastIndexOf(separator) + 1) + '0' + obj.value.substring(obj.value.lastIndexOf(separator) + 1, obj.value.length);
		                  		append = true;
		                  	}
						}
						break;
				}
			}
			if (append) {
				obj.value = obj.value + separator;
			}
			return status;
		};
		var kc = this._getKeyCode(event);
		var status = true;
		if (!this._isSpecialKey(event)) {
			var chrCode = String.fromCharCode(kc);
			var re = /[0-9\/]/;
			status = format(obj, chrCode);
			if (chrCode.search(re) == -1 || obj.value.length >= 10) {
				status = false;
			}
		}
		this._returnValue(event, status);
	},
	/**
	 * Autocompletion for IP addresses.
	 * @method ip
	 * @param event {event}
	 * @param input {DOM} an input of type text
	 * */
	ip: function(event, obj) {
		var separator = ".";
		var format = function(obj, chrCode) {
			var append = false;
			var status = true;
			var part = obj.value.split(separator);
			if ((obj.value == null || obj.value == "") && chrCode == "0") {
				obj.value = chrCode + separator;
				return false;
			}
			if (part.length > 4) {
				status = false;
			}
			switch (part.length) {
				case 1:
	          			var _1 = part[0];
	                	var n1 = parseInt(_1.charAt(0));
	                	var n2 = parseInt(_1.charAt(1));
	                	var nCode = parseInt(chrCode);
	                  	if (_1.length == 1) {
		                  	if (chrCode == separator) {
		                  		obj.value = obj.value + separator;
		                  	} 
		                  	else if (n1 == 0) {
		                  		obj.value = obj.value + separator;
							}
						} 
	                  	else if (_1.length == 2) {
		                  	if (chrCode == separator) {
		                  		obj.value = obj.value + separator;
		                  	} 
		                  	else if (n1 >= 3) {
		                  		obj.value = obj.value + separator;
		                  	} 
		                  	else if (n1 == 2) {
		                  		if (n2 == 5 && nCode > 5) {
			                  		obj.value = obj.value + separator;
		                  		} 
		                  		else if (n2 > 5) {
			                  		obj.value = obj.value + separator;		                  		
		                  		}
		                  	}
						} 
	                  	else if (_1.length == 3) {
	                  		obj.value = obj.value + separator;
		                }
		                break;
				case 2:
	          			var _1 = part[1];
	                	var n1 = parseInt(_1.charAt(0));
	                	var n2 = parseInt(_1.charAt(1));
	                	var nCode = parseInt(chrCode);
	                  	if (_1.length == 1) {
		                  	if (chrCode == separator) {
		                  		obj.value = obj.value + separator;
		                  	} 
		                  	else if (n1 == 0) {
		                  		obj.value = obj.value + separator;
		                  	}
		                } 
	                  	else if (_1.length == 2) {
		                  	if (chrCode == separator) {
		                  		obj.value = obj.value + separator;
		                  	} 
		                  	else if (n1 >= 3) {
		                  		obj.value = obj.value + separator;
		                  	} 
		                  	else if (n1 == 2) {
		                  		if (n2 == 5 && nCode > 5) {
			                  		obj.value = obj.value + separator;
		                  		} 
		                  		else if (n2 > 5) {
			                  		obj.value = obj.value + separator;		                  		
		                  		}
		                  		if (nCode == 0) {
		                  			status = false;
		                  		}
		                  	}
		                } 
	                  	else if (_1.length == 3) {
		                  	if (chrCode != separator){
		                  		obj.value = obj.value + separator;
		                  	}
		                }
		                break;
				case 3:
	          			var _1 = part[2];
	                	var n1 = parseInt(_1.charAt(0));
	                	var n2 = parseInt(_1.charAt(1));
	                	var nCode = parseInt(chrCode);
	                  	if (_1.length == 1) {
		                  	if (chrCode == separator) {
		                  		obj.value = obj.value + separator;
		                  	} 
		                  	else if (n1 == 0) {
		                  		obj.value = obj.value + separator;
		                  	}
		                } 
	                  	else if (_1.length == 2) {
		                  	if (chrCode == separator) {
		                  		obj.value = obj.value + separator;
		                  	} 
		                  	else if (n1 >= 3) {
		                  		obj.value = obj.value + separator;
		                  	} 
		                  	else if (n1 == 2) {
		                  		if (n2 == 5 && nCode > 5) {
			                  		obj.value = obj.value + separator;
		                  		} 
		                  		else if (n2 > 5) {
			                  		obj.value = obj.value + separator;		                  		
		                  		}
		                  		if (nCode == 0) {
		                  			status = false;
		                  		}
		                  	}
		                } 
	                  	else if (_1.length == 3) {
		                  	if (chrCode != separator){
		                  		obj.value = obj.value + separator;
		                  	}
		                }
		                break;
				case 4:
	          			var _1 = part[3];
	                	var n1 = parseInt(_1.charAt(0));
	                	if (n1 == 0) {
	                		status = false;
	                		break;
	                	}
	                	var n2 = parseInt(_1.charAt(1));
	                	var nCode = parseInt(chrCode);
	                	if (nCode == 0 && _1.length == 0) {
	                		obj.value = obj.value + "0";
	                		status = false;
	                		break;
	                	}
	                  	if (_1.length == 1) {
		                  	if (chrCode == separator) {
		                  		status = false;
		                  	} 
		                  	else if (n1 == 0) {
		                  		status = false;
		                  	}
		                } 
	                  	else if (_1.length == 2) {
		                  	if (chrCode == separator) {
		                  		status = false;
		                  	} 
		                  	else if (n1 >= 3) {
		                  		status = false;
		                  	} 
		                  	else if (n1 == 2) {
		                  		if (n2 == 5 && nCode > 5) {
			                  		status = false;
		                  		} 
		                  		else if (n2 > 5) {
			                  		status = false;		                  		
		                  		}
		                  		if (nCode == 0) {
		                  		}
		                  	}
		                } 
	                  	else if (_1.length == 3) {
		                  	if (chrCode != separator){
		                  		status = false;
		                  	}
		                } 
		                break;
			}
			return status;
		};
		var kc = this._getKeyCode(event);
		var status = true;
		if (!this._isSpecialKey(event)) {
			var chrCode = String.fromCharCode(kc);
			var re = /[0-9\/]/;
			status = format(obj, chrCode);
			if (chrCode.search(re) == -1 || obj.value.length >= 15) {
				status = false;
			}
		}
		this._returnValue(event, status);
	},
	/**
	 * Avoids entering character single or double quotes (" or ').
	 * @method noQuote
	 * @param event {event}
	 * @param input {DOM} an input of type text
	 * */
	noQuote: function(event, obj) {
		var kc = this._getKeyCode(event);
		var status = true;
		// 34 = double quote
		// 39 = single quote
		if (kc == 34 || kc == 39) {
			status = false;
		}
		this._returnValue(event, status);
	},
	/**
	 * Allows entering only characters matching given {@param} <code class="param">re</code>.
	 * @method mask
	 * @param event {event}
	 * @param input {DOM} an input of type text
	 * @param re {RegEx}
	 * */
	mask: function(event,obj,re) {
		var kc = this._getKeyCode(event);
		var status = true;
		if (!this._isSpecialKey(event)) {
			var chrCode = String.fromCharCode(kc);
			if (chrCode.search(re) == -1) {
				status = false;
			}
		}
		this._returnValue(event, status);
	},
	/**
	 * Allows entering only characters DON'T matching given {@param} <code class="param">re</code>.
	 * @method unmask
	 * @param event {event}
	 * @param input {DOM} an input of type text
	 * @param re {RegEx}
	 * */
	unmask: function(event,obj,re) {
		var kc = this._getKeyCode(event);
		var status = true;
		if (!this._isSpecialKey(event)) {
			var chrCode = String.fromCharCode(kc);
			if (chrCode.search(re) != -1) {
				status = false;
			}
		}
		this._returnValue(event, status);
	},
	/**
	 * Autocompletion for currency, optionally indicating precision.<br/>
	 * It uses dots for thousands and commas for decimals.
	 * @method currency
	 * @param event {event}
	 * @param input {DOM} an input of type text
	 * @param [options] {JSON} 
	 * <pre>
	 * precision: string // precision, optional with default "9999999999999999999999999.2"
	 * </pre>
	 * */
	currency: function(event,obj) {
		var kc = this._getKeyCode(event);
		var status = true;
		var args = arguments[2] || {};
		if (!this._isSpecialKey(event)) {
			var chrCode = String.fromCharCode(kc);
			var re = /[0-9]/;
			if (obj.value.length == 0 && chrCode.search(re) == -1) {
				status = false;
			} 
			else if (obj.value.length > 0) {
				var sp = obj.value.split(",");
				var spLen = sp.length;
				if (spLen >= 2 && chrCode == ",") {
					status = false;
				} 
				else if (chrCode != "." && chrCode != "," && chrCode.search(re) == -1) {
					status = false;
				} 
				else {
					if (chrCode == ".") {
						this._returnValue(event, false);
						return;
					}
					var formatLeft = function(v) {
						v = v.split(".").join("").split("").reverse();
						var res = "";
						for (var i = 1; i < v.length; i++) {
							if ((i) % 3 == 0) {
								res +=  ".";
							}
							res += v[i-1];
						}
						return res.split("").reverse().join("");
					};
					var left = sp[0];
					var right = sp[1] || null;
					var precision = args.precision || "9999999999999999999999999.2";
					var fullLen = parseInt(precision.split(".")[0]);
					var centLen = parseInt(precision.split(".")[1]);
					if (chrCode == "," && centLen <= 0) {
						this._returnValue(event, false);
						return;
					}
					if (right != null && typeof(right) != "undefined") {
						if (chrCode.search(re) == -1 || right.length >= centLen) {
							this._returnValue(event, false);
							return;
						}
					} 
					else if (chrCode == ",") {
					} 
					else if (obj.value.indexOf(",") != (obj.value.length - 1)) {
						if (left.split(".").join("").length >= (fullLen - centLen)) {
							this._returnValue(event, false);
							return;
						} 
						else {
							obj.value = formatLeft(chrCode + obj.value);
						}
					}
				}
			}
		}
		this._returnValue(event, status);
	},
	/**
	 * Autocompletion for time.
	 * @method time
	 * @param event {event}
	 * @param input {DOM} an input of type text
	 * @param [pattern] {String} one among "hh:mm", "hh.mm", "hh:mm:ss" and "hh.mm.ss". Default "hh:mm".
	 * */
	time: function(event, obj) {
		var timeFormat = null;
		if (arguments.length == 3) {
			var supportedFormats = ["hh:mm", "hh.mm", "hh:mm:ss", "hh.mm.ss"];
			var isSupported = false;
			for (var i = 0; i < supportedFormats.length; i++) {
				if (arguments[2].toLowerCase() == supportedFormats[i].toLowerCase()) {
					timeFormat = arguments[2];
					isSupported = true;
					break;
				}
			}
			if (!isSupported) {
				return;
			}
		}
		if (timeFormat == null) {
			timeFormat = "hh:mm";
		}
		var separator = timeFormat.indexOf(":") != -1 ? ":" : ".";
		var format = function(obj, chrCode) {
			if (obj.value.length == timeFormat.length) {
				return false;
			}
			var status = true;
			var tPart = obj.value.split(separator);
			switch (tPart.length) {
				case 1 :
					var hour = tPart[0];
					if (hour.length == 1) {
						if (chrCode == separator) {
							obj.value = '0' + obj.value;
						} 
						else if (hour.charAt(0) > '2' || (hour.charAt(0) == '2' && chrCode > '4')) {
							obj.value = '0' + obj.value + separator;
							if (chrCode > '5') {
								obj.value = obj.value + '0';
							}
						}
					} 
					else if (hour.length == 2) {
						if (chrCode != separator) {
							obj.value = obj.value + separator;
						}
					}
					break;
				case 2 :
					var hour = tPart[0];
					var minutes = tPart[1];
					if (hour.length == 1) {
						obj.value = '0' + obj.value;
					}
					if (chrCode == separator /*|| minutes.length == 2*/) {
						status = false;
					} 
					else if (minutes.length == 1) {
						if (minutes.charAt(0) > '5') {
							obj.value = obj.value.substring(0, obj.value.lastIndexOf(separator) + 1)  + '0' + obj.value.substring(obj.value.lastIndexOf(separator) + 1, obj.value.length);
							if (timeFormat.indexOf("ss") != -1) {
								obj.value = obj.value + separator;
							}
						}
					} 
					else if (minutes.length == 2) {
						if (chrCode != separator) {
							obj.value = obj.value + separator;
						}
					}
					break;
				case 3 :
					var minutes = tPart[1];
					var seconds = tPart[2];
					if (minutes.length == 1) {
						obj.value = '0' + obj.value;
					}
					if (chrCode == separator /*|| minutes.length == 2*/) {
						status = false;
					} 
					else if (seconds.length == 1) {
						if (seconds.charAt(0) > '5') {
							obj.value = obj.value.substring(0, obj.value.lastIndexOf(separator) + 1)  + '0' + obj.value.substring(obj.value.lastIndexOf(separator) + 1, obj.value.length);
							status = false;
						}
					}
					break;
			}
			return status;
		};
		var kc = this._getKeyCode(event);
		var status = true;
		if (!this._isSpecialKey(event)) {
			var chrCode = String.fromCharCode(kc);
			var re = /[0-9]/;
			status = format(obj, chrCode);
			if (chrCode.search(re) == -1 || obj.value.length >= timeFormat.length) {
				status = false;
			}
		}
		this._returnValue(event, status);
	},
	/**
	 * @method _returnValue
	 * @param event {event}
	 * @param object {DOM}
	 * @private
	 * */
	_returnValue: function(event, status) {
		if (!status && document.addEventListener) {
			event.preventDefault();
		}
		event.returnValue = status;
		event.cancelBubble = !status;
	},
	/**
	 * @method _getKeyCode
	 * @param event {event}
	 * @param object {DOM}
	 * @private
	 * */
	_getKeyCode: function(event) {
		var kc = event.keyCode;
		if (kc == 0) {
			kc = event.charCode;
		}
		return kc;
	},
	/**
	 * @method _isSpecialKey
	 * @param event {event}
	 * @param object {DOM}
	 * @private
	 * */
	_isSpecialKey: function(event) {
		var kc = event.keyCode;
		// 8 = backspace
		// 13 = enter
		if (kc == 13 || kc == 8 || (kc != 0 && (typeof(event.charCode) != "undefined") && !event.charCode)) {
			return true;
		}
		return false;
	}
};

Copyright © 2016 Francesco Mele. All rights reserved.