jQuery操作DOM工具类

本文介绍了一个基于jQuery的DOM操作工具库,提供了多种实用功能,包括数据验证、序列化、值设定及清理等,适用于网页表单处理及数据交互场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

jQuery操作DOM工具类

Utils.js代码

if (!window.Utils || typeof Utils !== 'function') {
	/**
	 * 工具类
	 * @returns {Utils}
	 * @constructor
	 */
	var Utils = function () {
		return this;
	};

	(function () {
		const REG_PKG_B_TO_E = /^\d*to\d*$/i,
			REG_PKG_I_NUM_X = /^(-?\d+(\.\d+)?)*num(-?\d+(\.\d+)?)*$/i;
		const REG_EMPTY_STR = /\s+/,  //无效字符
			REG_NUM = /^-?\d+(\.\d+)?$/, //数字
			REG_ZIP = /^[1-9]\d{5}$/,   //邮编
			REG_EMAIL = /^[a-zA-Z\d($\+\-\._#&)\u4e00-\u9fff]{1,20}@[a-zA-Z\d\-$_]{1,20}(\.[a-zA-Z\d]{2,3}){1,3}$/,  //邮箱
			REG_PHONE = /^(\+?86)?1(3|[5-9])\d{9}$/, //手机号
			REG_IDENTITY = /^(1[1-5]|2[1-3]|3[1-7]|4[1-6]|5[0-4]|6[1-5]|71|8[1-2])\d{4}((19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[1-2]\d|3[0-1]))\d{3}(\d|x|X)$/,   //身份证号
			REG_THOU = /^-?(\d+,{1})+\d+(\.\d+)?$/;     //数字千分位分隔

		Utils.prototype.getRegEmptyStr = function () {
			return REG_EMPTY_STR;
		};
		Utils.prototype.getRegNum = function () {
			return REG_NUM;
		};
		Utils.prototype.getRegZip = function () {
			return REG_ZIP;
		};
		Utils.prototype.getRegEmail = function () {
			return REG_EMAIL;
		};
		Utils.prototype.getRegPhone = function () {
			return REG_PHONE;
		};
		Utils.prototype.getRegIdentity = function () {
			return REG_IDENTITY;
		};
		Utils.prototype.getRegThou = function () {
			return REG_THOU;
		};

		/**
		 * 添加前缀。例:preAdd('0', 6, '*');    //结果:'*****0'
		 * @param n {@link Object}:被操作的本体;
		 * @param len {@link Number}:总长度;
		 * @param preStr {@link String}:(选参)被添加的前缀字符,默认“0”;
		 * @returns {@link String}:处理后的字符。
		 */
		Utils.prototype.preAdd = function (n, len, preStr) {
			if (!(n = String(n)) || (len = Number(len) - n.length) < 1)
				return n;
			preStr = preStr || '0';
			var pres = Array(++len).join(preStr);
			return pres + n;
		};

		/**
		 * 数字千分位分隔
		 * @param num {@link Number}:被处理的数值;
		 * @param bit {@link Number}:分隔位数,默认为3;
		 * @returns {@link String}:数字千分位字符。
		 */
		Utils.prototype.numToThou = function (num) {
			if (num === 0)
				return '0';

			var bit = arguments[1] || 3;
			var numStr = $.trim(String(num || ''));
			if (numStr && !isNaN(numStr)) {
				num = Number(numStr);	//防止"0001.00"
				var numSplit = numStr.split('.');
				var numInt = numSplit[0];
				numSplit[0] = String(Math.abs(numInt));
				var numArray = [];
				for (var i = numSplit[0].length; i > 0; i -= bit) {
					if (i >= bit) {
						var idx = i - bit;
						var sz = bit;
					} else {
						var idx = 0;
						var sz = i;
					}
					numArray.unshift(numSplit[0].substr(idx, sz));
				}
				return (num < 0 ? '-' : '') + numArray.join() + (!numSplit[1] ? '' : ('.' + numSplit[1]));
			}
			//return '0';
			return numStr;
		};
		/**
		 * 千分位转数字
		 * @param num {@link String}:被处理的千分位数值;
		 * @returns {@link String}:数字字符。
		 */
		Utils.prototype.thouToNum = function thouToNum(num) {
			if (num === 0)
				return '0';

			var numStr = $.trim(String(num || ''));
			if (REG_THOU.test(numStr))	//将“千分位”分隔字符处理为数字字符
				return numStr.replace(/,/g, '');
			return numStr;
		};
		/**
		 * 数字超出位数截断
		 * @param dom {@link Object}:被操作的DOM对象;
		 * @param ureLen {@link Number}:截取后,要保留的位数;
		 * @param minNum {@link Number}:输入的最小数值;
		 */
		Utils.prototype.numCut = function (dom, ureLen, minNum) {
			var kc = event.keyCode;
			if ((kc > 36 && kc < 41) || (kc > 110 && kc < 124))	//无效键码
				return;
			var ts = $(dom);
			try {
				var tsVal = ts.val();
				if (tsVal) {
					var reg = new RegExp('[^\\d\\.-]', 'g');
					if (reg.test(tsVal)) {
						tsVal = tsVal.replace(reg, '');
						ts.val(tsVal);
					}
					if (!isNaN(tsVal)) {
						var numval = Number(tsVal);
						minNum = Number(minNum) || 0;
						if (numval < minNum) {
							alert('输入的数值,请不要小于' + minNum);
							ts.val(minNum).next().val(minNum);
							return;
						}
						var maxNum = Math.pow(10, 19);
						if (Math.abs(numval) > maxNum) {
							alert('输入的数值 ' + tsVal + ' 过大!\n\r请不要超过 ' + maxNum + ',确认后再重新输入!');
							ts.val(maxNum).next().val(maxNum);
							return;
						}
						if (numval % 1 > 0 || tsVal.indexOf('.') != -1) {
							ureLen = parseInt(ureLen) || 2;
							var vsp = tsVal.split('.');
							if (vsp[1] && vsp[1].length > ureLen) {
//						        ts.val(numval.toFixed(ureLen));
								ts.val(Number(vsp[0] + '.' + vsp[1].substr(0, ureLen)));
							}
						}
					} else {
						var fltVal = parseFloat(tsVal + '0');	//末尾添加"0"后转化,防止首先输入"-"、"."等非数字字符。
						if (isNaN(fltVal))
							ts.val('');
						else if (fltVal != 0)
							ts.val(fltVal);
					}
				}
			} catch (e) {
				//
			}
		};

		/**
		 * 清空区域内容
		 * @param me {@link Object}:区域DOM对象;
		 * @param sel {@link String}:被清空元素的jQuery选择器;
		 * @returns {@link Number}:被清空元素数。
		 */
		Utils.prototype.cleanup = function (me, sel) {
			var num = 0;
			var sv = (me = $(me)).attr('cleanup') || me;
			var doms = $(sv).find(sel ? sel : '[name], input, select, textarea');
			doms.each(function (i) {
				var dom = $(this);
				if (dom.is('input')) {  //<input />
					var domType = dom.attr('type');
					if (domType == 'checkbox' || domType == 'radio')
						dom.prop('checked', false);
					else
						dom.val('');
				} else if (dom.is('select')) {  //<select></select>
					dom.find('option:selected').attr('selected', false);
				} else {
					dom.val('');
				}
				num++;
			});
			return num;
		};
		/**
		 * 提交验证
		 * @param obj {@link Object}:
		 * @param obj.sel {@link Object}:jQuery选择器,被验证的DOM范围;
		 * @param obj.hintPosi {@link Object}:jQuery选择器,提示位置;
		 * @param obj.hintDom {@link Object}:jQuery选择器,提示DOM体;
		 * @param obj.hintText {@link Object}:jQuery选择器,提示文本位置;
		 * @returns {@link Boolean}:是否验证通过:true - 通过。
		 */
		Utils.prototype.inputValidate = function (obj) {
			var result = true;
			if (Object.prototype.toString.call(obj) != '[object Object]' || !obj.sel)
				obj = {
					sel: obj
				};
			var valis = $(!obj.sel ? 'body' : obj.sel).find('[validate]');
			try {
				var run = function (valis, index, obj) {
					var cont = [];
					var me = valis.eq(index);
					var meVal = me.val();
					var vds = me.attr('validate').split(';');
					for (var i = 0; i < vds.length && $.trim(vds[i]); i++) {
						var vd = vds[i].toLowerCase();
						if (vd == 'notnull') {
							if (!$.trim(meVal))
								cont.push('不能为空');
						} else if (REG_PKG_B_TO_E.test(vd)) {
							if (!meVal)
								continue;
							var b2e = vd.split(/to/i);
							var b = Number(isNaN(b2e[0]) ? 0 : b2e[0]);
							var e = Number(isNaN(b2e[1]) ? 0 : b2e[1]);
							if ((meVal.length - b) * (meVal.length - e) > 0)
								cont.push(['字符数在', b, '-', e, '之间'].join(' '));
						} else if (vd == 'void') {
							if (REG_EMPTY_STR.test(meVal))
								cont.push('不能含空格等无效字符');
						} else if (REG_PKG_I_NUM_X.test(vd)) {
							if (!meVal)
								continue;
							if (!REG_NUM.test(meVal)) {
								cont.push('只能是数字');
								continue;
							}
							var i2x = vd.split(/num/i);
							if (i2x[0]) {
								var min = Number(isNaN(i2x[0]) ? 0 : i2x[0]);
								if (meVal < min)
									cont.push('最小值(' + min + ')');
							}
							if (i2x[1]) {
								var max = Number(isNaN(i2x[1]) ? 0 : i2x[1]);
								if (meVal > max)
									cont.push('最大值(' + max + ')');
							}
						} else if (vd == 'email') {
							if (!meVal)
								continue;
							if (!REG_EMAIL.test(meVal))
								cont.push('邮箱格式错误');
						} else if (vd == 'phone') {
							if (!meVal)
								continue;
							if (!REG_PHONE.test(meVal))
								cont.push('电话号格式错误');
						} else if (vd == 'zip') {
							if (!meVal)
								continue;
							if (!REG_ZIP.test(meVal))
								cont.push('邮编格式错误');
						} else {
							var isReg = false;
							try {
								isReg = new RegExp(vds[i]).test(meVal);
							} catch (e) {
								isReg = false;
							}
							if (!isReg)
								cont.push('不符合规则(' + vds[i] + ')');
						}
					}
					var hp = ((!obj.hintPosi) ? me.constructor : obj.hintPosi)(me);
					if (!cont.length) {
						hp.nextAll('[vhi="' + index + '"]').remove();
					} else {
						result = false;
						var labSpan = hp.nextAll('[vhi="' + index + '"]');
						if (!labSpan.length) {
							labSpan = $(obj.hintDom || '<span>');
							labSpan.addClass('hint').attr('vhi', index);
							labSpan.css(obj.hintCss || {});
							hp.after(labSpan);
						}
						(!obj.hintText ? labSpan : labSpan.find(obj.hintText)).text(cont.join(';'));
					}
				};
				for (var i = 0; i < valis.length; i++)
					run(valis, i, obj);
			} catch (e) {
				result = false;
				(!console ? window.console : console).error(e);
			}
			return result;
		};
		/**
		 * 设置DOM区域name值
		 * @param dom {@link Object}:jQuery选择器:DOM区域对象;
		 * @param obj {@link Object}:name属性对应的实体;
		 * @returns {@link Number}:已设置的元素数。
		 */
		Utils.prototype.setVal = function(dom, obj) {
			if (!obj || Object.prototype.toString.call(obj) != '[object Object]')	//强制"obj"为Object类型
				return -1;

			var num = 0;
			for (var k in obj) {	//效验obj是否含有效值
				if (obj[k] != null) {
					num++;	//num = 1;
					break;
				}
			}
			if (!num--)		//obj内部属性全部无效(num--:先赋值后运算,还原初始值为0)
				return -1;

			var ns = $(dom || 'body').find('[name]');
			var set = function (ns, i, obj) {
				var dom = ns.eq(i);
				var name = dom.attr('name');
				var v = obj[name];
				if (v == null)	//不过滤:Number: 0, Boolean: false, Array等
					return false;
				num++;
				if (dom.is('input')) {  //<input />
					var domType = dom.attr('type');
					if (domType == 'radio') {				//单选
						dom.prop('checked', dom.val() == String(v));
						return true;
					} else if (domType == 'checkbox') {		//多选
						var dv = dom.val();
						if (dv == String(v)) {				//防止Boolean类型判断错误
							dom.prop('checked', true);
						} else if (v instanceof Object) {	//是可遍历对象:Array或Object
							for (var k in v) {
								if (dv == String(v[k])) {
									dom.prop('checked', true);
									break;
								}
							}
						} else {
							dom.prop('checked', false);
						}
						return true;
					} else if (domType == 'file') {	//input file不可修改值
						num--;
						return false;
					}
				}
				dom.val(v);
				return true;
			};
			for (var i = 0, len = ns.length; i < len; i++)
				set(ns, i, obj);
			return num;
		};
		/**
		 * 序列化DOM区域name对象
		 * @param dom {@link Object}:jQuery选择器:DOM区域对象;
		 * @param obj {@link Object}:
		 * @param obj.trim {@link Boolean}:是否过滤前后导空白,默认:true;
		 * @param obj.blank {@link Boolean}:是否允许无效字符,默认:false;
		 * @param obj.empty {@link Boolean}:是否允许空字符,默认:false;
		 */
		Utils.prototype.serial = function (dom, obj) {
			var kv = {};
			var ns = $(dom || 'body').find('[name]');
			var seri = function (ns, i, obj) {
				var dom = ns.eq(i);
				if (dom.is('input')) {  //<input />
					var domType = dom.attr('type');
					if ((domType == 'checkbox' || domType == 'radio') && !dom.is(':checked'))   //跳过未选中
						return false;
				}
				var v = dom.val();
				v = !obj.trim ? $.trim(v) : v;  //是否过滤前后导空白
				if (
					(!obj.blank && (!v || !$.trim(v)))  //是否允许无效字符
					|| (!obj.empty && !v)               //是否允许空字符
				)
					return false;

				var k = dom.attr('name');
				if (domType == 'checkbox')  //checkbox单独处理(domType无作用域)
					(!kv[k] ? (kv[k] = []) : kv[k]).push(v);
				else
					kv[k] = v;
				return true;
			};
			if (!obj)
				obj = {};
			for (var i = 0, len = ns.length; i < len; i++)
				seri(ns, i, obj);
			return kv;
		};
	})();
}

DOM操作的部分常用功能,其它未涉及到的将逐渐补充、更新。
有其它更好功能的童鞋们,欢迎在此评论区分享成果。


测试示例:

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
		<meta name="viewport" content="width=device-width, initial-scale=1">
		<meta http-equiv="X-UA-Compatible" content="IE=edge">
		<title>Utils test</title>
		<script src="https://code.jquery.com/jquery-3.3.1.min.js" type="application/javascript"></script>
		<script src="./Utils.js" type="application/javascript"></script>
	</head>
	<body>
		<div k="cont">
			<div id="cont1">
				<label>ID:</label>
				<input name="id" validate="notNull;0num" /><!-- [validate]验证:非空、数字(最小值为0) -->
				<br/>
				<label>课程:</label>
				<input id="rd1" name="lesson" type="radio" value="app" />
				<label for="rd1">前端</label>
				<input id="rd2" name="lesson" type="radio" value="service" />
				<label for="rd2">后端</label>
				<br/>
				<label>书籍:</label>
				<input id="bok1" name="books" type="checkbox" value="JS" />
				<label for="bok1">JS</label>
				<input id="bok2" name="books" type="checkbox" value="JAVA" />
				<label for="bok2">JAVA</label>
				<br/>
				<label>价格:</label>
				<input name="money" validate="notNull;0num9.9"></input>
				<br/>
				<label>备注:</label>
				<textarea name="remark" validate="2to10"></textarea><!-- [validate]验证:字符数在2 - 10之间 -->
				<br/>
				<button class="cleanup" cleanup="[k='cont'] #cont1">清空</button>
				<button class="validate">验证</button>
				<br/>
				<button class="setv">赋值</button>
				<i id="setv"></i>
				<br/>
				<button class="serial">序列化DOM</button>
				<span id="serial"></span>
			</div>
			<hr/>
			<div id="cont2">
				<label>小功能:</label>
				<input name="text" value="1234567.8901" validate="notNull;^-?\d+$" />
				<button class="pre-add">添加前缀</button>
				<button class="num-thou">数字 > 千分位</button>
				<button class="thou-num">千分位 > 数字</button>
				<button class="num-cut">截断2位</button>
				<button class="validate">验证</button>
				<button class="cleanup" cleanup="#cont2">清空</button>
			</div>
		</div>
	</body>
</html>

<script type="text/javascript">
	var utils = new Utils();
	$(function () {
		/* 清空 */
		$('.cleanup').click(function (e) {
			utils.cleanup(this);
		});
		/* 验证(暂不支持"radio"和"checkbox") */
		$('#cont1 .validate').click(function (e) {
			utils.inputValidate('#cont1') && alert('验证通过');
		});
		$('#cont2 .validate').click(function (e) {
			var r = utils.inputValidate({
				sel: '#cont2',
				hintDom: '<p style="color: red"><b>',   //使用<p>标签提示
				hintText: 'b',  //提示内容显示到:"hintDom"创建的<p>标签下的<b>标签内,
				hintPosi: function (me) {
					return me.parent();
				}
			});
			r && alert('验证通过');
		});
		/* 赋值 */
		var setv = {
			id: -1,
			lesson: 'service',
			books: [ 'JS', 'JAVA' ],
			money: 90.1,
			remark: '使用 utils.SetVal 区域赋值'
		};
		$('#setv').text(JSON.stringify(setv));
		$('.setv').click(function (e) {
			utils.setVal('[k="cont"]', setv);
		});
		/* 序列化DOM */
		$('.serial').click(function (e) {
			var r = utils.serial('#cont1', {
				trim: false //不过滤前后导空白
			});
			$('#serial').text(JSON.stringify(r));
		});
		/* 添加前缀 */
		$('.pre-add').click(function (e) {
			var ipt = $('[name="text"]');
			var r = utils.preAdd(ipt.val(), 15);
			ipt.val(r);
		});
		/* 数字 > 千分位 */
		$('.num-thou').click(function (e) {
			var ipt = $('[name="text"]');
			var r = utils.numToThou(ipt.val());
			ipt.val(r);
		});
		/* 千分位 > 数字 */
		$('.thou-num').click(function (e) {
			var ipt = $('[name="text"]');
			var r = utils.thouToNum(ipt.val());
			ipt.val(r);
		});
		/* 截断2位 */
		$('.num-cut').click(function (e) {
			var ipt = $('[name="text"]');
			utils.numCut(ipt, 2);
		});
	});
</script>
<style type="text/css">
	/* 错误提示 */
	.hint {
		color: red;
		font-size: 12px;
	}
</style>

使用过程中,如出现bug,或有其它优化建议,欢迎在此文章“评论区”留言讨论,并留下您的邮箱,以便改正后及时通知您。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值