Angular 输入框实现自定义验证功能


Posted in Javascript onFebruary 19, 2017

此插件使用angular.js、JQuery实现。(jQuery的引入需在angular 之前)

用户可以 在输入框输入数据后验证 必填项、整数型、浮点型验证。

如果在form 里面的输入框验证,可以点击 提交按钮后,实现 必填项验证。

效果图如下:

Angular 输入框实现自定义验证功能

(1)验证未通过时,背景标红等样式为

input.ng-invalid, select.ng-invalid {
   background-color: #ee82ee !important;
   border: 1px solid #CCC;
  }
  .qtip {
   position: absolute;
   max-width: 260px;
   display: none;
   min-width: 50px;
   font-size: 10.5px;
   line-height: 12px;
   direction: ltr;
  }
  .qtip-content {
   position: relative;
   padding: 5px 9px;
   overflow: hidden;
   text-align: left;
   word-wrap: break-word;
  }
  .qtip-rounded, .qtip-tipsy {
   -moz-border-radius: 5px;
   -webkit-border-radius: 5px;
   border-radius: 5px;
  }
  .qtipmodal-ie6fix {
   position: absolute !important;
  }
  .box-shadow-tips {
   background-color: #F63;
   border-color: #F5A88F;
   color: white;
   -moz-box-shadow: 2px 2px 2px #969696;
   -webkit-box-shaow: 2px 2px 2px #969696;
   box-shadow: 2px 2px 2px #969696;
  }

因为angular.js 内置验证未通过时,会自动为 标签 增加 .ng-invalid 样式,因为这里重写此样式

 input.ng-invalid, select.ng-invalid {
 background-color: #ee82ee !important;
 
border: 1px solid #CCC;

} 

  (2)HTML 代码如下

<body ng-app="myApp">
<form name="baseInfoForm">
 <div ng-controller="testCtrl">
  <input type="text" ng-model="age" my-valid="r"><br>
  <input type="text" ng-model="name" my-valid="int fn:certCheck"><br>
  <input type="button" value="提交" ng-click="submit()">
 </div>
</form>
</body>

(3)此插件使用 directive myValid 实现

app.directive('myValid', ['$parse', 'uiTipsFactory', 'uiValidFactory', function ($parse, tips, valid) {
  var uiValidAttrIdName = 'ui-valid-id';
  return {
   restrict: 'A',
   require: 'ngModel',
   link: function (scope, el, attrs, ctrl) {
    var validId = el.attr(uiValidAttrIdName);
    if (!validId) {
     validId = Math.guid();
     el.attr(uiValidAttrIdName, validId);
    }
    var getRules = function () {
     return attrs.myValid;
    };
    var lastOldRules;
    var validFn = function (value, oldRules) {
     var sp = '_';
     var rules = getRules();
     var r = valid.check(value, rules, scope, attrs.uiValidTips);
     if (lastOldRules && !oldRules) {
      oldRules = lastOldRules;
     }
     if (r.flag && oldRules) {
      rules = rules ? rules + ' ' + oldRules : oldRules;
     }
     if (rules) {
      var arrInner = rules.split(' ');
      var i = 0;
      for (; i < arrInner.length; i++) {
       var oneRule = arrInner[i];
       if (!oneRule.trim()) {
        continue;
       }
       ctrl.$setValidity(attrs.ngModel + sp + oneRule, r.flag ? true : oneRule != r.rule);
      }
     }
     if (!r.flag) {
      tips.on(el, r.msg);
     } else {
      tips.off(el);
     }
     return r.flag;
    };
    var init = function () {
     var rules = getRules();
     if (!rules) {
      return;
     }
     var parsers = ctrl.$parsers;
     if (parsers && parsers.length > 0) {
      parsers.clean();
     }
     parsers.unshift(function (value) {
      return validFn(value) ? value : undefined;
     });
    };
    scope.$watch(attrs.ngModel, function (newVal, oldVal) {
     if (newVal === oldVal) {
      return;
     }
     if (ctrl.$modelValue != undefined && (ctrl.$invalid || el.hasClass('ng-invalid'))) {
      validFn(ctrl.$modelValue);
     }
    });
    scope.$watch(getRules, function (newRules, oldRules) {
     init();
     lastOldRules = oldRules;
     if (ctrl.$modelValue === undefined || ctrl.$modelValue === null) {
      var needValid = false;
      el.hasClass('ng-invalid');
      var isValNaN = ctrl.$viewValue !== ctrl.$viewValue;
      if (ctrl.$invalid || (ctrl.$viewValue !== undefined && !isValNaN)) {
       needValid = true;
      }
      if (needValid) {
       ctrl.$setViewValue(ctrl.$viewValue);
      }
     } else {
      if (!ctrl.$dirty && attrs.dirtyCheck) {
       console.log('----');
      } else {
       validFn(ctrl.$modelValue, oldRules);
      }
     }
    });
   }
  }
 }]);

通过 监听 attrs.ngModel,验证规则 rules ,ctrl.$parser 来实现 输入框内容改变的响应。

一旦使用此directive,则动态为当前输入框添加ID,以便在 验证通过后,改变输入框的验证背景信息。 

(4)验证逻辑处理 uiValidFactory

app.factory('uiValidFactory', ['$parse', 'uiTipsFactory', function ($parse, tips) {
  return {
   check: function (val, rules, $scope, defaultTips, extendParam) {
    if (!rules) {
     return {
      flag: true
     };
    }
    var rulesArr = rules.split(' '),
      isBlank = val === null || val === undefined || val === '' || ('' + val === '');
    //如果不是必填项 且没有输入值 则清除提示框
    if ($.inArray('r', rulesArr) === -1 && isBlank) {
     return {
      flag: true
     }
    }
    var i = 0, len = rulesArr.length;
    for (; i < len; i++) {
     var rule = rulesArr[i];
     if (!rule) {
      continue;
     }
     var flag = true;
     if ('r' === rule) {
      //如果是必填项,有值 返回true
      flag = !isBlank;
     } else if (rule.contains(':')) {
      //如果校验规则是 fn:ctrl.certCheck
      flag = this.checkRule(val, rule.split(/:/), $scope, extendParam);
     } else {
      //校验 规则是 int 用正则匹配 数字 邮箱 长度
      var pat = this.pats[rule];
      if (pat instanceof RegExp) {
       if (angular.isString(val)) {
        flag = this.mat(val, pat);
       }
      } else if (angular.isFunction(pat)) {
       flag = pat(val);
      } else {
       flag = false;
      }
     }
     //这是干什么的呢
     if (angular.isString(flag)) {
      return {
       flag: false,
       msg: flag,
       rule: rule
      }
     }
     if (flag === false) {
      var msg = this.getMsg(rule, defaultTips) || this.getMsg('tips.valid');
      console.log(msg);
      return {
       flag: false,
       msg: msg,
       rule: rule
      }
     }
    }
    return {
     flag: true
    }
   },
   checkRule: function (val, ruleArr, $scope, extendParam) {
    //ruleArr fn:certCheck
    var rule = ruleArr[0];
    if (rule === 'fn') {
     fnName = ruleArr[1];//指定被调函数的名字 certCheck
     var fn = $parse(fnName)($scope);
     if (!fn) {
      return true;
     }
     return fn.call($scope, val, extendParam);
    } else {
     return true;
    }
   },
   checkValidForm: function (formName) {
    //只检查必填项
    //使用属性筛选器 获得里面所有的元素
    var formContext = $('form[name="{0}"],[ng-form="{0}"],[data-ng-form="{0}"]'.format(formName)),
      validList = formContext.find('[my-valid]');//validList 不是数组,是伪数组
    if (!validList.length) {
     return;
    }
    var that = this,
      validFlags = [];
    validList.each(function () {
       var ele = $(this),
         val = ele.val(),
         ruleStr = ele.attr('my-valid');
       if (!ruleStr) {
        return true;
       }
       if (angular.isString(val)) {
        val = val.trim();
       }
       var validRules = ruleStr.split(' ');
       if ($.inArray('r', validRules) != -1 && !val) {
        var modelValue = ele.attr('ng-model') || ele.attr('data-ng-model');
        validFlags.push(modelValue);
        tips.on(ele, that.getMsg('r'));
       }
      }
    );
    return validFlags;
   },
   mat: function (val, pat) {
    if (!pat) {
     return;
    }
    return pat.test(val);
   }
   ,
   getMsg: function (rule, tips) {
    tips = tips || '';
    //可以在界面上直接写 tips
    if (tips && tips.contains(':')) {
     return tips;
    }
    var msg = this.msgs[rule];
    if (msg) {
     var params0 = tips.contains(':') ? tips.split(/:/)[0] : '';
     var params1 = '';
     if (rule.startsWith('min') || rule.startsWith('max')) {
      var ruleArr = rule.split(/:/);
      params1 = ruleArr[ruleArr.length - 1];
     }
     return msg.format(params0, params1);
    } else {
    }
   }
   ,
   regPat: function (code, pat, msg) {
    if (this.pat[code]) {
     return;
    }
    this.pats[code] = pat;
    this.msgs[code] = msg;
   }
   ,
   msgs: {
    'r': '必填',
    'int': '{0}必须为整数'
   }
   ,
   pats: {
    'int': /^[\-\+]?([0-9]+)$/
   }
  }
 }
 ])
 ;

       通过获取输入框 ele.myValid  验证规则,

1、如果是必填,则返回 标红此输入框,鼠标移上,则显示 验证信息 “必填””。

2、如果是整数、浮点型等验证,则通过 正则表达式进行验证。

      3、如果是最大(max)、最小(min),则自定义逻辑。

4、如果是 fn 验证,则根据 对应controller中函数进行验证。

5、用户点击提交按钮,则 判断是否必填项,验证不通过,对应元素背景标红。

(5) 验证不通过,提示Factory---uiTipsFactory

app.factory('uiTipsFactory', function () {
  return {
   filterClass: function (ele, invalid) {
    if (invalid) {
     //如果验证不通过
     ele.removeClass('ng-valid').removeClass('ng-pristine').addClass('ng-invalid').addClass('ng-dirty');
    } else {
     ele.removeClass('ng-invalid').addClass('ng-valid');
    }
   },
   on: function (ele, msg) {
    var lastTip = ele.data('last-tip');
    if (lastTip && lastTip === msg) {
     return;
    }
    ele.data('last-tip', msg);
    this.filterClass(ele, true);
    var offset = ele.offset();
    if (!offset.top && !offset.left && ele.is('hidden')) {
     offset = ele.show().offset();
    }
    var id = ele.attr('ui-valid-id');
    if (!id) {
     id = Math.guid();
     ele.attr('ui-valid-id', id);
    }
    if (id.contains('.')) {
     id = id.replace(/\./g, '_');
    }
    var top = offset.top,
      left = offset.left;
    var getTips = function () {
     var _tip = $('#vtip_' + id);
     if (_tip.length) {
      _tip.html(msg).css({
       'display': 'none',
       'top': top + 'px',
       'left': left + ele.width() + 10 + 'px'
      });
     } else {
      var html = '<div id="vtip_' + id + '" class="vtip qtip qtip-rounded box-shadow-tips">' +
        '<div class="qtip-content">' + msg + '</div>';
      $(html).css({
       'display': 'none',
       'position': 'absolute',
       'top': top + 'px',
       'left': left + ele.width() + 10 + 'px'
      }).appendTo($('body'));
     }
    };
    var bindTipsShow = function () {
     getTips();
     ele.unbind('mouseenter mouseleave').bind('mouseenter', function () {
      var _tip = $('#vtip_' + id);
      if (_tip.is(':hidden')) {
       _tip.show();
      }
     }).bind('mouseleave', function () {
      $('#vtip_' + id).hide();
     });
    };
    bindTipsShow();
   },
   off: function (ele) {
    ele.data('last-tip', '');
    this.filterClass(ele);
    var id = ele.attr('ui-valid-id');
    if (!id) {
     return;
    }
    if (id.contains('.')) {
     id = id.replace(/\./g, '_');
    }
    $('#vtip_' + id).remove();
    ele.unbind('mouseenter mouseleave');
   }
  }
 });

1、验证不通过,增加背景色,元素css处理如下

ele.removeClass('ng-valid').removeClass('ng-pristine').addClass('ng-invalid').addClass('ng-dirty');

验证通过,CSS处理如下

 ele.removeClass('ng-invalid').addClass('ng-valid');

 

2、背景提示语,则是在body上增加一个div层。

(6)其他相关代码

var app = angular.module('myApp', []);
 app.controller('testCtrl', ['$scope', 'uiValidFactory', function ($scope, uiValidFactory) {
    $scope.certCheck = function (val) {
     if (val > 32) {
      return "数字太大了";
     }
     return true;
    };
    $scope.submit = function () {
     if (!uiValidFactory.checkValidForm($scope.baseInfoForm.$name)) {
     }
    };
   }]
 );
 Math.guid = function () {
  var a = "", b = 1;
  for (; b <= 32; b++) {
   var c = Math.floor(Math.random() * 16).toString(16);
   a += c;
   if (b === 8 || b === 12 || b === 16 || b === 20) {
    a += '-';
   }
  }
  return a;
 };
 String.prototype.contains = String.prototype.contains || function (a) {
  return this.indexOf(a) != -1;
 };
 String.prototype.format = String.prototype.format || function () {
  var a = Array.prototype.slice.call(arguments);
  return this.replace(/\{(\d+)}/g, function (c, b) {
   return a[b];
  })
 };

 整个代码如下:

<!DOCTYPE html>
<html>
<head lang="en">
 <meta charset="UTF-8">
 <title></title>
 <script src="jquery-1.11.1.js"></script>
 <script src="angular.js"></script>
 <style type="text/css">
  input.ng-invalid, select.ng-invalid {
   background-color: #ee82ee !important;
   border: 1px solid #CCC;
  }
  .qtip {
   position: absolute;
   max-width: 260px;
   display: none;
   min-width: 50px;
   font-size: 10.5px;
   line-height: 12px;
   direction: ltr;
  }
  .qtip-content {
   position: relative;
   padding: 5px 9px;
   overflow: hidden;
   text-align: left;
   word-wrap: break-word;
  }
  .qtip-rounded, .qtip-tipsy {
   -moz-border-radius: 5px;
   -webkit-border-radius: 5px;
   border-radius: 5px;
  }
  .qtipmodal-ie6fix {
   position: absolute !important;
  }
  .box-shadow-tips {
   background-color: #F63;
   border-color: #F5A88F;
   color: white;
   -moz-box-shadow: 2px 2px 2px #969696;
   -webkit-box-shaow: 2px 2px 2px #969696;
   box-shadow: 2px 2px 2px #969696;
  }
 </style>
</head>
<body ng-app="myApp">
<form name="baseInfoForm">
 <div ng-controller="testCtrl">
  <input type="text" ng-model="age" my-valid="r"><br>
  <input type="text" ng-model="name" my-valid="int fn:certCheck"><br>
  <input type="button" value="提交" ng-click="submit()">
 </div>
</form>
</body>
<script type="text/javascript">
 var app = angular.module('myApp', []);
 app.controller('testCtrl', ['$scope', 'uiValidFactory', function ($scope, uiValidFactory) {
    $scope.certCheck = function (val) {
     if (val > 32) {
      return "数字太大了";
     }
     return true;
    };
    $scope.submit = function () {
     if (!uiValidFactory.checkValidForm($scope.baseInfoForm.$name)) {
     }
    };
   }]
 );
 Math.guid = function () {
  var a = "", b = 1;
  for (; b <= 32; b++) {
   var c = Math.floor(Math.random() * 16).toString(16);
   a += c;
   if (b === 8 || b === 12 || b === 16 || b === 20) {
    a += '-';
   }
  }
  return a;
 };
 String.prototype.contains = String.prototype.contains || function (a) {
  return this.indexOf(a) != -1;
 };
 String.prototype.format = String.prototype.format || function () {
  var a = Array.prototype.slice.call(arguments);
  return this.replace(/\{(\d+)}/g, function (c, b) {
   return a[b];
  })
 };
 app.factory('uiTipsFactory', function () {
  return {
   filterClass: function (ele, invalid) {
    if (invalid) {
     //如果验证不通过
     ele.removeClass('ng-valid').removeClass('ng-pristine').addClass('ng-invalid').addClass('ng-dirty');
    } else {
     ele.removeClass('ng-invalid').addClass('ng-valid');
    }
   },
   on: function (ele, msg) {
    var lastTip = ele.data('last-tip');
    if (lastTip && lastTip === msg) {
     return;
    }
    ele.data('last-tip', msg);
    this.filterClass(ele, true);
    var offset = ele.offset();
    if (!offset.top && !offset.left && ele.is('hidden')) {
     offset = ele.show().offset();
    }
    var id = ele.attr('ui-valid-id');
    if (!id) {
     id = Math.guid();
     ele.attr('ui-valid-id', id);
    }
    if (id.contains('.')) {
     id = id.replace(/\./g, '_');
    }
    var top = offset.top,
      left = offset.left;
    var getTips = function () {
     var _tip = $('#vtip_' + id);
     if (_tip.length) {
      _tip.html(msg).css({
       'display': 'none',
       'top': top + 'px',
       'left': left + ele.width() + 10 + 'px'
      });
     } else {
      var html = '<div id="vtip_' + id + '" class="vtip qtip qtip-rounded box-shadow-tips">' +
        '<div class="qtip-content">' + msg + '</div>';
      $(html).css({
       'display': 'none',
       'position': 'absolute',
       'top': top + 'px',
       'left': left + ele.width() + 10 + 'px'
      }).appendTo($('body'));
     }
    };
    var bindTipsShow = function () {
     getTips();
     ele.unbind('mouseenter mouseleave').bind('mouseenter', function () {
      var _tip = $('#vtip_' + id);
      if (_tip.is(':hidden')) {
       _tip.show();
      }
     }).bind('mouseleave', function () {
      $('#vtip_' + id).hide();
     });
    };
    bindTipsShow();
   },
   off: function (ele) {
    ele.data('last-tip', '');
    this.filterClass(ele);
    var id = ele.attr('ui-valid-id');
    if (!id) {
     return;
    }
    if (id.contains('.')) {
     id = id.replace(/\./g, '_');
    }
    $('#vtip_' + id).remove();
    ele.unbind('mouseenter mouseleave');
   }
  }
 });
 app.factory('uiValidFactory', ['$parse', 'uiTipsFactory', function ($parse, tips) {
  return {
   check: function (val, rules, $scope, defaultTips, extendParam) {
    if (!rules) {
     return {
      flag: true
     };
    }
    var rulesArr = rules.split(' '),
      isBlank = val === null || val === undefined || val === '' || ('' + val === '');
    //如果不是必填项 且没有输入值 则清除提示框
    if ($.inArray('r', rulesArr) === -1 && isBlank) {
     return {
      flag: true
     }
    }
    var i = 0, len = rulesArr.length;
    for (; i < len; i++) {
     var rule = rulesArr[i];
     if (!rule) {
      continue;
     }
     var flag = true;
     if ('r' === rule) {
      //如果是必填项,有值 返回true
      flag = !isBlank;
     } else if (rule.contains(':')) {
      //如果校验规则是 fn:ctrl.certCheck
      flag = this.checkRule(val, rule.split(/:/), $scope, extendParam);
     } else {
      //校验 规则是 int 用正则匹配 数字 邮箱 长度
      var pat = this.pats[rule];
      if (pat instanceof RegExp) {
       if (angular.isString(val)) {
        flag = this.mat(val, pat);
       }
      } else if (angular.isFunction(pat)) {
       flag = pat(val);
      } else {
       flag = false;
      }
     }
     //这是干什么的呢
     if (angular.isString(flag)) {
      return {
       flag: false,
       msg: flag,
       rule: rule
      }
     }
     if (flag === false) {
      var msg = this.getMsg(rule, defaultTips) || this.getMsg('tips.valid');
      console.log(msg);
      return {
       flag: false,
       msg: msg,
       rule: rule
      }
     }
    }
    return {
     flag: true
    }
   },
   checkRule: function (val, ruleArr, $scope, extendParam) {
    //ruleArr fn:certCheck
    var rule = ruleArr[0];
    if (rule === 'fn') {
     fnName = ruleArr[1];//指定被调函数的名字 certCheck
     var fn = $parse(fnName)($scope);
     if (!fn) {
      return true;
     }
     return fn.call($scope, val, extendParam);
    } else {
     return true;
    }
   },
   checkValidForm: function (formName) {
    //只检查必填项
    //使用属性筛选器 获得里面所有的元素
    var formContext = $('form[name="{0}"],[ng-form="{0}"],[data-ng-form="{0}"]'.format(formName)),
      validList = formContext.find('[my-valid]');//validList 不是数组,是伪数组
    if (!validList.length) {
     return;
    }
    var that = this,
      validFlags = [];
    validList.each(function () {
       var ele = $(this),
         val = ele.val(),
         ruleStr = ele.attr('my-valid');
       if (!ruleStr) {
        return true;
       }
       if (angular.isString(val)) {
        val = val.trim();
       }
       var validRules = ruleStr.split(' ');
       if ($.inArray('r', validRules) != -1 && !val) {
        var modelValue = ele.attr('ng-model') || ele.attr('data-ng-model');
        validFlags.push(modelValue);
        tips.on(ele, that.getMsg('r'));
       }
      }
    );
    return validFlags;
   },
   mat: function (val, pat) {
    if (!pat) {
     return;
    }
    return pat.test(val);
   }
   ,
   getMsg: function (rule, tips) {
    tips = tips || '';
    //可以在界面上直接写 tips
    if (tips && tips.contains(':')) {
     return tips;
    }
    var msg = this.msgs[rule];
    if (msg) {
     var params0 = tips.contains(':') ? tips.split(/:/)[0] : '';
     var params1 = '';
     if (rule.startsWith('min') || rule.startsWith('max')) {
      var ruleArr = rule.split(/:/);
      params1 = ruleArr[ruleArr.length - 1];
     }
     return msg.format(params0, params1);
    } else {
    }
   }
   ,
   regPat: function (code, pat, msg) {
    if (this.pat[code]) {
     return;
    }
    this.pats[code] = pat;
    this.msgs[code] = msg;
   }
   ,
   msgs: {
    'r': '必填',
    'int': '{0}必须为整数'
   }
   ,
   pats: {
    'int': /^[\-\+]?([0-9]+)$/
   }
  }
 }
 ])
 ;
 app.directive('myValid', ['$parse', 'uiTipsFactory', 'uiValidFactory', function ($parse, tips, valid) {
  var uiValidAttrIdName = 'ui-valid-id';
  return {
   restrict: 'A',
   require: 'ngModel',
   link: function (scope, el, attrs, ctrl) {
    var validId = el.attr(uiValidAttrIdName);
    if (!validId) {
     validId = Math.guid();
     el.attr(uiValidAttrIdName, validId);
    }
    var getRules = function () {
     return attrs.myValid;
    };
    var lastOldRules;
    var validFn = function (value, oldRules) {
     var sp = '_';
     var rules = getRules();
     var r = valid.check(value, rules, scope, attrs.uiValidTips);
     if (lastOldRules && !oldRules) {
      oldRules = lastOldRules;
     }
     if (r.flag && oldRules) {
      rules = rules ? rules + ' ' + oldRules : oldRules;
     }
     if (rules) {
      var arrInner = rules.split(' ');
      var i = 0;
      for (; i < arrInner.length; i++) {
       var oneRule = arrInner[i];
       if (!oneRule.trim()) {
        continue;
       }
       ctrl.$setValidity(attrs.ngModel + sp + oneRule, r.flag ? true : oneRule != r.rule);
      }
     }
     if (!r.flag) {
      tips.on(el, r.msg);
     } else {
      tips.off(el);
     }
     return r.flag;
    };
    var init = function () {
     var rules = getRules();
     if (!rules) {
      return;
     }
     var parsers = ctrl.$parsers;
     if (parsers && parsers.length > 0) {
      parsers.clean();
     }
     parsers.unshift(function (value) {
      return validFn(value) ? value : undefined;
     });
    };
    scope.$watch(attrs.ngModel, function (newVal, oldVal) {
     if (newVal === oldVal) {
      return;
     }
     if (ctrl.$modelValue != undefined && (ctrl.$invalid || el.hasClass('ng-invalid'))) {
      validFn(ctrl.$modelValue);
     }
    });
    scope.$watch(getRules, function (newRules, oldRules) {
     init();
     lastOldRules = oldRules;
     if (ctrl.$modelValue === undefined || ctrl.$modelValue === null) {
      var needValid = false;
      el.hasClass('ng-invalid');
      var isValNaN = ctrl.$viewValue !== ctrl.$viewValue;
      if (ctrl.$invalid || (ctrl.$viewValue !== undefined && !isValNaN)) {
       needValid = true;
      }
      if (needValid) {
       ctrl.$setViewValue(ctrl.$viewValue);
      }
     } else {
      if (!ctrl.$dirty && attrs.dirtyCheck) {
       console.log('----');
      } else {
       validFn(ctrl.$modelValue, oldRules);
      }
     }
    });
   }
  }
 }]);
</script>
</html>
Javascript 相关文章推荐
防止网站内容被拷贝的一些方法与优缺点好处与坏处分析
Nov 30 Javascript
15 个 JavaScript Web UI 库
May 19 Javascript
JavaScript Date对象 日期获取函数
Dec 19 Javascript
jQuery学习笔记 更改jQuery对象
Sep 19 Javascript
解析Javascript中中括号“[]”的多义性
Dec 03 Javascript
js function定义函数的几种不错方法
Feb 27 Javascript
红米手机抢购的js代码
Mar 10 Javascript
js脚本实现数据去重
Nov 27 Javascript
Angular.js与node.js项目里用cookie校验账户登录详解
Feb 22 Javascript
js实现鼠标拖拽div左右滑动
Jan 15 Javascript
基于postman获取动态数据过程详解
Sep 08 Javascript
H5 js点击按钮复制文本到粘贴板
Nov 19 Javascript
js实现九宫格的随机颜色跳转
Feb 19 #Javascript
原生JS实现垂直手风琴效果
Feb 19 #Javascript
js鼠标移动时禁止选中文字
Feb 19 #Javascript
canvas雪花效果核心代码分享
Feb 19 #Javascript
Ajax和Comet技术总结
Feb 19 #Javascript
thinkphp标签实现bootsrtap轮播carousel实例代码
Feb 19 #Javascript
Angularjs中的ui-bootstrap的使用教程
Feb 19 #Javascript
You might like
php的一个登录的类 [推荐]
2007/03/16 PHP
PHP imagegrabscreen和imagegrabwindow(截取网站缩略图)的实例代码
2013/11/07 PHP
ThinkPHP连接数据库及主从数据库的设置教程
2014/08/22 PHP
PHP实现多图上传(结合uploadify插件)思路分析
2016/11/30 PHP
php桥接模式应用案例分析
2019/10/23 PHP
基于jquery的滚动鼠标放大缩小图片效果
2011/10/27 Javascript
css transform 3D幻灯片特效实现步骤解读
2013/03/27 Javascript
JavaScript解析URL参数示例代码
2013/08/12 Javascript
JS可以控制样式的名称写法一览
2014/01/16 Javascript
javascript使用switch case实现动态改变超级链接文字及地址
2014/12/16 Javascript
javascript中利用柯里化函数实现bind方法【推荐】
2016/04/29 Javascript
vue组件父与子通信详解(一)
2017/11/07 Javascript
angular4 获取wifi列表中文显示乱码问题的解决
2018/10/20 Javascript
JS中使用react-tooltip插件实现鼠标悬浮显示框
2019/05/15 Javascript
node.js中fs文件系统模块的使用方法实例详解
2020/02/13 Javascript
[03:06]3分钟带你回顾DOTA2完美盛典&完美大师赛
2017/12/06 DOTA
使用python编写android截屏脚本双击运行即可
2014/07/21 Python
对Python的Django框架中的项目进行单元测试的方法
2016/04/11 Python
Python 中urls.py:URL dispatcher(路由配置文件)详解
2017/03/24 Python
Python实现网站注册验证码生成类
2017/06/08 Python
django 快速启动数据库客户端程序的方法示例
2019/08/16 Python
python检测服务器端口代码实例
2019/08/31 Python
TensorFlow2.X使用图片制作简单的数据集训练模型
2020/04/08 Python
python datetime时间格式的相互转换问题
2020/06/11 Python
澳大利亚在线购买儿童玩具:Toy Universe
2017/12/28 全球购物
军人违纪检讨书
2014/02/04 职场文书
哈弗商学院毕业生求职信
2014/02/26 职场文书
国际贸易专业求职信
2014/06/04 职场文书
陈胜吴广起义口号
2014/06/20 职场文书
离婚协议书的书写要求
2014/09/17 职场文书
2015年社区工作总结
2015/04/08 职场文书
2015年信息宣传工作总结
2015/05/26 职场文书
领导欢送会主持词
2015/07/06 职场文书
中秋节主题班会
2015/08/14 职场文书
Nginx访问日志及错误日志参数说明
2021/03/31 Servers
Python基于Opencv识别两张相似图片
2021/04/25 Python