var $string = {},
toString,
template,
parseURL,
buildURL,
mapQuery,
test,
contains,
trim,
clean,
camelCase,
hyphenate,
capitalize,
escapeRegExp,
toInt,
toFloat,
toSingleLine,
toHtml,
toTitle,
toQueryPair,
toQueryString, hexToRgb,
rgbToHex,
stripScripts,
substitute,
replaceAll, byteLength,
cutRight,
cutByBytes,
isNumber,
isEmail, encodeHtmlSimple,
decodeHtmlSimple,
decodeHtmlSimple2,
encodeHtmlAttributeSimple,
encodeHtmlAttribute,
encodeHtml,
encodeScript,
encodeHrefScript,
encodeRegExp,
encodeUrl,
encodeUriComponent,
vaildURL,
getCharWidth,
cutByWidth; /**
* 将任意变量转换为字符串的方法
* @param o
* @returns {string}
*/
toString = function(o){
return (o + "");
}; /**
* 多行或单行字符串模板处理
*
* @method template
* @memberOf string
*
* @return {String} 返回与数据对象合成后的字符串
*
* @example
* <script type="text/html" id="user_tmpl">
* <% for ( var i = 0; i < users.length; i++ ) { %>
* <li><a href="<%=users[i].url%>"><%=users[i].name%></a></li>
* <% } %>
* </script>
*
* Jx().$package(function(J){
* // 用 obj 对象的数据合并到字符串模板中
* template("Hello, {name}!", {
* name:"Beauty"
* });
* };
*/ template = (function(){
var openTag = '<%',
closeTag = '%>',
retTag = '$return',
vars = 'var ',
varsInTpl,
codeArr = ''.trim ?
[retTag + ' = "";', retTag + ' +=', ';', retTag + ';', 'print=function(){' + retTag + '+=[].join.call(arguments,"")},'] :
[retTag + ' = [];', retTag + '.push(', ')', retTag + '.join("");', 'print=function(){' + retTag + '.push.apply(arguments)},'],
keys = ('break,case,catch,continue,debugger,default,delete,do,else,false,finally,for,function,if'
+ ',in,instanceof,new,null,return,switch,this,throw,true,try,typeof,var,void,while,with'
// Reserved words
+ ',abstract,boolean,byte,char,class,const,double,enum,export,extends,final,float,goto'
+ ',implements,import,int,interface,long,native,package,private,protected,public,short'
+ ',static,super,synchronized,throws,transient,volatile' // ECMA 5 - use strict
+ ',arguments,let,yield').split(','),
keyMap = {}; for (var i = 0, len = keys.length; i < len; i++) {
keyMap[keys[i]] = 1;
} function _getCompileFn(source) {
vars = 'var ';
varsInTpl = {};
varsInTpl[retTag] = 1;
var openArr = source.split(openTag),
tmpCode = ''; for (var i = 0, len = openArr.length; i < len; i++) {
var c = openArr[i],
cArr = c.split(closeTag);
if (cArr.length == 1) {
tmpCode += _html(cArr[0]);
} else {
tmpCode += _js(cArr[0]);
tmpCode += cArr[1] ? _html(cArr[1]) : '';
}
} var code = vars + codeArr[0] + tmpCode + 'return ' + codeArr[3];
return new Function('$data', code);
} function _html(s) {
s = s
.replace(/('|"|\\)/g, '\\$1')
.replace(/\r/g, '\\r')
.replace(/\n/g, '\\n'); s = codeArr[1] + '"' + s + '"' + codeArr[2]; return s + '\n';
} function _js(s) {
if (/^=/.test(s)) {
s = codeArr[1] + s.substring(1).replace(/[\s;]*$/, '') + codeArr[2];
}
dealWithVars(s); return s + '\n';
} function dealWithVars(s) {
s = s.replace(/\/\*.*?\*\/|'[^']*'|"[^"]*"|\.[\$\w]+/g, '');
var sArr = s.split(/[^\$\w\d]+/);
for (var i = 0, len = sArr.length; i < len; i++) {
var c = sArr[i];
if (!c || keyMap[c] || /^\d/.test(c)) {
continue;
}
if (!varsInTpl[c]) {
if (c === 'print') {
vars += codeArr[4];
} else {
vars += (c + '=$data.hasOwnProperty("' + c + '")?$data.' + c + ':window.' + c + ',');
}
varsInTpl[c] = 1;
}
}
} var cache = {}; /**
* @param {String} str 模板字符串
* @param {Object} data 要套入的数据对象
*/
return function (str, data) {
// Figure out if we're getting a template, or if we need to
// load the template - and be sure to cache the result.
var fn = !/\W/.test(str) ?
cache[str] || (cache[str] = _getCompileFn(document.getElementById(str).innerHTML)) :
_getCompileFn(str); // Provide some basic currying to the user
return data ? fn(data) : fn;
}; })(); /**
* 分解 URL 为一个对象,成员为:scheme, user, pass, host, port, path, query, fragment
*
* @method parseURL
* @memberOf string
*
* @param {String} str URL 地址
* @return {Object} 如果解析失败则返回 null
*/
parseURL = function(str) {
var ret = null; if (null !== (ret = parseURL.RE.exec(str))) {
var specObj = {};
for (var i = 0, j = parseURL.SPEC.length; i < j ; i ++) {
var curSpec = parseURL.SPEC[i];
specObj[curSpec] = ret[i + 1];
}
ret = specObj;
specObj = null;
} return ret;
}; /**
* 将一个对象(成员为:scheme, user, pass, host, port, path, query, fragment)重新组成为一个字符串
*
* @method buildURL
* @memberOf string
*
* @param {Object} obj URl 对象
* @return {String} 如果是可接受的 url 则返回 true
*/
buildURL = function(obj) {
var ret = ''; // prefix & surffix
var prefix = {},
surffix = {}; for (var i = 0, j = parseURL.SPEC.length; i < j ; i ++) {
var curSpec = parseURL.SPEC[i];
if (!obj[curSpec]) {
continue;
}
switch (curSpec) {
case 'scheme':
surffix[curSpec] = '://';
break;
case 'pass':
prefix[curSpec] = ':';
case 'user':
prefix['host'] = '@';
break;
//case 'host':
case 'port':
prefix[curSpec] = ':';
break;
//case 'path':
case 'query':
prefix[curSpec] = '?';
break;
case 'fragment':
prefix[curSpec] = '#';
break;
} // rebuild
if (curSpec in prefix) {
ret += prefix[curSpec];
}
if (curSpec in obj) {
ret += obj[curSpec];
}
if (curSpec in surffix) {
ret += surffix[curSpec];
}
} prefix = null;
surffix = null;
obj = null; return ret;
}; /**
* @ignore
*/
parseURL.SPEC = ['scheme', 'user', 'pass', 'host', 'port', 'path', 'query', 'fragment'];
parseURL.RE = /^([^:]+):\/\/(?:([^:@]+):?([^@]*)@)?(?:([^/?#:]+):?(\d*))([^?#]*)(?:\?([^#]+))?(?:#(.+))?$/; /**
* 将 uri 的查询字符串参数映射成对象
*
* @method mapQuery
* @memberOf string
*
* @param {String} uri 要映射的 uri
* @return {Object} 按照 uri 映射成的对象
*
* @example
* Jx().$package(function(J){
* var url = "http://web.qq.com/?qq=4765078&style=blue";
* // queryObj 则得到一个{qq:"4765078", style:"blue"}的对象。
* var queryObj = mapQuery(url);
* };
*/
mapQuery = function(uri){
//window.location.search
uri = uri && uri.split('#')[0] || window.location.search; //remove hash
var i,
key,
value,
index = uri.indexOf("?"),
pieces = uri.substring(index + 1).split("&"),
params = {};
if (index === -1) {//如果连?号都没有,直接返回,不再进行处理. az 2011/5/11
return params;
} for (i = 0; i < pieces.length; i++) {
try {
index = pieces[i].indexOf("=");
key = pieces[i].substring(0, index);
value = pieces[i].substring(index + 1);
if (!(params[key] = unescape(value))) {
throw new Error("uri has wrong query string when run mapQuery.");
}
}
catch (e) {
//J.out("错误:[" + e.name + "] "+e.message+", " + e.fileName+", 行号:"+e.lineNumber+"; stack:"+typeof e.stack, 2);
}
}
return params;
}; /**
*
* test的方法
*
* @memberOf string
*
* @param {String|RegExp} regex 正则表达式,或者正则表达式的字符串
* @param {String} params 正则的参数
* @return {Boolean} 返回结果
*/
test = function(string, regex, params){
return ((typeof regex == 'string') ? new RegExp(regex, params) : regex).test(string);
}; /**
* 判断是否含有指定的字符串
*
* @memberOf string
* @name contains
* @function
* @param {String} string 是否含有的字符串
* @param {String} separator 分隔符,可选
* @return {Boolean} 如果含有,返回 true,否则返回 false
*/
contains = function(string1, string2, separator){
return (separator) ? (separator + string1 + separator).indexOf(separator + string2 + separator) > -1 : string1.indexOf(string2) > -1;
}; /**
* 清除字符串开头和结尾的空格
*
* @memberOf string
*
* @return {String} 返回清除后的字符串
*/
trim = function(string){
return String(string).replace(/^\s+|\s+$/g, '');
}; /**
* 清除字符串开头和结尾的空格,并把字符串之间的多个空格转换为一个空格
*
* @memberOf string
*
* @return {String} 返回清除后的字符串
*/
clean = function(string){
return trim(string.replace(/\s+/g, ' '));
}; /**
* 将“-”连接的字符串转换成驼峰式写法
*
* @memberOf string
*
* @return {String} 返回转换后的字符串
*/
camelCase = function(string){
return string.replace(/-\D/g, function(match){
return match.charAt(1).toUpperCase();
});
}; /**
* 将驼峰式写法字符串转换成“-”连接的
*
* @memberOf string
*
* @return {String} 返回转换后的字符串
*/
hyphenate = function(string){
return string.replace(/[A-Z]/g, function(match){
return ('-' + match.charAt(0).toLowerCase());
});
}; /**
* 将字符串转换成全大写字母
*
* @memberOf string
*
* @return {String} 返回转换后的字符串
*/
capitalize = function(string){
return string.replace(/\b[a-z]/g, function(match){
return match.toUpperCase();
});
}; /**
* 转换 RegExp 正则表达式
*
* @memberOf string
*
* @return {String} 返回转换后的字符串
*/
escapeRegExp = function(string){
return string.replace(/([-.*+?^${}()|[\]\/\\])/g, '\\$1');
}; /**
* 将字符串转换成整数
*
* @memberOf string
*
* @return {Number} 返回转换后的整数
*/
toInt = function(string, base){
return parseInt(string, base || 10);
}; /**
* 将字符串转换成浮点数
*
* @memberOf string
* @param {String} string 要转换的字符串
* @return {Number} 返回转换后的浮点数
*/
toFloat = function(string){
return parseFloat(string);
}; /**
* 将带换行符的字符串转换成无换行符的字符串
*
* @memberOf string
* @param {String} str 要转换的字符串
* @return {String} 返回转换后的字符串
*/
toSingleLine = function(str){
return String(str).replace(/\r/gi,"")
.replace(/\n/gi,"");
}; /**
* 将字符串转换成html源码
*
* @memberOf string
* @param {String} str 要转换的字符串
* @return {String} 返回转换后的html代码字符串
*/
toHtml = function(str){
return String(str).replace(/&/gi,"&")
.replace(/\\/gi,"\")
.replace(/\'/gi,"'")
.replace(/\"/gi,""")
.replace (/</gi,"<")
.replace(/>/gi,">")
.replace(/ /gi," ")
.replace(/\r\n/g,"<br />")
.replace(/\n\r/g,"<br />")
.replace(/\n/g,"<br />")
.replace(/\r/g,"<br />");
}; /**
* 将字符串转换成用于title的字符串
*
* @memberOf string
* @param {String} str 要转换的字符串
* @return {Number} 返回转换后的in title字符串
*/
toTitle = function(str){
return String(str).replace(/\\/gi,"\\")
.replace(/\'/gi,"\'")
.replace(/\"/gi,"\'");
}; /**
* 将颜色 Hex 写法转换成 RGB 写法
*
* @memberOf string
* @return {String} 返回转换后的字符串
* @author rewrite by dmyang
*/
hexToRgb = function(string){
var hex = string.match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/);
var _convert = function(array) {
var length = array.length;
if (length !== 3) return null;
for(var i=0, value; i<length; i++) {
value = array[i];
if(value.length === 1) value += value;
array[i] = parseInt(value, 16);
}
return 'rgb(' + array + ')';
};
return (hex) ? _convert(hex.slice(1)) : null;
}; /**
* 将颜色 RGB 写法转换成 Hex 写法
*
* @memberOf string
* @return {String} 返回转换后的字符串
* @author rewrite by dmyang
*/
rgbToHex = function(string){
var r = string.match(/\d{1,3}/g);
return (r) ? '#' + ((1 << 24) + ((r[0] << 0) << 16) + ((r[1] << 0) << 8) + (r[2] << 0)).toString(16).slice(1) : null;
}; /**
* 脱去script标签
*
* @memberOf string
* @return {String} 返回转换后的字符串
*/
stripScripts = function(string, option){
var scripts = '';
var text = string.replace(/<script[^>]*>([\s\S]*?)<\/script>/gi, function(){
scripts += arguments[1] + '\n';
return '';
});
if (option === true){
$exec(scripts);
}else if($type(option) == 'function'){
option(scripts, text);
}
return text;
}; /**
* 。。。。
*
* @memberOf string
* @param {Object} obj 要转换成查询字符串的对象
* @return {String} 返回转换后的查询字符串
*/
toQueryPair = function(key, value) {
return encodeURIComponent(String(key)) + "=" + encodeURIComponent(String(value));
}; /**
* 。。。。
*
* @memberOf string
* @param {Object} obj 要转换成查询字符串的对象
* @return {String} 返回转换后的查询字符串
*/
toQueryString = function(obj){
var result=[];
for(var key in obj){
result.push(toQueryPair(key, obj[key]));
}
return result.join("&");
}; /**
* 。。。。
*
* @memberOf string
* @return {String} 返回转换后的字符串
*/
substitute = function(string, object, regexp){
return string.replace(regexp || (/\\?\{([^{}]+)\}/g), function(match, name){
if (match.charAt(0) == '\\') return match.slice(1);
return (object[name] != undefined) ? object[name] : '';
});
}; /**
* 全局替换指定的字符串
*
* @memberOf string
* @return {String} 返回替换后的字符串
*/
replaceAll = function(string, reallyDo, replaceWith, ignoreCase) {
if (!RegExp.prototype.isPrototypeOf(reallyDo)) {
return string.replace(new RegExp(reallyDo, (ignoreCase ? "gi": "g")), replaceWith);
} else {
return string.replace(reallyDo, replaceWith);
}
}; /**
* 计算字符串的字节长度
*
* @memberOf string
* @param {String} string
* @param {Number} n 指定一个中文的字节数, 默认为2
* @return {Number} 返回自己长度
*/
byteLength = function(string,n){
n= n||2;
return string.replace(/[^\x00-\xff]/g,({2:"aa",3:"aaa"})[n]).length;
};
/**
* 按字符按给定长度裁剪给定字符串
* @memberOf string
* @param {String} string
* @param {Number} n
* @return {String}
*/
cutRight = function(string, n){
return string.substring(0, (string.length - n));
};
/**
* 按字节按给定长度裁剪给定字符串
* @memberOf string
* @param {String} string
* @param {Number} n
* @return {String}
*/
cutByBytes = function(string,n) {
var s= string;
while(byteLength(s)>n) {
s= cutRight(s,1);
}
return s;
};
/**
* 判断给定字符串是否是数字
* @memberOf string
* @name isNumber
* @function
*
* @param {String} string
* @param {Number} n
* @return {String}
*/
isNumber = function(string){
if (string.search(/^\d+$/) !== -1){
return true;
}
else{
return false;
}
};
/**
* 判断一个字符串是否是邮箱格式
* @memberOf string
* @param {String} emailStr
* @return {Boolean}
*/
isEmail = function(emailStr){
if (emailStr.search(/^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/) !== -1){
return true;
}
else{
return false;
}
}; /*
JS安全API v1.1
Created By Web Application Security Group of TSC
UpDate: 2007-12-08
*/ /**
* html正文编码, 对需要出现在HTML正文里(除了HTML属性外)的不信任输入进行编码
* @memberOf string
* @param {String} sStr
* @return {String}
*/
encodeHtmlSimple = function(sStr){
sStr = sStr.replace(/&/g,"&");
sStr = sStr.replace(/>/g,">");
sStr = sStr.replace(/</g,"<");
sStr = sStr.replace(/"/g,""");
sStr = sStr.replace(/'/g,"'");
return sStr;
}; /**
* html正文解码, 对HtmlEncode函数的结果进行解码
* @memberOf string
* @param {String} sStr
* @return {String}
*/
decodeHtmlSimple = function(sStr){
sStr = sStr.replace(/&/g,"&");
sStr = sStr.replace(/>/g,">");
sStr = sStr.replace(/</g,"<");
sStr = sStr.replace(/"/g,'"');
sStr = sStr.replace(/'/g,"'");
return sStr;
}; decodeHtmlSimple2 = function(sStr){
sStr = sStr.replace(/&/g,"&");
sStr = sStr.replace(/>/g,">");
sStr = sStr.replace(/</g,"<");
sStr = sStr.replace(/\\\\"/g,'"');
sStr = sStr.replace(/\\\\'/g,"'");
return sStr;
}; /**
* html属性编码:对需要出现在HTML属性里的不信任输入进行编码
注意:
(1)该函数不适用于属性为一个URL地址的编码.这些标记包括:a/img/frame/iframe/script/xml/embed/object...
属性包括:href/src/lowsrc/dynsrc/background/...
(2)该函数不适用于属性名为 style="[Un-trusted input]" 的编码
* @memberOf string
* @param {String} sStr
* @return {String}
*/
encodeHtmlAttributeSimple = function(sStr){
sStr = sStr.replace(/&/g,"&");
sStr = sStr.replace(/>/g,">");
sStr = sStr.replace(/</g,"<");
sStr = sStr.replace(/"/g,""");
sStr = sStr.replace(/'/g,"'");
sStr = sStr.replace(/=/g,"=");
sStr = sStr.replace(/`/g,"`");
return sStr;
}; /**
* 用做过滤直接放到HTML里的
* @memberOf string
* @param {String} sStr
* @return {String}
*/
encodeHtml = function(sStr) {
return sStr.replace(/[&'"<>\/\\\-\x00-\x09\x0b-\x0c\x1f\x80-\xff]/g, function(r){
return "&#"+r.charCodeAt(0)+";";
}).replace(/ /g, " ").replace(/\r\n/g, "<br />").replace(/\n/g, "<br />").replace(/\r/g, "<br />");
}; /**
* 用做过滤HTML标签里面的东东 比如这个例子里的<input value="XXXX"> XXXX就是要过滤的
* @memberOf string
* @param {String} sStr
* @return {String}
*/
encodeHtmlAttribute = function(sStr) {
return sStr.replace(/[&'"<>\/\\\-\x00-\x1f\x80-\xff]/g, function(r){
return "&#"+r.charCodeAt(0)+";";
});
}; /**
* 用做过滤直接放到HTML里js中的
* @memberOf string
* @param {String} sStr
* @return {String}
*/
encodeScript = function(sStr) {
sStr+="";//确保为String
return sStr.replace(/[\\"']/g, function(r){
return "\\"+r;
}).replace(/%/g, "\\x25").replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\x01/g, "\\x01");
}; /**
* 用做过滤直接放到<a href="javascript:XXXX">中的
* @memberOf string
* @param {String} sStr
* @return {String}
*/
encodeHrefScript = function(sStr) {
return encodeHtml(encodeUrl(escScript(sStr)));
}; /**
* 用做过滤直接放到正则表达式中的
* @memberOf string
* @param {String} sStr
* @return {String}
*/
encodeRegExp = function(sStr) {
return sStr.replace(/[\\\^\$\*\+\?\{\}\.\(\)\[\]]/g, function(a,b){
return "\\"+a;
});
}; /**
* 用做过滤直接URL参数里的 比如 http://show8.qq.com/abc_cgi?a=XXX XXX就是要过滤的
* @memberOf string
* @param {String} sStr
* @return {String}
*/
encodeUrl = function(sStr) {
return escape(sStr).replace(/\+/g, "%2B");
}; /**
对需要出现在一个URI的一部分的不信任输入进行编码
例如:
<a href="http://search.msn.com/results.aspx?q1=[Un-trusted-input]& q2=[Un-trusted-input]">Click Here!</a>
以下字符将会被编码:
除[a-zA-Z0-9.-_]以外的字符都会被替换成URL编码
*
* @memberOf string
* @param {String} sStr
* @return {String}
*/
encodeUriComponent = function(sStr){
sStr = encodeURIComponent(sStr);
sStr = sStr.replace(/~/g,"%7E");
sStr = sStr.replace(/!/g,"%21");
sStr = sStr.replace(/\*/g,"%2A");
sStr = sStr.replace(/\(/g,"%28");
sStr = sStr.replace(/\)/g,"%29");
sStr = sStr.replace(/'/g,"%27");
sStr = sStr.replace(/\?/g,"%3F");
sStr = sStr.replace(/;/g,"%3B");
return sStr;
}; /**
* 验证给定字符串是否是url, 如果是url 则返回正常的url
*
* @memberOf string
* @param {String} url
* @return {String}
*/
vaildURL = function(url){
url=encodeURI(url).replace(/(^\s*)|(\s*$)/g, ''),
protocolReg=/(^[a-zA-Z0-9]+[^.]):/,
domainReg=/^[\S.]+\.[\S.]+$/,
domainendReg=/[\w.]+\/(\S*)/,
jsReg=/;$/,
jpReg=/^[\s*]*javascript[\s*]*:/; if((!protocolReg.test(url)) && (!domainReg.test(url))){
url="";
}else{
if(!protocolReg.test(url)){
url="http://"+url;
}
if(!domainendReg.test(url)){
url=url+"/"; }
//如果是js为协议就清空
if(jpReg.test(url)){
url="";
}
} return url;
}; /**
* 获取字符实际宽度
* @memberOf string
* @param {String} str 需要计算的字符串
* @param {Number} fontSize 字体大小,可以不填
* @return {Number}
*/
getCharWidth = function(str,fontSize) {
var d= document.createElement("div");
d.style.visibility= "hidden";
d.style.width= "auto";
if(fontSize) {
d.style.fontSize= fontSize + "px";
}
d.style.position= "absolute";
d.innerHTML= encodeHtmlSimple(str);
document.body.appendChild(d);
var width= d.offsetWidth;
document.body.removeChild(d);
return width;
}; /**
* 按给定宽度裁剪字符串
* @memberOf string
* @param {String} str
* @param {Number} fontsize 字体大小
* @param {Number} width 限定的宽度
* @return {Number}
*/
cutByWidth = function(str,fontsize,width) {
for(var i=str.length;i>=0;--i)
{
str=str.substring(0, i);
if(getCharWidth(str, fontsize)<width)
{
return str;
}
}
return '';
}; $string.cutByWidth = cutByWidth;
$string.toString = toString;
$string.template = template;
$string.parseURL = parseURL;
$string.buildURL = buildURL;
$string.mapQuery = mapQuery;
$string.test = test;
$string.contains = contains;
$string.trim = trim;
$string.clean = clean;
$string.camelCase = camelCase;
$string.hyphenate = hyphenate;
$string.capitalize = capitalize;
$string.escapeRegExp = escapeRegExp;
$string.toInt = toInt;
$string.toFloat = toFloat;
$string.toSingleLine = toSingleLine; $string.toHtml = toHtml;
$string.toTitle = toTitle;
$string.toQueryPair = toQueryPair;
$string.toQueryString = toQueryString; $string.hexToRgb = hexToRgb;
$string.rgbToHex = rgbToHex;
$string.stripScripts = stripScripts;
$string.substitute = substitute;
$string.replaceAll = replaceAll; $string.byteLength = byteLength;
$string.cutRight = cutRight; $string.isNumber = isNumber;
$string.isEmail = isEmail; $string.cutByBytes = cutByBytes; //html正文编码:对需要出现在HTML正文里(除了HTML属性外)的不信任输入进行编码
$string.encodeHtmlSimple = encodeHtmlSimple; //html正文解码:对HtmlEncode函数的结果进行解码
$string.decodeHtmlSimple = decodeHtmlSimple;
$string.decodeHtmlSimple2 = decodeHtmlSimple2; /*
html属性编码:对需要出现在HTML属性里的不信任输入进行编码
注意:
(1)该函数不适用于属性为一个URL地址的编码.这些标记包括:a/img/frame/iframe/script/xml/embed/object...
属性包括:href/src/lowsrc/dynsrc/background/...
(2)该函数不适用于属性名为 style="[Un-trusted input]" 的编码
*/
$string.encodeHtmlAttributeSimple = encodeHtmlAttributeSimple; //用做过滤HTML标签里面的东东 比如这个例子里的<input value="XXXX"> XXXX就是要过滤的
$string.encodeHtmlAttribute = encodeHtmlAttribute; //用做过滤直接放到HTML里的
$string.encodeHtml = encodeHtml; //用做过滤直接放到HTML里js中的
$string.encodeScript = encodeScript; //用做过滤直接放到<a href="javascript:XXXX">中的
$string.encodeHrefScript = encodeHrefScript; //用做过滤直接放到正则表达式中的
$string.encodeRegExp = encodeRegExp; //用做过滤直接URL参数里的 比如 http://show8.qq.com/abc_cgi?a=XXX XXX就是要过滤的
$string.encodeUrl = encodeUrl; /*
对需要出现在一个URI的一部分的不信任输入进行编码
例如:
<a href="http://search.msn.com/results.aspx?q1=[Un-trusted-input]& q2=[Un-trusted-input]">Click Here!</a>
以下字符将会被编码:
除[a-zA-Z0-9.-_]以外的字符都会被替换成URL编码
*/
$string.encodeUriComponent = encodeUriComponent; $string.vaildURL = vaildURL; $string.getCharWidth = getCharWidth; /**
* underscore.string.js
*/
var underscore_string=(function(){ // Defining helper functions. var nativeTrim = String.prototype.trim;
var nativeTrimRight = String.prototype.trimRight;
var nativeTrimLeft = String.prototype.trimLeft; var parseNumber = function (source) {
return source * 1 || 0;
}; var strRepeat = function (str, qty) {
if (qty < 1) return '';
var result = '';
while (qty > 0) {
if (qty & 1) result += str;
qty >>= 1, str += str;
}
return result;
}; var slice = [].slice; var defaultToWhiteSpace = function (characters) {
if (characters == null)
return '\\s';
else if (characters.source)
return characters.source;
else
return '[' + _s.escapeRegExp(characters) + ']';
}; var escapeChars = {
lt: '<',
gt: '>',
quot: '"',
apos: "'",
amp: '&'
}; var reversedEscapeChars = {};
for (var key in escapeChars) {
reversedEscapeChars[escapeChars[key]] = key;
} // sprintf() for JavaScript 0.7-beta1
// http://www.diveintojavascript.com/projects/javascript-sprintf
//
// Copyright (c) Alexandru Marasteanu <alexaholic [at) gmail (dot] com>
// All rights reserved. var sprintf = (function () {
function get_type(variable) {
return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase();
} var str_repeat = strRepeat; var str_format = function () {
if (!str_format.cache.hasOwnProperty(arguments[0])) {
str_format.cache[arguments[0]] = str_format.parse(arguments[0]);
}
return str_format.format.call(null, str_format.cache[arguments[0]], arguments);
}; str_format.format = function (parse_tree, argv) {
var cursor = 1, tree_length = parse_tree.length, node_type = '', arg, output = [], i, k, match, pad, pad_character, pad_length;
for (i = 0; i < tree_length; i++) {
node_type = get_type(parse_tree[i]);
if (node_type === 'string') {
output.push(parse_tree[i]);
}
else if (node_type === 'array') {
match = parse_tree[i]; // convenience purposes only
if (match[2]) { // keyword argument
arg = argv[cursor];
for (k = 0; k < match[2].length; k++) {
if (!arg.hasOwnProperty(match[2][k])) {
throw new Error(sprintf('[_.sprintf] property "%s" does not exist', match[2][k]));
}
arg = arg[match[2][k]];
}
} else if (match[1]) { // positional argument (explicit)
arg = argv[match[1]];
}
else { // positional argument (implicit)
arg = argv[cursor++];
} if (/[^s]/.test(match[8]) && (get_type(arg) != 'number')) {
throw new Error(sprintf('[_.sprintf] expecting number but found %s', get_type(arg)));
}
switch (match[8]) {
case 'b':
arg = arg.toString(2);
break;
case 'c':
arg = String.fromCharCode(arg);
break;
case 'd':
arg = parseInt(arg, 10);
break;
case 'e':
arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential();
break;
case 'f':
arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg);
break;
case 'o':
arg = arg.toString(8);
break;
case 's':
arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg);
break;
case 'u':
arg = Math.abs(arg);
break;
case 'x':
arg = arg.toString(16);
break;
case 'X':
arg = arg.toString(16).toUpperCase();
break;
}
arg = (/[def]/.test(match[8]) && match[3] && arg >= 0 ? '+' + arg : arg);
pad_character = match[4] ? match[4] == '0' ? '0' : match[4].charAt(1) : ' ';
pad_length = match[6] - String(arg).length;
pad = match[6] ? str_repeat(pad_character, pad_length) : '';
output.push(match[5] ? arg + pad : pad + arg);
}
}
return output.join('');
}; str_format.cache = {}; str_format.parse = function (fmt) {
var _fmt = fmt, match = [], parse_tree = [], arg_names = 0;
while (_fmt) {
if ((match = /^[^\x25]+/.exec(_fmt)) !== null) {
parse_tree.push(match[0]);
}
else if ((match = /^\x25{2}/.exec(_fmt)) !== null) {
parse_tree.push('%');
}
else if ((match = /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(_fmt)) !== null) {
if (match[2]) {
arg_names |= 1;
var field_list = [], replacement_field = match[2], field_match = [];
if ((field_match = /^([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
field_list.push(field_match[1]);
while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') {
if ((field_match = /^\.([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
field_list.push(field_match[1]);
}
else if ((field_match = /^\[(\d+)\]/.exec(replacement_field)) !== null) {
field_list.push(field_match[1]);
}
else {
throw new Error('[_.sprintf] huh?');
}
}
}
else {
throw new Error('[_.sprintf] huh?');
}
match[2] = field_list;
}
else {
arg_names |= 2;
}
if (arg_names === 3) {
throw new Error('[_.sprintf] mixing positional and named placeholders is not (yet) supported');
}
parse_tree.push(match);
}
else {
throw new Error('[_.sprintf] huh?');
}
_fmt = _fmt.substring(match[0].length);
}
return parse_tree;
}; return str_format;
})(); // Defining underscore.string var _s = { isBlank: function (str) {
if (str == null) str = '';
return (/^\s*$/).test(str);
}, stripTags: function (str) {
if (str == null) return '';
return String(str).replace(/<\/?[^>]+>/g, '');
}, capitalize: function (str) {
str = str == null ? '' : String(str);
return str.charAt(0).toUpperCase() + str.slice(1);
}, chop: function (str, step) {
if (str == null) return [];
str = String(str);
step = ~~step;
return step > 0 ? str.match(new RegExp('.{1,' + step + '}', 'g')) : [str];
}, clean: function (str) {
return _s.strip(str).replace(/\s+/g, ' ');
}, count: function (str, substr) {
if (str == null || substr == null) return 0;
return String(str).split(substr).length - 1;
}, chars: function (str) {
if (str == null) return [];
return String(str).split('');
}, swapCase: function (str) {
if (str == null) return '';
return String(str).replace(/\S/g, function (c) {
return c === c.toUpperCase() ? c.toLowerCase() : c.toUpperCase();
});
}, escapeHTML: function (str) {
if (str == null) return '';
return String(str).replace(/[&<>"']/g, function (m) {
return '&' + reversedEscapeChars[m] + ';';
});
}, unescapeHTML: function (str) {
if (str == null) return '';
return String(str).replace(/\&([^;]+);/g, function (entity, entityCode) {
var match; if (entityCode in escapeChars) {
return escapeChars[entityCode];
} else if (match = entityCode.match(/^#x([\da-fA-F]+)$/)) {
return String.fromCharCode(parseInt(match[1], 16));
} else if (match = entityCode.match(/^#(\d+)$/)) {
return String.fromCharCode(~~match[1]);
} else {
return entity;
}
});
}, escapeRegExp: function (str) {
if (str == null) return '';
return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
}, splice: function (str, i, howmany, substr) {
var arr = _s.chars(str);
arr.splice(~~i, ~~howmany, substr);
return arr.join('');
}, insert: function (str, i, substr) {
return _s.splice(str, i, 0, substr);
}, include: function (str, needle) {
if (needle === '') return true;
if (str == null) return false;
return String(str).indexOf(needle) !== -1;
}, join: function () {
var args = slice.call(arguments),
separator = args.shift(); if (separator == null) separator = ''; return args.join(separator);
}, lines: function (str) {
if (str == null) return [];
return String(str).split("\n");
}, reverse: function (str) {
return _s.chars(str).reverse().join('');
}, startsWith: function (str, starts) {
if (starts === '') return true;
if (str == null || starts == null) return false;
str = String(str);
starts = String(starts);
return str.length >= starts.length && str.slice(0, starts.length) === starts;
}, endsWith: function (str, ends) {
if (ends === '') return true;
if (str == null || ends == null) return false;
str = String(str);
ends = String(ends);
return str.length >= ends.length && str.slice(str.length - ends.length) === ends;
}, succ: function (str) {
if (str == null) return '';
str = String(str);
return str.slice(0, -1) + String.fromCharCode(str.charCodeAt(str.length - 1) + 1);
}, titleize: function (str) {
if (str == null) return '';
return String(str).replace(/(?:^|\s)\S/g, function (c) {
return c.toUpperCase();
});
}, camelize: function (str) {
return _s.trim(str).replace(/[-_\s]+(.)?/g, function (match, c) {
return c.toUpperCase();
});
}, underscored: function (str) {
return _s.trim(str).replace(/([a-z\d])([A-Z]+)/g, '$1_$2').replace(/[-\s]+/g, '_').toLowerCase();
}, dasherize: function (str) {
return _s.trim(str).replace(/([A-Z])/g, '-$1').replace(/[-_\s]+/g, '-').toLowerCase();
}, classify: function (str) {
return _s.titleize(String(str).replace(/_/g, ' ')).replace(/\s/g, '');
}, humanize: function (str) {
return _s.capitalize(_s.underscored(str).replace(/_id$/, '').replace(/_/g, ' '));
}, trim: function (str, characters) {
if (str == null) return '';
if (!characters && nativeTrim) return nativeTrim.call(str);
characters = defaultToWhiteSpace(characters);
return String(str).replace(new RegExp('\^' + characters + '+|' + characters + '+$', 'g'), '');
}, ltrim: function (str, characters) {
if (str == null) return '';
if (!characters && nativeTrimLeft) return nativeTrimLeft.call(str);
characters = defaultToWhiteSpace(characters);
return String(str).replace(new RegExp('^' + characters + '+'), '');
}, rtrim: function (str, characters) {
if (str == null) return '';
if (!characters && nativeTrimRight) return nativeTrimRight.call(str);
characters = defaultToWhiteSpace(characters);
return String(str).replace(new RegExp(characters + '+$'), '');
}, truncate: function (str, length, truncateStr) {
if (str == null) return '';
str = String(str);
truncateStr = truncateStr || '...';
length = ~~length;
return str.length > length ? str.slice(0, length) + truncateStr : str;
}, /**
* _s.prune: a more elegant version of truncate
* prune extra chars, never leaving a half-chopped word.
* @author github.com/rwz
*/
prune: function (str, length, pruneStr) {
if (str == null) return ''; str = String(str);
length = ~~length;
pruneStr = pruneStr != null ? String(pruneStr) : '...'; if (str.length <= length) return str; var tmpl = function (c) {
return c.toUpperCase() !== c.toLowerCase() ? 'A' : ' ';
},
template = str.slice(0, length + 1).replace(/.(?=\W*\w*$)/g, tmpl); // 'Hello, world' -> 'HellAA AAAAA' if (template.slice(template.length - 2).match(/\w\w/))
template = template.replace(/\s*\S+$/, '');
else
template = _s.rtrim(template.slice(0, template.length - 1)); return (template + pruneStr).length > str.length ? str : str.slice(0, template.length) + pruneStr;
}, words: function (str, delimiter) {
if (_s.isBlank(str)) return [];
return _s.trim(str, delimiter).split(delimiter || /\s+/);
}, pad: function (str, length, padStr, type) {
str = str == null ? '' : String(str);
length = ~~length; var padlen = 0; if (!padStr)
padStr = ' ';
else if (padStr.length > 1)
padStr = padStr.charAt(0); switch (type) {
case 'right':
padlen = length - str.length;
return str + strRepeat(padStr, padlen);
case 'both':
padlen = length - str.length;
return strRepeat(padStr, Math.ceil(padlen / 2)) + str
+ strRepeat(padStr, Math.floor(padlen / 2));
default: // 'left'
padlen = length - str.length;
return strRepeat(padStr, padlen) + str;
}
}, lpad: function (str, length, padStr) {
return _s.pad(str, length, padStr);
}, rpad: function (str, length, padStr) {
return _s.pad(str, length, padStr, 'right');
}, lrpad: function (str, length, padStr) {
return _s.pad(str, length, padStr, 'both');
}, sprintf: sprintf, vsprintf: function (fmt, argv) {
argv.unshift(fmt);
return sprintf.apply(null, argv);
}, toNumber: function (str, decimals) {
if (str == null || str == '') return 0;
str = String(str);
var num = parseNumber(parseNumber(str).toFixed(~~decimals));
return num === 0 && !str.match(/^0+$/) ? Number.NaN : num;
}, numberFormat: function (number, dec, dsep, tsep) {
if (isNaN(number) || number == null) return ''; number = number.toFixed(~~dec);
tsep = tsep || ','; var parts = number.split('.'), fnums = parts[0],
decimals = parts[1] ? (dsep || '.') + parts[1] : ''; return fnums.replace(/(\d)(?=(?:\d{3})+$)/g, '$1' + tsep) + decimals;
}, strRight: function (str, sep) {
if (str == null) return '';
str = String(str);
sep = sep != null ? String(sep) : sep;
var pos = !sep ? -1 : str.indexOf(sep);
return ~pos ? str.slice(pos + sep.length, str.length) : str;
}, strRightBack: function (str, sep) {
if (str == null) return '';
str = String(str);
sep = sep != null ? String(sep) : sep;
var pos = !sep ? -1 : str.lastIndexOf(sep);
return ~pos ? str.slice(pos + sep.length, str.length) : str;
}, strLeft: function (str, sep) {
if (str == null) return '';
str = String(str);
sep = sep != null ? String(sep) : sep;
var pos = !sep ? -1 : str.indexOf(sep);
return ~pos ? str.slice(0, pos) : str;
}, strLeftBack: function (str, sep) {
if (str == null) return '';
str += '';
sep = sep != null ? '' + sep : sep;
var pos = str.lastIndexOf(sep);
return ~pos ? str.slice(0, pos) : str;
}, toSentence: function (array, separator, lastSeparator, serial) {
separator = separator || ', '
lastSeparator = lastSeparator || ' and '
var a = array.slice(), lastMember = a.pop(); if (array.length > 2 && serial) lastSeparator = _s.rtrim(separator) + lastSeparator; return a.length ? a.join(separator) + lastSeparator + lastMember : lastMember;
}, toSentenceSerial: function () {
var args = slice.call(arguments);
args[3] = true;
return _s.toSentence.apply(_s, args);
}, slugify: function (str) {
if (str == null) return ''; var from = "ąàáäâãåæćęèéëêìíïîłńòóöôõøùúüûñçżź",
to = "aaaaaaaaceeeeeiiiilnoooooouuuunczz",
regex = new RegExp(defaultToWhiteSpace(from), 'g'); str = String(str).toLowerCase().replace(regex, function (c) {
var index = from.indexOf(c);
return to.charAt(index) || '-';
}); return _s.dasherize(str.replace(/[^\w\s-]/g, ''));
}, surround: function (str, wrapper) {
return [wrapper, str, wrapper].join('');
}, quote: function (str) {
return _s.surround(str, '"');
}, exports: function () {
var result = {}; for (var prop in this) {
if (!this.hasOwnProperty(prop) || prop.match(/^(?:include|contains|reverse)$/)) continue;
result[prop] = this[prop];
} return result;
}, repeat: function (str, qty, separator) {
if (str == null) return ''; qty = ~~qty; // using faster implementation if separator is not needed;
if (separator == null) return strRepeat(String(str), qty); // this one is about 300x slower in Google Chrome
for (var repeat = []; qty > 0; repeat[--qty] = str) {
}
return repeat.join(separator);
}, levenshtein: function (str1, str2) {
if (str1 == null && str2 == null) return 0;
if (str1 == null) return String(str2).length;
if (str2 == null) return String(str1).length; str1 = String(str1);
str2 = String(str2); var current = [], prev, value; for (var i = 0; i <= str2.length; i++)
for (var j = 0; j <= str1.length; j++) {
if (i && j)
if (str1.charAt(j - 1) === str2.charAt(i - 1))
value = prev;
else
value = Math.min(current[j], current[j - 1], prev) + 1;
else
value = i + j; prev = current[j];
current[j] = value;
} return current.pop();
}
}; // Aliases
_s.strip = _s.trim;
_s.lstrip = _s.ltrim;
_s.rstrip = _s.rtrim;
_s.center = _s.lrpad;
_s.rjust = _s.lpad;
_s.ljust = _s.rpad;
_s.contains = _s.include;
return _s;
})(); _.extend($string,underscore_string);