1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > 使用原生js来替换title属性的悬浮文字提示-可自定义样式和出现时间-190826更新版本2.0源代码

使用原生js来替换title属性的悬浮文字提示-可自定义样式和出现时间-190826更新版本2.0源代码

时间:2023-03-03 17:29:42

相关推荐

使用原生js来替换title属性的悬浮文字提示-可自定义样式和出现时间-190826更新版本2.0源代码

简介

要让一个DOM元素出现悬浮文字提示,一般情况下,我们都会选择使用H5的title属性。例如:

<div title="456">123</div>

这样设置之后,当鼠标在div上悬浮过了一段时间之后,网页上鼠标位置附近就会出现悬浮文字提示,例如这样:

但是,不同的浏览器,悬浮等待的时间和悬浮文字的样式都可能会不一样,例如chrome上显示是白底灰字,firefox上就可能是黄底黑字,时长可能是3s或者1s,如果为了确保不同浏览器的用户体验的效果趋于一致的话,那么我们就需要禁用默认的title属性,改用js手动实现悬浮文字的提示。

1.需求分析

为了提高组件的简洁性,所以这里我采用原生js进行编码,不兼容IE 6 7 8,并且没有做过渡动画,只是简单是隐藏显示,有兴趣的同学可以改用jquery重构来提高代码兼容性,用fadeIn fadeOut等动画效果代替直接的显示隐藏。

经分析,H5的title属性的作用逻辑如下:

鼠标进入元素时,延时一定时间后显示悬浮文字提示,并且当鼠标在元素内移动时移除文字提示鼠标离开元素时,移除文字提示文字提示为一个inline-block的div或span,固定定位,位置在鼠标位置的附近。

因为这个组件比较简单,所以我就直接上代码啦:

2.代码解析

js和html测试代码如下:

<!DOCTYPE html><html><head><meta charset="utf-8"><title></title><style>.box{margin-top: 100px;text-align: center;}</style></head><body><div class="box" title="456">123</div><div><span title="hello world!">asdjkasl</span><span title="aslkdjsakl">fjksdkfj</span></div><script>function test(){alert(1);}//使用自定义的悬浮文字提示代替原生的title属性,采用addEventListner进行事件绑定,不兼容IE 6 7 8var titleTools = {_init : function(time){var temp = time;time = parseInt(time);if(!isNaN(time)&&time>=0){this.timeout = time;}else{console.warn("param "+time+" is not a number or out of range! using default timeout setting");}//选中所有含有title属性的节点var eles = document.querySelectorAll('*[title]');for(var i=0;i<eles.length;i++){//隐藏原先的title属性,改用js进行控制if(eles[i].title){eles[i].dataset.title = eles[i].title;eles[i].title = '';}//绑定函数eles[i].timeoutms = this.timeout;eles[i].addEventListener("mouseenter",this.title);eles[i].addEventListener("mouseleave",this.clear);eles[i].leaveAction = this.clear;}},//延时显示文字timeout : 500,//显示提示文字的函数绑定在mouseenter中title : function(e){clearTimeout(this.timer);var self = this;self.removeEventListener("mousemove",this.leaveAction);this.timer = setTimeout(function(){var div = document.createElement('div');div.innerHTML = self.dataset.title;div.style.cssText = 'display:inline-block;padding:0 5px;line-height:1.3;color:#000;background:#fff;border:1px solid #000;font-size:13px;position:fixed;left:'+(e.clientX+5)+'px;top:'+(3+e.clientY)+'px;z-index:999';document.body.appendChild(div);self.titleElement = div;self.addEventListener("mousemove",self.leaveAction);},this.timeoutms);},//清除文字提示框的函数,绑定在mousemove和mouseleave上clear : function(e){clearTimeout(this.timer);var div = this.titleElement;if(div&&div.parentNode){div.parentNode.removeChild(div);}}};</script><script>titleTools._init(300);</script></body></html>

上面这个代码还是比较简单,涉及的知识点主要有:

1.原生js获取节点的方法,document.querySelector()和document.querySelectorAll().这两个函数,接受的参数都是一个css选择器字符串,例如’.box’, ".father .son:nth-of-type(1)"之类的,总之只要能够写在css中的选择器,这里都可以使用。其中,document.querySelector()返回的是第一个匹配的原生DOM节点,和document.getElementById()有点类似,但是更加强大,而document.querySelectorAll()返回的是一个原生节点数组,存储所有匹配到的节点,和document.getElementsByClassName()有点像,但是更好用。

2.通配符选择器*用于选中网页上的所有节点,属性选择器[]用于选中含有某个属性或属性值为某个特定值的节点。搭配在一起后*[title]用于选中所有含有title属性的节点。

3. JavaScript中函数和对象this的指向问题,函数的this通常指向函数的上一层对象,上面的代码中频繁地使用到了this,如果大家对js的this的概念含糊不清的话可能会看不懂,建议大家百度一下或参考:JS this指向总结

3.结语

这个组件比较简单,测试什么的我就不贴图啦,大家自己把代码拷到本地运行就知道效果了,先写到这里吧,本文作者郑伟斌,写于/4/26,转载请注明出处

4.版本2.0源代码

v2.0采用jQuery改写,使用了MutationObserver来自动监听新元素的插入,使用者只需在页面初始化时调用titleTools.init()即可

;(function(window,document,$){var titleTools = tt = {$box: null,_init : function(time,selector){var $box = selector ? $(selector) : $('body');this.$box = $box;var temp = time;time = parseInt(time);if(!isNaN(time)&&time>=0){tt.timeout = time;}else{console.warn("param "+time+" is not a number or out of range! using default timeout setting");}//选中所有含有title属性的节点$box.find('*[title],*[data-optionaltitle]').each(function(index,ele){if(ele.title){$(ele).attr('data-optionaltitle',ele.title).removeAttr('title');} tt.bind(ele);});//监听body的后代节点插入和对title、data-optionaltitle属性的修改var MutationObserver = window.MutationObserver || window.WebkitMutationObserver || window.MozMutationObserver;if(!tt.observer){var observer = this.observer = new MutationObserver(function(mutations,observer){mutations.forEach(function(mutation){var type = mutation.type;var target = mutation.target;if(type == 'attributes'){//通过定时器达到异步执行的目的setTimeout(function(){//title属性只识别增加,不识别清空操作if(mutation.attributeName == 'title'){//确保事件绑定tt.bind(target);if(target.title) $(target).attr('data-optionaltitle',target.title).removeAttr('title');}//如果需要清空title则将data-optionaltitle赋值为空else if(mutation.attributeName == 'data-optionaltitle'){//确保事件绑定tt.bind(target);}},0);//异步函数会等待所有同步代码执行完毕后才开始执行}else if(type == 'childList'){var adds = mutation.addedNodes;var removes = mutation.removedNodes;//nodeList数组//通过定时器达到异步执行的目的setTimeout(function(){$(adds).each(function(index,ele){if(ele.nodeType == 1){tt._init(tt.timeout,ele);}});$(removes).each(function(index,ele){//解绑事件tt.unbind(ele);});},0);}});});var options = {attributes: true,attributeFilter: ['title','data-optionaltitle'],attributeOldValue: true,childList: true,subtree: true};$box.each(function(index,ele){observer.observe(ele,options);});}},dispose: function(){if(tt.observer){tt.observer.disconnect;delete tt.observer;}var $box = tt.$box;$.each($box,function(index,ele){var $self = $(ele);$self.attr('title',$self.attr('data-optionaltitle')).removeAttr('data-optionaltitle');tt.unbind($self);});},bind: function(ele){tt.unbind(ele);$(ele).on("mouseover.titletools",titleTools.title).on("mouseout.titletools",titleTools.clears)},unbind: function(ele){$(ele).off('mousemove.titletools mouseover.titletools mouseout.titletools')},//延时显示文字timeout : 500,className : 'custom-title-box',styles : {"display" : "inline-block","padding": "4px 5px","line-height" : "1.34","color" : "#fff","background" : "rgba(0,0,0,0.7)","max-width" : "25em","border-radius" : "2px","font-size": "12px","position" : "fixed","z-index" : "999","text-align" : "justify"},remove : function(){$('.'+this.className).remove();},//显示提示文字的函数绑定在mouseover中title : function(e){e = e || window.event;e.stopPropagation ? e.stopPropagation() : window.event.cancelBubble = true;var self = this;self.nowX = e.clientX;self.nowY = e.clientY;$(self).on("mousemove.titletools",tt.moveRecord);},//moveRecord : function(e){e.stopPropagation ? e.stopPropagation() : window.event.cancelBubble = true;e = e || window.event;var type = e.type;var thisf = arguments.callee;var self = this;self.nowX = e.clientX;self.nowY = e.clientY;clearTimeout(this.timer);this.timer = setTimeout(function(){tt.remove();if(!$(self).attr("data-optionaltitle")) return;var div = document.createElement('div');div.className = tt.className;div.innerHTML = $(self).attr("data-optionaltitle");$(div).css(tt.styles);$(div).css({"left" : (self.nowX+15)+'px',"top" : (8+self.nowY)+'px'});document.body.appendChild(div);self.titleElement = div;$(self).off('mousemove.titletools');},tt.timeout);},//清除文字提示框的函数,绑定在mousemove和mouseout上clears : function(e){e.stopPropagation ? e.stopPropagation() : window.event.cancelBubble = true;clearTimeout(this.timer);tt.remove();}};window.titleTools = titleTools;})(window,document,jQuery)

更新时间: /8/26

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。