zoukankan      html  css  js  c++  java
  • jquery插件 源码

    下面是对Jquery几个经常用到的地方进行的增强。

    功能是参考百度七巧板JS框架来完成的。

    一、页面属性

    $.page.getHeight():获取页面高度

    $.page.getWidth():获取页面宽度
    $.page.createStyleSheet(options):在页面中创建样式表对象
    $.page.getScrollTop():获取纵向滚动量
    $.page.getScrollLeft():获取横向滚动量
    $.page.getViewHeight():获取页面视觉区域高度
    $.page.getViewWidth():获取页面视觉区域宽度
    $.page.getMousePosition(element):获得页面里的目前鼠标所在的坐标
    $.page.getPosition(element):获取目标元素相对于整个文档左上角的位置
    $.page.lazyLoadImage(options):延迟加载图片. 默认只加载可见高度以上的图片, 随着窗口滚动加载剩余图片.注意: 仅支持垂直方向.
    $.page.loadCssFile(path):动态在页面上加载一个外部css文件
    $.page.loadJsFile(path):动态在页面上加载一个外部js文件
    $.page.load(resources, options, ignoreAllLoaded):加载一组资源,支持多种格式资源的串/并行加载,支持每个文件有单独回调函数。

    二、浏览器判断
    $.browser.ie
    $.browser.firefox
    $.browser.chrome
    $.browser.isGecko
    $.browser.isWebkit
    $.browser.isStrict
    $.browser.opera
    $.browser.safari



    三、平台判断
    $.platform.isAndroid
    $.platform.isIpad
    $.platform.isIphone
    $.platform.isMacintosh
    $.platform.isWindows
    $.platform.isX11



    四、字符串处理
    $.string.decodeHTML(source):对目标字符串进行html解码
    $.string.encodeHTML(source):对目标字符串进行html编码
    $.string.stripTags(source):去掉字符串中的html标签
    $.string.escapeReg(source):将目标字符串中可能会影响正则表达式构造的字符串进行转义。
    $.string.trim(source):删除目标字符串两端的空白字符



    五、类型
    $.lang.guid():返回一个当前页面的唯一标识字符串。
    $.lang.isFunction(source):判断目标参数是否为function或Function实例
    $.lang.isElement(source):判断目标参数是否为Element对象
    $.lang.isArray(source):判断目标参数是否Array对象



    六、数组
    $.array.indexOf(source, match, fromIndex):查询数组中指定元素的索引位置
    $.array.contains(source, obj):判断一个数组中是否包含给定元素
    $.array.empty(source):清空一个数组
    $.array.lastIndexOf(source, match, fromIndex):从后往前,查询数组中指定元素的索引位置
    $.array.map(source, iterator, thisObject):遍历数组中所有元素,将每一个元素应用方法进行转换,并返回转换后的新数组。
    $.array.reduce(source, iterator, initializer):遍历数组中所有元素,将每一个元素应用方法进行合并,并返回合并后的结果。
    $.array.remove(source, match):移除数组中的项
    $.array.removeAt(source, index):移除数组中的项
    $.array.unique(source, compareFn):过滤数组中的相同项。如果两个元素相同,会删除后一个元素。



    七、cookie
    $.cookie.getRaw(key):获取cookie的值,不对值进行解码
    $.cookie.setRaw(key, value, options):设置cookie的值,不对值进行编码
    $.cookie.remove(key, options):删除cookie的值
    $.cookie.get(key):获取cookie的值,用decodeURIComponent进行解码
    $.cookie.set(key, value, options):设置cookie的值,用encodeURIComponent进行编码



    八、整数
    $.number.comma(source, length):为目标数字添加逗号分隔
    $.number.randomInt(min, max):生成随机整数,范围是[min, max]
    $.number.pad(source, length):对目标数字进行0补齐处理



    九、日志
    $.sio.log(url):通过请求一个图片的方式令服务器存储一条日志,常用于记录用户点击位置,进行分析统计



    十、URL
    $.url.escapeSymbol(source):对字符串进行%#&+=以及和s匹配的所有字符进行url转义
    $.url.getQueryValue(url, key):根据参数名从目标URL中获取参数值
    $.url.jsonToQuery(json, replacer_opt):将json对象解析成query字符串

    $.url.queryToJson(url):解析目标URL中的参数成json对象

       1 ;(function($){
       2     $.extend({
       3         hasClass:function(targetClassName){
       4             var className = $(this).attr("class");
       5             var classArray = className.split(" ");
       6             if(className && classArray.length == 0){
       7                 if(targetClassName == className) return true;
       8             }else if(className && classArray.length > 0){
       9                 for(var i=0; i<=classArray.length-1; i++){
      10                     if(classArray[i] == targetClassName) return true;
      11                 }
      12             }
      13 
      14             return false;
      15         },
      16         
      17         getDocument:function (element) {
      18             return $.lang.isElement(element) ? element : element.ownerDocument || element.document;
      19         }
      20     });
      21 })(jQuery);
      22 
      23 ;(function($){
      24     $.lang = $.lang || {};
      25     
      26     $.lang.isFunction = function (source) {
      27         // chrome下,'function' == typeof /a/ 为true.
      28         return '[object Function]' == Object.prototype.toString.call(source);
      29     };
      30     
      31     $.lang.isString = function (source) {
      32         return '[object String]' == Object.prototype.toString.call(source);
      33     };
      34 })(jQuery);
      35 
      36 ;(function($){
      37     
      38     $.page = $.page || {};
      39     $.page.xy = {x:0, y:0};//当前鼠标坐标
      40 
      41     $.page.getHeight = $.page.getHeight || function(){
      42         var doc = document,
      43         body = doc.body,
      44         html = doc.documentElement,
      45         client = doc.compatMode == 'BackCompat' ? body : doc.documentElement;
      46 
      47         return Math.max(html.scrollHeight, body.scrollHeight, client.clientHeight);
      48     };
      49 
      50     $.page.getWidth  = $.page.getWidth || function () {
      51         var doc = document,
      52         body = doc.body,
      53         html = doc.documentElement,
      54         client = doc.compatMode == 'BackCompat' ? body : doc.documentElement;
      55 
      56         return Math.max(html.scrollWidth, body.scrollWidth, client.clientWidth);
      57     };
      58 
      59     $.page.createStyleSheet = $.page.createStyleSheet || function(options){
      60         var op = options || {},
      61             doc = op.document || document,
      62             s;
      63 
      64         if ($.browser.ie) {
      65             //修复ie下会请求一个undefined的bug  berg 2010/08/27 
      66             if(!op.url)
      67                 op.url = "";
      68             return doc.createStyleSheet(op.url, op.index);
      69         } else {
      70             s = "<style type='text/css'></style>";
      71             op.url && (s="<link type='text/css' rel='stylesheet' href='"+op.url+"'/>");
      72             $("HEAD:eq(0)").after(s);
      73         }
      74     };
      75 
      76     $.page.getScrollTop =  $.page.getScrollTop || function(){
      77         var d = document;
      78         return window.pageYOffset || d.documentElement.scrollTop || d.body.scrollTop;
      79     };
      80 
      81     $.page.getScrollLeft= $.page.getScrollLeft || function () {
      82         var d = document;
      83         return window.pageXOffset || d.documentElement.scrollLeft || d.body.scrollLeft;
      84     };
      85 
      86     $.page.getViewHeight = $.page.getViewHeight || function () {
      87         var doc = document,
      88             client = doc.compatMode == 'BackCompat' ? doc.body : doc.documentElement;
      89 
      90         return client.clientHeight;
      91     };
      92 
      93     $.page.getViewWidth = function () {
      94         var doc = document,
      95             client = doc.compatMode == 'BackCompat' ? doc.body : doc.documentElement;
      96 
      97         return client.clientWidth;
      98     };
      99     
     100     $(document).bind("mousemove", function(e){
     101         e = window.event || e;
     102         $.page.xy.x = e.clientX;
     103         $.page.xy.y = e.clientY;
     104         //console.log(e.clientX+","+e.clientY);
     105     });
     106 
     107     $.page.getMousePosition = $.page.getMousePosition || function(){
     108         return {
     109             x : $.page.getScrollLeft() + $.page.xy.x,
     110             y : $.page.getScrollTop() + $.page.xy.y
     111         };
     112     };
     113 
     114     /**
     115      * 获取目标元素相对于整个文档左上角的位置
     116      * @grammar $.dom.getPosition(element)
     117      * @param {HTMLElement|string} element 目标元素或目标元素的id
     118      *             
     119      * @returns {Object} 目标元素的位置,键值为top和left的Object。
     120      */
     121     $.page.getPosition = function (element) {
     122         var doc = $.getDocument(element),
     123             browser = $.browser
     124         // Gecko 1.9版本以下用getBoxObjectFor计算位置
     125         // 但是某些情况下是有bug的
     126         // 对于这些有bug的情况
     127         // 使用递归查找的方式
     128             BUGGY_GECKO_BOX_OBJECT = browser.isGecko > 0 && 
     129                                      doc.getBoxObjectFor &&
     130                                      $(element).css('position') == 'absolute' &&
     131                                      (element.style.top === '' || element.style.left === ''),
     132             pos = {"left":0,"top":0},
     133             viewport = (browser.ie && !browser.isStrict) ? doc.body : doc.documentElement,
     134             parent;
     135         var box;
     136         
     137         if(element == viewport){
     138             return pos;
     139         }
     140 
     141         if(element.getBoundingClientRect){ // IE and Gecko 1.9+
     142             //当HTML或者BODY有border width时, 原生的getBoundingClientRect返回值是不符合预期的
     143             //考虑到通常情况下 HTML和BODY的border只会设成0px,所以忽略该问题.
     144             doc = document;
     145             box = element.getBoundingClientRect();
     146 
     147             pos.left = Math.floor(box.left) + Math.max(doc.documentElement.scrollLeft, doc.body.scrollLeft);
     148             pos.top  = Math.floor(box.top)  + Math.max(doc.documentElement.scrollTop,  doc.body.scrollTop);
     149             
     150             // IE会给HTML元素添加一个border,默认是medium(2px)
     151             // 但是在IE 6 7 的怪异模式下,可以被html { border: 0; } 这条css规则覆盖
     152             // 在IE7的标准模式下,border永远是2px,这个值通过clientLeft 和 clientTop取得
     153             // 但是。。。在IE 6 7的怪异模式,如果用户使用css覆盖了默认的medium
     154             // clientTop和clientLeft不会更新
     155             pos.left -= doc.documentElement.clientLeft;
     156             pos.top  -= doc.documentElement.clientTop;
     157             
     158             var htmlDom = doc.body,
     159                 // 在这里,不使用element.style.borderLeftWidth,只有computedStyle是可信的
     160                 htmlBorderLeftWidth = parseInt($(htmlDom).css('borderLeftWidth')),
     161                 htmlBorderTopWidth = parseInt($(htmlDom).css('borderTopWidth'));
     162             if(browser.ie && !browser.isStrict){
     163                 pos.left -= isNaN(htmlBorderLeftWidth) ? 2 : htmlBorderLeftWidth;
     164                 pos.top  -= isNaN(htmlBorderTopWidth) ? 2 : htmlBorderTopWidth;
     165             }
     166         /*
     167          * 因为firefox 3.6和4.0在特定页面下(场景待补充)都会出现1px偏移,所以暂时移除该逻辑分支
     168          * 如果 2.0版本时firefox仍存在问题,该逻辑分支将彻底移除. by rocy 2011-01-20
     169         } else if (doc.getBoxObjectFor && !BUGGY_GECKO_BOX_OBJECT){ // gecko 1.9-
     170 
     171             // 1.9以下的Gecko,会忽略ancestors的scroll值
     172             // https://bugzilla.mozilla.org/show_bug.cgi?id=328881 and
     173             // https://bugzilla.mozilla.org/show_bug.cgi?id=330619
     174 
     175             box = doc.getBoxObjectFor(element);
     176             var vpBox = doc.getBoxObjectFor(viewport);
     177             pos.left = box.screenX - vpBox.screenX;
     178             pos.top  = box.screenY - vpBox.screenY;
     179             */
     180         } else { // safari/opera/firefox
     181             parent = element;
     182 
     183             do {
     184                 pos.left += parent.offsetLeft;
     185                 pos.top  += parent.offsetTop;
     186                 // safari里面,如果遍历到了一个fixed的元素,后面的offset都不准了
     187                 if (browser.isWebkit > 0 && $(parent).css('position') == 'fixed') {
     188                     pos.left += doc.body.scrollLeft;
     189                     pos.top  += doc.body.scrollTop;
     190                     break;
     191                 }
     192                 
     193                 parent = parent.offsetParent;
     194             } while (parent && parent != element);
     195 
     196             // 对body offsetTop的修正
     197             if(browser.opera > 0 || (browser.isWebkit > 0 && $(parent).css('position') == 'absolute')){
     198                 pos.top  -= doc.body.offsetTop;
     199             }
     200 
     201             // 计算除了body的scroll
     202             parent = element.offsetParent;
     203             while (parent && parent != doc.body) {
     204                 pos.left -= parent.scrollLeft;
     205                 // see https://bugs.opera.com/show_bug.cgi?id=249965
     206     //            if (!b.opera || parent.tagName != 'TR') {
     207                 if (!browser.opera || parent.tagName != 'TR') {
     208                     pos.top -= parent.scrollTop;
     209                 }
     210                 parent = parent.offsetParent;
     211             }
     212         }
     213 
     214         return pos;
     215     };
     216 
     217     /**
     218      * 延迟加载图片. 默认只加载可见高度以上的图片, 随着窗口滚动加载剩余图片.注意: 仅支持垂直方向.
     219      * @grammar $.page.lazyLoadImage([options])
     220      * @param {Object} options
     221      * @param {String} [options.className] 延迟加载的IMG的className,如果不传入该值将延迟加载所有IMG.
     222      * @param {Number} [options.preloadHeight] 预加载的高度, 可见窗口下该高度内的图片将被加载.
     223      * @param {String} [options.placeHolder] 占位图url.
     224      * @param {Function} [options.onlazyload] 延迟加载回调函数,在实际加载时触发.
     225      */
     226     $.page.lazyLoadImage = function(options) {
     227         options = options || {};
     228         options.preloadHeight = options.preloadHeight || 0;
     229 
     230         $(document).ready(function() {
     231             var imgs = document.getElementsByTagName('IMG'),
     232                     targets = imgs,
     233                     len = imgs.length,
     234                     i = 0,
     235                     viewOffset = getLoadOffset(),
     236                     srcAttr = 'data-tangram-ori-src',
     237                     target;
     238             //避免循环中每次都判断className
     239             if (options.className) {
     240                 targets = [];
     241                 for (; i < len; ++i) {
     242                     if ($(imgs[i]).hasClass(options.className)) {
     243                         targets.push(imgs[i]);
     244                     }
     245                 }
     246             }
     247             //计算需要加载图片的页面高度
     248             function getLoadOffset() {
     249                 return $.page.getScrollTop() + $.page.getViewHeight() + options.preloadHeight;
     250             }
     251             //加载可视图片
     252             for (i = 0, len = targets.length; i < len; ++i) {
     253                 target = targets[i];
     254                 if ($.page.getPosition(target).top > viewOffset) {
     255                     target.setAttribute(srcAttr, target.src);
     256                     options.placeHolder ? target.src = options.placeHolder : target.removeAttribute('src');
     257                 }
     258             }
     259             //处理延迟加载
     260             var loadNeeded = function() {
     261                 var viewOffset = getLoadOffset(),
     262                     imgSrc,
     263                     finished = true,
     264                     i = 0,
     265                     len = targets.length;
     266                 for (; i < len; ++i) {
     267                     target = targets[i];
     268                     imgSrc = target.getAttribute(srcAttr);
     269                     imgSrc && (finished = false);
     270                     if ($.page.getPosition(target).top < viewOffset && imgSrc) {
     271                         target.src = imgSrc;
     272                         target.removeAttribute(srcAttr);
     273                         $.lang.isFunction(options.onlazyload) && options.onlazyload(target);
     274                     }
     275                 }
     276                 //当全部图片都已经加载, 去掉事件监听
     277                 finished && $(window).unbind('scroll', loadNeeded);
     278             };
     279 
     280             $(window).bind('scroll', loadNeeded);
     281         });
     282     };
     283 
     284     /**
     285      * 动态在页面上加载一个外部css文件
     286      * @grammar $.page.loadCssFile(path)
     287      * @param {string} path css文件路径
     288      */
     289     $.page.loadCssFile = function (path) {
     290         var element = document.createElement("link");
     291         
     292         element.setAttribute("rel", "stylesheet");
     293         element.setAttribute("type", "text/css");
     294         element.setAttribute("href", path);
     295 
     296         document.getElementsByTagName("head")[0].appendChild(element);        
     297     };
     298 
     299 
     300     /**
     301      * 动态在页面上加载一个外部js文件
     302      * @grammar $.page.loadJsFile(path)
     303      * @param {string} path js文件路径
     304      */
     305     $.page.loadJsFile = function (path) {
     306         var element = document.createElement('script');
     307 
     308         element.setAttribute('type', 'text/javascript');
     309         element.setAttribute('src', path);
     310         element.setAttribute('defer', 'defer');
     311 
     312         document.getElementsByTagName("head")[0].appendChild(element);    
     313     };
     314 
     315     /**
     316      *
     317      * 加载一组资源,支持多种格式资源的串/并行加载,支持每个文件有单独回调函数。
     318      *
     319      * @name $.page.load
     320      * @function
     321      * @grammar $.page.load(resources[, options])
     322      *
     323      * @param {Array} resources               资源描述数组,单个resource含如下属性.
     324      * @param {String} resources.url           链接地址.
     325      * @param {String} [resources.type]        取值["css","js","html"],默认参考文件后缀.
     326      * @param {String} [resources.requestType] 取值["dom","ajax"],默认js和css用dom标签,html用ajax.
     327      * @param {Function} resources.onload        当前resource加载完成的回调函数,若requestType为ajax,参数为xhr(可能失效),responseText;若requestType为dom,无参数,执行时this为相应dom标签。.
     328      *
     329      * @param {Object} [options]               可选参数.
     330      * @param {Function} [options.onload]        资源全部加载完成的回调函数,无参数。.
     331      * @param {Boolean} [options.parallel]      是否并行加载,默认为false,串行。.
     332      * @param {Boolean} [ignoreAllLoaded]       全部加载之后不触发回调事件.主要用于内部实现.
     333      *
     334      *
     335      * @remark
     336      *  //串行实例
     337      *  baidu.page.load([
     338      *      { url : "http://img.baidu.com/js/tangram-1.3.2.js" },
     339      *      {url : "http://xxx.baidu.com/xpath/logicRequire.js",
     340      *          onload : fnOnRequireLoaded
     341      *      },
     342      *      { url : "http://xxx.baidu.com/xpath/target.js" }
     343      *  ],{
     344      *      onload : fnWhenTargetOK
     345      *  });
     346      *  //并行实例
     347      *  baidu.page.load([
     348      *      {
     349      *          url : "http://xxx.baidu.com/xpath/template.html",
     350      *          onload : fnExtractTemplate
     351      *      },
     352      *      { url : "http://xxx.baidu.com/xpath/style.css"},
     353      *      {
     354      *          url : "http://xxx.baidu.com/xpath/import.php?f=baidu.*",
     355      *          type : "js"
     356      *      },
     357      *      {
     358      *          url : "http://xxx.baidu.com/xpath/target.js",
     359      *      },
     360      *      {
     361      *          url : "http://xxx.baidu.com/xpath/jsonData.js",
     362      *          requestType : "ajax",
     363      *          onload : fnExtractData
     364      *      }
     365      *  ],{
     366      *      parallel : true,
     367      *      onload : fnWhenEverythingIsOK
     368      * });
     369      */
     370     $.page.load = function(resources, options, ignoreAllLoaded) {
     371         options = options || {};
     372         var self = $.page.load,
     373             cache = self._cache = self._cache || {},
     374             loadingCache = self._loadingCache = self._loadingCache || {},
     375             parallel = options.parallel;
     376 
     377         function allLoadedChecker() {
     378             for (var i = 0, len = resources.length; i < len; ++i) {
     379                 if (! cache[resources[i].url]) {
     380                     setTimeout(arguments.callee, 10);
     381                     return;
     382                 }
     383             }
     384             options.onload();
     385         };
     386 
     387         function loadByDom(res, callback) {
     388             var node, loaded, onready;
     389             switch (res.type.toLowerCase()) {
     390                 case 'css' :
     391                     node = document.createElement('link');
     392                     node.setAttribute('rel', 'stylesheet');
     393                     node.setAttribute('type', 'text/css');
     394                     break;
     395                 case 'js' :
     396                     node = document.createElement('script');
     397                     node.setAttribute('type', 'text/javascript');
     398                     node.setAttribute('charset', res.charset || self.charset);
     399                     break;
     400                 case 'html' :
     401                     node = document.createElement('iframe');
     402                     node.frameBorder = 'none';
     403                     break;
     404                 default :
     405                     return;
     406             }
     407 
     408             // HTML,JS works on all browsers, CSS works only on IE.
     409             onready = function() {
     410                 if (!loaded && (!this.readyState ||
     411                         this.readyState === 'loaded' ||
     412                         this.readyState === 'complete')) {
     413                     loaded = true;
     414                     // 防止内存泄露
     415                     $(node).unbind('load', onready);
     416                     $(node).unbind('readystatechange', onready);
     417                     //node.onload = node.onreadystatechange = null;
     418                     callback.call(window, node);
     419                 }
     420             };
     421             $(node).bind('load', onready);
     422             $(node).bind('readystatechange', onready);
     423             //CSS has no onload event on firefox and webkit platform, so hack it.
     424             if (res.type == 'css') {
     425                 (function() {
     426                     //避免重复加载
     427                     if (loaded) return;
     428                     try {
     429                         node.sheet.cssRule;
     430                     } catch (e) {
     431                         setTimeout(arguments.callee, 20);
     432                         return;
     433                     }
     434                     loaded = true;
     435                     callback.call(window, node);
     436                 })();
     437             }
     438 
     439             node.href = node.src = res.url;
     440             document.getElementsByTagName('head')[0].appendChild(node);
     441         }
     442 
     443         //兼容第一个参数直接是资源地址.
     444         $.lang.isString(resources) && (resources = [{url: resources}]);
     445         //避免递归出错,添加容错.
     446         if (! (resources && resources.length)) return;
     447 
     448         function loadResources(res) {
     449             var url = res.url,
     450                 shouldContinue = !!parallel,
     451                 cacheData,
     452                 callback = function(textOrNode) {
     453                     //ajax存入responseText,dom存入节点,用于保证onload的正确执行.
     454                     cache[res.url] = textOrNode;
     455                     delete loadingCache[res.url];
     456 
     457                     if ($.lang.isFunction(res.onload)) {
     458                         //若返回false, 则停止接下来的加载.
     459                         if (false === res.onload.call(window, textOrNode)) {
     460                             return;
     461                         }
     462                     }
     463                     //串行时递归执行
     464                     !parallel && self(resources.slice(1), options, true);
     465                     if ((! ignoreAllLoaded) && $.lang.isFunction(options.onload)) {
     466                         allLoadedChecker();
     467                     }
     468                 };
     469             //默认用后缀名, 并防止后缀名大写
     470             res.type = res.type || url.replace(/^[^?#]+.(css|js|html)(?|#| |$)[^?#]*/i, '$1'); //[bugfix]修改xxx.js?v这种情况下取不到js的问题。 
     471             //默认html格式用ajax请求,其他都使用dom标签方式请求.
     472             res.requestType = res.requestType || (res.type == 'html' ? 'ajax' : 'dom');
     473 
     474             if (cacheData = cache[res.url]) {
     475                 callback(cacheData);
     476                 return shouldContinue;
     477             }
     478             if (!options.refresh && loadingCache[res.url]) {
     479                 setTimeout(function() {loadResources(res);}, 10);
     480                 return shouldContinue;
     481             }
     482             loadingCache[res.url] = true;
     483             if (res.requestType.toLowerCase() == 'dom') {
     484                 loadByDom(res, callback);
     485             }else {//ajax
     486                 $.getScript(res.url, function(responseText){
     487                     callback(responseText);
     488                 });
     489             }
     490             //串行模式,通过callback方法执行后续
     491             return shouldContinue;
     492         };
     493 
     494         $.each(resources, function(k, item){
     495             loadResources(item);
     496         });
     497     };
     498     //默认编码设置为UTF8
     499     $.page.load.charset = 'UTF8';
     500 })(jQuery);
     501 
     502 ;(function($){
     503     /**
     504      * 判断浏览器类型
     505      */
     506     $.browser = $.browser || {};
     507 
     508     $.browser.ie = /msie (d+.d+)/i.test(navigator.userAgent) ? (document.documentMode || + RegExp['x241']) : undefined;
     509     
     510     $.browser.firefox = /firefox/(d+.d+)/i.test(navigator.userAgent) ? + RegExp['x241'] : undefined;
     511 
     512     $.browser.chrome = /chrome/(d+.d+)/i.test(navigator.userAgent) ? + RegExp['x241'] : undefined;
     513     
     514     //判断是否为gecko内核
     515     $.browser.isGecko = /gecko/i.test(navigator.userAgent) && !/like gecko/i.test(navigator.userAgent);
     516     
     517     //判断是否为webkit内核
     518     $.browser.isWebkit = /webkit/i.test(navigator.userAgent);
     519     
     520     //判断是否严格标准的渲染模式
     521     $.browser.isStrict = document.compatMode == "CSS1Compat";
     522 
     523     $.browser.opera = /opera(/| )(d+(.d+)?)(.+?(version/(d+(.d+)?)))?/i.test(navigator.userAgent) ?  + ( RegExp["x246"] || RegExp["x242"] ) : undefined;
     524 
     525     (function(){
     526         var ua = navigator.userAgent;
     527         /**
     528          * 判断是否为safari浏览器, 支持ipad
     529          * @property safari safari版本号
     530          * @grammar $.browser.safari
     531          */
     532         $.browser.safari = /(d+.d)?(?:.d)?s+safari/?(d+.d+)?/i.test(ua) && !/chrome/i.test(ua) ? + (RegExp['x241'] || RegExp['x242']) : undefined;
     533     })();
     534 })(jQuery);
     535 
     536 
     537 ;(function($){
     538     /**
     539      * 判断平台类型和特性的属性
     540      */
     541     $.platform = $.platform || {};
     542 
     543     /**
     544      * 判断是否为android平台
     545      */
     546     $.platform.isAndroid = /android/i.test(navigator.userAgent);
     547 
     548 
     549     /**
     550      * 判断是否为ipad平台
     551      */
     552     $.platform.isIpad = /ipad/i.test(navigator.userAgent);
     553 
     554     /**
     555      * 判断是否为iphone平台
     556      */
     557     $.platform.isIphone = /iphone/i.test(navigator.userAgent);
     558 
     559 
     560     /**
     561      * 判断是否为macintosh平台
     562      */
     563     $.platform.isMacintosh = /macintosh/i.test(navigator.userAgent);
     564 
     565 
     566 
     567     /**
     568      * 判断是否为windows平台
     569      */
     570     $.platform.isWindows = /windows/i.test(navigator.userAgent);
     571 
     572 
     573 
     574     /**
     575      * 判断是否为x11平台
     576      */
     577     $.platform.isX11 = /x11/i.test(navigator.userAgent);
     578 })(jQuery);
     579 
     580 
     581 ;(function($){
     582     /**
     583      * String增强
     584      */
     585     $.string = $.string || {};
     586 
     587     /**
     588      * 对目标字符串进行html解码
     589      * @grammar $.string.decodeHTML(source)
     590      * @param {string} source 目标字符串
     591      *             
     592      * @returns {string} html解码后的字符串
     593      */
     594     $.string.decodeHTML = function (source) {
     595         var str = String(source)
     596                     .replace(/"/g,'"')
     597                     .replace(/</g,'<')
     598                     .replace(/>/g,'>')
     599                     .replace(/&/g, "&");
     600         //处理转义的中文和实体字符
     601         return str.replace(/&#([d]+);/g, function(_0, _1){
     602             return String.fromCharCode(parseInt(_1, 10));
     603         });
     604     };
     605 
     606     /**
     607      * 对目标字符串进行html编码
     608      * @grammar $.string.encodeHTML(source)
     609      * @param {string} source 目标字符串
     610      * 编码字符有5个:&<>"'
     611      *             
     612      * @returns {string} html编码后的字符串
     613      */
     614     $.string.encodeHTML = function (source) {
     615         return String(source)
     616                     .replace(/&/g,'&')
     617                     .replace(/</g,'<')
     618                     .replace(/>/g,'>')
     619                     .replace(/"/g, """)
     620                     .replace(/'/g, "'");
     621     };
     622 
     623     /**
     624      * 去掉字符串中的html标签
     625      * @function
     626      * @grammar $.string.stripTags(source)
     627      * @param {string} source 要处理的字符串.
     628      * @return {String}
     629      */
     630     $.string.stripTags = function(source) {
     631         return String(source || '').replace(/<[^>]+>/g, '');
     632     };
     633 
     634     /**
     635      * 将目标字符串中可能会影响正则表达式构造的字符串进行转义。
     636      * @grammar $.string.escapeReg(source)
     637      * @param {string} source 目标字符串
     638      * @remark
     639      * 给以下字符前加上“”进行转义:.*+?^=!:${}()|[]/
     640      *             
     641      * @returns {string} 转义后的字符串
     642      */
     643     $.string.escapeReg = function (source) {
     644         return String(source)
     645                 .replace(new RegExp("([.*+?^=!:x24{}()|[\]/\\])", "g"), '\x241');
     646     };
     647 
     648     /**
     649      * 删除目标字符串两端的空白字符
     650      * @grammar $.string.trim(source)
     651      * @param {string} source 目标字符串
     652      * @remark
     653      * 不支持删除单侧空白字符
     654      *             
     655      * @returns {string} 删除两端空白字符后的字符串
     656      */
     657 
     658     (function () {
     659         var trimer = new RegExp("(^[\s\t\xa0\u3000]+)|([\u3000\xa0\s\t]+x24)", "g");
     660         
     661         $.string.trim = function (source) {
     662             return String(source)
     663                     .replace(trimer, "");
     664         };
     665     })();
     666 })(jQuery);
     667 
     668 
     669 ;(function($){
     670     /**
     671      * GUID
     672      */
     673     $.lang = $.lang || {};
     674     /**
     675      * 返回一个当前页面的唯一标识字符串。
     676      * @grammar $.lang.guid()
     677      *             
     678      * @returns {String} 当前页面的唯一标识字符串
     679      */
     680     $.lang.guid = function() {
     681         return "TANGRAM$" + $.lang._counter ++;
     682     };
     683 
     684     //不直接使用window,可以提高3倍左右性能
     685     $.lang._counter = $.lang._counter || 1;
     686     $.guid = $.lang.guid;//设置$.page.guid别名$.guid
     687 
     688 
     689     /**
     690      * 判断目标参数是否为function或Function实例
     691      * @grammar $.lang.isFunction(source)
     692      * @param {Any} source 目标参数
     693      * @returns {boolean} 类型判断结果
     694      */
     695     $.lang.isFunction = function (source) {
     696         // chrome下,'function' == typeof /a/ 为true.
     697         return '[object Function]' == Object.prototype.toString.call(source);
     698     };
     699 
     700     /**
     701      * 判断目标参数是否为Element对象
     702      * @grammar $.lang.isElement(source)
     703      * @param {Any} source 目标参数
     704      * @returns {boolean} 类型判断结果
     705      */
     706     $.lang.isElement = function (source) {
     707         return !!(source && source.nodeName && source.nodeType == 1);
     708     };
     709 
     710     /**
     711      * 判断目标参数是否Array对象
     712      * @grammar $.lang.isArray(source)
     713      * @param {Any} source 目标参数   
     714      * @returns {boolean} 类型判断结果
     715      */
     716     $.lang.isArray = function (source) {
     717         return '[object Array]' == Object.prototype.toString.call(source);
     718     };
     719 })(jQuery);
     720 
     721 ;(function($){
     722     /**
     723      * Array增强
     724      */
     725      $.array = $.array || {};
     726 
     727     /**
     728      * 查询数组中指定元素的索引位置
     729      * @grammar $.array.indexOf(source, match[, fromIndex])
     730      * @param {Array} source 需要查询的数组
     731      * @param {Any} match 查询项
     732      * @param {number} [fromIndex] 查询的起始位索引位置,如果为负数,则从source.length+fromIndex往后开始查找
     733      *             
     734      * @returns {number} 指定元素的索引位置,查询不到时返回-1
     735      */
     736     $.array.indexOf = function (source, match, fromIndex) {
     737         var len = source.length,
     738             iterator = match;
     739             
     740         fromIndex = fromIndex | 0;
     741         if(fromIndex < 0){//小于0
     742             fromIndex = Math.max(0, len + fromIndex)
     743         }
     744         for ( ; fromIndex < len; fromIndex++) {
     745             if(fromIndex in source && source[fromIndex] === match) {
     746                 return fromIndex;
     747             }
     748         }
     749         
     750         return -1;
     751     };
     752 
     753     /**
     754      * 判断一个数组中是否包含给定元素
     755      * @grammar $.array.contains(source, obj)
     756      * @param {Array} source 需要判断的数组.
     757      * @param {Any} obj 要查找的元素.
     758      * @return {boolean} 判断结果.
     759      * @author berg
     760      */
     761     $.array.contains = function(source, obj) {
     762         return ($.array.indexOf(source, obj) >= 0);
     763     };
     764 
     765     /**
     766      * 清空一个数组
     767      * @grammar $.array.empty(source)
     768      * @param {Array} source 需要清空的数组.
     769      * @author berg
     770      */
     771     $.array.empty = function(source) {
     772         source.length = 0;
     773     };
     774 
     775     /**
     776      * 从后往前,查询数组中指定元素的索引位置
     777      * @grammar $.array.lastIndexOf(source, match)
     778      * @param {Array} source 需要查询的数组
     779      * @param {Any} match 查询项
     780      * @param {number} [fromIndex] 查询的起始位索引位置,如果为负数,则从source.length+fromIndex往前开始查找
     781      *             
     782      * @returns {number} 指定元素的索引位置,查询不到时返回-1
     783      */
     784 
     785     $.array.lastIndexOf = function (source, match, fromIndex) {
     786         var len = source.length;
     787 
     788         fromIndex = fromIndex | 0;
     789 
     790         if(!fromIndex || fromIndex >= len){
     791             fromIndex = len - 1;
     792         }
     793         if(fromIndex < 0){
     794             fromIndex += len;
     795         }
     796         for(; fromIndex >= 0; fromIndex --){
     797             if(fromIndex in source && source[fromIndex] === match){
     798                 return fromIndex;
     799             }
     800         }
     801         
     802         return -1;
     803     };
     804 
     805     /**
     806      * 遍历数组中所有元素,将每一个元素应用方法进行转换,并返回转换后的新数组。
     807      * @grammar $.array.map(source, iterator[, thisObject])
     808      * @param {Array}    source   需要遍历的数组.
     809      * @param {Function} iterator 对每个数组元素进行处理的函数.
     810      * @param {Object} [thisObject] 函数调用时的this指针,如果没有此参数,默认是当前遍历的数组
     811      * @return {Array} map后的数组.
     812      */
     813     $.array.map = function(source, iterator, thisObject) {
     814         var results = [],
     815             i = 0,
     816             l = source.length;
     817         for (; i < l; i++) {
     818             results[i] = iterator.call(thisObject || source, source[i], i);
     819         }
     820         return results;
     821     };
     822 
     823     /**
     824      * 遍历数组中所有元素,将每一个元素应用方法进行合并,并返回合并后的结果。
     825      * @grammar $.array.reduce(source, iterator[, initializer])
     826      * @param {Array}    source 需要遍历的数组.
     827      * @param {Function} iterator 对每个数组元素进行处理的函数,函数接受四个参数:上一次reduce的结果(或初始值),当前元素值,索引值,整个数组.
     828      * @param {Object}   [initializer] 合并的初始项,如果没有此参数,默认用数组中的第一个值作为初始值.
     829      * @return {Array} reduce后的值.
     830      */
     831     $.array.reduce = function(source, iterator, initializer) {
     832         var i = 0,
     833             l = source.length,
     834             found = 0;
     835 
     836         if( arguments.length < 3){
     837             //没有initializer的情况,找到第一个可用的值
     838             for(; i < l; i++){
     839                 initializer = source[i++];
     840                 found = 1;
     841                 break;
     842             }
     843             if(!found){
     844                 return ;
     845             }
     846         }
     847 
     848         for (; i < l; i++) {
     849             if( i in source){
     850                 initializer = iterator(initializer, source[i] , i , source);
     851             }
     852         }
     853         return initializer;
     854     };
     855 
     856     /**
     857      * 移除数组中的项
     858      * @grammar $.array.remove(source, match)
     859      * @param {Array} source 需要移除项的数组
     860      * @param {Any} match 要移除的项
     861      *             
     862      * @returns {Array} 移除后的数组
     863      */
     864     $.array.remove = function (source, match) {
     865         var len = source.length;
     866             
     867         while (len--) {
     868             if (len in source && source[len] === match) {
     869                 source.splice(len, 1);
     870             }
     871         }
     872         return source;
     873     };
     874 
     875     /**
     876      * 移除数组中的项
     877      * @grammar $.array.removeAt(source, index)
     878      * @param {Array} source 需要移除项的数组
     879      * @param {number} index 要移除项的索引位置
     880      * @returns {Any} 被移除的数组项
     881      */
     882     $.array.removeAt = function (source, index) {
     883         return source.splice(index, 1)[0];
     884     };
     885 
     886     /**
     887      * 过滤数组中的相同项。如果两个元素相同,会删除后一个元素。
     888      * @grammar $.array.unique(source[, compareFn])
     889      * @param {Array} source 需要过滤相同项的数组
     890      * @param {Function} [compareFn] 比较两个数组项是否相同的函数,两个数组项作为函数的参数。
     891      *             
     892      * @returns {Array} 过滤后的新数组
     893      */
     894     $.array.unique = function (source, compareFn) {
     895         var len = source.length,
     896             result = source.slice(0),
     897             i, datum;
     898             
     899         if ('function' != typeof compareFn) {
     900             compareFn = function (item1, item2) {
     901                 return item1 === item2;
     902             };
     903         }
     904         
     905         // 从后往前双重循环比较
     906         // 如果两个元素相同,删除后一个
     907         while (--len > 0) {
     908             datum = result[len];
     909             i = len;
     910             while (i--) {
     911                 if (compareFn(datum, result[i])) {
     912                     result.splice(len, 1);
     913                     break;
     914                 }
     915             }
     916         }
     917 
     918         return result;
     919     };
     920 })(jQuery);
     921 
     922 ;(function(){
     923     /**
     924      * 操作cookie的方法
     925      * @namespace $.cookie
     926      */
     927     $.cookie = $.cookie || {};
     928 
     929     /**
     930      * 验证字符串是否合法的cookie键名
     931      * 
     932      * @param {string} source 需要遍历的数组
     933      * @meta standard
     934      * @return {boolean} 是否合法的cookie键名
     935      */
     936     $.cookie._isValidKey = function (key) {
     937         // http://www.w3.org/Protocols/rfc2109/rfc2109
     938         // Syntax:  General
     939         // The two state management headers, Set-Cookie and Cookie, have common
     940         // syntactic properties involving attribute-value pairs.  The following
     941         // grammar uses the notation, and tokens DIGIT (decimal digits) and
     942         // token (informally, a sequence of non-special, non-white space
     943         // characters) from the HTTP/1.1 specification [RFC 2068] to describe
     944         // their syntax.
     945         // av-pairs   = av-pair *(";" av-pair)
     946         // av-pair    = attr ["=" value] ; optional value
     947         // attr       = token
     948         // value      = word
     949         // word       = token | quoted-string
     950         
     951         // http://www.ietf.org/rfc/rfc2068.txt
     952         // token      = 1*<any CHAR except CTLs or tspecials>
     953         // CHAR       = <any US-ASCII character (octets 0 - 127)>
     954         // CTL        = <any US-ASCII control character
     955         //              (octets 0 - 31) and DEL (127)>
     956         // tspecials  = "(" | ")" | "<" | ">" | "@"
     957         //              | "," | ";" | ":" | "" | <">
     958         //              | "/" | "[" | "]" | "?" | "="
     959         //              | "{" | "}" | SP | HT
     960         // SP         = <US-ASCII SP, space (32)>
     961         // HT         = <US-ASCII HT, horizontal-tab (9)>
     962             
     963         return (new RegExp("^[^\x00-\x20\x7f\(\)<>@,;:\\\"\[\]\?=\{\}\/\u0080-\uffff]+x24")).test(key);
     964     };
     965 
     966     /**
     967      * 获取cookie的值,不对值进行解码
     968      * @grammar $.cookie.getRaw(key)
     969      * @param {string} key 需要获取Cookie的键名
     970      * @returns {string|null} 获取的Cookie值,获取不到时返回null
     971      */
     972     $.cookie.getRaw = function (key) {
     973         if ($.cookie._isValidKey(key)) {
     974             var reg = new RegExp("(^| )" + key + "=([^;]*)(;|x24)"),
     975                 result = reg.exec(document.cookie);
     976                 
     977             if (result) {
     978                 return result[2] || null;
     979             }
     980         }
     981 
     982         return null;
     983     };
     984 
     985     /**
     986      * 设置cookie的值,不对值进行编码
     987      * @grammar $.cookie.setRaw(key, value[, options])
     988      * @param {string} key 需要设置Cookie的键名
     989      * @param {string} value 需要设置Cookie的值
     990      * @param {Object} [options] 设置Cookie的其他可选参数
     991      * @config {string} [path] cookie路径
     992      * @config {Date|number} [expires] cookie过期时间,如果类型是数字的话, 单位是毫秒
     993      * @config {string} [domain] cookie域名
     994      * @config {string} [secure] cookie是否安全传输
     995      * @remark
     996      * 
     997     <b>options参数包括:</b><br>
     998     path:cookie路径<br>
     999     expires:cookie过期时间,Number型,单位为毫秒。<br>
    1000     domain:cookie域名<br>
    1001     secure:cookie是否安全传输
    1002      */
    1003     $.cookie.setRaw = function (key, value, options) {
    1004         if (!$.cookie._isValidKey(key)) {
    1005             return;
    1006         }
    1007         
    1008         options = options || {};
    1009         //options.path = options.path || "/"; // meizz 20100402 设定一个初始值,方便后续的操作
    1010         //berg 20100409 去掉,因为用户希望默认的path是当前路径,这样和浏览器对cookie的定义也是一致的
    1011         
    1012         // 计算cookie过期时间
    1013         var expires = options.expires;
    1014         if ('number' == typeof options.expires) {
    1015             expires = new Date();
    1016             expires.setTime(expires.getTime() + options.expires);
    1017         }
    1018         
    1019         document.cookie =
    1020             key + "=" + value
    1021             + (options.path ? "; path=" + options.path : "")
    1022             + (expires ? "; expires=" + expires.toGMTString() : "")
    1023             + (options.domain ? "; domain=" + options.domain : "")
    1024             + (options.secure ? "; secure" : ''); 
    1025     };
    1026 
    1027     /**
    1028      * 删除cookie的值
    1029      * @grammar $.cookie.remove(key, options)
    1030      * @param {string} key 需要删除Cookie的键名
    1031      * @param {Object} options 需要删除的cookie对应的 path domain 等值
    1032      */
    1033     $.cookie.remove = function (key, options) {
    1034         options = options || {};
    1035         options.expires = new Date(0);
    1036         $.cookie.setRaw(key, '', options);
    1037     };
    1038 
    1039     /**
    1040      * 获取cookie的值,用decodeURIComponent进行解码
    1041      * @grammar $.cookie.get(key)
    1042      * @param {string} key 需要获取Cookie的键名
    1043      * @remark
    1044      * <b>注意:</b>该方法会对cookie值进行decodeURIComponent解码。如果想获得cookie源字符串,请使用getRaw方法。
    1045      *             
    1046      * @returns {string|null} cookie的值,获取不到时返回null
    1047      */
    1048     $.cookie.get = function (key) {
    1049         var value = $.cookie.getRaw(key);
    1050         if ('string' == typeof value) {
    1051             value = decodeURIComponent(value);
    1052             return value;
    1053         }
    1054         return null;
    1055     };
    1056 
    1057     /**
    1058      * 设置cookie的值,用encodeURIComponent进行编码
    1059      * @grammar $.cookie.set(key, value[, options])
    1060      * @param {string} key 需要设置Cookie的键名
    1061      * @param {string} value 需要设置Cookie的值
    1062      * @param {Object} [options] 设置Cookie的其他可选参数
    1063      * @config {string} [path] cookie路径
    1064      * @config {Date|number} [expires] cookie过期时间,如果类型是数字的话, 单位是毫秒
    1065      * @config {string} [domain] cookie域名
    1066      * @config {string} [secure] cookie是否安全传输
    1067      * @remark
    1068      * 
    1069     1. <b>注意:</b>该方法会对cookie值进行encodeURIComponent编码。如果想设置cookie源字符串,请使用setRaw方法。<br><br>
    1070     2. <b>options参数包括:</b><br>
    1071     path:cookie路径<br>
    1072     expires:cookie过期时间,Number型,单位为毫秒。<br>
    1073     domain:cookie域名<br>
    1074     secure:cookie是否安全传输
    1075      */
    1076     $.cookie.set = function (key, value, options) {
    1077         $.cookie.setRaw(key, encodeURIComponent(value), options);
    1078     };
    1079 })(jQuery);
    1080 
    1081 ;(function($){
    1082     $.number = $.number || {};
    1083 
    1084     /**
    1085      * 为目标数字添加逗号分隔
    1086      * @grammar $.number.comma(source[, length])
    1087      * @param {number} source 需要处理的数字
    1088      * @param {number} [length] 两次逗号之间的数字位数,默认为3位
    1089      *             
    1090      * @returns {string} 添加逗号分隔后的字符串
    1091      */
    1092     $.number.comma = function (source, length) {
    1093         if (!length || length < 1) {
    1094             length = 3;
    1095         }
    1096 
    1097         source = String(source).split(".");
    1098         source[0] = source[0].replace(new RegExp('(\d)(?=(\d{'+length+'})+$)','ig'),"$1,");
    1099         return source.join(".");
    1100     };
    1101 
    1102     /**
    1103      * 生成随机整数,范围是[min, max]
    1104      * @grammar $.number.randomInt(min, max) 
    1105      * 
    1106      * @param     {number} min     随机整数的最小值
    1107      * @param     {number} max     随机整数的最大值
    1108      * @return     {number}         生成的随机整数
    1109      */
    1110     $.number.randomInt = function(min, max){
    1111         return Math.floor(Math.random() * (max - min + 1) + min);
    1112     };
    1113 
    1114     /**
    1115      * 对目标数字进行0补齐处理
    1116      * @grammar $.number.pad(source, length)
    1117      * @param {number} source 需要处理的数字
    1118      * @param {number} length 需要输出的长度
    1119      *             
    1120      * @returns {string} 对目标数字进行0补齐处理后的结果
    1121      */
    1122     $.number.pad = function (source, length) {
    1123         var pre = "",
    1124             negative = (source < 0),
    1125             string = String(Math.abs(source));
    1126 
    1127         if (string.length < length) {
    1128             pre = (new Array(length - string.length + 1)).join('0');
    1129         }
    1130 
    1131         return (negative ?  "-" : "") + pre + string;
    1132     };
    1133 })(jQuery);
    1134 
    1135 ;(function($){
    1136     $.sio = $.sio || {};
    1137     /**
    1138      * 通过请求一个图片的方式令服务器存储一条日志
    1139      * @grammar $.sio.log(url)
    1140      * @param {string} url 要发送的地址.
    1141      */
    1142     $.sio.log = function(url) {
    1143       var img = new Image(),
    1144           key = 'tangram_sio_log_' + Math.floor(Math.random() *
    1145                 2147483648).toString(36);
    1146 
    1147       // 这里一定要挂在window下
    1148       // 在IE中,如果没挂在window下,这个img变量又正好被GC的话,img的请求会abort
    1149       // 导致服务器收不到日志
    1150       window[key] = img;
    1151 
    1152       img.onload = img.onerror = img.onabort = function() {
    1153         // 下面这句非常重要
    1154         // 如果这个img很不幸正好加载了一个存在的资源,又是个gif动画
    1155         // 则在gif动画播放过程中,img会多次触发onload
    1156         // 因此一定要清空
    1157         img.onload = img.onerror = img.onabort = null;
    1158 
    1159         window[key] = null;
    1160 
    1161         // 下面这句非常重要
    1162         // new Image创建的是DOM,DOM的事件中形成闭包环引用DOM是典型的内存泄露
    1163         // 因此这里一定要置为null
    1164         img = null;
    1165       };
    1166 
    1167       // 一定要在注册了事件之后再设置src
    1168       // 不然如果图片是读缓存的话,会错过事件处理
    1169       // 最后,对于url最好是添加客户端时间来防止缓存
    1170       // 同时服务器也配合一下传递Cache-Control: no-cache;
    1171       img.src = url;
    1172     };
    1173 })(jQuery);
    1174 
    1175 
    1176 ;(function($){
    1177     $.url = $.url || {};
    1178     /**
    1179      * 对字符串进行%#&+=以及和s匹配的所有字符进行url转义
    1180      * @grammar $.url.escapeSymbol(source)
    1181      * @param {string} source 需要转义的字符串.
    1182      * @return {string} 转义之后的字符串.
    1183      * @remark
    1184      * 用于get请求转义。在服务器只接受gbk,并且页面是gbk编码时,可以经过本转义后直接发get请求。
    1185      *
    1186      * @return {string} 转义后的字符串
    1187      */
    1188     $.url.escapeSymbol = function(source) {
    1189         
    1190         //TODO: 之前使用s来匹配任意空白符
    1191         //发现在ie下无法匹配中文全角空格和纵向指标符v,所以改s为f
    	v以及中文全角空格和英文空格
    1192         //但是由于ie本身不支持纵向指标符v,故去掉对其的匹配,保证各浏览器下效果一致
    1193         return String(source).replace(/[#%&+=/\  f
    	]/g, function(all) {
    1194             return '%' + (0x100 + all.charCodeAt()).toString(16).substring(1).toUpperCase();
    1195         });
    1196     };
    1197 
    1198     /**
    1199      * 根据参数名从目标URL中获取参数值
    1200      * @grammar $.url.getQueryValue(url, key)
    1201      * @param {string} url 目标URL
    1202      * @param {string} key 要获取的参数名
    1203      *             
    1204      * @returns {string|null} - 获取的参数值,其中URI编码后的字符不会被解码,获取不到时返回null
    1205      */
    1206     $.url.getQueryValue = function (url, key) {
    1207         var reg = new RegExp(
    1208                             "(^|&|\?|#)" 
    1209                             + $.string.escapeReg(key) 
    1210                             + "=([^&#]*)(&|x24|#)", 
    1211                         "");
    1212         var match = url.match(reg);
    1213         if (match) {
    1214             return match[2];
    1215         }
    1216         
    1217         return null;
    1218     };
    1219 
    1220     /**
    1221      * 将json对象解析成query字符串
    1222      * @grammar $.url.jsonToQuery(json[, replacer])
    1223      * @param {Object} json 需要解析的json对象
    1224      * @param {Function=} replacer_opt 对值进行特殊处理的函数,function (value, key)
    1225      *             
    1226      * @return {string} - 解析结果字符串,其中值将被URI编码,{a:'&1 '} ==> "a=%261%20"。
    1227      */
    1228     $.url.jsonToQuery = function (json, replacer_opt) {
    1229         var result = [], 
    1230             itemLen,
    1231             replacer = replacer_opt || function (value) {
    1232               return $.url.escapeSymbol(value);
    1233             };
    1234             
    1235         $.each(json, function(item, key){
    1236             // 这里只考虑item为数组、字符串、数字类型,不考虑嵌套的object
    1237             if ($.lang.isArray(item)) {
    1238                 itemLen = item.length;
    1239                 // value的值需要encodeURIComponent转义吗?
    1240                 // FIXED 优化了escapeSymbol函数
    1241                 while (itemLen--) {
    1242                     result.push(key + '=' + replacer(item[itemLen], key));
    1243                 }
    1244             } else {
    1245                 result.push(key + '=' + replacer(item, key));
    1246             }
    1247         });
    1248         
    1249         return result.join('&');
    1250     };
    1251 
    1252 
    1253     /**
    1254      * 解析目标URL中的参数成json对象
    1255      * @grammar $.url.queryToJson(url)
    1256      * @param {string} url 目标URL
    1257      *             
    1258      * @returns {Object} - 解析为结果对象,其中URI编码后的字符不会被解码,'a=%20' ==> {a:'%20'}。
    1259      */
    1260     $.url.queryToJson = function (url) {
    1261         var query   = url.substr(url.lastIndexOf('?') + 1),
    1262             params  = query.split('&'),
    1263             len     = params.length,
    1264             result  = {},
    1265             i       = 0,
    1266             key, value, item, param;
    1267         
    1268         for (; i < len; i++) {
    1269             if(!params[i]){
    1270                 continue;
    1271             }
    1272             param   = params[i].split('=');
    1273             key     = param[0];
    1274             value   = param[1];
    1275             
    1276             item = result[key];
    1277             if ('undefined' == typeof item) {
    1278                 result[key] = value;
    1279             } else if ($.lang.isArray(item)) {
    1280                 item.push(value);
    1281             } else { // 这里只可能是string了
    1282                 result[key] = [item, value];
    1283             }
    1284         }
    1285         
    1286         return result;
    1287     };
    1288 })(jQuery);
  • 相关阅读:
    征战蓝桥 —— 2017年第八届 —— C/C++A组第7题——正则问题
    征战蓝桥 —— 2017年第八届 —— C/C++A组第7题——正则问题
    征战蓝桥 —— 2017年第八届 —— C/C++A组第7题——正则问题
    征战蓝桥 —— 2017年第八届 —— C/C++A组第8题——包子凑数
    征战蓝桥 —— 2017年第八届 —— C/C++A组第8题——包子凑数
    征战蓝桥 —— 2017年第八届 —— C/C++A组第8题——包子凑数
    征战蓝桥 —— 2017年第八届 —— C/C++A组第9题——分巧克力
    征战蓝桥 —— 2017年第八届 —— C/C++A组第9题——分巧克力
    征战蓝桥 —— 2017年第八届 —— C/C++A组第9题——分巧克力
    征战蓝桥 —— 2017年第八届 —— C/C++A组第10题——油漆面积
  • 原文地址:https://www.cnblogs.com/chris-oil/p/4166792.html
Copyright © 2011-2022 走看看