如何重新开始循环javascript循环

How to restart cycling javascript cycle

我不知道如何让标题更清楚,尽管问题本身对我来说已经足够清楚了。

我一直在使用这个 jQuery 插件:

http://felix-kling.de/blog/2011/04/14/jQuery-Function-Toggle-plugin/

弥补jQuery中弃用和移除的切换功能。

那么我有以下功能:

<script>
$( document ).ready(function() {
    $("span.letra").funcToggle('click',     
        function() {$(this).addClass("ex1");},
        function() {$(this).removeClass("ex1").addClass("ex2")},
        function() {$(this).removeClass("ex2").addClass("ex3")},
        function() {$(this).removeClass("ex3")}
    );
});
</script>

我使用 classes 是因为我将此逻辑应用于许多元素,尽管我只希望被点击的元素在每次被点击时都经历循环。

每个 class 向元素添加一个不同的 background-color。

现在,在元素之后我有一个 "clean all" 按钮,它将删除每个元素中的每一个 class,将它们全部返回到 "unclicked" 状态。

<script>
$( document ).ready(function() {
    $("span.limpar").click(     
        function() {$("span.letra").removeClass("ex1 ex2 ex3");}
    );
});
</script>

正如您在上面看到的那样,现在这个按钮的作用是删除任何元素可能具有的每个 class。

现在解决我的问题:

假设我点击了一个元素两次。最后,单击的元素应用了 "ex2" class。

现在假设我点击了 "clean all" 按钮,激活了上面的第二个脚本。它删除了我之前通过点击应用到它的 "ex2" class。

现在,如果我再次单击 同一元素 ,单击会像 第三次 单击一样进行,激活 funcToggle 中的第三个函数脚本。

我想要的代码不仅能从所有相关元素中清除 classes,还能重新启动 funcToggle 脚本,这样任何对 already-clicked 元素的点击都会注册为首先点击该序列。

您可以使用 class 或使用 data-* 属性。

使用 data-* 属性更容易,因为您使用的是单值 data-ex 属性。在使用 classes 时,你需要做一些复杂的事情来匹配确切的 className,替换正确的 class(保持其他 classes 不变)等

使用 data-* 属性(最简单):

var $letra = $("span.letra");

$letra.click(function(){
  $(this).attr('data-ex', function(i, v){
    return v? ++v%4 : 1;
  });
});

$('.limpar').click(function(){
  $letra.attr("data-ex", "");
});
.letra{
    cursor:pointer;
    display:inline-block;
    padding:20px;
    background:#eee;
    margin:10px;
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -moz-user-select: none;
    user-select: none;
}

[data-ex='1']{background:yellow;}
[data-ex='2']{background:orange;}
[data-ex='3']{background:red;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<button class="limpar">LIMPAR</button><br>

<span class="letra">Letra</span>
<span class="letra">Letra</span>
<span class="letra">Letra</span>

使用class:

所以你有三个 classes ex1ex2ex3

添加 jQuery 一个虚拟 ex0 class
(P.S:如果需要,您可以使用默认样式在 CSS 中设置 ex0 class 的样式。
为什么? 因为您可以从 ex* class 中读取数字,增加该数字并将 class 替换为增加的数字。
使用提醒运算符(模数)%4 循环你的三个 classes:

var $letra = $("span.letra");

$letra.addClass("ex0").click(function(){ // Assign 'ex0' Class and Click listener
  $(this).attr('class', function(i, v){  // Modify Class Value...
    return v.replace(/ex\d+/, "ex"+ (++v.match(/ex(\d+)/)[1] % 4));
  });
});

$('.limpar').click(function(){
  $letra.attr("class", function(i, v){
    return v.replace(/ex\d+/, "ex0"); // Set back to the dummy 'ex0' Class
  });
});
.letra{
  display:inline-block;
  padding:20px;
  background:#eee;
  margin:10px;
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  -moz-user-select: none;
  user-select: none;
}

.ex1{background:yellow;}
.ex2{background:orange;}
.ex3{background:red;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<button class="limpar">LIMPAR</button><br>


<span class="letra">ex0</span>
<span class="letra">ex0</span>
<span class="letra ex1">ex1</span>
<span class="letra ex2">ex2</span>
<span class="letra ex3">ex3</span>

尝试

(function cycle(elem, clear, arr) {
    // clear classes , reset `cycle`
    clear.one("click.toggle", function () {
        console.log("clear all");
        elem.removeClass(arr.join(" "))
        .clearQueue("toggle").trigger("click.toggle")
    });
    return $.when(elem.queue("toggle", $.map(arr.concat($.noop())
        , function (val, key) {
            return function (next) {
                return $(this).one("click.toggle", function (e) {
                    // add current class, remove previously added class,
                    // call next item in `toggle` queue
                    return $(e.target).addClass(val).removeClass(arr[key - 1]) 
                           && next()
                });
            }
        })
    // return `toggle` promise, `clear`
    ).dequeue("toggle").promise("toggle"), clear, arr)
        .then(function (elem, clear, arr) {
        // `cycle` done , do stuff ,
        // remove added classes , reset `cycle`
        console.log("done");
        clear.off("click.toggle");
        return elem.removeClass(arr.join(" ")) && cycle(elem, clear, arr) 
    });
}($("span.letra"), $("span.limpar"), ["ex1", "ex2", "ex3"]));

(function cycle(elem, clear, arr) {
    clear.one("click.toggle", function () {
        console.log("clear all");
        elem.removeClass(arr.join(" "))
        .clearQueue("toggle").trigger("click.toggle")
    });
    return $.when(elem.queue("toggle", $.map(arr.concat($.noop()), function (val, key) {
        return function (next) {
            return $(this).one("click.toggle", function (e) {
                return $(e.target).addClass(val).removeClass(arr[key - 1]) && next()
            });
        }
    })).dequeue("toggle").promise("toggle"), clear, arr)
        .then(function (elem, clear, arr) {
        console.log("done");
        clear.off("click.toggle");
        return elem.removeClass(arr.join(" ")) && cycle(elem, clear, arr) 
    });
}($("span.letra"), $("span.limpar"), ["ex1", "ex2", "ex3"]));
.ex1 {
    background-color:red;
}
.ex2 {
    background-color:green;
}
.ex3 {
    background-color:blue;
}
.letra {
    width:150px;
    height:150px;
    border:1px solid purple;
    display:block;
    font-size: 36px;
    text-align:center;
}
.limpar {
    background:yellow;
    border:1px solid #000;
    display:block;
    width:136px;
    padding:7px;
    margin-top:1px;
    font-size:18px;
    text-align:center;
    
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<span class="letra">click</span>
<span class="limpar">clear all</span>

也许您使用 funcToggle 还有另一个原因,但它似乎对这项特定工作来说更像是一种阻碍而不是帮助。

这是另一种方法。

$('span.letra').on('click', function() {
  var $this = $(this);
  if($this.is('.ex1,.ex2,.ex3')) {
    $this.filter('.ex3').toggleClass('ex3');
    $this.filter('.ex2').toggleClass('ex2 ex3');
    $this.filter('.ex1').toggleClass('ex1 ex2');
  }else{
    $this.toggleClass('ex1');
  }
});

将状态存储在一个地方(例如元素上的一组 类)通常比尝试保持多个系统同步更利于您的理智。

也就是说,如果你想减少重复,你可以这样做:

$('span.letrb').on('click', function() {
  var $this = $(this);
  var ex = (1 + parseInt($this.data('ex') || 0)) % 4;
  $this.data('ex', ex);
  $this.removeClass('ex1 ex2 ex3');
  if (ex > 0) {
    $this.addClass('ex'+ex);
  }
});

这需要您记得同时重置数据和 类:

$('span.letrb').removeClass('ex1 ex2 ex3').data('ex', 0);