zoukankan      html  css  js  c++  java
  • l2Overlay: 原生 JavaScript 实现 Hoverpop 效果插件 p

    最近想给自己做的项目加上类似于 Facebook 的 Namecard 效果,即鼠标移动到制定目标后浮现一个信息卡,在鼠标移开目标或者信息卡后则自动隐藏。

    搜索了一下好像没有现成的插件可用,找到过几个仿 Facebook Style 的代码片段,但是感觉代码质量比我的还要糟糕,而且也不完全符合自己的要求,所以就花了一个下午的时间,用原生 JavaScript 写了一个类 Facebook Style 的 Namecard (hoverpop)插件。

    l2Overlay

    参看演示效果可以到:l2Overlay 演示

    l2Overlay 的 CSS 代码

    l2Overlay 的样式主要是模仿 Facebook 的 Namecard,下面是根据我的 l2Overlay 编写的 CSS 样式:

    1. .l2OverlayWrapper {
    2. font-size:12px;
    3. color:#333333;
    4. line-height:1.8;
    5. background-color:#FFFFFF;
    6. border:1px solid #8C8C8C;
    7. box-shadow:0010px#C8C8C8;
    8. margin:9px0;
    9. position: relative;
    10. max-width:300px;
    11. _width:300px;
    12. }
    13. .l2OverlayArrow {
    14. position: absolute;
    15. width:16px;
    16. height:9px;
    17. background:url("arrow.png") no-repeat -50px0px transparent;
    18. }
    19. .arrow-lt .l2OverlayArrow {
    20. left:15px;
    21. top:-9px;
    22. }
    23. .arrow-rt .l2OverlayArrow {
    24. right:15px;
    25. top:-9px;
    26. }
    27. .arrow-lb .l2OverlayArrow {
    28. background-position:-17px0;
    29. left:15px;
    30. bottom:-9px;
    31. _bottom:-15px;
    32. }
    33. .arrow-rb .l2OverlayArrow {
    34. background-position:-17px0;
    35. right:15px;
    36. bottom:-9px;
    37. _bottom:-15px;
    38. }
    39. .l2OverlayContent {
    40. margin:10px;
    41. }
    42. .l2Action {
    43. padding:010px;
    44. margin:10px-10px-10px;
    45. background-color:#F2F2F2;
    46. border-top:1px solid #CCCCCC;
    47. line-height:34px;
    48. height:34px;
    49. }
    50. .l2Title {
    51. border-bottom:1px dotted #CCCCCC;
    52. font-size:14px;
    53. font-weight: bold;
    54. margin:0010px;
    55. }

    l2Overlay 的 Javascript 代码

    Js 代码不压缩只有 9.88 kb,YUI 压缩后只有 4.15 kb,对于不想只为了一个效果而引用一个库的来说,绝对是很好的选择。

    1. /**
    2. * Plugin Name: l2Overlay
    3. * Plugin Author: LOO2K
    4. * Plugin Address: http://loo2k.com/blog/l2overlay-a-javascript-based-hoverpop-plugin/
    5. * Plugin Edition: 0.1
    6. * Last updated: 2012.05.19
    7. */
    8. function l2Overlay(){
    9. this.initialize.apply(this, arguments);
    10. }
    11.  
    12. l2Overlay.prototype ={
    13. /*
    14. * object 要应用 l2Overlay 的元素 对象或者数组
    15. * content 显示内容 'function|html|string|target'
    16. * option 选项
    17. * option = {
    18. * 'title' = 'string', // defalut undefied
    19. * 'pos' = 'auto|lt|lb|rt|tb', // default auto
    20. * 'cache' = 'true|false' // default false
    21. * }
    22. */
    23. initialize:function(object, content, option){
    24. this.id =(newDate()).getTime();
    25. this.createElement();
    26. var _this =this;
    27. this.object = object;
    28. this.content = content;
    29. this.option ={
    30. 'title': option.title ||undefined,
    31. 'pos': option.pos ||'auto',
    32. 'cache': option.cache ||false
    33. };
    34. this.hidel2Overlay;
    35. this.l2Overlay.onmouseover =function(){
    36. _this.cancleHide();
    37. }
    38. this.l2Overlay.onmouseout =function(){
    39. _this.hideOverlay();
    40. }
    41. if(typeofthis.object ==='object'&&typeofthis.object.length ==='number'){
    42. for(var i =0; i <this.object.length; i++){
    43. this.addEvent(this.object[i]);
    44. }
    45. }elseif(typeofthis.object =='object'&&!(this.object instanceof Array)){
    46. this.addEvent(this.object);
    47. }else{
    48. alert('传入对象错误');
    49. }
    50. },
    51. createElement:function(){
    52. // 生成基本模版
    53. if(!document.getElementById('l2Overlay_'+this.id)){
    54. var overlay = document.createElement('div');
    55. overlay.id ='l2Overlay_'+this.id;
    56. overlay.style.position ='absolute';
    57. overlay.style.zIndex ='9999';
    58. overlay.style.display ='none';
    59. var wrapper = document.createElement('div');
    60. wrapper.className ='l2OverlayWrapper';
    61. var arrow = document.createElement('div');
    62. arrow.className ='l2OverlayArrow';
    63.  
    64. var content = document.createElement('div');
    65. content.className ='l2OverlayContent';
    66. wrapper.appendChild(arrow);
    67. wrapper.appendChild(content);
    68. overlay.appendChild(wrapper);
    69. document.getElementsByTagName('body')[0].appendChild(overlay);
    70. }
    71. this.l2Overlay = document.getElementById('l2Overlay_'+this.id);
    72. var wrapper =this.l2Overlay.getElementsByTagName('div')[0].getElementsByTagName('div');
    73. this.l2Content = wrapper[1];
    74. this.l2Arrow = wrapper[0];
    75. },
    76. getPos:function(el){
    77. var ua = navigator.userAgent.toLowerCase();
    78. var isOpera =(ua.indexOf('opera')!=-1);
    79. var isIE =(ua.indexOf('msie')!=-1&&!isOpera);
    80. if( el.parentNode ===null|| el.style.display =='none'){
    81. returnfalse;
    82. }
    83. var parent =null;
    84. var pos =[];
    85. var box;
    86.  
    87. if( el.getBoundingClientRect ){
    88. // For IE
    89. box = el.getBoundingClientRect();
    90. var scrollTop =Math.max(document.documentElement.scrollTop, document.body.scrollTop);
    91. var scrollLeft =Math.max(document.documentElement.scrollLeft, document.body.scrollLeft);
    92. return{
    93. x: box.left + scrollLeft,
    94. y: box.top + scrollTop
    95. };
    96. }elseif( document.getBoxObjectFor ){
    97. // For FF
    98. box = document.getBoxObjectFor(el);
    99. var borderLeft =(el.style.borderLeftWidth)? parseInt(el.style.borderLeftWidth):0;
    100. var borderTop =(el.style.borderTopWidth)? parseInt(el.style.borderTopWidth):0;
    101. pos =[box.x - borderLeft, box.y - borderTop];
    102. }else{
    103. // For Safari & Opera
    104. pos =[el.offsetLeft, el.offsetTop];
    105. parent = el.offsetParent;
    106. if( parent != el ){
    107. while(parent){
    108. pos[0]+= parent.offsetLeft;
    109. pos[1]+= parent.offsetTop;
    110. parent = parent.offsetParent;
    111. }
    112. }
    113. if( ua.indexOf('opera')!=-1||(ua.indexOf('safari')!=-1&& el.style.position =='absolute')){
    114. pos[0]-= document.body.offsetLeft;
    115. pos[1]-= document.body.offsetTop;
    116. }
    117. }
    118. if( el.parentNode ){
    119. parent = el.parentNode;
    120. }else{
    121. parent =null;
    122. }
    123. // account for any scrolled ancestors
    124. while(parent && parent.tagName !='BODY'&& parent.tagName !='HTML'){
    125. pos[0]-= parent.scrollLeft;
    126. pos[1]-= parent.scrollTop;
    127. if(parent.parentNode){
    128. parent = parent.parentNode;
    129. }else{
    130. parent =null;
    131. }
    132. }
    133. return{
    134. x: pos[0],
    135. y: pos[1]
    136. };
    137. },
    138. getSize:function(element){
    139. if(element.offsetWidth !==0){
    140. /* 元素不是display:none的情况,这个时候是能得到尺寸的 */
    141. return{
    142. 'width': element.offsetWidth,
    143. 'height': element.offsetHeight
    144. };
    145. }
    146. var old ={};
    147. /* 将display:none元素设成visibility:hidden */
    148. var options ={
    149. position:"absolute",
    150. visibility:"hidden",
    151. display:"block"
    152. }
    153. for(var name in options ){
    154. old[ name ]= element.style[ name ];
    155. element.style[ name ]= options[ name ];
    156. }
    157. var temp ={
    158. 'width': element.offsetWidth,
    159. 'height': element.offsetHeight
    160. };
    161. for(var name in options ){
    162. element.style[ name ]= old[ name ];
    163. }
    164. return temp;
    165. },
    166. hideOverlay:function(){
    167. var _this =this;
    168. this.hidel2Overlay = setTimeout(function(){
    169. _this.l2Overlay.style.display ='none';
    170. },100);
    171. },
    172. cancleHide:function(){
    173. if(this.hidel2Overlay ){
    174. clearTimeout(this.hidel2Overlay);
    175. }
    176. },
    177. getBrowser:function(){
    178. var offset ={
    179. 'top': document.documentElement.scrollTop || document.body.scrollTop,
    180. 'left': document.documentElement.scrollLeft || document.body.scrollLeft
    181. }
    182. return offset;
    183. },
    184. addEvent:function(object){
    185. var _this =this;
    186. //var _object = this.object;
    187. var _object = object;
    188. _object.onmouseover =function(){
    189. _this.cancleHide();
    190. // 缓存模块
    191. if( _this.option.cache &&this.l2cache ){
    192. _this.l2Content.innerHTML =this.l2cache;
    193. }elseif(typeof _this.content ==='function'){
    194. _this.l2Content.innerHTML = _this.content.apply(this, arguments);;
    195. //console.log(_this.content());
    196. }else{
    197. _this.l2Content.innerHTML = _this.content;
    198. }
    199. if( _this.option.cache &&!this.l2cache ){
    200. this.l2cache = _this.l2Content.innerHTML;
    201. }
    202. // 定位模块
    203. var position = _this.getPos(this);
    204. var curTop = position.y;
    205. var curLeft = position.x;
    206. var offset = _this.getSize(_this.l2Overlay);
    207. var self = _this.getSize(this);
    208. var browser = _this.getBrowser();
    209. var pos ='';
    210. if( _this.option.pos ==='auto'){
    211. if((curLeft - browser.left - offset.width)>0){
    212. pos +='r';
    213. }else{
    214. pos +='l';
    215. }
    216. if((curTop - browser.top - offset.height)>0){
    217. pos +='b';
    218. }else{
    219. pos +='t';
    220. }
    221. }else{
    222. pos = _this.option.pos;
    223. }
    224. switch(pos){
    225. case'lt':
    226. _this.l2Overlay.className ='arrow-lt';
    227. oTop = curTop + self.height;
    228. oLeft = curLeft;
    229. break;
    230. case'rt':
    231. _this.l2Overlay.className ='arrow-rt';
    232. oTop = curTop + self.height;
    233. oLeft = curLeft - offset.width + self.width;
    234. break;
    235. case'rb':
    236. _this.l2Overlay.className ='arrow-rb';
    237. oTop = curTop - offset.height;
    238. oLeft = curLeft - offset.width + self.width;
    239. break;
    240. case'lb':
    241. default:
    242. _this.l2Overlay.className ='arrow-lb';
    243. oTop = curTop - offset.height;
    244. oLeft = curLeft;
    245. break;
    246. }
    247. _this.l2Overlay.style.top = oTop +'px';
    248. _this.l2Overlay.style.left = oLeft +'px';
    249. _this.l2Overlay.style.display ='';
    250. }
    251. _object.onmouseout =function(){
    252. _this.hideOverlay();
    253. }
    254. }
    255. }

    l2Overlay 的使用方法

    l2Overlay 创建了一个函数对象 l2Overlay,接受三个参数。分别为:

    1. object: 传入的必须是 HTML 元素,或者是 HTML 元素数组;
    2. content: 显示内容,可以是函数,HTML 代码,或者字符串,作用域为 object;
    3. option: option 对象可以设置 l2Overlay 显示的位置以及是否启用缓存;
    1. var applyLinks = document.getElementById('demo').getElementsByTagName('a');
    2. var content =function(){
    3. var html ='<div class="l2Title">这是一个标题</div>';
    4. html +='Function 内的作用域为该链接,如执行 this.href 可以得到该链接的地址:';
    5. html +=this.href;
    6. html +='<div class="l2Action"><a href="#">添加</a> | <a href="#">修改</a> | <a href="#">删除</a></div>';
    7. return html;
    8. }
    9. var options ={'pos':'','cache':true};
    10. new l2Overlay(applyLinks, content, options);

    参看演示效果可以到:l2Overlay 演示

    下载插件可以到:l2Overlay 下载

    小总结

    第一次写 JavaScript 插件,功夫不到家,代码仅供参考 :P

    其实这个用 jQuery 等库实现会简单很多,而且代码行数也会少很多,但是为了熟悉原生的 JavaScript 还是自己动手写了一遍。

  • 相关阅读:
    linux软件安装方式
    docker 安装 jenkins touch: cannot touch ‘/var/jenkins_home/copy_reference_file.log’: Permission denied Can not write to /var/jenkins_home/copy_reference_file.log. Wrong volume permissions?
    [ERR] Node goodsleep.vip:6379 is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0.
    Linux 常用命令 服务器间scp 用户 export 创建文件、软连接
    redis 安装 集群 主从 哨兵 docker
    WPF密码框中禁止复制、粘贴
    Application 统计在线人数
    【转义字符】HTML 字符实体&lt; &gt: &amp;等
    SQL语句统计每天的数据
    正则表达式计算代码数
  • 原文地址:https://www.cnblogs.com/anyuqi/p/2726288.html
Copyright © 2011-2022 走看看