- 1 2 3 4 5 6 7 8 9 10 input.ng - invalid,
- select.ng - invalid {
- 11 background - color: #ee82ee ! important;
- 12 border: 1px solid#CCC;
- 13
- }
- 14 15.qtip {
- 16 position: absolute;
- 17 max - width: 260px;
- 18 display: none;
- 19 min - width: 50px;
- 20 font - size: 10.5px;
- 21 line - height: 12px;
- 22 direction: ltr;
- 23
- }
- 24 25.qtip - content {
- 26 position: relative;
- 27 padding: 5px 9px;
- 28 overflow: hidden;
- 29 text - align: left;
- 30 word - wrap: break - word;
- 31
- }
- 32 33.qtip - rounded,
- .qtip - tipsy {
- 34 - moz - border - radius: 5px;
- 35 - webkit - border - radius: 5px;
- 36 border - radius: 5px;
- 37
- }
- 38 39.qtipmodal - ie6fix {
- 40 position: absolute ! important;
- 41
- }
- 42 43.box - shadow - tips {
- 44 background - color: #F63;
- 45 border - color: #F5A88F;
- 46 color: white;
- 47 - moz - box - shadow: 2px 2px 2px#969696;
- 48 - webkit - box - shaow: 2px 2px 2px#969696;
- 49 box - shadow: 2px 2px 2px#969696;
- 50
- }
- 51 52 53 54 55 56
- 57
- 58 59 60 61 62 63
- var app = angular.module('myApp', []);
- 64 65 app.controller('testCtrl', ['$scope', 'uiValidFactory',
- function($scope, uiValidFactory) {
- 66 $scope.certCheck = function(val) {
- 67
- if (val > 32) {
- 68
- return "数字太大了";
- 69
- }
- 70
- return true;
- 71
- };
- 72 73 $scope.submit = function() {
- 74
- if (!uiValidFactory.checkValidForm($scope.baseInfoForm.$name)) {
- 75 76
- }
- 77 78
- };
- 79
- }] 80);
- 81 82 Math.guid = function() {
- 83
- var a = "",
- b = 1;
- 84
- for (; b <= 32; b++) {
- 85
- var c = Math.floor(Math.random() * 16).toString(16);
- 86 a += c;
- 87
- if (b === 8 || b === 12 || b === 16 || b === 20) {
- 88 a += ' - ';
- 89
- }
- 90
- }
- 91
- return a;
- 92
- };
- 93 94 String.prototype.contains = String.prototype.contains ||
- function(a) {
- 95
- return this.indexOf(a) != -1;
- 96
- };
- 97 98 String.prototype.format = String.prototype.format ||
- function() {
- 99
- var a = Array.prototype.slice.call(arguments);
- 100
- return this.replace(/\{(\d+)}/g,
- function(c, b) {
- 101
- return a[b];
- 102
- }) 103
- };
- 104 105 app.factory('uiTipsFactory',
- function() {
- 106
- return {
- 107 filterClass: function(ele, invalid) {
- 108
- if (invalid) {
- 109 //如果验证不通过
- 110 ele.removeClass('ng - valid').removeClass('ng - pristine').addClass('ng - invalid').addClass('ng - dirty');
- 111
- } else {
- 112 ele.removeClass('ng - invalid').addClass('ng - valid');
- 113
- }
- 114
- },
- 115 on: function(ele, msg) {
- 116
- var lastTip = ele.data('last - tip');
- 117
- if (lastTip && lastTip === msg) {
- 118
- return;
- 119
- }
- 120 121 ele.data('last - tip', msg);
- 122 this.filterClass(ele, true);
- 123 124
- var offset = ele.offset();
- 125
- if (!offset.top && !offset.left && ele.is('hidden')) {
- 126 offset = ele.show().offset();
- 127
- }
- 128 129
- var id = ele.attr('ui - valid - id');
- 130
- if (!id) {
- 131 id = Math.guid();
- 132 ele.attr('ui - valid - id', id);
- 133
- }
- 134 135
- if (id.contains('.')) {
- 136 id = id.replace(/\./g, '_');
- 137
- }
- 138 139
- var top = offset.top,
- 140 left = offset.left;
- 141 142
- var getTips = function() {
- 143
- var _tip = $('#vtip_' + id);
- 144
- if (_tip.length) {
- 145 _tip.html(msg).css({
- 146'display': 'none',
- 147'top': top + 'px',
- 148'left': left + ele.width() + 10 + 'px'149
- });
- 150 151
- } else {
- 152
- var html = '' + 153'' + msg + '';
- 154 $(html).css({
- 155'display': 'none',
- 156'position': 'absolute',
- 157'top': top + 'px',
- 158'left': left + ele.width() + 10 + 'px'159
- }).appendTo($('body'));
- 160
- }
- 161
- };
- 162 163
- var bindTipsShow = function() {
- 164 getTips();
- 165 ele.unbind('mouseenter mouseleave').bind('mouseenter',
- function() {
- 166
- var _tip = $('#vtip_' + id);
- 167
- if (_tip.is(': hidden')) {
- 168 _tip.show();
- 169
- }
- 170
- }).bind('mouseleave',
- function() {
- 171 $('#vtip_' + id).hide();
- 172
- });
- 173 174
- };
- 175 176 bindTipsShow();
- 177
- },
- 178 off: function(ele) {
- 179 ele.data('last - tip', '');
- 180 this.filterClass(ele);
- 181
- var id = ele.attr('ui - valid - id');
- 182 183
- if (!id) {
- 184
- return;
- 185
- }
- 186 187
- if (id.contains('.')) {
- 188 id = id.replace(/\./g, '_');
- 189
- }
- 190 191 $('#vtip_' + id).remove();
- 192 ele.unbind('mouseenter mouseleave');
- 193
- }
- 194
- }
- 195
- });
- 196 197 app.factory('uiValidFactory', ['$parse', 'uiTipsFactory',
- function($parse, tips) {
- 198
- return {
- 199 check: function(val, rules, $scope, defaultTips, extendParam) {
- 200
- if (!rules) {
- 201
- return {
- 202 flag: true 203
- };
- 204
- }
- 205 206
- var rulesArr = rules.split(''),
- 207 isBlank = val === null || val === undefined || val === '' || ('' + val === '');
- 208 209 //如果不是必填项 且没有输入值 则清除提示框
- 210
- if ($.inArray('r', rulesArr) === -1 && isBlank) {
- 211
- return {
- 212 flag: true 213
- }
- 214
- }
- 215
- var i = 0,
- len = rulesArr.length;
- 216
- for (; i < len; i++) {
- 217
- var rule = rulesArr[i];
- 218
- if (!rule) {
- 219
- continue;
- 220
- }
- 221 222
- var flag = true;
- 223
- if ('r' === rule) {
- 224 //如果是必填项,有值 返回true
- 225 flag = !isBlank;
- 226
- } else if (rule.contains(': ')) {
- 227 //如果校验规则是 fn:ctrl.certCheck
- 228 flag = this.checkRule(val, rule.split(/:/), $scope, extendParam);
- 229
- } else {
- 230 //校验 规则是 int 用正则匹配 数字 邮箱 长度
- 231
- var pat = this.pats[rule];
- 232
- if (pat instanceof RegExp) {
- 233
- if (angular.isString(val)) {
- 234 flag = this.mat(val, pat);
- 235
- }
- 236
- } else if (angular.isFunction(pat)) {
- 237 flag = pat(val);
- 238
- } else {
- 239 flag = false;
- 240
- }
- 241
- }
- 242 243 //这是干什么的呢
- 244
- if (angular.isString(flag)) {
- 245
- return {
- 246 flag: false,
- 247 msg: flag,
- 248 rule: rule 249
- }
- 250
- }
- 251 252
- if (flag === false) {
- 253
- var msg = this.getMsg(rule, defaultTips) || this.getMsg('tips.valid');
- 254 console.log(msg);
- 255
- return {
- 256 flag: false,
- 257 msg: msg,
- 258 rule: rule 259
- }
- 260
- }
- 261
- }
- 262 263
- return {
- 264 flag: true 265
- }
- 266
- },
- 267 checkRule: function(val, ruleArr, $scope, extendParam) {
- 268 //ruleArr fn:certCheck
- 269
- var rule = ruleArr[0];
- 270
- if (rule === 'fn') {
- 271 fnName = ruleArr[1]; //指定被调函数的名字 certCheck
- 272
- var fn = $parse(fnName)($scope);
- 273
- if (!fn) {
- 274
- return true;
- 275
- }
- 276
- return fn.call($scope, val, extendParam);
- 277
- } else {
- 278
- return true;
- 279
- }
- 280
- },
- 281 checkValidForm: function(formName) {
- 282 //只检查必填项
- 283 //使用属性筛选器 获得里面所有的元素
- 284
- var formContext = $('form[name = "{0}"], [ng - form = "{0}"], [data - ng - form = "{0}"]'.format(formName)),
- 285 validList = formContext.find(' [my - valid]'); //validList 不是数组,是伪数组
- 286
- if (!validList.length) {
- 287
- return;
- 288
- }
- 289 290
- var that = this,
- 291 validFlags = [];
- 292 validList.each(function() {
- 293
- var ele = $(this),
- 294 val = ele.val(),
- 295 ruleStr = ele.attr('my - valid');
- 296
- if (!ruleStr) {
- 297
- return true;
- 298
- }
- 299
- if (angular.isString(val)) {
- 300 val = val.trim();
- 301
- }
- 302 303
- var validRules = ruleStr.split('');
- 304
- if ($.inArray('r', validRules) != -1 && !val) {
- 305
- var modelValue = ele.attr('ng - model') || ele.attr('data - ng - model');
- 306 validFlags.push(modelValue);
- 307 tips.on(ele, that.getMsg('r'));
- 308
- }
- 309
- }
- 310);
- 311
- return validFlags;
- 312
- },
- 313 mat: function(val, pat) {
- 314
- if (!pat) {
- 315
- return;
- 316
- }
- 317
- return pat.test(val);
- 318
- }
- 319 320,
- 321 getMsg: function(rule, tips) {
- 322 tips = tips || '';
- 323 //可以在界面上直接写 tips
- 324
- if (tips && tips.contains(': ')) {
- 325
- return tips;
- 326
- }
- 327 328
- var msg = this.msgs[rule];
- 329
- if (msg) {
- 330
- var params0 = tips.contains(': ') ? tips.split(/:/)[0] : '';
- 331
- var params1 = '';
- 332
- if (rule.startsWith('min') || rule.startsWith('max')) {
- 333
- var ruleArr = rule.split(/:/);
- 334 params1 = ruleArr[ruleArr.length - 1];
- 335
- }
- 336
- return msg.format(params0, params1);
- 337
- } else {
- 338 339
- }
- 340
- }
- 341,
- 342 regPat: function(code, pat, msg) {
- 343
- if (this.pat[code]) {
- 344
- return;
- 345
- }
- 346 347 this.pats[code] = pat;
- 348 this.msgs[code] = msg;
- 349 350
- }
- 351,
- 352 msgs: {
- 353'r': '必填',
- 354'int': ' {
- 0
- }必须为整数'355
- }
- 356,
- 357 pats: {
- 358'int': /^[\-\+]?([0-9]+)$/359
- }
- 360
- }
- 361
- }
- 362]) 363;
- 364 365 app.directive('myValid', ['$parse', 'uiTipsFactory', 'uiValidFactory',
- function($parse, tips, valid) {
- 366
- var uiValidAttrIdName = 'ui - valid - id';
- 367
- return {
- 368 restrict: 'A',
- 369 require: 'ngModel',
- 370 link: function(scope, el, attrs, ctrl) {
- 371
- var validId = el.attr(uiValidAttrIdName);
- 372 373
- if (!validId) {
- 374 validId = Math.guid();
- 375 el.attr(uiValidAttrIdName, validId);
- 376
- }
- 377 378
- var getRules = function() {
- 379
- return attrs.myValid;
- 380
- };
- 381 382
- var lastOldRules;
- 383 384
- var validFn = function(value, oldRules) {
- 385
- var sp = '_';
- 386
- var rules = getRules();
- 387
- var r = valid.check(value, rules, scope, attrs.uiValidTips);
- 388
- if (lastOldRules && !oldRules) {
- 389 oldRules = lastOldRules;
- 390
- }
- 391 392
- if (r.flag && oldRules) {
- 393 rules = rules ? rules + '' + oldRules: oldRules;
- 394
- }
- 395 396
- if (rules) {
- 397
- var arrInner = rules.split('');
- 398
- var i = 0;
- 399
- for (; i < arrInner.length; i++) {
- 400
- var oneRule = arrInner[i];
- 401
- if (!oneRule.trim()) {
- 402
- continue;
- 403
- }
- 404 405 ctrl.$setValidity(attrs.ngModel + sp + oneRule, r.flag ? true: oneRule != r.rule);
- 406
- }
- 407
- }
- 408 409
- if (!r.flag) {
- 410 tips.on(el, r.msg);
- 411
- } else {
- 412 tips.off(el);
- 413
- }
- 414 415
- return r.flag;
- 416
- };
- 417 418
- var init = function() {
- 419
- var rules = getRules();
- 420
- if (!rules) {
- 421
- return;
- 422
- }
- 423 424
- var parsers = ctrl.$parsers;
- 425
- if (parsers && parsers.length > 0) {
- 426 parsers.clean();
- 427
- }
- 428 429 parsers.unshift(function(value) {
- 430
- return validFn(value) ? value: undefined;
- 431
- });
- 432
- };
- 433 434 scope.$watch(attrs.ngModel,
- function(newVal, oldVal) {
- 435
- if (newVal === oldVal) {
- 436
- return;
- 437
- }
- 438
- if (ctrl.$modelValue != undefined && (ctrl.$invalid || el.hasClass('ng - invalid'))) {
- 439 validFn(ctrl.$modelValue);
- 440
- }
- 441
- });
- 442 443 scope.$watch(getRules,
- function(newRules, oldRules) {
- 444 init();
- 445 446 lastOldRules = oldRules;
- 447 448
- if (ctrl.$modelValue === undefined || ctrl.$modelValue === null) {
- 449
- var needValid = false;
- 450 el.hasClass('ng - invalid');
- 451
- var isValNaN = ctrl.$viewValue !== ctrl.$viewValue;
- 452 453
- if (ctrl.$invalid || (ctrl.$viewValue !== undefined && !isValNaN)) {
- 454 needValid = true;
- 455
- }
- 456 457 458
- if (needValid) {
- 459 ctrl.$setViewValue(ctrl.$viewValue);
- 460
- }
- 461 462
- } else {
- 463
- if (!ctrl.$dirty && attrs.dirtyCheck) {
- 464 console.log('----');
- 465
- } else {
- 466 validFn(ctrl.$modelValue, oldRules);
- 467
- }
- 468
- }
- 469
- });
- 470 471 472
- }
- 473
- }
- 474
- }]);
- 475 476 477
来源: http://www.bubuko.com/infodetail-1950318.html