使用Javascript(不是CSS!)在悬停时同时替换多个<li>文本

时间:2015-07-18 17:39:18

标签: javascript jquery

我需要一次更改多个菜单项悬停时的文本,但我不能使用CSS,也不能为每个单独的项目提供自己的CSS类。我想要做的是当鼠标悬停在.menu-wrapper上方的任何地方时,Javascript会用相关的替换文本替换每个<li>项目文本。

我有一个适用于单个项目的脚本:

    <div class="menu-wrapper">
        <ul>
            <li>WORD1</li>
        </ul>
    </div>

使用Javascript:

var originalText = $('.menu-wrapper > ul > li').text();

$('.menu-wrapper').hover(function () {

    var $p = $(this).find('li');
    $p.fadeOut(300, function () {
        $(this).text('replacement word 1').fadeIn(300);
    });
}, function () {
    // set original text
    $(this).find('li').fadeOut(300, function () {
        $(this).text(originalText).fadeIn(300);
    });
});

但很明显,如果添加多个<li>项,它会中断,因为它只存储一个.text()变量并在第一个mouseout事件之后连接所有条目。

我尝试使用switch语句来查找.text()的值并相应地更改文本值,但它不起作用(我的Javascript很弱......)。

我很感激任何帮助。我只有四个项目来替换文本,因此根据需要重复任何脚本都不是问题。通常情况下,我会给每个人一个自己的阶级身份并使用我已经拥有的但不幸的是我不能。

请不要建议使用CSS,因为我已经知道如何做到这一点,但为此我需要使用Javascript。

我在其他地方找不到这个问题。

谢谢!

5 个答案:

答案 0 :(得分:2)

主要问题是第一行:

var originalText = $('.menu-wrapper > ul > li').text();

这将从集合中的所有元素获取所有文本

你可以做的是使用jQuery data()将这些文本存储在每个元素上,方法是循环遍历元素并处理实例:

$('.menu-wrapper > ul > li').each(function(){
     $(this).data('original', $(this).text());
});

然后在鼠标输出部分hover中再次使用data()读取先前存储的文本

$(this).find('li').fadeOut(300, function () {
    var originalText = $(this).data('original');
    $(this).text(originalText).fadeIn(300);
});

新文字的几个选项:

将其作为数据属性放入标记

<li data-alt_text="alternate word">

然后在鼠标输入回调中:

$p.fadeOut(300, function () {
    $(this).text($(this).data('alt_text')).fadeIn(300);
});

或者放入数组并使用第一个循环将数组数据添加到元素

var words=['W1','W2','W3'];
// first argument of "each" is "index"
$('.menu-wrapper > ul > li').each(function(index){
     $(this).data(
         {
             'alt_text': words[index],
             'original', $(this).text()
           }
      );
});

答案 1 :(得分:1)

您可以利用javascripts能力将任何属性分配给对象(元素)以存储原始文本,而不是将其存储在单个变量中(或使用jquery数据功能来执行相同的操作)

$('.menu-wrapper li').hover(function () {    
    $(this).fadeOut(300, function () {
        this.originalText = $(this).text();
        $(this).text('replacement word 1').fadeIn(300);
    });
}, function () {
    // set original text
    $(this).fadeOut(300, function () {
        $(this).text(this.originalText).fadeIn(300);
    });
});

fiddle

为了使其正常工作,您可以使用.menu-wrapper绑定到div中的各个li元素,而不是直接绑定到.menu-wrapper li div。之后,可以在更改之前存储原始文本。事先也可以这样做,存储所有值,这种方式的优点是你总是存储最新值,以防文本在启动后动态改变。

将替换文本耦合到li元素,而不更改html 最安全将替换文本耦合到文本。最简单的是基于索引的解决方案:

var replacements = ['replacement Word1', 'for word2' , 'third time\'s a charm'];

$('.menu-wrapper li').hover(function () {    
    var $this=  $(this);
    $this.fadeOut(300, function () {
        $this.data('originalText', $this.text()).
        text(replacements[$this.index()]).fadeIn(300);
    });
}, function () {
    // set original text
    $(this).fadeOut(300, function () {
        $(this).text($(this).data('originalText')).fadeIn(300);
    });
});

fiddle

为了完整起见,这可以在使用li文本时提供替代方法(前提是文本可以用作属性):

var replacements ={ 
    WORD1 : 'replacement Word1',
    WORD2 : 'for word2',
    WORD3: 'third time\'s a charm'
 };

$('.menu-wrapper li').hover(function () {    
    var $this=  $(this);
    $this.fadeOut(300, function () {
        $this.data('originalText', $this.text()).
        text(replacements[$this.text()]).fadeIn(300);
    });
}, function () {
    // set original text
    $(this).fadeOut(300, function () {
        $(this).text($(this).data('originalText')).fadeIn(300);
    });
});

fiddle

答案 2 :(得分:0)

这是解决问题的简短解决方案:

var originalText;
$('.menu-wrapper').hover(function () {

var $p = $(this).find('li');
    $p.fadeOut(300, function () {
        this.originalText = $(this).text(); // STORES VALUE BEFORE REPLACEMENT
        $(this).text('replacement word 1').fadeIn(300);
    });
}, function () {
    $(this).find('li').fadeOut(300, function () {
        $(this).text(this.originalText).fadeIn(300);
    });
});

在替换之前,只需将该元素的值存储在originalText中。

答案 3 :(得分:0)

我们可以使用两个数组来存储原始文本和新文本。然后使用$ .each循环遍历每个lis并使用它们的索引替换文本 HTML:

<div class="menu-wrapper">
    <ul>
        <li>WORD1</li>
        <li>WORD2</li>
        <li>WORD3</li>
    </ul>
</div>

jQuery:

var originaltext = ['Word1','Word2','Word3'];
var newText = ['New text1','New text2','New text3'];
$('.menu-wrapper').hover(function () {
  $('.menu-wrapper li').each(function(i){
    $this = $(this);
     $this.html(newText[i])   
  });
}, function(){
    $('.menu-wrapper li').each(function(i){
      $this = $(this);
      $this.html(originaltext[i])   
    });

});

jsfiddle

答案 4 :(得分:0)

由于这里的所有其他答案都使用jQuery,我将添加一个用vanilla js完成的。

为此,我们需要使用javascript闭包。使用它是为了在淡出完成时,我们有(a)元素刚刚褪色,(b)更重要的是,它是originalStrings数组的索引。 (B)在这里更重要,因为目标元素是动画代码已经存在的东西 - 我们可以轻松地将原始元素传递给回调函数。但是,我们确实需要与每个元素对应的索引或字符串。关闭提供了一种方法。

以下代码将淡出所有/任何匹配的元素,然后在更改文本后执行淡入。

使用这里找到的公式:Math: Ease In, ease Out a displacement using Hermite curve with time constraint然后我们可以设置一些代码来执行平滑的淡入淡出/移动/缩放音高/音量滑动等等。我这样做了一个最终的几个函数促进简单的动画。我在下面列出了缩小版本,这是一个完全不依赖于其他资源的完整解决方案。

<!DOCTYPE html>
<html>
<head>
<script>
"use strict";
window.addEventListener('load', onDocLoaded, false);

function onDocLoaded()
{
    document.getElementById('goBtn').addEventListener('click', onButtonClick, false);
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// animation stuff
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function cubicHermite(a,b,d,e,c){var g=a*a,f=g*a;return(2*f-3*g+1)*b+(f-2*g+a)*e+(-2*f+3*g)*d+(f-g)*c}
function interp(a,b,d,e,c){var g,f;f=e/(a/2+b+d/2);g=f*a/2;f*=b;return c<=a?cubicHermite(c/a,0,g,0,f/b*a):c<=a+b?g+f*(c-a)/b:cubicHermite((c-a-b)/d,g+f,e,f/b*d,0)}
function linear(a){return a}
function cubic(a){return interp(0.35,0.3,0.35,1,a)}
function doAnimStep(a,b,d,e,c){a<=b?(setTimeout(function(){doAnimStep(a,b,d,e,c)},d),e(a/b),a++):void 0!=c&&null!=c&&c()}
function doAnim3(totalMs, stepCallbackFunc, doneCallbackFunc)
{
    var stepDelay = 1000 / 60.0;        // set anim to 60 fps
    var numSteps = (totalMs / stepDelay)>>0;
    setTimeout( doAnim3TimeoutCallback, stepDelay );
    function doAnim3TimeoutCallback()
    {
        doAnimStep(0, numSteps, stepDelay, stepCallbackFunc, doneCallbackFunc);
    };
}
function animFadeOut(elem, callback){ doAnim3(500,function(raw){elem.style.opacity=1-cubic(raw)},callback); }
function animFadeIn(elem, callback) { doAnim3(500,function(raw){elem.style.opacity=cubic(raw)},callback); }
////////////////////////////////////////////////////////////////////////////////////////////////////////////////




var replacementStrings = [ "replacement 1", "I'm next", "mee too", "fourth item" ];
function onButtonClick(evt)
{
    var originalStrings = [];
    var targetLiElems = document.querySelectorAll('.menu-wrapper > ul > li');
    for (var i=0,n=targetLiElems.length;i<n;i++)
    {
        var curElem = targetLiElems[i];
        originalStrings.push(curElem.innerText);
        animFadeOut(curElem, createFunc(i) );
    }
    function createFunc(i)
    {
        return function(){ var curElem = targetLiElems[i]; curElem.innerText = replacementStrings[i]; animFadeIn(curElem); };
    }
}
</script>
<style>
</style>
</head>
<body>
    <button id='goBtn'>Change the text</button>
    <div class="menu-wrapper">
        <ul>
            <li>WORD1</li>
            <li>WORD2</li>
            <li>WORD3</li>
            <li>WORD4</li>
        </ul>
    </div>
</body>
</html>