jQuery中的智能切换类

时间:2012-10-16 08:13:01

标签: javascript jquery

我正在尝试实现一个脚本来为特定元素设置不同的类名...

让我们假设dom看起来像这样:

<body class='pre-existing-class-name'>

如果我做

smartToogle('body', 'new-class');
// the dom should look like this
// <body class='pre-existing-class-name new-class'>
smartToogle('body', 'new-class-2');
// the dom should look like this
// <body class='pre-existing-class-name new-class-2'>

我做了以下代码,但它不起作用:

var smartToogle = function (element, newClassName) {
    var oldClassName;
    var $element = $(element);

    $element.addClass(newClassName);
    if (oldClassName !== newClassName) {
        $element.removeClass(oldClassName);
    }
    oldClassName = newClassName;
};

要求:
1)我正在使用查询
2)我想传递一个类名,即新名称。


解决方案:
以下代码有效,但我不喜欢它,因为它使用全局变量 任何提示修复它?

function myToggle(newClassName) {
    if (window.oldClassName) {
         $('body').toggleClass(window.oldClassName);
    }
    window.oldClassName = newClassName;
    $('body').toggleClass(newClassName);
}

11 个答案:

答案 0 :(得分:8)

您可以使用元素的数据属性,可以使用

访问
$(element).data(attrib_name)

您的方法只需要进行一些小改动

function myToggle(newClassName) {
    if (window.oldClassName) {
         $('body').toggleClass(window.oldClassName);
    }
    window.oldClassName = newClassName;
    $('body').toggleClass(newClassName);
}

可以替换为

function myToggle(element, newClassName) {
    if ($(element).data('oldClassName')) {
         $(element).toggleClass($(element).data('oldClassName'));
    }
    $(element).data('oldClassName', newClassName)
    $(element).toggleClass(newClassName);
}

希望这能为你解决。

答案 1 :(得分:5)

<强>更新

您需要了解一件事。 如果您想要两种不同的行为,则行为更改不需要2个不同的类。 一个就足够了,因为您可以根据类 on off 来改变行为。

假设我想让我的元素以一种方式产生红色悬停事件。 并希望它与CSS有另一种方式的蓝色悬停事件。 然后这是要走的路:

$('#toggle').click(function(){
    $('.normal').each(function(){
        $(this).toggleClass('active');
    });        
});

JSFiddle Demo

这里我们使用一个按钮切换所有div并改变他们的CSS行为,现在看起来很简单吗?

但是,如果您需要切换 Javascript / jQuery事件,那么这将无法做到。在这种情况下,您将需要使用其他3种方法来管理它; .on().off().hasClass()

$('#toggle').click(function(){
    $('.normal').each(function(){
        if($(this).hasClass('active')){
            $(this).off('click');
        } else {
            $(this).on('click', function(){
                alert('You are clicking on an active div.');
            });
        }
        $(this).toggleClass('active');
    });        
});

JSFiddle Demo 2

如您所见,我们添加了 if语句。如果元素具有.active类,我们将.off()转为.click()。如果没有活动课程,我们会转到.click() .on()。在if语句下,我们始终切换.active类。所以这不必放在if语句中。

我希望这能为你解决所有问题,祝你好运!


旧答案:

最好在这里使用.toggleClass()

在元素上使用第一个类作为默认属性,第二个类作为.active,例如用于交互。

此外,使用.on('click', function(){})绑定将使您能够添加在切换元素后立即绑定的交互。

答案 2 :(得分:3)

这是一个小提琴:http://jsfiddle.net/NCwmF/2/

我是一个小jQuery插件。删除当前的智能类(如果有)并添加新的智能类。如果在没有参数className的情况下调用,则仅删除当前的智能类。

$.fn.smartToggle = function (className) {

    var dataId = 'smartToggle';

    return this.each(function () {

        var $el = $(this);

        $el
            .removeClass($el.data(dataId) || '')
            .addClass(className)
            .data(dataId, className);
    });
};

像其他jQuery方法一样使用它:

$('body').smartToggle('myClass');

答案 3 :(得分:2)

NEW,SIMPLER ANSWER 类似于之前的工作,增加了2个:1。)如果最初没有类,则工作; 2.)如果其他函数在两次调用之间更改元素类,则可以工作。我还更改了函数名称,因此它不会干扰jQuerys本机toggleClass。

$.fn.fancyToggleClass = function(new_class) {
return this.each(function() {

    // get the last class this function added (if exists) or false (if not)
    var $this = $(this),
        toggled_class = $this.data('toggled-class') || false;       

    // if we dont have an original class, then set it based on current class
    if (toggled_class) {
        $this.removeClass(toggled_class);
    }

    // add new class and store as data, 
    // which we check for next time function is called
    $this.addClass(new_class).data('toggled-class', new_class);

    // alert the class, just as a check to make sure everything worked! 
    // remove this for production, or switch to console.log
    alert('element class: ' + $this.attr('class'));

});
}

更新小提琴:http://jsfiddle.net/facultymatt/xSvFC/3/

OLD ANSWER 我建议将原始类存储在elements data属性中。然后,您的函数可以检查是否设置了此数据,如果清楚,则元素类添加元素数据中的原始类以及您在函数中传递的新类。

如果未设置数据,该函数将在当第一次运行时将当前类存储为数据。

查看这个小提琴,找到一个有评论的工作示例:http://jsfiddle.net/facultymatt/xSvFC/

这是代码。它是一个jquery函数,因此可以在任何元素上调用(也可以链接!)

$.fn.toggleClass = function(new_class) {
    return this.each(function() {

        // cache selector for this
        $this = $(this);

        // get original class (if exists) or false (if not)
        var original_class = $this.data('original-class') || false;       

        // if we dont have an original class, then set it based on current class
        if (!original_class) {

            original_class = $this.attr('class');
            $this.data('original-class', original_class);

        // we do have an original class, so we know user is now trying to add class 
        // here we clear the class, add the original class, and add the new class           
        } else {

            // assign the original class, and new class, 
            // and a space to keep the classes from becoming one 
            $this.attr('class', original_class + ' ' + new_class);

        }

        // alert the class, just as a check to make sure everything worked! 
        // remove this for production, or switch to console.log
        alert('element class: ' + $this.attr('class'));

    });
}

希望这有帮助!

答案 4 :(得分:1)

要避免使用全局变量,可以使用@ankur写入的数据属性。以下是您的问题的可行解决方案:

function myToggle(element, newClassName) { 
    if (!$(element).data('baseclassname')) { 
        $(element).data('baseclassname', $(element).attr('class')); 
    } 
    $(element)
        .attr('class', $(element).data('baseclassname'))
        .addClass(newClassName); 
}

答案 5 :(得分:0)

这可以帮到你吗?

var smartToogle = function (element, preExistingClassName, newClassName) {
    $(element)[0].className = preExistingClassName + ' ' + newClassName;
};

答案 6 :(得分:0)

只需使用hasClass即可。但是你必须告诉函数两个类是什么:

function smartToggle(element, class1, class2) {
    var $element = $(element);

    if ($element.hasClass(class1)) {
        $element.removeClass(class1);
        $element.addClass(class2);
    }
    else {
        $element.removeClass(class2);
        $element.addClass(class1);
    }
}

答案 7 :(得分:0)

$(function(){
    var smartToggle = function (element, newClassName) {
        var elementClasses = element.attr('class');

        element.addClass(newClassName);

        // check if there is more than one class on the element
        if(elementClasses .indexOf(' ') >= 0){
            var oldClassNames = elementClasses.split(" ");

            if (oldClassNames[oldClassNames.length - 1] !== newClassName) {
                element.removeClass(oldClassNames[oldClassNames.length - 1]);
            }
        }

    };

    smartToggle($('.test'), 'newclass');
    smartToggle($('.test'), 'newclass2');
});

演示 - http://jsfiddle.net/Q9A8N/ (查看控制台,了解每次传递的动态)

这应该做你想要的,但作为@ T.J。克劳德说它相当脆弱,并假设您要删除的类是元素中的最后一个。

答案 8 :(得分:0)

作为对您问题的回答,我会选择ankur's answer

作为Sem's answer的后续,关于jQuery事件的处理:

您可以使用on函数根据实时过滤器处理来自父节点的任何jquery事件:

function myToggle(element, newClassName) {
    if ($(element).data('oldClassName')) {
         $(element).toggleClass($(element).data('oldClassName'));
    }
    $(element).data('oldClassName', newClassName);
    $(element).toggleClass(newClassName);
}

//event delegation : 'on' is called on the $('.divContainer') node, but we handle
//clicks on '.divItm' items, depending on their current class
$('.divContainer')
.on('click', '.divItm.plain', function(){ myToggle( this, 'red' ); })
.on('click', '.divItm.red', function(){ myToggle( this, 'blue' ); })
.on('click', '.divItm.blue', function(){ myToggle( this, 'plain' ); });

//initialize each item with the 'plain' class
myToggle( $('.divItm'), 'plain' );

这是jsFiddle

您将注意到,每次单击某个项目时调用的函数取决于其“实时”类,并且每次项目更改类时您都不需要手动启用/禁用click处理程序。

您可以从documentation page了解更多详情。

答案 9 :(得分:0)

var smartToogle = function (element, newClass) {
  var $element = $(element),
      currentClass = $element.data('toggle-class');

  if (currentClass != newClass) $element.data('toggle-class',newClass).removeClass(currentClass || '');

  $element.toggleClass(newClass);
};

或其他变体:

$.fn.smartToogle = function (newClass) {
      currentClass = this.data('toggle-class');

  if (currentClass != newClass) this.data('toggle-class',newClass).removeClass(currentClass || '');

  this.toggleClass(newClass);
};

答案 10 :(得分:0)

在此实现中,您必须保留对此fancytoggle实例的引用。

var fancytoggle = function(el, oldClass){
    // create a function scope so we'll have a reference to oldClass 
    return function(newClass) {
        // toggle the old class and the new class
        $(el).toggleClass(oldClass+ ' ' + newClass);
        // update the new class to be the old class
        oldClass = newClass;
    };
};

对于您的示例,代码看起来像。

var bodytoggle = fancytoggle('body', 'pre-existing-class-name');
bodytoggle('new-class');
// 'new-class' replaces 'pre-existing-class-name'
bodytoggle('new-class-2');
// 'new-class-2' replaces 'new-class'

要查看其中的行为,请参阅http://jsfiddle.net/aaf2L/6/