1 /** 2 * JET (Javascript Extension Tools) 3 * Copyright (c) 2009, KDV.cn, All rights reserved. 4 * Code licensed under the BSD License: 5 * http://developer.kdv.cn/jet/license.txt 6 * 7 * @fileOverview Jx! 8 * @version 1.0 9 * @author Kinvix(<a href="mailto:Kinvix@gmail.com">Kinvix@gmail.com</a>) 10 * @description 11 * 12 */ 13 14 /** 15 * @description 16 * Package: Jx.string 17 * 18 * Need package: 19 * Jx.core.js 20 * 21 */ 22 23 24 /** 25 * 3.[Javascript core]: String 字符串处理 26 */ 27 Jx().$package(function(J){ 28 29 /** 30 * string 名字空间 31 * 32 * @namespace 33 * @name string 34 */ 35 J.string = J.string || {}; 36 var $S = J.string, 37 toString, 38 template, 39 isURL, 40 parseURL, 41 buildURL, 42 mapQuery, 43 test, 44 contains, 45 trim, 46 clean, 47 camelCase, 48 hyphenate, 49 capitalize, 50 escapeRegExp, 51 toInt, 52 toFloat, 53 toSingleLine, 54 toHtml, 55 toTitle, 56 toQueryPair, 57 toQueryString, 58 59 hexToRgb, 60 rgbToHex, 61 stripScripts, 62 substitute, 63 replaceAll, 64 65 byteLength, 66 cutRight, 67 cutByBytes, 68 isNumber, 69 isEmail, 70 71 encodeHtmlSimple, 72 decodeHtmlSimple, 73 decodeHtmlSimple2, 74 encodeHtmlAttributeSimple, 75 encodeHtmlAttribute, 76 encodeHtml, 77 encodeScript, 78 encodeHrefScript, 79 encodeRegExp, 80 encodeUrl, 81 encodeUriComponent, 82 vaildTencentUrl, 83 vaildUrl, 84 getCharWidth; 85 86 87 /** 88 * 将任意变量转换为字符串的方法 89 * 90 * @method toString 91 * @memberOf string 92 * 93 * @param {Mixed} o 任意变量 94 * @return {String} 返回转换后的字符串 95 */ 96 toString = function(o){ 97 return (o + ""); 98 }; 99 100 /** 101 * 多行或单行字符串模板处理 102 * 103 * @method template 104 * @memberOf string 105 * 106 * @param {String} str 模板字符串 107 * @param {Object} obj 要套入的数据对象 108 * @return {String} 返回与数据对象合成后的字符串 109 * 110 * @example 111 * <script type="text/html" id="user_tmpl"> 112 * <% for ( var i = 0; i < users.length; i++ ) { %> 113 * <li><a href="<%=users[i].url%>"><%=users[i].name%></a></li> 114 * <% } %> 115 * </script> 116 * 117 * Jx().$package(function(J){ 118 * // 用 obj 对象的数据合并到字符串模板中 119 * J.template("Hello, {name}!", { 120 * name:"Kinvix" 121 * }); 122 * }; 123 */ 124 template = function(str, data){ 125 /*! 126 * jstemplate: a light & fast js tamplate engine 127 * License MIT (c) 岑安 128 * 129 * Modify by azrael @ 2012/9/28 130 */ 131 var //global = typeof window != 'undefined' ? window : {}, 132 openTag = '<%', 133 closeTag = '%>', 134 retTag = '$return', 135 vars = 'var ', 136 varsInTpl, 137 codeArr = ''.trim ? 138 [retTag + ' = "";', retTag + ' +=', ';', retTag + ';', 'print=function(){' + retTag + '+=[].join.call(arguments,"")},'] : 139 [retTag + ' = [];', retTag + '.push(', ')', retTag + '.join("");', 'print=function(){' + retTag + '.push.apply(arguments)},'], 140 keys = ('break,case,catch,continue,debugger,default,delete,do,else,false,finally,for,function,if' 141 + ',in,instanceof,new,null,return,switch,this,throw,true,try,typeof,var,void,while,with' 142 // Reserved words 143 + ',abstract,boolean,byte,char,class,const,double,enum,export,extends,final,float,goto' 144 + ',implements,import,int,interface,long,native,package,private,protected,public,short' 145 + ',static,super,synchronized,throws,transient,volatile' 146 147 // ECMA 5 - use strict 148 + ',arguments,let,yield').split(','), 149 keyMap = {}; 150 151 for (var i = 0, len = keys.length; i < len; i ++) { 152 keyMap[keys[i]] = 1; 153 } 154 155 function _getCompileFn (source) { 156 vars = 'var '; 157 varsInTpl = {}; 158 varsInTpl[retTag] = 1; 159 var openArr = source.split(openTag), 160 tmpCode = ''; 161 162 for (var i = 0, len = openArr.length; i < len; i ++) { 163 var c = openArr[i], 164 cArr = c.split(closeTag); 165 if (cArr.length == 1) { 166 tmpCode += _html(cArr[0]); 167 } else { 168 tmpCode += _js(cArr[0]); 169 tmpCode += cArr[1] ? _html(cArr[1]) : ''; 170 } 171 } 172 173 var code = vars + codeArr[0] + tmpCode + 'return ' + codeArr[3]; 174 var fn = new Function('$data', code); 175 176 return fn; 177 } 178 179 function _html (s) { 180 s = s 181 .replace(/('|"|\\)/g, '\\$1') 182 .replace(/\r/g, '\\r') 183 .replace(/\n/g, '\\n'); 184 185 s = codeArr[1] + '"' + s + '"' + codeArr[2]; 186 187 return s + '\n'; 188 } 189 190 function _js (s) { 191 if (/^=/.test(s)) { 192 s = codeArr[1] + s.substring(1).replace(/[\s;]*$/, '') + codeArr[2]; 193 } 194 dealWithVars(s); 195 196 return s + '\n'; 197 } 198 199 function dealWithVars (s) { 200 s = s.replace(/\/\*.*?\*\/|'[^']*'|"[^"]*"|\.[\$\w]+/g, ''); 201 var sarr = s.split(/[^\$\w\d]+/); 202 for (var i = 0, len = sarr.length; i < len; i ++) { 203 var c = sarr[i]; 204 if (!c || keyMap[c] || /^\d/.test(c)) { 205 continue; 206 } 207 if (!varsInTpl[c]) { 208 if (c === 'print') { 209 vars += codeArr[4]; 210 } else { 211 vars += (c + '=$data.hasOwnProperty("'+c+'")?$data.' + c + ':window.' + c + ','); 212 } 213 varsInTpl[c] = 1; 214 } 215 } 216 } 217 218 // function getValue (v, $data){ 219 // return $data.hasOwnProperty(v) ? $data[v] : global[v]; 220 // } 221 222 // function jstemplate (id, source, data) { 223 // if (typeof arguments[1] == 'object' && arguments[2] == undefined) { 224 // data = source; 225 // source = id; 226 // id = null; 227 // } 228 // return (id && _cache[id]) ? _cache[id](data, getValue) : jstemplate.compile(id, source, data); 229 // } 230 231 // jstemplate.compile = function (id, source, data) { 232 // vars = 'var '; 233 // varsInTpl = {}; 234 235 // var compileFn = _getCompileFn(source); 236 // if (id) { 237 // _cache[id] = compileFn; 238 // } 239 // //console.log(compileFn) 240 // return compileFn(data, getValue); 241 // } 242 243 // jstemplate.openTag = '<%'; 244 // jstemplate.closeTag = '%>'; 245 246 var cache = {}; 247 return function(str, data){ 248 // Figure out if we're getting a template, or if we need to 249 // load the template - and be sure to cache the result. 250 var fn = !/\W/.test(str) ? 251 cache[str] || (cache[str] = _getCompileFn(document.getElementById(str).innerHTML)) : 252 _getCompileFn(str); 253 254 // Provide some basic currying to the user 255 return data ? fn(data) : fn; 256 }; 257 }(); 258 259 /** 260 * 判断是否是一个可接受的 url 串 261 * 262 * @method isURL 263 * @memberOf string 264 * 265 * @param {String} str 要检测的字符串 266 * @return {Boolean} 如果是可接受的 url 则返回 true 267 */ 268 isURL = function(str) { 269 return isURL.RE.test(str); 270 }; 271 272 /** 273 * @ignore 274 */ 275 isURL.RE = /^(?:ht|f)tp(?:s)?\:\/\/(?:[\w\-\.]+)\.\w+/i; 276 277 278 /** 279 * 分解 URL 为一个对象,成员为:scheme, user, pass, host, port, path, query, fragment 280 * 281 * @method parseURL 282 * @memberOf string 283 * 284 * @param {String} str URL 地址 285 * @return {Object} 如果解析失败则返回 null 286 */ 287 parseURL = function(str) { 288 var ret = null; 289 290 if (null !== (ret = parseURL.RE.exec(str))) { 291 var specObj = {}; 292 for (var i = 0, j = parseURL.SPEC.length; i < j ; i ++) { 293 var curSpec = parseURL.SPEC[i]; 294 specObj[curSpec] = ret[i + 1]; 295 } 296 ret = specObj; 297 specObj = null; 298 } 299 300 return ret; 301 }; 302 303 304 /** 305 * 将一个对象(成员为:scheme, user, pass, host, port, path, query, fragment)重新组成为一个字符串 306 * 307 * @method buildURL 308 * @memberOf string 309 * 310 * @param {Object} obj URl 对象 311 * @return {String} 如果是可接受的 url 则返回 true 312 */ 313 buildURL = function(obj) { 314 var ret = ''; 315 316 // prefix & surffix 317 var prefix = {}, 318 surffix = {}; 319 320 for (var i = 0, j = parseURL.SPEC.length; i < j ; i ++) { 321 var curSpec = parseURL.SPEC[i]; 322 if (!obj[curSpec]) { 323 continue; 324 } 325 switch (curSpec) { 326 case 'scheme': 327 surffix[curSpec] = '://'; 328 break; 329 case 'pass': 330 prefix[curSpec] = ':'; 331 case 'user': 332 prefix['host'] = '@'; 333 break; 334 //case 'host': 335 case 'port': 336 prefix[curSpec] = ':'; 337 break; 338 //case 'path': 339 case 'query': 340 prefix[curSpec] = '?'; 341 break; 342 case 'fragment': 343 prefix[curSpec] = '#'; 344 break; 345 } 346 347 // rebuild 348 if (curSpec in prefix) { 349 ret += prefix[curSpec]; 350 } 351 if (curSpec in obj) { 352 ret += obj[curSpec]; 353 } 354 if (curSpec in surffix) { 355 ret += surffix[curSpec]; 356 } 357 } 358 359 prefix = null; 360 surffix = null; 361 obj = null; 362 363 return ret; 364 }; 365 366 /** 367 * @ignore 368 */ 369 parseURL.SPEC = ['scheme', 'user', 'pass', 'host', 'port', 'path', 'query', 'fragment']; 370 parseURL.RE = /^([^:]+):\/\/(?:([^:@]+):?([^@]*)@)?(?:([^/?#:]+):?(\d*))([^?#]*)(?:\?([^#]+))?(?:#(.+))?$/; 371 372 /** 373 * 将 uri 的查询字符串参数映射成对象 374 * 375 * @method mapQuery 376 * @memberOf string 377 * 378 * @param {String} uri 要映射的 uri 379 * @return {Object} 按照 uri 映射成的对象 380 * 381 * @example 382 * Jx().$package(function(J){ 383 * var url = "http://web.qq.com/?qq=4765078&style=blue"; 384 * // queryObj 则得到一个{qq:"4765078", style:"blue"}的对象。 385 * var queryObj = J.mapQuery(url); 386 * }; 387 */ 388 mapQuery = function(uri){ 389 //window.location.search 390 var i, 391 key, 392 value, 393 uri = uri && uri.split('#')[0] || window.location.search, //remove hash 394 index = uri.indexOf("?"), 395 pieces = uri.substring(index + 1).split("&"), 396 params = {}; 397 if(index === -1){//如果连?号都没有,直接返回,不再进行处理. az 2011/5/11 398 return params; 399 } 400 for(i=0; i<pieces.length; i++){ 401 try{ 402 index = pieces[i].indexOf("="); 403 key = pieces[i].substring(0,index); 404 value = pieces[i].substring(index+1); 405 if(!(params[key] = unescape(value))){ 406 throw new Error("uri has wrong query string when run mapQuery."); 407 } 408 } 409 catch(e){ 410 //J.out("错误:[" + e.name + "] "+e.message+", " + e.fileName+", 行号:"+e.lineNumber+"; stack:"+typeof e.stack, 2); 411 } 412 } 413 return params; 414 }; 415 416 /** 417 * 418 * test的方法 419 * 420 * @memberOf string 421 * 422 * @param {String|RegExp} regex 正则表达式,或者正则表达式的字符串 423 * @param {String} params 正则的参数 424 * @return {Boolean} 返回结果 425 */ 426 test = function(string, regex, params){ 427 return ((typeof regex == 'string') ? new RegExp(regex, params) : regex).test(string); 428 }; 429 430 /** 431 * 判断是否含有指定的字符串 432 * 433 * @memberOf string 434 * @name contains 435 * @function 436 * @param {String} string 是否含有的字符串 437 * @param {String} separator 分隔符,可选 438 * @return {Boolean} 如果含有,返回 true,否则返回 false 439 */ 440 contains = function(string1, string2, separator){ 441 return (separator) ? (separator + string1 + separator).indexOf(separator + string2 + separator) > -1 : string1.indexOf(string2) > -1; 442 }; 443 444 /** 445 * 清除字符串开头和结尾的空格 446 * 447 * @memberOf string 448 * 449 * @return {String} 返回清除后的字符串 450 */ 451 trim = function(string){ 452 return String(string).replace(/^\s+|\s+$/g, ''); 453 }; 454 455 /** 456 * 清除字符串开头和结尾的空格,并把字符串之间的多个空格转换为一个空格 457 * 458 * @memberOf string 459 * 460 * @return {String} 返回清除后的字符串 461 */ 462 clean = function(string){ 463 return trim(string.replace(/\s+/g, ' ')); 464 }; 465 466 /** 467 * 将“-”连接的字符串转换成驼峰式写法 468 * 469 * @memberOf string 470 * 471 * @return {String} 返回转换后的字符串 472 */ 473 camelCase = function(string){ 474 return string.replace(/-\D/g, function(match){ 475 return match.charAt(1).toUpperCase(); 476 }); 477 }; 478 479 /** 480 * 将驼峰式写法字符串转换成“-”连接的 481 * 482 * @memberOf string 483 * 484 * @return {String} 返回转换后的字符串 485 */ 486 hyphenate = function(string){ 487 return string.replace(/[A-Z]/g, function(match){ 488 return ('-' + match.charAt(0).toLowerCase()); 489 }); 490 }; 491 492 /** 493 * 将字符串转换成全大写字母 494 * 495 * @memberOf string 496 * 497 * @return {String} 返回转换后的字符串 498 */ 499 capitalize = function(string){ 500 return string.replace(/\b[a-z]/g, function(match){ 501 return match.toUpperCase(); 502 }); 503 }; 504 505 /** 506 * 转换 RegExp 正则表达式 507 * 508 * @memberOf string 509 * 510 * @return {String} 返回转换后的字符串 511 */ 512 escapeRegExp = function(string){ 513 return string.replace(/([-.*+?^${}()|[\]\/\\])/g, '\\$1'); 514 }; 515 516 /** 517 * 将字符串转换成整数 518 * 519 * @memberOf string 520 * 521 * @return {Number} 返回转换后的整数 522 */ 523 toInt = function(string, base){ 524 return parseInt(string, base || 10); 525 }; 526 527 /** 528 * 将字符串转换成浮点数 529 * 530 * @memberOf string 531 * @param {Sring} string 要转换的字符串 532 * @return {Number} 返回转换后的浮点数 533 */ 534 toFloat = function(string){ 535 return parseFloat(string); 536 }; 537 538 /** 539 * 将带换行符的字符串转换成无换行符的字符串 540 * 541 * @memberOf string 542 * @param {Sring} str 要转换的字符串 543 * @return {Sring} 返回转换后的字符串 544 */ 545 toSingleLine = function(str){ 546 return String(str).replace(/\r/gi,"") 547 .replace(/\n/gi,""); 548 }; 549 550 /** 551 * 将字符串转换成html源码 552 * 553 * @memberOf string 554 * @param {Sring} str 要转换的字符串 555 * @return {Sring} 返回转换后的html代码字符串 556 */ 557 toHtml = function(str){ 558 return String(str).replace(/&/gi,"&") 559 .replace(/\\/gi,"\") 560 .replace(/\'/gi,"'") 561 .replace(/\"/gi,""") 562 .replace (/</gi,"<") 563 .replace(/>/gi,">") 564 .replace(/ /gi," ") 565 .replace(/\r\n/g,"<br />") 566 .replace(/\n\r/g,"<br />") 567 .replace(/\n/g,"<br />") 568 .replace(/\r/g,"<br />"); 569 }; 570 571 572 573 /** 574 * 将字符串转换成用于title的字符串 575 * 576 * @memberOf string 577 * @param {Sring} str 要转换的字符串 578 * @return {Number} 返回转换后的in title字符串 579 */ 580 toTitle = function(str){ 581 return String(str).replace(/\\/gi,"\\") 582 .replace(/\'/gi,"\'") 583 .replace(/\"/gi,"\'"); 584 }; 585 586 587 588 589 590 591 /** 592 * 将颜色 Hex 写法转换成 RGB 写法 593 * 594 * @memberOf string 595 * @return {String} 返回转换后的字符串 596 */ 597 hexToRgb = function(string, array){ 598 var hex = string.match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/); 599 return (hex) ? hex.slice(1).hexToRgb(array) : null; 600 }; 601 602 /** 603 * 将颜色 RGB 写法转换成 Hex 写法 604 * 605 * @memberOf string 606 * @return {String} 返回转换后的字符串 607 */ 608 rgbToHex = function(string, array){ 609 var rgb = string.match(/\d{1,3}/g); 610 return (rgb) ? rgb.rgbToHex(array) : null; 611 }; 612 613 /** 614 * 脱去script标签 615 * 616 * @memberOf string 617 * @return {String} 返回转换后的字符串 618 */ 619 stripScripts = function(string, option){ 620 var scripts = ''; 621 var text = string.replace(/<script[^>]*>([\s\S]*?)<\/script>/gi, function(){ 622 scripts += arguments[1] + '\n'; 623 return ''; 624 }); 625 if (option === true){ 626 $exec(scripts); 627 }else if($type(option) == 'function'){ 628 option(scripts, text); 629 } 630 return text; 631 }; 632 633 /** 634 * 。。。。 635 * 636 * @memberOf string 637 * @param {Object} obj 要转换成查询字符串的对象 638 * @return {String} 返回转换后的查询字符串 639 */ 640 toQueryPair = function(key, value) { 641 return encodeURIComponent(String(key)) + "=" + encodeURIComponent(String(value)); 642 }; 643 644 /** 645 * 。。。。 646 * 647 * @memberOf string 648 * @param {Object} obj 要转换成查询字符串的对象 649 * @return {String} 返回转换后的查询字符串 650 */ 651 toQueryString = function(obj){ 652 var result=[]; 653 for(var key in obj){ 654 result.push(toQueryPair(key, obj[key])); 655 } 656 return result.join("&"); 657 }; 658 659 660 661 /** 662 * 。。。。 663 * 664 * @memberOf string 665 * @return {String} 返回转换后的字符串 666 */ 667 substitute = function(string, object, regexp){ 668 return string.replace(regexp || (/\\?\{([^{}]+)\}/g), function(match, name){ 669 if (match.charAt(0) == '\\') return match.slice(1); 670 return (object[name] != undefined) ? object[name] : ''; 671 }); 672 }; 673 674 /** 675 * 全局替换指定的字符串 676 * 677 * @memberOf string 678 * @return {String} 返回替换后的字符串 679 */ 680 replaceAll = function(string, reallyDo, replaceWith, ignoreCase) { 681 if (!RegExp.prototype.isPrototypeOf(reallyDo)) { 682 return string.replace(new RegExp(reallyDo, (ignoreCase ? "gi": "g")), replaceWith); 683 } else { 684 return string.replace(reallyDo, replaceWith); 685 } 686 }; 687 688 /** 689 * 计算字符串的字节长度 690 * 691 * @memberOf string 692 * @param {String} string 693 * @param {Number} n 指定一个中文的字节数, 默认为2 694 * @return {Number} 返回自己长度 695 */ 696 byteLength = function(string,n){ 697 n= n||2; 698 return string.replace(/[^\x00-\xff]/g,({2:"aa",3:"aaa"})[n]).length; 699 }; 700 /** 701 * 按字符按给定长度裁剪给定字符串 702 * @memberOf string 703 * @param {String} string 704 * @param {Number} n 705 * @return {String} 706 */ 707 cutRight = function(string, n){ 708 return string.substring(0, (string.length - n)); 709 }; 710 /** 711 * 按字节按给定长度裁剪给定字符串 712 * @memberOf string 713 * @param {String} string 714 * @param {Number} n 715 * @return {String} 716 */ 717 cutByBytes = function(string,n) { 718 var s= string; 719 while(byteLength(s)>n) { 720 s= cutRight(s,1); 721 } 722 return s; 723 }; 724 /** 725 * 判断给定字符串是否是数字 726 * @memberOf string 727 * @name isNumber 728 * @function 729 * 730 * @param {String} string 731 * @param {Number} n 732 * @return {String} 733 */ 734 isNumber = function(string){ 735 if (string.search(/^\d+$/) !== -1){ 736 return true; 737 } 738 else{ 739 return false; 740 } 741 }; 742 /** 743 * 判断一个字符串是否是邮箱格式 744 * @memberOf string 745 * @param {String} emailStr 746 * @return {Boolean} 747 */ 748 isEmail = function(emailStr){ 749 if (emailStr.search(/^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/) !== -1){ 750 return true; 751 } 752 else{ 753 return false; 754 } 755 }; 756 757 758 759 760 /* 761 JS安全API v1.1 762 Created By Web Application Security Group of TSC 763 UpDate: 2007-12-08 764 */ 765 766 767 /** 768 * html正文编码, 对需要出现在HTML正文里(除了HTML属性外)的不信任输入进行编码 769 * @memberOf string 770 * @param {String} sStr 771 * @return {String} 772 */ 773 var encodeHtmlSimple = function(sStr){ 774 sStr = sStr.replace(/&/g,"&"); 775 sStr = sStr.replace(/>/g,">"); 776 sStr = sStr.replace(/</g,"<"); 777 sStr = sStr.replace(/"/g,"""); 778 sStr = sStr.replace(/'/g,"'"); 779 return sStr; 780 }; 781 782 /** 783 * html正文解码, 对HtmlEncode函数的结果进行解码 784 * @memberOf string 785 * @param {String} sStr 786 * @return {String} 787 */ 788 var decodeHtmlSimple = function(sStr){ 789 sStr = sStr.replace(/&/g,"&"); 790 sStr = sStr.replace(/>/g,">"); 791 sStr = sStr.replace(/</g,"<"); 792 sStr = sStr.replace(/"/g,'"'); 793 sStr = sStr.replace(/'/g,"'"); 794 return sStr; 795 }; 796 797 var decodeHtmlSimple2 = function(sStr){ 798 sStr = sStr.replace(/&/g,"&"); 799 sStr = sStr.replace(/>/g,">"); 800 sStr = sStr.replace(/</g,"<"); 801 sStr = sStr.replace(/\\\\"/g,'"'); 802 sStr = sStr.replace(/\\\\'/g,"'"); 803 return sStr; 804 }; 805 806 /** 807 * html属性编码:对需要出现在HTML属性里的不信任输入进行编码 808 注意: 809 (1)该函数不适用于属性为一个URL地址的编码.这些标记包括:a/img/frame/iframe/script/xml/embed/object... 810 属性包括:href/src/lowsrc/dynsrc/background/... 811 (2)该函数不适用于属性名为 style="[Un-trusted input]" 的编码 812 * @memberOf string 813 * @param {String} sStr 814 * @return {String} 815 */ 816 var encodeHtmlAttributeSimple = function(sStr){ 817 sStr = sStr.replace(/&/g,"&"); 818 sStr = sStr.replace(/>/g,">"); 819 sStr = sStr.replace(/</g,"<"); 820 sStr = sStr.replace(/"/g,"""); 821 sStr = sStr.replace(/'/g,"'"); 822 sStr = sStr.replace(/=/g,"="); 823 sStr = sStr.replace(/`/g,"`"); 824 return sStr; 825 }; 826 827 828 829 830 /** 831 * 用做过滤直接放到HTML里的 832 * @memberOf string 833 * @param {String} sStr 834 * @return {String} 835 */ 836 var encodeHtml = function(sStr) { 837 return sStr.replace(/[&'"<>\/\\\-\x00-\x09\x0b-\x0c\x1f\x80-\xff]/g, function(r){ 838 return ""+r.charCodeAt(0)+";"; 839 }).replace(/ /g, " ").replace(/\r\n/g, "<br />").replace(/\n/g, "<br />").replace(/\r/g, "<br />"); 840 }; 841 842 /** 843 * 用做过滤HTML标签里面的东东 比如这个例子里的<input value="XXXX"> XXXX就是要过滤的 844 * @memberOf string 845 * @param {String} sStr 846 * @return {String} 847 */ 848 var encodeHtmlAttribute = function(sStr) { 849 return sStr.replace(/[&'"<>\/\\\-\x00-\x1f\x80-\xff]/g, function(r){ 850 return ""+r.charCodeAt(0)+";"; 851 }); 852 }; 853 854 /** 855 * 用做过滤直接放到HTML里js中的 856 * @memberOf string 857 * @param {String} sStr 858 * @return {String} 859 */ 860 var encodeScript = function(sStr) { 861 sStr+="";//确保为String 862 return sStr.replace(/[\\"']/g, function(r){ 863 return "\\"+r; 864 }).replace(/%/g, "\\x25").replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\x01/g, "\\x01"); 865 }; 866 867 868 869 /** 870 * 用做过滤直接放到<a href="javascript:XXXX">中的 871 * @memberOf string 872 * @param {String} sStr 873 * @return {String} 874 */ 875 var encodeHrefScript = function(sStr) { 876 return encodeHtml(encodeUrl(escScript(sStr))); 877 }; 878 879 /** 880 * 用做过滤直接放到正则表达式中的 881 * @memberOf string 882 * @param {String} sStr 883 * @return {String} 884 */ 885 var encodeRegExp = function(sStr) { 886 return sStr.replace(/[\\\^\$\*\+\?\{\}\.\(\)\[\]]/g, function(a,b){ 887 return "\\"+a; 888 }); 889 }; 890 891 /** 892 * 用做过滤直接URL参数里的 比如 http://show8.qq.com/abc_cgi?a=XXX XXX就是要过滤的 893 * @memberOf string 894 * @param {String} sStr 895 * @return {String} 896 */ 897 var encodeUrl = function(sStr) { 898 return escape(sStr).replace(/\+/g, "%2B"); 899 }; 900 901 /** 902 对需要出现在一个URI的一部分的不信任输入进行编码 903 例如: 904 <a href="http://search.msn.com/results.aspx?q1=[Un-trusted-input]& q2=[Un-trusted-input]">Click Here!</a> 905 以下字符将会被编码: 906 除[a-zA-Z0-9.-_]以外的字符都会被替换成URL编码 907 * 908 * @memberOf string 909 * @param {String} sStr 910 * @return {String} 911 */ 912 var encodeUriComponent = function(sStr){ 913 sStr = encodeURIComponent(sStr); 914 sStr = sStr.replace(/~/g,"%7E"); 915 sStr = sStr.replace(/!/g,"%21"); 916 sStr = sStr.replace(/\*/g,"%2A"); 917 sStr = sStr.replace(/\(/g,"%28"); 918 sStr = sStr.replace(/\)/g,"%29"); 919 sStr = sStr.replace(/'/g,"%27"); 920 sStr = sStr.replace(/\?/g,"%3F"); 921 sStr = sStr.replace(/;/g,"%3B"); 922 return sStr; 923 }; 924 925 /** 926 url转向验证 927 描述:对通过javascript语句载入(或转向)的页面进行验证,防止转到第三方网页和跨站脚本攻击 928 返回值:true -- 合法;false -- 非法 929 例: 930 合法的值 931 http://xxx.qq.com/hi/redirect.html?url=http://www.qq.com 932 http://xxx.qq.com/hi/redirect.html?url=a.html 933 http://xxx.qq.com/hi/redirect.html?url=/a/1.html 934 非法的值 935 http://xxx.qq.com/hi/redirect.html?url=http://www.baidu.com 936 http://xxx.qq.com/hi/redirect.html?url=javascript:codehere 937 http://xxx.qq.com/hi/redirect.html?url=//www.qq.com 938 * 939 * @memberOf string 940 * @param {String} sUrl 941 * @return {String} 942 */ 943 var vaildTencentUrl = function(sUrl){ 944 return (/^(https?:\/\/)?[\w\-.]+\.(qq|paipai|soso|taotao)\.com($|\/|\\)/i).test(sUrl)||(/^[\w][\w\/\.\-_%]+$/i).test(sUrl)||(/^[\/\\][^\/\\]/i).test(sUrl) ? true : false; 945 }; 946 947 948 /** 949 * 验证给定字符串是否是url, 如果是url 则返回正常的url 950 * 951 * @memberOf string 952 * @param {String} sUrl 953 * @return {String} 954 */ 955 var vaildUrl = function(url){ 956 var url=encodeURI(url).replace(/(^\s*)|(\s*$)/g, ''), 957 protocolReg=/(^[a-zA-Z0-9]+[^.]):/, 958 domainReg=/^[\S.]+\.[\S.]+$/, 959 domainendReg=/[\w.]+\/(\S*)/, 960 jsReg=/;$/, 961 jpReg=/^[\s*]*javascript[\s*]*:/; 962 963 if((!protocolReg.test(url)) && (!domainReg.test(url))){ 964 url=""; 965 }else{ 966 if(!protocolReg.test(url)){ 967 url="http://"+url; 968 } 969 if(!domainendReg.test(url)){ 970 url=url+"/"; 971 972 } 973 //如果是js为协议就清空 974 if(jpReg.test(url)){ 975 url=""; 976 } 977 } 978 979 return url; 980 }; 981 982 983 /** 984 * 获取字符实际宽度 985 * @memberOf string 986 * @param {String} str 需要计算的字符串 987 * @param {Number} fontsize 字体大小,可以不填 988 * @return {Number} 989 */ 990 var getCharWidth = function(str,fontsize) { 991 var d= document.createElement("div"); 992 d.style.visibility= "hidden"; 993 d.style.width= "auto"; 994 if(fontsize) { 995 d.style.fontSize= fontsize + "px"; 996 } 997 d.style.position= "absolute"; 998 d.innerHTML= J.string.encodeHtmlSimple(str); 999 document.body.appendChild(d); 1000 var width= d.offsetWidth; 1001 document.body.removeChild(d); 1002 return width; 1003 }; 1004 1005 /** 1006 * 按给定宽度裁剪字符串 1007 * @memberOf string 1008 * @param {String} str 1009 * @param {Number} fontsize 字体大小 1010 * @param {Number} width 限定的宽度 1011 * @return {Number} 1012 */ 1013 var cutByWidth = function(str,fontsize,width) { 1014 for(var i=str.length;i>=0;--i) 1015 { 1016 str=str.substring(0, i); 1017 if(getCharWidth(str, fontsize)<width) 1018 { 1019 return str; 1020 } 1021 } 1022 return ''; 1023 }; 1024 $S.cutByWidth = cutByWidth; 1025 $S.toString = toString; 1026 $S.template = template; 1027 $S.isURL = isURL; 1028 $S.parseURL = parseURL; 1029 $S.buildURL = buildURL; 1030 $S.mapQuery = mapQuery; 1031 $S.test = test; 1032 $S.contains = contains; 1033 $S.trim = trim; 1034 $S.clean = clean; 1035 $S.camelCase = camelCase; 1036 $S.hyphenate = hyphenate; 1037 $S.capitalize = capitalize; 1038 $S.escapeRegExp = escapeRegExp; 1039 $S.toInt = toInt; 1040 $S.toFloat = toFloat; 1041 $S.toSingleLine = toSingleLine; 1042 1043 $S.toHtml = toHtml; 1044 $S.toTitle = toTitle; 1045 $S.toQueryPair = toQueryPair; 1046 $S.toQueryString = toQueryString; 1047 1048 $S.hexToRgb = hexToRgb; 1049 $S.rgbToHex = rgbToHex; 1050 $S.stripScripts = stripScripts; 1051 $S.substitute = substitute; 1052 $S.replaceAll = replaceAll; 1053 1054 $S.byteLength = byteLength; 1055 $S.cutRight = cutRight; 1056 1057 $S.isNumber = isNumber; 1058 $S.isEmail = isEmail; 1059 1060 $S.cutByBytes = cutByBytes; 1061 1062 //html正文编码:对需要出现在HTML正文里(除了HTML属性外)的不信任输入进行编码 1063 $S.encodeHtmlSimple = encodeHtmlSimple; 1064 1065 //html正文解码:对HtmlEncode函数的结果进行解码 1066 $S.decodeHtmlSimple = decodeHtmlSimple; 1067 $S.decodeHtmlSimple2 = decodeHtmlSimple2; 1068 1069 1070 /* 1071 html属性编码:对需要出现在HTML属性里的不信任输入进行编码 1072 注意: 1073 (1)该函数不适用于属性为一个URL地址的编码.这些标记包括:a/img/frame/iframe/script/xml/embed/object... 1074 属性包括:href/src/lowsrc/dynsrc/background/... 1075 (2)该函数不适用于属性名为 style="[Un-trusted input]" 的编码 1076 */ 1077 $S.encodeHtmlAttributeSimple = encodeHtmlAttributeSimple; 1078 1079 //用做过滤HTML标签里面的东东 比如这个例子里的<input value="XXXX"> XXXX就是要过滤的 1080 $S.encodeHtmlAttribute = encodeHtmlAttribute; 1081 1082 //用做过滤直接放到HTML里的 1083 $S.encodeHtml = encodeHtml; 1084 1085 //用做过滤直接放到HTML里js中的 1086 $S.encodeScript = encodeScript; 1087 1088 //用做过滤直接放到<a href="javascript:XXXX">中的 1089 $S.encodeHrefScript = encodeHrefScript; 1090 1091 //用做过滤直接放到正则表达式中的 1092 $S.encodeRegExp = encodeRegExp; 1093 1094 //用做过滤直接URL参数里的 比如 http://show8.qq.com/abc_cgi?a=XXX XXX就是要过滤的 1095 $S.encodeUrl = encodeUrl; 1096 1097 /* 1098 对需要出现在一个URI的一部分的不信任输入进行编码 1099 例如: 1100 <a href="http://search.msn.com/results.aspx?q1=[Un-trusted-input]& q2=[Un-trusted-input]">Click Here!</a> 1101 以下字符将会被编码: 1102 除[a-zA-Z0-9.-_]以外的字符都会被替换成URL编码 1103 */ 1104 $S.encodeUriComponent = encodeUriComponent; 1105 1106 /* 1107 url转向验证 1108 描述:对通过javascript语句载入(或转向)的页面进行验证,防止转到第三方网页和跨站脚本攻击 1109 返回值:true -- 合法;false -- 非法 1110 例: 1111 合法的值 1112 http://xxx.qq.com/hi/redirect.html?url=http://www.qq.com 1113 http://xxx.qq.com/hi/redirect.html?url=a.html 1114 http://xxx.qq.com/hi/redirect.html?url=/a/1.html 1115 非法的值 1116 http://xxx.qq.com/hi/redirect.html?url=http://www.baidu.com 1117 http://xxx.qq.com/hi/redirect.html?url=javascript:codehere 1118 http://xxx.qq.com/hi/redirect.html?url=//www.qq.com 1119 */ 1120 $S.vaildTencentUrl = vaildTencentUrl; 1121 1122 $S.vaildUrl = vaildUrl; 1123 1124 $S.getCharWidth = getCharWidth; 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 }); 1141 1142 1143 1144 1145 1146 1147 1148 1149