3

谢谢参观。我正在尝试使用 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)
        });

    });
});
4

2 回答 2

2

我很确定这就是你想要的,我从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

于 2012-09-20T17:34:46.747 回答
1

试试这个尺寸:http: //jsfiddle.net/Bv57T/3/

主要变化:

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

这是我在小提琴中使用的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;看看这个例子:动画过渡

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

于 2012-09-19T14:57:52.077 回答