扩展jQuery选择器


jQuery本身提供了一些强大的带有冒号的选择器,比如:first, :even这些。但是这些还满足不了需求的话,可以自己扩展一个选择器。比如要选择一些文本为”hello world”的链接,用jQuery自带的:contain是可以,但是它会把”hello world, I’m Michael”也选择进来,不够精确。于是我们就自己定义一个:text

$.extend($.expr[':'], {
    text: function(a, i, m) {
        return ((a.textContent
        || a.innerText
        || jQuery(a).text()
        || "") === m[3]);
    }
});

用$(“a:text(‘hello world’)”)来调用上面的方法,函数里的m[3]就是输入的参数,在这里为”hello world”。

测试一下:猛击我

  • hello world
  • hello world
  • hello world, I’m Michael.
  • hello world
  • hello world, I’m Leo.

[转贴] JS中如何判断字符串类型的数字

var str = "37";
var n = Number(str);
if (!isNaN(n))
{
    alert("是数字");
}

注意:在 JavaScript 中,对于省略写法(如:”.3″、”-.3″)、科学计数法(如:”3e7″、”3e-7″)、十六进制数(如:”0xFF”、”0x3e7″)均被认定为数字格式,这类字符串都可以用 Number 转化成数字。

isNaN 返回一个 Boolean 值,指明提供的值是否是 NaN ,NaN 的意思是 not a number(不是一个数字)。

语法:isNaN(numValue)

跨域请求的iframe解决方案(2)

将上一篇文章中的代码封装一下,基于jQuery。

用法:

// xs的意思是cross site
$.xsget({
  url: "http://127.0.0.1/server.html",
  callback: function (data) {
    alert(data);
  }
});

源代码:

(function ($) {
  $.extend({
    "xsget": function (options) {
      $.extend(options, $.xsget.defaults);
      var iframe = document.createElement("iframe"),
                same_domain = false;
      iframe.style.display = "none";
      document.body.appendChild(iframe);
      // 当iframe加载完之后触发的函数
      function iframe_load() {
        if (same_domain) {
          // 调用回调函数
          if (typeof options.callback === "function") {
            options.callback(iframe.contentWindow.name);
          }
          // 关闭iframe的窗口
          iframe.contentWindow.close();
          // 移除iframe
          document.body.removeChild(iframe);
        } else {
          same_domain = true;
          iframe.contentWindow.location = options.proxyUrl;
        }
      }
      // 在IE下要用attachEvent来添加iframe的onload事件
      if (iframe.attachEvent) {
        iframe.attachEvent("onload", function () {
          iframe_load();
        });
      }
      else {
        iframe.onload = iframe_load;
      }
      iframe.src = options.url;
    }
  });
  $.extend($.xsget, {
    "defaults": {
      // 默认的空白页面,在网站的根目录下
      proxyUrl: "/empty.html"
    }
  });
})(jQuery);

跨域请求的iframe解决方案(1)

跨域的解决方案有许多种,就不一一介绍了,在这里主要总结一下用iframe来解决跨域的方法。

首先,说明一下window.name这个属性,我们要用这个属性来保存从服务器返回的数据。

  1. window.name的值在同一浏览器窗口加载不同的页面后依然存在。(比如在同一浏览器窗口下,先访问页面a.html,将window.name设定为”Hello World”,然后再访问b.html,window.name仍然是”Hello World”。)
  2. window.name最多可以支持2MB的值。

接下来结合代码来说明这个解决方案。为了实现跨域访问,当然要找到两个不同的域,最简单的,用http://localhost/和http://127.0.0.1/就可以了。新建一个client.html并假定其在http://localhost/这个域下面,用来向http://127.0.0.1/域下的页面server.html发送异步请求。下面是发送请求的代码:

var iframe1 = document.createElement("iframe");
iframe1.src = "http://127.0.0.1/server.html";
(function() {
	// 当iframe加载完之后触发的函数
	function iframe1_load() {
	}
	// 在IE下要用attachEvent来添加iframe的onload事件
	if(iframe1.attachEvent) {
		iframe1.attachEvent("onload", function(){
			iframe1_load();
		});
	}
	else {
		iframe1.onload = iframe1_load;
	}
})();
document.body.appendChild(iframe1);

注意这里的iframe1_load函数,它在iframe1完全加载完之后被浏览器调用,我们在这里取回从服务器返回的数据。上面说过,从服务器返回的数据应该是保存在window.name里的,改写一下iframe1_load:

function iframe1_load() {
	alert(iframe1.contentWindow.name);
}

但由于同源策略的原因,上面的语句会报错,因为iframe1访问的页面在http://127.0.0.1/这个域,而这上面的JavaScript所在的页面是在http://localhost/,所以client.html暂时还不能访问iframe1的大部分属性。这个时候聪明的同学就能想到,如果把iframe1导航到http://localhost/下面的页面不就可以访问window.name了吗?而且上面也说过window.name在换了页面之后,还是存在的。

根据上面的分析,在http://localhost/下建一个新的页面empty.html(不用往里添加代码,只要保证不404就好。),在iframe1_load函数中先把iframe1导航到http://localhost/empty.html,然后再从iframe1的window.name里取数据。注意,iframe1导航到新页面之后浏览器会再次调用iframe1_load,从而造成死循环,所以还要加个标记。

var iframe1 = document.createElement("iframe");
iframe1.style.display = "none";
document.body.appendChild(iframe1);
(function () {
    var same_domain = false;
    // 当iframe加载完之后触发的函数
    function iframe1_load() {
        if (same_domain) {
            // 取得从服务器返回的数据
            alert(iframe1.contentWindow.name);
            // 关闭iframe1的窗口
            iframe1.contentWindow.close();
            // 移除iframe1
            document.body.removeChild(iframe1);
        } else {
            same_domain = true;
            // 不能用iframe1.src = "empty.html",在IE下有错误
            iframe1.contentWindow.location = "empty.html";
        }
    }
    // 在IE下要用attachEvent来添加iframe的onload处理函数
    if (iframe1.attachEvent) {
        iframe1.attachEvent("onload", function () {
            iframe1_load();
        });
    }
    else {
        iframe1.onload = iframe1_load;
    }
})();
iframe1.src = "http://127.0.0.1/server.html";

server.html的代码

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
	<title>Server</title>
	<script type="text/javascript">
		window.name = "HELLO WORLD";
	</script>
</head>
<body>
</body>
</html>

IE下的JavaScript条件编译

/*@cc_on!@*/0 && alert("别用IE了");

不要用setAttribute设置className

创建了一个新的元素,然后添加class,发现用setAttribute(“class”, “foo”)这种方式在IE6下不起作用。查了一下jQuery的源代码:

// internal only, use addClass("class")
add: function( elem, classNames ) {
	jQuery.each((classNames || "").split(/\s+/), function(i, className){
		if ( elem.nodeType == 1 && !jQuery.className.has( elem.className, className ) )
			elem.className += (elem.className ? " " : "") + className;
	});
},

之后改为elem.className = “foo”就可以了。

获取元素在页面的绝对位置

源代码:

var getCoords = function (el) {
    var box = el.getBoundingClientRect(),
        doc = el.ownerDocument,
        body = doc.body,
        html = doc.documentElement,
        clientTop = html.clientTop || body.clientTop || 0,
        clientLeft = html.clientLeft || body.clientLeft || 0,
        top = box.top + (self.pageYOffset || html.scrollTop || body.scrollTop) - clientTop,
        left = box.left + (self.pageXOffset || html.scrollLeft || body.scrollLeft) - clientLeft;
    return { 'top': top, 'left': left };
};

其中self.pageYOffset为window.self.pageYOffset,是火狐的一个属性,相当于document.body.scrollTop。以下是它的定义:

Definition: The pageYOffset property is used to determine the Y coordinate of the scroll position in some browsers. This is not a reserved word so you can declare your own variable or function called pageYOffset but if you do then you will not be able to find or alter the scroll position of a window in some browsers.

禁用或启用一个ValidationGroup里的全部验证控件

功能:禁用或启用一个ValidationGroup里的全部验证控件。

源代码:

var ValidationGroupEnable = function (group, enabled) {
    for (var i = 0; i < Page_Validators.length; i++) {
        if (Page_Validators[i].validationGroup == group) {
            ValidatorEnable(Page_Validators[i], enabled);
        }
    }
}