开发者社区> 范大脚脚> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

【position也可以很复杂】当弹出层遇上了鼠标定位(下)

简介:
+关注继续查看
前言

接着昨天的内容写,为了保证内容连续性,这里还是把昨天的内容拷了过来。

请用现代浏览器测试

引出问题

有图有真相,我们来看一个智联招聘里面经常出现的图层:



他这个是没有什么问题的,我们来简单看看其实现:

 View Code
复制代码
 1 <div id="zbwJobSearch">
 2          <div style="width: 710px;" class="sPopupDiv">
 3              <div class="sPopupTitle213 sPopupTitle">
 4                  <h1>
 5                      选择职位</h1>
 6                  <div class="sButtonBlock">
 7                      <a onclick="return zbw.PopupDiv.allIns['buttonSelJobType'].fnClickAll()" href="#"
 8                          class="blueButton">不限</a> <a onclick="return zbw.PopupDiv.allIns['buttonSelJobType'].fnClickClose()"
 9                              href="#" class="blueButton">关闭</a></div>
10                  <div class="clear">
11                  </div>
12              </div>
13              <div class="clear">
14              </div>
15              <div class="sPopupBlock">
16              </div>
17          </div>
18 </div>
复制代码


他一开始便有一个容器在页面上,看着我们这个“zbwJobSearch”的容器,他是一个一般流的东西,里面放了3个绝对定位的东西,从这里看出,他这个不只是用于职位选择还有城市选择什么的。。。。

然后我们把多余的东西给去掉,点击了一下我本来以为会发送http请求什么的,重新获取数据,再生成我们看到的那颗树,但是解压js后发现这个东西好像被写到了js中,基本就是生成了这个东西:

 生成的职位列表
他是一个表格,里面有很多事件!!!



我们这个td里面有一个span元素,给span了一个click事件,点击后会弹出我们要的结果:



然后进行最后的操作。

分析问题

好了,到了这里我们不知道我把问题解释清楚没有:

1 点击外部按钮便弹出了我们要的第一个弹出层。

2 点击其中的“加号”或者文字便弹出具有多选框的可选项

3 选择项目点击确定。

以上几个做完,我们的流程便结束了。

优化方案

不知从什么时间开始,我有了一点代码洁癖,看着这个代码我怎么就感觉有点不爽,他这个东西主要有以下问题:

1 table渲染速度慢

2 td/span有太多的事件,过多的事件绑定对我们的性能也有影响。

3 他的click函数全部写到了标签上(仁者见仁,我是非常不喜欢这样做)

其它

我们来看看,他其它地方其实做了一定处理:

<span onclick="zbw.PopupDiv.allIns['buttonSelJobType'].fnPopupChildren(this,['348','物流/仓储'])" class="availItem">物流/仓储</span>
为了防止命名冲突,我们看看这家伙定义的命名空间可长可长了。长到我都不想看了。。。。

好了暂时其它问题我这里还没发现,只不过我认为其中几个图片按钮相关可以用标签实现啦。。。

既然说都说了这么多,那我们不如先来写一个呗,写了再继续我们的问题吧!

实现职位选择功能

我们现在一起来实现这个职位选择功能,所以我们先分析下我们需要干些什么:

① 点击text在text处出现弹出层

② 弹出层出来后,我们点击其中的“加号”或者文字便弹出第三个弹出层

③ 选择第三个弹出层里面的checkbox项目最后点击确定后便将选择插入text(多项以分号分割)

若是想要优化的话,也许可以尝试点击后再加载数据再生成dom,一旦生成后便将dom缓存起来,我们这里作为demo就不搞那么多事情了。

第一步,准备工作

下拉选择文本

实现功能前,我们先准备一点点小东西,第一个就是长得像下拉菜单的文本框:

复制代码
 1 <html xmlns="http://www.w3.org/1999/xhtml">
 2 <head>
 3     <title></title>
 4     <style type="text/css">
 5         .dropText { display: inline-block; border: 1px solid #B6B6B6; border-right: none; border-radius: 5px 0 0 5px; 
cursor: pointer; margin-right: 20px; }
 6         .dropText input { border: none; border-radius: 5px 0 0 5px; cursor: pointer; padding-left: 5px; }
 7         .dropText span { display: inline-block; margin-right: -10px; width: 20px; border: 1px solid #B6B6B6; 
border-radius: 0 5px 5px 0; margin: -1px -20px -1px 0; text-align: center; padding: 4px 0 4px 8px; }
 8         .dropText i { display: inline-block; border: 6px solid black; border-color: black transparent transparent; 
border-bottom: none; vertical-align: 3px; }
 9     </style>
10     <script src="../../scripts/jquery-1.7.1.js" type="text/javascript"></script>
11     <script type="text/javascript">
12         $(document).ready(function () {
13         });
14     </script>
15 </head>
16 <body>
17     <div style="margin: 100px auto; padding-left: 100px;">
18         <div class="dropText" id="dropText">
19             <input type="text" placeholder="请选择职位" /><span><i></i>&nbsp;</span>
20         </div>
21         <span>dddd</span>
22     </div>
23 </body>
24 </html>
复制代码


我们来看看我们形成的这个框,这个在现代浏览器还能看,而且各位千万不要小看这个东西,这个东西真不像各位想象那么简单,比如我这个代码就有很大的优化空间!

PS:各位看到我的span里面多了一个&nbsp;我为什么会这么做?不这么做有什么影响?i被设置为inline-block对整体行对齐有什么影响,这块代码还可以如何优化?这个问题暂时留给各位了,我们下来再一起解决,这个对行内元素的理解有莫大的帮助,请各位动手吧。

十字开关

复制代码
 1 <style type="text/css">
 2 /*十字开关*/
 3 .croSwitch { display: inline-block; border: 1px solid #108efe; border-radius: 4px; width: 16px; 
height: 16px; text-align: center; position: relative; cursor: pointer; }
 4 .croSwitch i { background-color: #108efe; border-radius: 6px; position: absolute; }
 5         
 6 .croSwitch .horizontal { width: 12px; height: 2px; left: 2px; top: 7px; }
 7 .croSwitch .vertical { height: 12px; width: 2px; top: 2px; left: 7px; }
 8 .cls .vertical { display: none; }
 9 </style>
10 
11 <span class="croSwitch"><i class="horizontal"></i><i class="vertical"></i></span>
12 <span class="croSwitch cls"><i class="horizontal"></i><i class="vertical"></i></span>
复制代码


虽然很丑但是很温柔。。。

Ps:请思考若是外层span不设置高度会有什么后果

好啦,小东西大概懂弄好了,我们现在来组织职位的dom结构吧。

职位列表样式

我们首先根据上面的表格,使用jquery操作他生成如下结构:

 最新的结构


 

好了,我们现在来调整一下样式。



 

由于这个家伙着实太丑了,我放弃了,我这里上传个图片好了。。。。

 

可运行代码:

 基本列表样式


PS:第三个坑,不知道各位发现没,就算使用背景图片,我们的小图片看上去感觉还是有一些问题呢,我们是不是应该看看呢?

好了,我们将我们第一阶段的代码连起来:

 带交互代码
三层弹出:

我们在样式上做一点优化,加上鼠标hover效果,其它暂时不管。于是我们来看看他点击时候再弹出功能如何实现呢?我们这里看看原来的代码:

<span onclick="zbw.PopupDiv.allIns['buttonSelJobType'].fnPopupChildren(this,['306','生产/加工/制造'])" class="availItem">生产/加工/制造</span>
我们看着,他这里有一个id,所以我这里有这样一个实现思路:

① 这个id必定对应着自己的id,我们根据此id可以选出其子项(根据省id可以得出市id)

② 由于他这个数据是一次性读出的,所以父级id对应子项应该已经缓存起来了,可以是字符串,也可以是dom结构

③ 然后我们这里先预先定义一个这样的结构:

复制代码
1 var jobListObj = {
2 '1': 'dom',
3 '2': 'dom',
4 '3': 'dom',
5 '4': 'dom'
6 }
复制代码
现在的逻辑便是,我们点击“加号”或者文字,从而获取我们的id(1-4),我们根据id获取dom,我们再定位我们的dom在应该出现的位置,整个逻辑结束。

于是我们来测试下我们的思路是否正确,因为原来就没有绑定id上,我们现在为四个角搞一个id即可,四个方向上能正常显示,我们这里就不管了。

PS:写到这里其实已经离题了,想说的问题还没说呢,我们其实没必要实现这个功能的,但是都走到这一步了只能硬着头皮写下去了。。。

最后形成的代码:

 View Code
演示效果,可运行(友情提示请使用IE9+)

咳咳,离题离的离谱

昨天最初想写的东西和以上的东西没有多大关联,偏题偏得离谱啊!!!

我当时很臭屁的认为自己能1,2个小时完成这个功能来着,最后发现这家伙还真不是那么简单的。。。这不,今天又花了2个小时才搞出这么一个四不像的东西,而且我也不想继续搞这个了,因为这次的主题不是这个,职位选择框我们暂时就这个样式吧,以后有机会再形成插件。

现在我们开始进行下一步探讨,看看问题出现在哪。

正文开始

我们看到,这个职位选择框,其实本身没有什么问题,但是卡了组员1.5天的东西到底是什么呢?

其实是需求,因为需求变更,原来放在页面上,好好的元素,现在被放在了一个弹出层里面,于是各种各样的问题都出来了。。。。

① 弹出层的遮盖层z-index过大,遮盖了我们的职位层

② 弹出层本身的z-index过大,也遮盖了我们的职位层

但是以上两个问题都比较好处理,比较难处理的出来了:

这个项目之前的项目人员并不是像我这样将各个弹出层独立出来,都是以body为包含快(containing block),而是放在了一个div里面

并且将这个div放进了弹出层那个容器里面,于是我们来看看可能出现的问题:

① 由于absolute的包含快有所不同,其依赖最近的布局元素,所以之前js计算位置的方法可能失效

② 不知道原来处于什么考虑,代码中div容器布局为relative。。。。。其定位方法十分诡异

③ 奇怪的现象就是二级弹出层正常显示,三级弹出层你压根找不到!!!

以上便是组员遇到的问题,还有一个客观的因素就是原来的js依次分布到三个不同的地方,然后代码又全部压缩过了,我处理的时候还需要解压什么的,而且原来的代码中有很多地方没有分号,没有报错真是个奇迹(其实经常出现莫名的js错误啦,总之坑很多)。

我看着代码后不一会就发现了问题所在,问题本身并不难,解决也比较轻易,但是知不知道就很重要了。

原来实现思路:

① 由于装第一个弹出层的div是relative定位的,所以他定位到下拉框的实现方法和我们想象的不一样,是相对于div的位置,而不是body



 

他这个实现方案,我们不予评价,但是就这种方法要伤害多少我多少脑细胞,我就确实不想去想了。。。这里我居然还有点佩服原来开发的思维能力了。。。

② 他第一步,弹出层居然还能精准定位到下拉文本,但是当他再点击弹出层里面的文字准备弹出最终的东西时,终于开始悲剧了。。。



我那两个倒霉的组员要干神马事情呢,他们面临的又是什么呢:

① 在绝对定位弹出层上面(parent)有个正常流文本下拉文本框与div容器(div),并且该容器是relative定位的

② div中有2块弹出层(tan1,tan2),点击parent上面的下拉文本便弹出tan1,并且其定位必须精准,1像素只差都会很难看

③ 在tan1出来后,便点击tan1中的文字,根据该文字元素定位tan2

PS:不知道你们晕没有,反正我是晕了

人家这个插件本来是用于普通流的,其根元素为body,但是现在搞到弹出层里面来了,所以出现了这些问题。

我最后就直接总结了一下他这个最大的问题,就是实现过于复杂,所以昨天才忍不住自己写了一个(虽然效果不好。。。)

当然,最后我的解决方案更加诡异,这里就不说明了,因为没有什么意义,但是根据这个东西,我却提炼了一点点很有意思的东西与大家分享呢。这也是组员找不到问题的原因。

relative与鼠标点的定位

有例子有真相!!!

 View Code
各位看看我们这个代码干的事情:

复制代码
 1 <html xmlns="http://www.w3.org/1999/xhtml">
 2 <head>
 3     <title></title>
 4     <style type="text/css">
 5         body { font: 12px 'PTSansRegular',Arial,Helvetica,sans-serif; background: #D1D1D1; }
 6         ul, li { margin: 0; padding: 0}
 7         li { list-style: none; }
 8         
 9         #tabs_container { width: 400px; height: 200px; background: white;}
10         #tabs { border-bottom: 1px solid #1C87D5; padding: 5px 5px 0;  width: 690px; margin: 0 auto;  }
11         #tabs li { padding: 5px 10px;  cursor: pointer; display: inline-block; background: #1C87D5; color: White; }
12         #tabs li.sec { color: black;}
13         
14         #parent { width: 700px; height: 400px; background: white; margin: 0 auto; position: relative; }
15         #parent div { filter:alpha(opacity=50); -moz-opacity:0.5; opacity:0.5; font-weight:bold; background: red; position: absolute; }
16     </style>
17 </head>
18 <body>
19     <ul id="tabs" >
20         <li type="draw" class="sec">画矩形框</li>
21         <li type="drag">拖到矩形框</li>
22     </ul>
23     <div id="parent">
24     </div>
25     <div id="state"></div>
26 </body>
27 </html>
复制代码
① parent容器的定位是relative

② 我们在parent里面画的div是absolute

③ 但是,我们div定位是根据鼠标的x/y确定的,而这个是相对于body的,所以我们这里会错位(因为div是相对于parent布局,不是body)

④ 为了解决错位问题,我们便要用x/y减去parent的offset top与left

此块单独处理问题不大,就怕页面中弹出层过多时候导致你已经分不清谁是谁的包含快了,所以便会出现错位问题,这也是同事迟迟不能解决问题的症结点。

z-index

扩展知识:http://www.qianduan.net/that-thing-on-the-z-index.html

说道定位就不得不提z-index,这个家伙在IE7以下又是一个坑爹的货,了不起哪天各位又会碰到,反正我组员就碰到了,在IE7下,这个就是个混蛋!!!

关于html堆栈的那块,各位可以看看博客园寒冬的博客,堆栈顺序对z-index影响很大,我这里就不描述了。

我们遇到z-index时候,会很天真的认为z-index设置的越大时候,便应该更靠近我们,但是定位元素多了后,却总是发现这样那样的bug一大堆!!!(IE7以下尤其恶心),具体这块的拓展可以看看聂微东大哥的博客,关于z-index的描述已经十分详尽了,我这里简单说下:

每一个定位元素都有其根元素,当根元素为定位元素时,该元素的子元素若是也出现定位元素,子元素将受到父元素z-index的制约。

借用东哥一句话,元素要靠前也是拼爹的!

inline与inline-block

关于PS中的问题,感觉没人关注,我这里也不花精力去描述了,但是有个东西应该提出来:

我们上次说了,其实IE6/7是支持inline-block的,只不过块级元素对其支持不是很好罢了,但是我这里想把inline-block再一次提出来说一下,因为我们可能被他的名字迷惑了!!!

inline-block便应该包含inline与block的特性,对不!

是的,他包含了block的特性,但是我不认为他包含了inline的特性,因为inline的特性的核心是inline boxes,那么我们的inline-block拥有吗?

PS:答案是拥有的,我私下搞了半个小时,昨天以为没有inline boxes,以为发现新大陆了,丢人啦,,,,

结语

我今天又唧唧歪歪说了一大堆,也不知道各位有没有什么收获呢,明天我们还是一起来研究点有意义的事情吧,我感觉我对行内元素还是不够熟悉,明天我们就一起看看行内元素哇? 


本文转自叶小钗博客园博客,原文链接:http://www.cnblogs.com/yexiaochai/p/3141582.html,如需转载请自行联系原作者

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
css动画:文字向上移动并逐渐消失 点击按钮显示+1上移淡出
css动画:文字向上移动并逐渐消失 点击按钮显示+1上移淡出
0 0
点击图片或者鼠标划过切换样式的另一种写法
点击图片或者鼠标划过切换样式的另一种写法
0 0
每日一学—设置页面文字大小随屏幕大小变化而变化(rem布局)
每日学一点加强技术水平,夯实基础。 阅读这篇文章,一起学习rem布局吧。
0 0
Qml实用技巧:在可视元素之前半透明覆盖一个可视元素,阻止鼠标透(界面)传(防止点击到被遮挡的按钮)
Qml实用技巧:在可视元素之前半透明覆盖一个可视元素,阻止鼠标透(界面)传(防止点击到被遮挡的按钮)
0 0
利用自定义动画 animate() 方法,实现某图书网站中“近 7 日畅销榜”中的图书无缝垂直向上滚动特效:当光标移入到图书上时,停止滚动,鼠标移开时,继续滚动
利用自定义动画 animate() 方法,实现某图书网站中“近 7 日畅销榜”中的图书无缝垂直向上滚动特效:当光标移入到图书上时,停止滚动,鼠标移开时,继续滚动
0 0
原生js判断某个区域的滚动条滚动到了底部
原生js判断某个区域的滚动条滚动到了底部
0 0
小程序 - swiper除了左右切换还有上下滚动超出屏幕的内容
本来呢,我是有专门整理小程序恶心bug的文章的,每次只要添加汇总就好, 但是呢,鉴于这个问题的恶心程度,所以我把他单独拿出来说了。 ——————————————--------------------------------------------------产品经理都说恶心的需求---------...
2003 0
+关注
文章
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载