7

我正在尝试实现一个脚本来在特定元素上设置不同的类名……</p>

假设 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);
}
4

11 回答 11

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);
}

希望这可以为您解决。

于 2012-10-18T10:15:44.410 回答
5

更新:

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

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

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

JSFiddle 演示

在这里,我们使用一个按钮来切换所有 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 演示 2

如您所见,我们添加了一个if 语句。如果元素具有.active类,我们.off().click(). 如果没有活跃的班级,我们将.click() .on(). 在 if 语句下,我们总是切换.active类。所以这不必放在 if 语句中。

我希望这能为你清除一切,祝你好运!


老答案:

最好在.toggleClass()这里使用。

将元素上的第一个类用于默认属性,将第二个类.active用于交互。

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

于 2012-10-16T08:15:48.220 回答
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');
于 2012-10-19T22:55:04.750 回答
2

新的,更简单的答案 工作方式与以前类似,但增加了 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/

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

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

查看此小提琴以获取带有注释的工作示例: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'));

    });
}

希望这可以帮助!

于 2012-10-23T21:11:07.530 回答
1

为避免全局变量,您可以使用@ankur 所写的数据属性。这是您的问题的有效解决方案:

function myToggle(element, newClassName) { 
    if (!$(element).data('baseclassname')) { 
        $(element).data('baseclassname', $(element).attr('class')); 
    } 
    $(element)
        .attr('class', $(element).data('baseclassname'))
        .addClass(newClassName); 
}
于 2012-10-18T21:51:08.977 回答
0

这对你有用吗?

var smartToogle = function (element, preExistingClassName, newClassName) {
    $(element)[0].className = preExistingClassName + ' ' + newClassName;
};
于 2012-10-16T08:18:07.457 回答
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);
    }
}
于 2012-10-16T08:18:46.643 回答
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/(查看控制台以查看每次传递时它在做什么)

那应该可以满足您的要求,但是正如@TJ Crowder 所说,它相当脆弱,并假定您要删除的类是元素上的最后一个。

于 2012-10-16T08:31:20.357 回答
0

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

作为Sem 的回答的后续,关于 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每次项目更改类时手动启用/禁用处理程序。

您可以从文档页面了解更多详细信息。

于 2012-10-23T12:09:49.350 回答
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);
};
于 2012-10-23T18:53:35.047 回答
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/

于 2012-10-24T18:35:43.027 回答