1 /**
  2  *
  3  * utils方法
  4  * @fileOverView core/utils
  5  * @author  <a href="mailto:zhang.gd@foxmail.com">Zhang Guangda</a>
  6  * @date    2012-10-25
  7  */
  8 define("core/utils", function() {
  9 	/**
 10 	 * @class  we utils方法
 11 	 */
 12 	$we.utils = {
 13 
 14 		/**
 15 		 * 初始化命名空间
 16 		 * @param  {String} router 命名空间的名称
 17 		 * @param  {Object} root   命名空间的基准,默认是window
 18 		 */
 19 		initNameSpace: function(router, root) {
 20 			if(!router || router == '') {
 21 				return;
 22 			}
 23 			var p = root || window,
 24 				arrNS = router.split('.');
 25 			for(var i = 0, len = arrNS.length; i < len; i++) {
 26 				if(!p[arrNS[i]]) {
 27 					p[arrNS[i]] = {};
 28 				}
 29 				p = p[arrNS[i]];
 30 			}
 31 		},
 32 
 33 		/**
 34 		 * ajax请求统一封装
 35 		 * @param  {string}  url     URL
 36 		 * @param  {object}  data    数据
 37 		 * @param  {function}  success 成功的回调
 38 		 * @param  {function}  fail    失败的回调
 39 		 * @param  {string}  method  POST/GET
 40 		 * @param  {Boolean} isJsonp 是否是jsonp
 41 		 * @return {object} jxhr
 42 		 */
 43 		request: function(url, data, success, fail, method, isJsonp) {
 44 			var loginTryMaxTimes = 1;
 45 				loginTryTimes = 0, // 初始化登录尝试次数
 46 				option = {
 47 					url: url,
 48 					headers: {
 49 						"X-Requested-With": "XMLHttpRequest" // 标识该请求为ajax请求
 50 					},
 51 					data: data,
 52 					success: function(resp) {
 53 						var obj;
 54 						if(typeof resp == "object") {
 55 							// 如果jQuery能够正常解析,那么直接赋值
 56 							obj = resp;
 57 						} else {
 58 							// 如果jQuery不能够正常解析,那么eval 一下
 59 							try {
 60 								obj = eval("(" + resp + ")");
 61 							} catch(e) {
 62 								alert($we.ERROR.AJAX_PARSE_FAIL);
 63 							}
 64 						}
 65 
 66 						// 判断返回结构是否合法
 67 						if(obj && typeof obj.errno != 'undefined' && typeof obj.msg != "undefined") {
 68 							// error no 为0,则说明请求是成功的
 69 							if(obj.errno == 0) {
 70 								success(obj);
 71 							} else {
 72 								// 如果返回的错误码是未登录
 73 								if(parseInt(obj.errno) == $we.ERRNO.NOT_LOGIN) {
 74 									// 在登录尝试达到最大次数之前,尝试去登录
 75 									if (++loginTryTimes <= loginTryMaxTimes) {
 76 										$we.setLogin(true, function() {
 77 											$.ajax(option);
 78 										}, function() {
 79 											fail(obj);
 80 										});	
 81 									} else {
 82 										// 超过登录尝试次数之后,触发失败
 83 										fail(obj);
 84 									}
 85 									
 86 									return;
 87 								}
 88 								// 错误码小于0,则为业务错误
 89 								if(parseInt(obj.errno) < 0) {
 90 									fail(obj);
 91 								} else {
 92 									// 否则,为系统错误
 93 									fail({
 94 										errno: obj.errno,
 95 										msg: '系统内部错误,请稍后再试!Error: '+obj.errno
 96 									});
 97 								}
 98 							}
 99 						}
100 					},
101 					error: function(resp) {
102 						// 请求失败,返回系统错误
103 						fail({
104 							errno: 502,
105 							msg: '网络超时,请重试!'
106 						});
107 					},
108 					type: method
109 				};
110 
111 			if ($we.conf.RUNTIME.__NOJSON) {
112 				isJsonp = false;
113 				option.type = "POST";
114 			}
115 
116 			// 如果是jsonp
117 			if(isJsonp) {
118 				option.dataType = "jsonp";
119 				option.jsonp = "_jsonp";
120 				option.type = "GET";
121 			}
122 
123 			// 如果存在流程,那么判断流程里的一些属性
124 			if($we && $we.process) {
125 				// 获取当前流程的id,和flow
126 				var p_id = $we.process.getData("id"),
127 					p_flow = $we.process.getData("flow");
128 				// 如果存在流程id,那么请求参数里面加入流程id
129 				if(p_id) {
130 					option.data["we_process_id"] = p_id;
131 					option.data["_src"] = window.location.hostname;
132 				}
133 				// 如果存在流程名称,那么请求参数里面假如流程名称
134 				if(p_flow) option.data["_flow"] = p_flow;
135 			}
136 
137 			return $.ajax(option);
138 		},
139 
140 		/**
141 		 * script loader
142 		 * @param  {mixed} file 需要加载的文件,string或者array
143 		 * @param  {string} path 路径
144 		 * @return {function}      回调函数
145 		 */
146 		include: function(file, path, callback) {
147 			var head = document.getElementsByTagName("head")[0] || document.documentElement,
148 				path = path || "",
149 				files = typeof file == "string" ? [file] : file, // 统一转成array
150 				done = 0, // 已经加载完的数量
151 				len = files.length; // 总共需要加载的文件数量
152 
153 			$(files).each(function(index) {
154 				var name = this.toString().replace(/^\s|\s$/g, ""), // 去除前后空格
155 					att = name.split('.'), 
156 					ext = att[att.length - 1].toLowerCase(),
157 					isCSS = ext == "css",
158 					tagName = isCSS ? "link" : "script",
159 					tag = document.createElement(tagName); // 创建link 或者 script
160 
161 				if(isCSS) {
162 					tag.href = path + name;
163 					tag.rel = "stylesheet";
164 					tag.type = "text/css";
165 				} else {
166 					tag.type = "text/javascript";
167 					tag.src = path + name;
168 				}
169 
170 				// 如果不是css且存在callback,那么需要处理一下回调函数的问题
171 				if(!isCSS && typeof callback == "function") {
172 					// 处理每个script load完之后的事件
173 					var _handleCb = function() {
174 						// 增加一个完成数,如果全部都完成,处理回调
175 						if(++done == len) setTimeout(callback, 1);
176 						// 删除当前的script
177 						if(head && tag.parentNode) {
178 							head.removeChild(tag);
179 						}
180 					};
181 
182 					if(tag.readyState) { // IE
183 						tag.onreadystatechange = function() {
184 							if(tag.readyState == "loaded" || tag.readyState == "complete") {
185 								_handleCb();
186 								tag.onreadystatechange = null; // memory leak
187 							}
188 						};
189 					} else { //Others
190 						tag.onload = _handleCb;
191 					}
192 				}
193 
194 				// 这句话一定一定要放在最后,否则在IE下会有各种诡异问题
195 				head.appendChild(tag);
196 			});
197 		},
198 
199 		/**
200 		 * 让浏览器执行脚本
201 		 * @param  {string} text   需要执行的脚本代码
202 		 * @param  {bool} 	bTrans 是否需要转译 < > 特殊符号
203 		 */
204 		exec: function(text, bTrans) {
205 			if(!text) return text;
206 			if(bTrans) {
207 				text = text.replace(/</g, "<").replace(/>/g, ">").replace(/&/g, "&");
208 			}
209 
210 			if(window.execScript) {
211 				window.execScript(text);
212 			} else {
213 				var script = document.createElement('script');
214 				script.setAttribute('type', 'text/javascript');
215 				script.text = text;
216 				document.head.appendChild(script);
217 				document.head.removeChild(script);
218 			}
219 			return text;
220 		},
221 
222 		/**
223 		 * 根据值是否undefined来设置默认值
224 		 * @param {mixed} v  要检测的值
225 		 * @param {mixed} d  默认值
226 		 */
227 		setValue: function(v, d) {
228 			if(typeof v == "undefined") return d;
229 			else return v;
230 		},
231 
232 		/**
233 		 * 增加一个stylesheet
234 		 * @param {string} css css的具体text
235 		 * @param {dom} doc document
236 		 */
237 		addStyleSheet: function(css, doc) {
238 			doc = doc || document;
239 			head = document.getElementsByTagName('head')[0], style = document.createElement('style');
240 
241 			style.type = 'text/css';
242 			if(style.styleSheet) {
243 				style.styleSheet.cssText = css;
244 			} else {
245 				style.appendChild(document.createTextNode(css));
246 			}
247 			head.appendChild(style);
248 		},
249 
250 		/**
251 		 * 获取表单元素
252 		 * @param ele 表单容器
253 		 * @private
254 		 */
255 		getFormElements: function (ele)
256 		{
257 			var FORM_Tag = ['INPUT', 'SELECT', 'TEXTAREA'];
258 			/**
259 			 * 是否是表单Tag
260 			 * @param tagName
261 			 * @private
262 			 */
263 			var _isFormTag = function (tagName)
264 			{
265 			    var formTag = false;
266 			    $.each(FORM_Tag, function (i, t)
267 			    {
268 			        if (t == tagName) {
269 			            formTag = true;
270 			        }
271 			    });
272 			    return formTag;
273 			};
274 		    var elements = [];
275 		    var isFormTag = _isFormTag(ele[0].tagName);
276 
277 		    if (isFormTag) {
278 		        elements.push(ele);
279 		    }
280 		    else {
281 		        $.each(FORM_Tag, function (i, t)
282 		        {
283 		            var _t = ele.find(t);
284 		            if (_t && _t.length > 0) {
285 		                $.each(_t, function (i, e)
286 		                {
287 		                    elements.push(e);
288 		                })
289 		            }
290 		        });
291 		    }
292 		    return elements;
293 		},
294 
295 		/**
296 		 * 验证表单
297 		 * @param ele 验证元素
298 		 */
299 		validForm:function (ele)
300 		{
301 		    var v = true;
302 
303 		    ele = $(ele);
304 
305 		    /**
306 		     * 验证表单试
307 		     * @type {Object}
308 		     */
309 		    var ValidExpression = {
310 		        "require":function (e, args)
311 		        {
312 		            var value = $.trim(e.val());
313 		            if (value.length == 0) {
314 		                return {valid:false, error_msg:"不能为空!"};
315 		            }
316 		            return {valid:true, error_msg:""};
317 		        },
318 
319 		        "url":function (e, args)
320 		        {
321 		            var value = e.val();
322 		            if (value.length > 0) {
323 		                if (!/(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/.test(value)) {
324 		                    return {valid:false, error_msg:"输入的url格式不正确!"};
325 		                }
326 		            }
327 		            return {valid:true, error_msg:""};
328 		        },
329 
330 		        "email":function (e, args)
331 		        {
332 		            var value = e.val();
333 		            if (value.length > 0) {
334 		                if (!/^(?:[a-z\d]+[_\-\+\.]?)*[a-z\d]+@(?:([a-z\d]+\-?)*[a-z\d]+\.)+([a-z]{2,})+$/i.test(value)) {
335 		                    return {valid:false, error_msg:"输入的Email格式不正确!"};
336 		                }
337 		            }
338 		            return {valid:true, error_msg:""};
339 		        },
340 
341 		        "number":function (e, args)
342 		        {
343 		            var value = e.val();
344 		            var ph = $(e).attr("PlaceHolder");
345 		            if (ph && ph.length > 0 && value == ph) {
346 		                value = "";
347 		            }
348 		            if (value.length > 0) {
349 		                if (!/(^-?\d\d*\.\d*$)|(^-?\d\d*$)|(^-?\.\d\d*$)/.test(value)) {
350 		                    return {valid:false, error_msg:"必须输入数字!"};
351 		                }
352 		            }
353 		            return {valid:true, error_msg:""};
354 		        },
355 
356 		        "int":function (e, args)
357 		        {
358 		            var value = e.val();
359 		            if (value.length > 0) {
360 		                if (!/(^-?\d\d*$)/.test(value)) {
361 		                    return {valid:false, error_msg:"必须输入整数!"};
362 		                }
363 		            }
364 		            return {valid:true, error_msg:""};
365 		        },
366 
367 		        "float":function (e, args)
368 		        {
369 		            var value = e.val();
370 		            if (value.length > 0) {
371 		                if (!/[\+-]*\d+\.?\d*/.test(value)) {
372 		                    return {valid:false, error_msg:"必须输入小数!"};
373 		                }
374 		            }
375 		            return {valid:true, error_msg:""};
376 		        },
377 
378 		        "date":function (e, args)
379 		        {
380 		            //日期正则 hash
381 		            var regexp_date = {
382 		                d:{
383 		                    reg:/^(19[0-9]{2}|2[0-9]{3})-(0{0,1}[1-9]{1}|1[0-2]{1}){1}-(0{0,1}[1-9]|(1|2)[0-9]|3[0-1]){1}$/, //v-date-d
384 		                    format:"2010-02-02"
385 		                }
386 		                // }
387 		            };
388 
389 		            var _reg = regexp_date[args[0]];
390 		            var value = e.val();
391 		            if (value.length > 0) {
392 		                if (!_reg.reg.test(value)) {
393 		                    return {valid:false, error_msg:"必须输入合法的日期格式" + _reg.format + "!"};
394 		                }
395 		            }
396 		            return {valid:true, error_msg:""};
397 		        },
398 
399 		        "max":function (e, args)
400 		        {
401 		            var value = e.val();
402 
403 		            if (value.length > 0) {
404 		                if (!value || Number(value) > Number(args[0])) {
405 		                    return {valid:false, error_msg:"不能为空且不超过最大值" + args[0] + "!"};
406 		                }
407 		            }
408 		            return {valid:true, error_msg:""};
409 		        },
410 
411 		        "min":function (e, args)
412 		        {
413 		            var value = e.val();
414 		            if (value.length > 0) {
415 		                if (!value || Number(value) < Number(args[0])) {
416 		                    return {valid:false, error_msg:"不能为空且不低于最小值" + args[0] + "!"};
417 		                }
418 		            }
419 		            return {valid:true, error_msg:""};
420 		        },
421 
422 		        "range":function (e, args)
423 		        {
424 		            var value = e.val();
425 		            if (value.length > 0) {
426 		                if (!value || (Number(value) < Number(args[0])) || Number(value) > Number(args[1])) {
427 		                    return {valid:false, error_msg:"不能为空且应在" + args[0] + "之间的" + args[1] + "值!"};
428 		                }
429 		            }
430 		            return {valid:true, error_msg:""};
431 		        },
432 
433 		        "phone":function (e, args)
434 		        {
435 		            /**
436 		             *手机号码
437 		             *中国移动134,135,136,137,138,139,150,151,157,158,159号码段
438 		             *中国联通的131,132,133,153,155,156号码段
439 		             *中国电信3G手机号码段188
440 		             *中国网通3G手机号码189号码段
441 		             *固定电话区号最小3位,最大4位
442 		             *固定电话号码段5位至8位不等
443 		             *有人或许不习惯写区号
444 		             *香港台湾澳门等地区号为0085x,因为香港手机和台湾号码为8位。故暂时不做单独考虑
445 		             */
446 		            var reg_phone = new RegExp("(^1((3|5)[0-9]|8[8-9])[0-9]{8}$)|(^0[0-9]{2,3}-[0-9]{5,8}$)|(^[0-9]{5,8}$)");
447 		            var value = e.val();
448 		            if (value.length > 0) {
449 		                if (!reg_phone.test(value)) {
450 		                    return {valid:false, error_msg:"请输入正确的电话号码!"};
451 		                }
452 		            }
453 		            return {valid:true, error_msg:""};
454 		        },
455 
456 		        "equal":function(e,args){
457 		            var value = e.val();
458 		            if (value.length > 0) {
459 		            	var equalName = args[0];
460 		                var container=$("div[containerid='"+e.attr('container')+"']");
461 		                container = container || $(document.body);
462 		                var e2 = container.find('*').filter(function(){
463 		                    return $(this).attr('name')==equalName;
464 		                });
465 		                e2=$(e2);
466 		                if(value!=e2.val()){
467 		                    return {valid:false, error_msg:e.attr('label')+"必须和"+e2.attr('label')+"一致"};
468 		                }
469 		            }
470 		            return {valid:true, error_msg:""};
471 		        },
472 
473 		        /**
474 		         * 身份证号
475 		         * @param e
476 		         * @param args
477 		         */
478 		        "id_card":function(e,args){
479 		            var card = e.val();
480 		            if (card.length > 0) {
481 		                var errorMessage = "您输入的身份证号码不正确,请重新输入";
482 		                var result= $we.string.validIdCard(card);
483 		                if(!result){
484 		                    return {valid:false, error_msg:errorMessage};
485 		                }
486 		            }
487 		            return {valid:true, error_msg:""};
488 		        },
489 
490 		        /**
491 		         * 自定义正则
492 		         *
493 		         * @param e
494 		         * @param args
495 		         */
496 		        "custom":function(e,args){
497 		            var value = e.val();
498 		            if (value.length > 0) {
499 		                if (!args[0].test(value)) {
500 		                    return {valid:false, error_msg:"格式不正确!"};
501 		                }
502 		            }
503 		            return {valid:true, error_msg:""};
504 		        }
505 		    };
506 
507 		    /**
508 		     * 显示Error
509 		     *
510 		     * @param eName
511 		     * @param message
512 		     */
513 		    var showError = function(eName,message){
514 		        $('.tip_' + eName).html('<p class="we_cell_error_tips"><i class="we_icon_error"></i>' + message + '</p>');
515 		    };
516 
517 		    /**
518 		     * 显示成功信息
519 		     */
520 		    var showSuccess = function(eName,message){
521 		        $('.tip_' + eName).html('<p class="we_cell_suc_tips"><i class="we_icon_suc"></i>' + message + '</p>');
522 		    };
523 
524 		    /**
525 		    *  显示警告信息
526 		    */
527 		    var showInfo = function(eName,message){
528 		        $('.tip_' + eName).html('<p class="we_cell_info_tips">' + message + '</p>');
529 		    };
530 
531 		    /**
532 		     * 清楚Tip
533 		     * @param eName
534 		     */
535 		    var clearTip = function(eName){
536 		        $('.tip_' + eName).html('');
537 		    };
538 
539 		    /**
540 		     * 验证表单组件
541 		     * @param e
542 		     * @private
543 		     */
544 		    var _valid = function (e)
545 		    {
546 		        var eName = e.attr('name');
547 		        var expression = e[0].expression || '';
548 		        var require = e.attr('require') == 'true';
549 
550 		        var _vv = {valid:true, error_msg:"" ,error_notice_type:null};
551 
552 		        /**
553 		         * Build Result
554 		         *
555 		         * @param _result
556 		         * @private
557 		         */
558 		        var _buildResult = function(_result){
559 		            if (_result['valid']) {
560 		                var success = e.attr('success');
561 		                if(success && success.length>0){
562 		                    showSuccess(eName,success);
563 		                }else{
564 		                    clearTip(eName);
565 		                }
566 		                e.removeClass("we_input_error");
567 		            }
568 		            else {
569 		                if(_result['error_notice_type']=='info'){
570 		                    //TODO 为require所定制
571 		                    showInfo(eName,"不能为空");
572 		                    e.removeClass("we_input_error");
573 		                }else{
574 		                   var error = e.attr('error');
575 		                    if(!(error && error.length>0)){
576 		                        error = _result['error_msg'];
577 		                    }
578 		                    showError(eName,error);
579 		                    e.addClass("we_input_error");
580 		                }
581 		                v = _result['valid'];
582 		            }
583 		        };
584 		        if(require){
585 		            var _result = ValidExpression['require'](e);
586 		            if(!_result['valid'] && _vv['valid']){
587 		                _vv = _result;
588 		                _vv['error_notice_type'] = 'info';
589 		            }
590 		        }
591 
592 		        if(typeof expression === "function"){
593 		            var expressionResult = expression(e);
594 		            if(typeof expressionResult == 'string'){
595 		                var _result = ValidExpression['custom'](e,[new RegExp(expressionResult)]);
596 		                if(!_result['valid'] && _vv['valid']){
597 		                    _vv = _result;
598 		                }
599 		            }else{
600 		                var _result = expressionResult;
601 		                if(!_result['valid'] && _vv['valid']){
602 		                    _vv = _result;
603 		                }
604 		            }
605 		        }else{
606 		            var _tmpList = expression.split(" ");
607 		            $.each(_tmpList, function (i, _parse)
608 		            {
609 		                _parse = _parse.split("-");
610 		                var num = _parse.length;
611 		                var parseFunc = ValidExpression[_parse[0]];
612 		                if (parseFunc) {
613 		                    var args = [];
614 		                    if (num > 1) {
615 		                        for (var j = 1; j < num; j++) {
616 		                            args.push(_parse[j]);
617 		                        }
618 		                    }
619 		                    var _result = parseFunc(e, args);
620 		                    if(!_result['valid'] && _vv['valid']){
621 		                        _vv = _result;
622 		                    }
623 		                }
624 		            });
625 		        }
626 		        _buildResult(_vv);
627 		    };
628 
629 		    var feList = $we.utils.getFormElements(ele);
630 		    if (feList && feList.length > 0) {
631 		        $.each(feList, function (i, e)
632 		        {
633 		            e = $(e);
634 		            _valid(e);
635 		        });
636 		    }
637 		    return v;
638 		}
639 	};
640 
641 	return $we.utils;
642 
643 });