纯 JavaScript 工具提示

问题描述 投票:0回答:6

我正在尝试用纯 JavaScript 制作一个工具提示,如

hover
所示。就像 Stack Overflow 中的一样,将鼠标悬停在配置文件名称上时会显示
div

我尝试使用

onmouseover
onmouseout
并添加
setTimeout
让用户有几秒钟的时间将鼠标移动到工具提示内容上。但它并没有像我想象的那样工作。

我真的更喜欢纯 JavaScript,而不是使用任何库。有人可以帮帮我吗?


这就是我在纯 JavaScript 中所做的。

HTML

<div class = "name" onmouseover="show()" onmouseout="hide()">
    NAME
        <div class = "tooltip">
            PROFILE DETAILS
        </div>
    </div>

    <div class = "name" onmouseover="show()" onmouseout="hide()">
    NAME 2
        <div class = "tooltip" >
            PROFILE DETAILS 2
        </div>
    </div>

    <div class = "name" onmouseover="show()" onmouseout="hide()">
    NAME 3
        <div class = "tooltip" >
            PROFILE DETAILS 3
        </div>
    </div>

CSS

.name{
        float:left;
        margin:100px;
        border:1px solid black;
    }
    .tooltip{
        position:absolute;
        margin:5px;
        width:200px;
        height:100px;
        border:1px solid black;
        display:none;
    }

JavaScript

var name = document.getElementsByclassName("name");
    var tp = document.getElementsByclassName("tooltip");

    function show(){
        tp.style.display="block";
    }
    function hide(){
        tp.style.display="";
    }
javascript tooltip
6个回答
46
投票

无需 JavaScript 的解决方案

这使用CSS伪悬停来设置隐藏元素的显示。显示内容不需要在样式中而不是在元素上,这样它就可以在悬停时被覆盖。

.couponcode:hover .coupontooltip {
  /* NEW */
  display: block;
}

.coupontooltip {
  display: none;
  /* NEW */
  background: #C8C8C8;
  margin-left: 28px;
  padding: 10px;
  position: absolute;
  z-index: 1000;
  width: 200px;
  height: 100px;
}

.couponcode {
  margin: 100px;
}
<div class="couponcode">First Link
  <span class="coupontooltip">Content 1</span>
  <!-- UPDATED -->
</div>

<div class="couponcode">Second Link
  <span class="coupontooltip"> Content 2</span>
  <!-- UPDATED -->
</div>

外部链接

后续:

如果您需要支持非常旧的浏览器,则需要在鼠标进入 div 时向外部元素添加一个类。当鼠标离开时删除该类。


编辑

你的代码不起作用,因为 tp 是什么?是元素的集合,您将其视为一个元素。您需要做的就是传递对元素的引用

HTML:

<div class = "name" onmouseover="show(this)" onmouseout="hide(this)">  <!-- added "this" 2 times -->

**JavaScript:

//var name = document.getElementsByclassName("name");  /* not needed */
//    var tp = document.getElementsByclassName("tooltip"); /* not needed */


function show (elem) {  /* added argument */
    elem.style.display="block"; /* changed variable to argument */
}
function hide (elem) { /* added argument */
    elem.style.display="";  /* changed variable to argument */
}

11
投票

问题说:

纯 JavaScript 工具提示

但我认为在现代我们可以使用普通的 JS 和 CSS。特别是,当我们想要提供好看的款式时,这是必须的。

这个例子是纯JS和CSS的简单实现。

让我们使用

CSS
创建工具提示,并使用
JS
添加修改行为。对于此示例,我们将定义一个
tip
属性来存储将在工具提示上显示的文本。

visibility: hidden;
opacity: 0;
将保持
.tooltip
隐藏,并在
[tip]:hover
时出现。此外,我们可以使用
style.transform
重新定位工具提示的发射点。

const elements = [...document.querySelectorAll('[tip]')]

for (const el of elements) {
  const tip = document.createElement('div')
  tip.classList.add('tooltip')
  tip.textContent = el.getAttribute('tip')
  const x = el.hasAttribute('tip-left') ? 'calc(-100% - 5px)' : '16px'
  const y = el.hasAttribute('tip-top') ? '-100%' : '0'
  tip.style.transform = `translate(${x}, ${y})`
  el.appendChild(tip)
  el.onpointermove = e => {
    if (e.target !== e.currentTarget) return

    const rect = tip.getBoundingClientRect()
    const rectWidth = rect.width + 16
    const vWidth = window.innerWidth - rectWidth
    const rectX = el.hasAttribute('tip-left') ? e.clientX - rectWidth : e.clientX + rectWidth
    const minX = el.hasAttribute('tip-left') ? 0 : rectX
    const maxX = el.hasAttribute('tip-left') ? vWidth : window.innerWidth
    const x = rectX < minX ? rectWidth : rectX > maxX ? vWidth : e.clientX
    tip.style.left = `${x}px`
    tip.style.top = `${e.clientY}px`
  }
}
[tip] .tooltip {
  position: fixed;
  font-size: 16px;
  line-height: 20px;
  padding: 5px;
  background: #444;
  border: 1px solid #222;
  visibility: hidden;
  opacity: 0;
  box-shadow: -2px 2px 5px rgba(0, 0, 0, 0.2);
  transition: opacity 0.3s, visibility 0s;
  color: white;
  min-width: 120px;
}

[tip]:hover .tooltip {
  visibility: visible;
  opacity: 1;
}

button {
  display: block;
  cursor: pointer;
  padding: 8px 15px;
  border: 1px solid gray;
  border-radius: 4px;
  margin: 50px 5px;
  width: 200px;
  font-size: 18px;
  background: white;
}

button:hover {
  border-color: dodgerblue;
}
<button tip="Click me here!">I have a tooltip</button>
<button tip="Click me aswell!" tip-top tip-left>Top-left tooltip</button>


7
投票

对于非自定义的工具提示,您只需在主

div
的标题属性中添加您想要在工具提示中显示的消息即可。就像这样:

<div class = "name" onmouseover="show()" onmouseout="hide()" title="PROFILE DETAILS">

那么就不需要添加

onmouseover
onmouseout
事件处理程序。


6
投票

修复原始代码

我正在寻找类似的东西,我发现了这个页面。 它对我有帮助,但我必须修复你的代码才能使其正常工作。我认为这就是你尝试过的。 您必须通过对象的“ID”来引用它们。 这是我所做的,它有效:

function show(elem) {
  elem.style.display = "block";
}

function hide(elem) {
  elem.style.display = "";
}
.name {
  float: left;
  margin: 100px;
  border: 1px solid black;
}

.tooltip {
  position: absolute;
  margin: 5px;
  width: 200px;
  height: 50px;
  border: 1px solid black;
  display: none;
}
<div class="name" onmouseover="show(tooltip1)" onmouseout="hide(tooltip1)">
  NAME
  <div class="tooltip" id="tooltip1">
    PROFILE DETAILS
  </div>
</div>

<div class="name" onmouseover="show(tooltip2)" onmouseout="hide(tooltip2)">
  NAME 2
  <div class="tooltip" id="tooltip2">
    PROFILE DETAILS 2
  </div>
</div>

<div class="name" onmouseover="show(tooltip3)" onmouseout="hide(tooltip3)">
  NAME 3
  <div class="tooltip" id="tooltip3">
    PROFILE DETAILS 3
  </div>
</div>

外部链接


3
投票

即使是 $(document).ready,也很难用纯 JS 来完成——看这里: $(document).ready 相当于没有 jQuery

所以我使用一个简单的版本:

window.addEventListener("load", function () {
    var couponcodes = document.getElementsByClassName("couponcode");
    for (var i = 0; i < couponcodes.length; i++) {
        couponcodes[i].addEventListener("mouseover", function () {
            var coupontooltip = this.getElementsByClassName("coupontooltip")[0];
            coupontooltip.removeAttribute("style");
        });
        couponcodes[i].addEventListener("mouseout", function () {
            var coupontooltip = this.getElementsByClassName("coupontooltip")[0];
            coupontooltip.style.display = "none";
        });
    }
});

http://jsfiddle.net/mynetx/5qbP3/


2
投票

使用 popper+tippy 遇到了一些滞后,开始搜索替代方案并找到了 @Teocci 的上面很好的答案

我需要进行以下调整,因此这是修改后的代码:

  • 由于 css/innerHTML 冲突,将提示添加到 body,而不是 el
  • 使用js mouseevents进行切换,防止嵌套触发器
  • 始终位于底部的用例的箭头
  • 能够清除之前所有通过 DOM 变化进行动态调用的提示

CSS

.tooltip {
    position: fixed;
    z-index: 99;
    font-size: 12px;
    line-height: 12px;
    padding: 5px;
    background: #222;
    color: #fff;
    border: 1px solid #aaa;
    border-radius: 5px;
    font-family: sans-serif;
    box-sizing: border-box;
    /*box-shadow: -1px 2px 5px rgba(0, 0, 0, 0.2);*/
    transition: opacity 0.3s, visibility 0s;
    visibility: hidden;
    opacity: 0;
}

.tooltip-arrow{
    position: absolute;
    top: -4px;
    width: 7px;
    height: 7px;
    background: inherit;
    transform: rotate(45deg);
    border-top: 1px solid #aaa;
    border-left: 1px solid #aaa;
}

/* just for demo */
.box{
    margin: 25px;
    padding: 25px;
}

HTML

<div class="box" style="background:orange;" data-tip="hello i'm the parent">
    <div class="box" style="background:green;" data-tip="hi i'm the child"></div>
</div>

JS

function initTips(){
    // purge previous for dynamic render
    Array.from(document.querySelectorAll('.tooltip')).forEach(el => {
        el.remove()
    })

    // built upon: https://stackoverflow.com/a/69340293/10885535
    Array.from(document.querySelectorAll('[data-tip]')).forEach(el => {
        // tip
        let tip = document.createElement('div')
        tip.classList.add('tooltip')
        tip.innerText = el.getAttribute('data-tip')
        document.body.appendChild(tip)

        // arrow
        let arrow = document.createElement('div')
        arrow.classList.add('tooltip-arrow')
        tip.appendChild(arrow)

        // position tip + arrow once added
        setTimeout(() => {
            let elmPos = el.getBoundingClientRect()
            let tipPos = tip.getBoundingClientRect()
            tip.style.left = (elmPos.left + (elmPos.width - tipPos.width)/2) + 'px'
            tip.style.top = (elmPos.bottom + 5)+'px'
            arrow.style.left = (tipPos.width/2 - 5) + 'px'
        }, 0)

        // toggle with mouse
        el.onmouseover = e => {
            tip.style.opacity = 1
            tip.style.visibility = 'visible'
            e.stopPropagation() // stop parent
        };
         el.onmouseout = e => {
            tip.style.opacity = 0
            tip.style.visibility = 'hidden'
        };
    });
}

// kickoff
initTips()

// test calling again ie after dynamic content
setTimeout(initTips, 1000)
© www.soinside.com 2019 - 2024. All rights reserved.