【问题标题】:JQuery UI (effects core) addClass/removeClass on one element with multiple selectors...but there's a catchJQuery UI(效果核心)在一个具有多个选择器的元素上添加类/删除类......但有一个问题
【发布时间】:2012-09-19 02:55:37
【问题描述】:

感谢您的观看。我正在尝试使用 jQ UI addClass / remove Class 方法在单击前面的同级 div 时展开 hr 元素。 jQ UI 效果核心支持两个类之间的平滑动画过渡:http://jqueryui.com/demos/removeClass/。此外,必须使用 $ 动态添加 hr 以实现更广泛的站点设计。

以下是拼图的部分:

  1. 我的代码呈现四个 100x100px 同级 div 的行。这些 div 没有类,但如果有帮助,请随时添加它们——每个 div 最终都会有一个独特的类。在每 4 个 div 之后,动态添加一个 hr。
  2. 单击任何给定的 div 后,下一小时必须切换到“打开”类,这会导致行扩展。如果再次单击此 div,它必须从 hr 切换/删除“open”类,导致 hr 缩小到其原始大小。
  3. 如果点击一个 div 展开一个 hr,然后点击另一个 div,则必须触发两个动画:首先,必须删除“open”类,导致行缩回,然后该类必须是重新添加以重新打开该行。但是,例如,如果单击一个 div 打开第二行,然后单击第一个 hr 之前的第二个 div,则此操作必须先关闭第二个 hr,然后再打开第二个 div 对应的 hr。

我被困住了。我尝试了许多 jQ 函数组合,但结果很奇怪。你看到的是我得到的最接近的。感谢您试一试。随意添加到代码中,但是你可以让它工作。

<!--HTML...the children divs of ".main" can have their own unique classes if that helps-->
<div class="main">
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
</div>

/*CSS-some of this creates other events not mentioned above. These are simplified versions of what I need for my final site design*/

.main  {
    width: 450px;
}
.main div {
    height: 100px;
    width: 100px;
    background-color: #000;
    margin: 3px;
    float:left;
}
div.select   {
    background-color: #f00;
    border: 2px solid #00F;
    margin: 3px;
    float:left;
    display: block;
}
div.active   {
    background-color: #f00;
    margin: 3px;
    float:left;
    display: block;
}
hr  {
    background-color: #FF0;
    float: left;
    display: block;
    height: 20px;
    width: 450px;
}
hr.open {
    float: left;
    display: block;
    height: 300px;
    width: 450px;

}

/*the JS - sorry about the double quotes.  I'm using Dreamweaver, which seems to add them to everything*/

$(document).ready(function() {
//dynamcally adds the <hr> after every 4th div.
    $(".main div:nth-child(4n)").after('<hr class="closed"></hr>');
//puts a blue border on the squares
    $('.main div').hover(function()  {
        $(this).addClass('select');
    },
    function() {
        $(this).removeClass('select')
    });
//changes the color of the active square to red and "deactivates" the previous one.
    $('.main div').click(function()  {
        $(this).toggleClass('active').siblings().removeClass('active');
    });
//here in lies the problem...???
    $('.main div').click(function()  {
        $('hr').removeClass('open', 1000);
        $(this).toggle
        (function() {
            $(this).nextAll("hr").first().addClass('open', 500);
        },
        function()  {
            $(this).nextAll("hr").first().removeClass('open', 500)
        });

    });
});

【问题讨论】:

  • 仅供参考,这是 jQuery,而不是 jQuery UI。 jQuery UI 是一系列 UI 插件,如 Autocomplete、Tabs 等。
  • 嘿,巴尔玛。请注意,addClass 和 removeClass 参数包含一个持续时间组件——这会为过渡 b/t 类设置动画,并且只能使用 UI 效果核心。 jqueryui.com/demos/toggleClass。如果我不需要顺序动画来实现这一点,我的困境很容易解决。
  • 您是否尝试过使用 HR 以外的元素?我意识到使用普通的 div 会阻塞很多其他代码;也许尝试一个跨度并将其设置为display: block。我真的觉得在许多浏览器中对 HR 样式的支持确实不是那么好,并且很容易成为您问题的根源,但我不得不承认,我已经很长时间没有考虑过使用这样的 HR。跨度>
  • 我用你的东西创建了一个 jsfiddle:jsfiddle.net/Bv57T/1 似乎工作得很好。关于可以点击和不能点击的地方有一些怪癖。我会尝试使用它,看看我是否可以得到更流畅的东西。

标签: jquery animation multiple-instances css-selectors toggleclass


【解决方案1】:

我很确定这就是你想要的,我从http://makr.com 复制了一般的 HTML 布局(你提到这就是你想要的):

演示:http://jsfiddle.net/SO_AMK/xm7Sk/

jQuery:

$(".main article:nth-child(4n)").after('<hr class="split"></hr>');
$(".main > article .slidedown").click(function(e) {
        e.stopPropagation();
}); // If you click on the slidedown, it won't collapse

var canAnimate = true,
    slideIsOpen = false,
    animateSpeed = 1000;

$(".main > article").hover(function() {
    $(this).addClass("hover");
}, function() {
    $(this).removeClass("hover");
}).click(function() {
    if (canAnimate) {
        canAnimate = false;
        var article = $(this),
            isThisOpen = article.hasClass("active");
        if (isThisOpen) {
            $(".main").queue(function () {
                hideSlide($(this))
            });
        }
        else {
            if (slideIsOpen) {
                $(".main").queue(function () {
                    hideSlide($(this));
                }).queue(function () {
                    positionPage(article, $(this));
                }).queue(function () {
                    showSlide(article, $(this));
                }).queue(function () {
                    positionPage(article, $(this));
                });
            }
            else {
                $(".main").queue(function () {
                    positionPage(article, $(this));
                }).queue(function () {
                    showSlide(article, $(this));
                }).queue(function () {
                    positionPage(article, $(this));
                });
            }
        }
    }
});

function showSlide(elm, main) {
        canAnimate = false;
        slideIsOpen = true;
        elm.nextAll("hr.split").first().addClass("active", animateSpeed);

        elm.children(".slidedown").css("top", (elm.offset().top + 114)).addClass("active").slideToggle(animateSpeed);

        elm.addClass("active");
        main.dequeue();
        canAnimate = true;
}

function hideSlide(main) {
        canAnimate = false;
        $(".main article.active").nextAll("hr.split.active").removeClass("active", animateSpeed);

        $(".main article.active").children(".slidedown").removeClass("active").slideToggle(animateSpeed);

        $(".main article.active").removeClass("active");
        $(main).dequeue();
        canAnimate = true;
        slideIsOpen = false;
}

function positionPage(elm, main) {
    canAnimate = false;
    var body;
    if ($.browser.safari) {
        body = $("body");
    }
    else {
        body = $("html");
    }
    var elmTop = elm.offset().top,
        bodyScroll = body.scrollTop();
    if (bodyScroll - elmTop == 0) {
        var speed = 0;
    }
    else {
        var speed = animateSpeed;
    }
    body.animate({
        scrollTop: elmTop
    }, speed, function () {
        main.dequeue();
        canAnimate = true;
    })
}​

对于这么小的东西来说,这可能看起来像是一个大脚本,但它有一些故障保险。唯一的错误是,如果您在转换过程中开始快速单击,有时队列会以错误的顺序结束。但是,一般用户在动画期间不会快速点击:D

【讨论】:

  • A.M.K.,这太棒了!谢啦!!现在我要试着弄清楚这一切的意义和作用。完美。
  • A.M.K.,一直在搞乱这段代码。有一件事,在单击文章之前需要隐藏行。原因是当产品线被过滤时,所有的小时都被删除然后重新添加。我用这个 sn-p 做到了: $("article:visible:odd:odd").after('
    ');不能用 nth-child 来做,因为它也计算隐藏元素。如果 hr.split 最初没有隐藏,则在动态添加它们时会导致抖动。但是我还不能让你的代码通过隐藏的行变得流畅。如果您有修复,请告诉我。
  • 明白了 - 就像弄乱边距和 elm.offset().top + xxx 一样简单......再次感谢!!!
【解决方案2】:

试穿尺寸:http://jsfiddle.net/Bv57T/3/

主要变化:

  1. 您有 2 个 .click 绑定到同一个选择器 $('.main div')。我相信,这在技术上是受支持的,但没有理由这样做,这会使您的代码更难遵循。
  2. .toggle() 不将函数作为参数。检查documentation;这不像hover()
  3. 没有理由为添加和删除设置单独的函数。您还删除了两次课程。您是否希望下一个 HR 动画化并保持开放?还是希望它立即打开和关闭?如果是后者,这条线$('hr').removeClass('open', 1000); 没有理由。如果是前者,则没有理由在其中包含 $(this).nextAll("hr").first().removeClass('open', 500) 的第二个 function()。

这是我在小提琴中使用的 javascript

$(document).ready(function() {
    //dynamcally adds the <hr> after every 4th div.
    $(".main div:nth-child(4n)").after('<hr class="closed"></hr>');
    //puts a blue border on the squares
    $('.main div').hover(
        function()  {
            $(this).addClass('select');
        },
        function() {
            $(this).removeClass('select')
    });
    //changes the color of the active square to red and "deactivates" the previous one.
    $('.main div').click(function()  {
        $('hr.open').removeClass('open', 1000);
        if(!$(this).hasClass('active')) {
           $(this).nextAll("hr").first().addClass('open', 500);
        }
        $(this).toggleClass('active').siblings().removeClass('active');
    });
});​

如果这不是您想要的,并且无法从这里弄清楚,请继续发帖,我可以再试一次。

编辑新的和改进的版本:http://jsfiddle.net/Bv57T/4/ 也更新了上面的js。

如果您在动画正在进行时单击第二个 div,仍然可以伪造它。您可以通过在动画期间将(全局)布尔值设置为 true 并在开始下一个动画之前检查它来解决这个问题。

但问题的根源在于您试图将 UI 的状态(换句话说,DOM)作为应用程序的状态加倍。即使是简单的操作(正如您所见),这也会变得非常棘手。对于此类事情,我首选的方法是使用将 UI 与应用程序分开的库。这些通常被称为 MVC(模型-视图-控制器)或 MVVM(模型-视图-视图模型——我讨厌的一个绰号,因为它故意让人感到困惑)。我最喜欢的是knockout.js。完全兼容 jQuery 和 jQuery UI;看看这个例子:animated transitions

还有更多这样的库。 Backbone.js 就是其中之一,knockback.js 结合了敲除和骨干。我知道我忘记了其他一些受欢迎的和好的...

【讨论】:

  • 谢谢,Patick M。问题是当你点击同一个 div 两次时,它应该关闭 hr。正如您的小提琴一样,单击相同的 div 两次首先关闭然后重新打开相应的 hr。那是我最初的问题。也许我们可以对您单击的 div 的“活动”类做些什么。单击 div 时,它的类变为“活动”。所以也许点击 div.active 只会关闭 hr 而点击任何非“活动” div 会关闭任何 hr 然后打开下一个?不太确定如何实现这一点。这是我尝试过的,但它没有表现:
  • $('.main div.active').click(function() { $('hr').removeClass('open', 250); }); $('.main div').not('.active').click(function() { $('hr').removeClass('open', 250); $(this).nextAll("hr") .first().addClass('open', 1000); }); });
  • 啊,我明白了。是的,您必须对 jQuery 进行一些类检查才能区分。我预计您的示例绑定的问题在于,当没有活动元素时,它们会在开始时绑定。因此,您必须在每次事件后重新绑定它们。可行,但我会在今天晚些时候发表一些不同的想法。
  • fyi,看起来 makr 的网站设计师在大部分代码中都使用了原型。
  • .toggle() 确实有一个接受函数参数的表单,请参阅api.jquery.com/toggle-event
猜你喜欢
  • 1970-01-01
  • 2011-11-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-05
  • 1970-01-01
  • 1970-01-01
  • 2010-12-19
相关资源
最近更新 更多