最近,公司需要使用jQuery mobile来构建一个移动应用,期间遇到了一个场景:需要一个可以折叠的控件,当点击这个控件header的右侧时,展开内容;左侧是不可点击的,只是一些说明性的文字或者图片。如下图所示:
当看到这样的需求时,给我的第一感觉就是用jQuery mobile中的Collapsible控件,但是在经过研究后,发现该控件本身无法实现部分点击使其展开。于是我就想是否可以使header右侧部分向右浮动于header之上,并改变header的点击事件,使其绑定到header左侧,从而达到目的。
既然有了方案,就开始动手吧。
1、首先很简单,通过CSS,控制header右侧部分的位置, 代码如下:
<h3> <div class="handler"> Search Options </div> <div style="float: right; margin-top: -20px;"> <div style="float: right; margin: 0; padding: 0;"> columnN </div>
…… <div style="float: right; margin: 0 5px 0 0; padding: 0;"> Column3 </div> <div style="float: right; margin: 0 5px 0 0; padding: 0;"> Column2 </div> <div style="float: right; margin: 0 5px 0 0; padding: 0;"> column1 </div> </div> </h3>
注:中间部分的列,可以根据需要添加多次
2、将h3上的单击事件,移到handler上
1)在jQuery mobile源代码中查找header的单击事件,代码如下:
collapsibleHeading .bind( "click", function( event ) { var type = collapsibleHeading.is( ".ui-collapsible-heading-collapsed" ) ? "expand" : "collapse"; collapsible.trigger( type ); event.preventDefault(); });
2)从源码中分析得知,只需要把click事件绑定到<div class=”handler”>上即可,改动后,代码如下:
var expandHandler = collapsibleHeading.find(o.handler).length > 0 ? collapsibleHeading.find(".handler, .ui-icon") : collapsibleHeading; expandHandler.bind("click", function (event) { var type = collapsibleHeading.is(".ui-collapsible-heading-collapsed") ? "expand" : "collapse"; collapsible.trigger(type); event.preventDefault(); });
到目前为止,对Collapsible控件的修改基本已经完成。但是在使用一段时间后,发现如下一个问题:前端这个header的细节暴露过多,使用起来太麻烦。于是通过简单的封装和调整,前端的header简化为:
<h3> <div class="handler"> Search Options </div> <div>column1</div><div>column2</div> <div>column3</div>……<div>columnN</div> </h3>
调整后的js源码如下:
1、 在options对象中,增加一个成员:
$.widget("mobile.collapsible", $.mobile.widget, { options: { …… handler: ".handler" }
2、 控制div样式的代码
var cols = collapsibleHeading.find("div").not(".handler").remove(); for(var i = cols.length - 1; i >=0; i--){ var style = "float: right; margin: 0 5px 0 0; padding: 0;"; if(i== cols.length - 1){ style = "float: right; margin: 0; padding: 0;"; } collapsibleHeading.find(".ui-btn-text").append($(cols.get(i)).attr("style", style)); } collapsibleHeading.find("div").not(".handler").wrapAll("<div style='float: right; margin-top: -20px;'></div>");
3、 事件代码:
var expandHandler = collapsibleHeading.find(o.handler).length > 0 ? collapsibleHeading.find(".handler, .ui-icon") : collapsibleHeading; expandHandler.bind("click", function (event) { var type = collapsibleHeading.is(".ui-collapsible-heading-collapsed") ? "expand" : "collapse"; collapsible.trigger(type); event.preventDefault(); });
问题终于解决了,最终代码见附件