用jQuery判断一个元素是否显示:$(element).is(“:visible”)
类似的,判断一个元素是不是第一个子元素:$(element).is(“:first-child”)
用jQuery判断一个元素是否显示:$(element).is(“:visible”)
类似的,判断一个元素是不是第一个子元素:$(element).is(“:first-child”)
通常的情况下,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);
前几天写一个打分的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方法有一个参数,表示要设定的等级。
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”。
测试一下:猛击我
将上一篇文章中的代码封装一下,基于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来解决跨域的方法。
首先,说明一下window.name这个属性,我们要用这个属性来保存从服务器返回的数据。
接下来结合代码来说明这个解决方案。为了实现跨域访问,当然要找到两个不同的域,最简单的,用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>
最近在做一个项目,其中有个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});
现将jQuery的Tabs控件添加了两个方法next和prev及一个事件beforegotonext,以便更好的支持用户操作。
(function($) { $.extend($.ui.tabs.prototype, { next: function() { var self = this, o = this.options; var i = o.selected; var n = i + 1; while ((n < self.anchors.length) && (self.lis.eq(n).hasClass('ui-state-disabled') || (self.lis.eq(n).css("display") == "none"))) { n++; } if (n < self.anchors.length) { if (self._trigger('beforegotonext', null, self._ui(self.anchors[i], self.panels[i])) !== false) self.select(n); } }, prev: function() { var self = this, o = this.options; var p = o.selected - 1; while ((p >= 0) && (self.lis.eq(p).hasClass('ui-state-disabled') || (self.lis.eq(p).css("display") == "none"))) { p--; } if (p >= 0) self.select(p); } }); })(jQuery);
$("#tabs").tabs("next"); $("#tabs").tabs("prev");
$("#tabs").tabs({ "beforegotonext": function(event, ui) { // anchor element of the selected (clicked) tab var tab = ui.tab; // element, that contains the selected/clicked tab contents var panel = ui.panel; // zero-based index of the selected (clicked) tab var index = ui.index; } });