七月 6, 2010
by 小寒
1 comment
在firebug下面用console.debug($(‘a’))打印jQuery()返回值时,会发现控制台输出是一个数组,但我们知道jQuery()返回的确实一个对象,只不过这个对象有length属性和数字的下标,最重要的是还有一个splice方法。只要满足这三点,就会在控制台输出一个数组。自己建了个例子模拟一下。
function Foo() {
return new Foo.prototype.init();
}
Foo.prototype = {
init: function() {
this.length = 1;
this[0] = 'hello world';
return this;
},
say: function() {
alert('hi');
},
length: 0,
splice: [].splice
}
Foo.prototype.init.prototype = Foo.prototype;
Foo();
PS: 如果想用firebug打印完整的jQuery对象,请用console.dir()。
JavaScript
三月 1, 2010
by 小寒
0 comments
用jQuery判断一个元素是否显示:$(element).is(“:visible”)
类似的,判断一个元素是不是第一个子元素:$(element).is(“:first-child”)
jQuery
二月 9, 2010
by 小寒
1 comment
通常的情况下,IE6中的select元素永远是在最上面的,即使覆盖在它上面的元素的z-index再大也不起作用。比如说有个id为div1的元素绝对定位在select元素的上面。这里假设div1的z-index比select的大,但在IE6里看上去还是select在上面,div1并不能覆盖住它。为了解决这个问题,只能在div1和select中间插入一个和div1的位置以及大小一样的iframe来达到覆盖select的效果。
网上有个叫bgiframe的jQuery插件可以达到这个效果。拿上面的例子来说,它动态的在div1里插入一个透明的iframe,iframe的尺寸是用IE特有的CSS expression计算的,这么做的好处在于iframe随时都可以保持和div1同样大小,缺点是CSS expression太占资源了,可能会导致浏览器假死,如果覆盖在select上的元素的尺寸在运行时不会改变的话,就没必要用CSS expression。所以把bgiframe的代码改了一下。
改过之后的代码,记录一下:
(function($){
$.fn.bgIframe = $.fn.bgiframe = function(s) {
if ($.browser.msie && /6.0/.test(navigator.userAgent)) {
s = $.extend({
top : 'auto',
left : 'auto',
width : 'auto',
height : 'auto',
src : 'javascript:false;'
}, s || {});
var prop = function(n) {
return n&&n.constructor==Number?n+'px':n;
};
return this.each(function() {
if ( $('> iframe.bgiframe', this).length == 0 ) {
var iframe = $('<iframe frameborder="0" tabindex="-1"></iframe>')
.addClass("bgiframe")
.css({
display: 'block',
position: 'absolute',
zIndex: '-1',
opacity: 0,
top: s.top === 'auto'?
((this.clientTop || 0)*-1 + 'px'): prop(s.top),
left: s.left === 'auto'?
((this.clientLeft || 0)*-1 + 'px'): prop(s.left),
width: s.width === 'auto'?
(this.offsetWidth + 'px'): prop(s.width),
height: s.height === 'auto'?
(this.offsetHeight + 'px'): prop(s.height)
})
.insertBefore(this.firstChild);
}
});
}
return this;
};
})(jQuery);
JavaScript, jQuery
一月 15, 2010
by 小寒
2 comments
前几天写一个打分的UI,没有实现功能,现在把功能加入进来,并且用jQuery封装一下。
演示地址:http://www.zhoumingzhi.com/wp-content/uploads/2010/01/rating/demo.html
下载地址:http://code.google.com/p/rating-widget/downloads/list
用法:
$(function () {
$(".ui-rating").rating({
"activate": 7,
"total": 10,
"select": function (event, ui) {
},
"change": function (event, ui) {
}
});
});
用一个空的块元素标签实例化即可,最好是用div。
参数说明:
|
参数
|
类型
|
说明
|
|
total
|
number/string
|
级别总数,通常来说就是指星星的个数,除非是用半个星星表示一个等级。
|
|
activate
|
number/string
|
当前选中的级别,一般用来指示所有用户选的平均值。
|
|
select
|
function(event, ui)
|
处理点击事件的函数。event参数代表事件,ui.level表示选中的级别。
|
|
change
|
function(event, ui)
|
这个函数在鼠标移动时被触发。event参数代表事件,ui.level表示鼠标划过的级别。
|
方法说明:
$(".ui-rating").rating("option", "activate", 5);
$(".ui-rating").rating("enable");
$(".ui-rating").rating("disable");
activate方法有一个参数,表示要设定的等级。
CSS, jQuery
一月 12, 2010
by 小寒
0 comments
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.
JavaScript, jQuery
十二月 20, 2009
by 小寒
0 comments
将上一篇文章中的代码封装一下,基于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);
JavaScript, jQuery
十二月 19, 2009
by 小寒
1 comment
跨域的解决方案有许多种,就不一一介绍了,在这里主要总结一下用iframe来解决跨域的方法。
首先,说明一下window.name这个属性,我们要用这个属性来保存从服务器返回的数据。
- window.name的值在同一浏览器窗口加载不同的页面后依然存在。(比如在同一浏览器窗口下,先访问页面a.html,将window.name设定为”Hello World”,然后再访问b.html,window.name仍然是”Hello World”。)
- 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>
JavaScript, jQuery
十月 21, 2009
by 小寒
9 comments
最近在做一个项目,其中有个UI要做成类似jQuery UI中Accordion的样子。但是Accordion在某一时刻只可以展开一个Panel,所以就改写了一下Accordion,让它可以同时展开多个Panel。
源代码:
(function($) {
if ($.ui.accordion) {
var old_clickHandler = $.ui.accordion.prototype._clickHandler;
var new_clickHandler = function(event, target) {
var o = this.options;
if (o.disabled) return false;
// called only when using activate(false) to close all parts programmatically
if (!event.target && o.collapsible) {
this.headers.removeClass("ui-state-active ui-corner-top")
.addClass("ui-state-default ui-corner-all")
.find(".ui-icon")
.removeClass(o.icons.headerSelected)
.addClass(o.icons.header);
this.headers.next().addClass('ui-accordion-content-active');
var toHide = this.headers.next(),
data = {
options: o,
newHeader: $([]),
oldHeader: o.headers,
newContent: $([]),
oldContent: toHide
},
toShow = (this.active = $([]));
this._toggle(toShow, toHide, data);
return false;
}
// get the click target
var clicked = $(event.currentTarget || target);
var clickedIsActive = clicked.next().css("display") != "none";
// if animations are still active, or the active header is the target, ignore click
if (this.running || (!o.collapsible && clickedIsActive)) {
return false;
}
// switch classes
clicked.toggleClass("ui-state-active")
.toggleClass("ui-corner-top")
.toggleClass("ui-state-default")
.toggleClass("ui-corner-all")
.find(".ui-icon")
.toggleClass(o.icons.headerSelected)
.toggleClass(o.icons.header);
clicked.next().addClass('ui-accordion-content-active');
// find elements to show and hide
var toShow = clicked.next(),
toHide = clickedIsActive ? clicked.next() : $([]),
data = {
options: o,
newHeader: clickedIsActive && o.collapsible ? $([]) : clicked,
oldHeader: $([]),
newContent: clickedIsActive && o.collapsible ? $([]) : toShow.find('> *'),
oldContent: $([])
},
down = true;
this._toggle(toShow, toHide, data, clickedIsActive, down);
return false;
};
$.extend($.ui.accordion.defaults, {
collapsible: true,
multipleMode: false
});
$.extend($.ui.accordion.prototype, {
_clickHandler: function(event, target) {
if (this.options.multipleMode === true) {
new_clickHandler.apply(this, arguments);
}
else {
old_clickHandler.apply(this, arguments);
}
}
});
};
})(jQuery);
将上面的代码保存成.js文件并引入到页面,调用的时候只要设置multipleMode为true就可以了。
$("#accordion").accordion({multipleMode: true});
JavaScript, jQuery