Toggle between two classes in jQuery

I'm trying to modify the icons for the jQuery UI portlets. Rather than have a plus to minimize and a minus to expand, I wanted to switch them.

I've only had limited success with it where the first time to click the minus it flips to a plus, but the plus never flips to a minus. Any help on this would be much appreciated.

Here's a sample HTML:

<script src="scripts/jquery-1.3.2.js" type="text/javascript" ></script>
<script src="scripts/ui/ui.core.js" type="text/javascript"></script>
<script src="scripts/ui/ui.sortable.js" type="text/javascript"></script>

<div class="column">
    <div class="portlet">
        <div class="portlet-header">Links</div>
        <div class="portlet-content">Lorem ipsum dolor sit amet, consectetuer adipiscing elit</div>
    </div>
</div>

Here's what I came up with for the jQuery:

<script type="text/javascript">
    $(function() {
        $(".column").sortable({
            connectWith: '.column'
        });

        $(".portlet").addClass("ui-widget ui-widget-content ui-helper-clearfix ui-corner-all")
        .find(".portlet-header")
            .addClass("ui-widget-header ui-corner-all")
            .prepend('<span class="ui-icon ui-icon-minusthick"></span>')
            .prepend('<span class="ui-icon ui-icon-closethick"></span>')
            .end()
        .find(".portlet-content");

        $(".portlet-header .ui-icon-minusthick").click(function() {
            $(this).removeClass("ui-icon-minusthick");
            $(this).addClass("ui-icon-plusthick");
            $(this).parents(".portlet:first").find(".portlet-content").toggle();
        });

        $(".portlet-header .ui-icon-plusthick").click(function() {
            $(this).removeClass("ui-icon-plusthick");
            $(this).addClass("ui-icon-minusthick");
            $(this).parents(".portlet:first").find(".portlet-content").toggle();
        });

        $(".portlet-header .ui-icon-closethick").click(function() {
            $(this).parents(".portlet:first").toggle();
        });

        $(".column").disableSelection();
    });
</script>


EDIT: Here's the original javascript from the jQuery UI demo site:

<script type="text/javascript">
$(function() {
    $(".column").sortable({
        connectWith: '.column'
    });

    $(".portlet").addClass("ui-widget ui-widget-content ui-helper-clearfix ui-corner-all")
        .find(".portlet-header")
            .addClass("ui-widget-header ui-corner-all")
            .prepend('<span class="ui-icon ui-icon-plusthick"></span>')
            .end()
        .find(".portlet-content");

    $(".portlet-header .ui-icon").click(function() {
        $(this).toggleClass("ui-icon-minusthick");
        $(this).parents(".portlet:first").find(".portlet-content").toggle();
    });

    $(".column").disableSelection();
});
</script>

I'm not exactly sure how they were able to get the plus and minus to toggle correctly.

Answers


It probably because when you bind those functions there are no results for $(".portlet-header .ui-icon-plusthick"). It doesn't find it. You may add this binding to $(".portlet-header .ui-icon-minusthick").click(function() { ... after adding "ui-icon-plusthick" class.

EDIT: Alternative solution could be:

$(".portlet-header .ui-icon-minusthick").toggle(function() {
        $(this).removeClass("ui-icon-minusthick");
        $(this).addClass("ui-icon-plusthick");
        $(this).parents(".portlet:first").find(".portlet-content").toggle();
    }, function() {
        $(this).removeClass("ui-icon-plusthick");
        $(this).addClass("ui-icon-minusthick");
        $(this).parents(".portlet:first").find(".portlet-content").toggle();
    });

So first click would be first function and second click would be second function.


How about

$(YOUR_ELEMENT).live("EVENT_NAME", function() {
    $(".portlet-header").toggleClass("ui-icon-plus").toggleClass("ui-icon-minus");
});

Even more shorter

$(YOUR_ELEMENT).live("EVENT_NAME", function() {
    $(".portlet-header").toggleClass("ui-icon-plus ui-icon-minus");
});

EDIT

As of jQuery 1.7, the .live() method is deprecated. Use .on() to attach event handlers. Users of older versions of jQuery should use .delegate() in preference to .live().


jQuery API reference


You can try the below code

$(this).toggleClass('ui-icon-plusthick ui-icon-minusthick');

I wrote this jQuery function, not a plugin, to cycle through any number of classes. Two acts like a toggle. Just put your CSV of classnames in the element's data-classes. Then cycle it with $(selector).cycleClass()

See it in use at www.PluginExamples.com/draggable choose draggable-axis.

(function($){
    $.fn.cycleClass = function(){
        if( !$(this).data("aClasses") ){
            var classes = $(this).attr("data-classes").split(",");
            $(this).data("aClasses", classes);
            $(this).data("classes", classes.join(" "));
            $(this).data("class", classes.length);
        }
        $(this).data("class",($(this).data("class")+1) % $(this).data("aClasses").length);
        $(this).removeClass($(this).data("classes"))
            .addClass( $(this).data("aClasses")[$(this).data("class")] );
        return $(this);
    }
});

Instead of doing all that Javascript, why don't you just modify the ui-icon-plusthick CSS class to show the minus image instead of the plus image?


Need Your Help

How does a generic constraint prevent boxing of a value type with an implicitly implemented interface?

c# .net generics interface boxing

My question is somewhat related to this one: Explicitly implemented interface and generic constraint.