简体   繁体   中英

Adding a class transversely with JQuery based on click event

Background

I am building a notifications dropdown that shows when the notification has been read or unread. The user has a the ability to mark the notification as "read" by clicking on the icon thus turning it in to a check mark and a tooltip that changes to the option to make it unread. So, if it's unread, the icon is yellow and the tooltip says "Mark as read". If the user clicks on it to make it read, the icon switches to a check mark, it turns green, and the tooltip changes text to mark it as unread. All that is working, however, there is yet another icon on the left side of the li that I would like to toggle to background green when the user clicks on the icon I explained above.

What have I tried?

I tried playing around with the .parent() , .siblings() , .find() and other methods since I am almost certain that they will be my solution, but I unfortunaly either got the all of the to toggle, or none at all, or the right icon stops working, etc. I'm obviously not structuring my function parameters right.

I hard-coded the bg-success class on the middle li to show you what I am trying to achieve.

So, if someone could help me turn that doggone left icon's background green by adding the bg-success class when the "read/unread" icon in it's own li is clicked, I would really appreciate it.

Here is my CODEPEN

And here is my code also:

HTML

<div class="container">
    <header>
        <ul class="nav navbar-nav navbar-right">
            <li class="dropdown open">
                <a href="javascript:;" data-toggle="dropdown" class="dropdown-toggle has-notify" data-click="toggle-notify">
                    <i class="fa fa-bell"></i>
                </a>
                <ul class="dropdown-menu dropdown-notification pull-right">
                    <li class="dropdown-header">Notifications (5)</li>
                    <li class="notification-item">
                        <a href="javascript:;">
                            <div class="media"><i class="fa fa-exclamation-triangle"></i></div>
                            <div class="message"><p class="desc">Server down on 1/24/2016.</p></div>
                            <div class="option" data-toggle="tooltip" data-title="Mark as Read" data-click="set-message-status" data-status="unread" data-container="body"><i class="fa fa-circle-o"></i></div>
                        </a>
                    </li>
                    <li class="notification-item">
                        <a href="javascript:;">
                            <div class="media bg-success"><i class="fa fa-thumb-tack"></i></div>
                            <div class="message"><p class="desc">Approve documents in outbox.</p></div>
                            <div class="option read" data-toggle="tooltip" data-title="Mark as Unread" data-click="set-message-status" data-status="read" data-container="body"><i class="fa fa-circle-o"></i></div>
                        </a>
                    </li>
                    <li class="notification-item">
                        <a href="javascript:;">
                            <div class="media"><i class="fa fa-calendar-plus-o"></i></div>
                            <div class="message"><p class="desc">New event posted.</p></div>
                            <div class="option" data-toggle="tooltip" data-title="Mark as Read" data-click="set-message-status" data-status="read" data-container="body"><i class="fa fa-circle-o"></i></div>
                        </a>
                    </li>
                </ul>
            </li>
        </ul>
    </header>
</div>

CSS

.navbar-nav .open .dropdown-menu {
    position: absolute;
    background: #000;
    border: 1px solid;
    -webkit-box-shadow: 0 3px 8px rgba(0,0,0,0.25);
    box-shadow: 0 3px 8px rgba(0,0,0,0.25);
}
.navbar .dropdown-menu.pull-right {
    right: 0;
    left: auto;
}
.navbar .dropdown-menu {
    max-width: 360px;
    left: 0;
}

.navbar-nav .open .dropdown-menu .dropdown-header {
    padding: 5px 20px 8px;
    border-bottom: 1px solid rgba(248,151,29,0.77);
    color: rgba(248,151,29,0.77);
    font-size: 15px;
    font-weight: 100;
    letter-spacing: 1px;
    text-transform: uppercase;
    font-family: "ABeeZee",sans-serif;
}
.dropdown-menu>li.dropdown-header {
    padding: 5px 20px 8px;
    border-bottom: 1px solid #bbb;
}

.dropdown-notification>li.notification-item {
    position: relative;
}

.navbar-nav .open .dropdown-notification>li.notification-item>a {
    padding: 15px 20px;
}
.dropdown-notification>li.notification-item a {
    padding: 15px 20px;
}
.dropdown-menu>li>a {
    font-size: 12px;
    padding: 5px 20px;
    color: #bbb;
}

.dropdown-menu>li>a:hover, .dropdown-menu>li>a:focus {
    background: #101113;
    color: #bbb;
}

.dropdown-notification>li.notification-item a:before, 
.dropdown-notification>li.notification-item a:after {
    content: '';
    display: table;
    clear: both;
}

.dropdown-notification>li.notification-item .media {
    float: left;
    width: 40px;
    height: 40px;
    overflow: hidden;
    text-align: center;
    line-height: 40px;
    -webkit-border-radius: 50%;
    -moz-border-radius: 50%;
    -ms-border-radius: 50%;
    border-radius: 50%;
    background: #ccc;
    color: #000;
}

.dropdown-notification>li.notification-item .media i {
    font-size: 15px;
}

.dropdown-notification>li.notification-item .media+.message {
    margin-left: 50px;
}
.dropdown-notification>li.notification-item .message {
    padding-right: 20px;
}

.dropdown-notification>li.notification-item .desc {
    font-size: 12px;
    font-weight: 300;
    margin-bottom: 3px;
    color: #8f8f8f;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
p {
    color: #bbb;
}
.dropdown-notification>li.notification-item .option {
    position: absolute;
    right: 10px;
    top: 10px;
    padding: 5px 10px;
    font-size: 12px;
}
.dropdown-notification>li.notification-item .option .fa:before {
    color: #F8971D;
}

.dropdown-notification>li.notification-item .option.read .fa:before {
    content: '\f058';
    color: #47a877;
}

.bg-success {
    background: #47a877 !important;
}

JQUERY

$('[data-click="set-message-status"]').on('click', function (e) {
        e.stopPropagation();
        e.preventDefault();

        var status = $(this).attr('data-status');
        var tooltipText = 'Mark as Read';
        if (status == 'read') {
            $(this).removeClass('read');
            //$('.notification-item').find('.media').removeClass('bg-success');
            $(this).attr('data-status', 'unread');
            //$('.notification-item').find('.media').attr('data-status', 'unread');
        } else {
            $(this).addClass('read');
            //$('.notification-item').find('.media').addClass('bg-success');
            $(this).attr('data-status', 'read');
            //$('.notification-item').find('.media').attr('data-status', 'read');
            tooltipText = 'Mark as Unread';
        }
        $(this).tooltip('hide').attr('data-original-title', tooltipText).tooltip('fixTitle');
    });

Thank you!

Targeting the media class of the clicked icon "read/unread" using $(this).parents('a').find('.media') and adding/removing class using addClass()/removeClass() methodes :

$(this).parents('a').find('.media').addClass('bg-success'); //add class
//And 
$(this).parents('a').find('.media').removeClass('bg-success'); //remove class

Hope this helps.


Snippet

 $('[data-click="set-message-status"]').on('click', function (e) { e.stopPropagation(); e.preventDefault(); var status = $(this).attr('data-status'); var tooltipText = 'Mark as Read'; if (status == 'read') { $(this).removeClass('read'); //$('.notification-item').find('.media').removeClass('bg-success'); $(this).attr('data-status', 'unread'); //$('.notification-item').find('.media').attr('data-status', 'unread'); $(this).parents('a').find('.media').removeClass('bg-success'); } else { $(this).addClass('read'); //$('.notification-item').find('.media').addClass('bg-success'); $(this).attr('data-status', 'read'); //$('.notification-item').find('.media').attr('data-status', 'read'); $(this).parents('a').find('.media').addClass('bg-success'); tooltipText = 'Mark as Unread'; } $(this).tooltip('hide').attr('data-original-title', tooltipText).tooltip('fixTitle'); }); 
  .navbar-nav .open .dropdown-menu { position: absolute; background: #000; border: 1px solid; -webkit-box-shadow: 0 3px 8px rgba(0,0,0,0.25); box-shadow: 0 3px 8px rgba(0,0,0,0.25); } .navbar .dropdown-menu.pull-right { right: 0; left: auto; } .navbar .dropdown-menu { max-width: 360px; left: 0; } .navbar-nav .open .dropdown-menu .dropdown-header { padding: 5px 20px 8px; border-bottom: 1px solid rgba(248,151,29,0.77); color: rgba(248,151,29,0.77); font-size: 15px; font-weight: 100; letter-spacing: 1px; text-transform: uppercase; font-family: "ABeeZee",sans-serif; } .dropdown-menu>li.dropdown-header { padding: 5px 20px 8px; border-bottom: 1px solid #bbb; } .dropdown-notification>li.notification-item { position: relative; } .navbar-nav .open .dropdown-notification>li.notification-item>a { padding: 15px 20px; } .dropdown-notification>li.notification-item a { padding: 15px 20px; } .dropdown-menu>li>a { font-size: 12px; padding: 5px 20px; color: #bbb; } .dropdown-menu>li>a:hover, .dropdown-menu>li>a:focus { background: #101113; color: #bbb; } .dropdown-notification>li.notification-item a:before, .dropdown-notification>li.notification-item a:after { content: ''; display: table; clear: both; } .dropdown-notification>li.notification-item .media { float: left; width: 40px; height: 40px; overflow: hidden; text-align: center; line-height: 40px; -webkit-border-radius: 50%; -moz-border-radius: 50%; -ms-border-radius: 50%; border-radius: 50%; background: #ccc; color: #000; } .dropdown-notification>li.notification-item .media i { font-size: 15px; } .dropdown-notification>li.notification-item .media+.message { margin-left: 50px; } .dropdown-notification>li.notification-item .message { padding-right: 20px; } .dropdown-notification>li.notification-item .desc { font-size: 12px; font-weight: 300; margin-bottom: 3px; color: #8f8f8f; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } p { color: #bbb; } .dropdown-notification>li.notification-item .option { position: absolute; right: 10px; top: 10px; padding: 5px 10px; font-size: 12px; } .dropdown-notification>li.notification-item .option .fa:before { color: #F8971D; } .dropdown-notification>li.notification-item .option.read .fa:before { content: '\\f058'; color: #47a877; } .bg-success { background: #47a877 !important; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css" rel="stylesheet"/> <link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet"/> <div class="container"> <header> <ul class="nav navbar-nav navbar-right"> <li class="dropdown open"> <a href="javascript:;" data-toggle="dropdown" class="dropdown-toggle has-notify" data-click="toggle-notify"> <i class="fa fa-bell"></i> </a> <ul class="dropdown-menu dropdown-notification pull-right"> <li class="dropdown-header">Notifications (5)</li> <li class="notification-item"> <a href="javascript:;"> <div class="media"><i class="fa fa-exclamation-triangle"></i></div> <div class="message"><p class="desc">Server down on 1/24/2016.</p></div> <div class="option" data-toggle="tooltip" data-title="Mark as Read" data-click="set-message-status" data-status="unread" data-container="body"><i class="fa fa-circle-o"></i></div> </a> </li> <li class="notification-item"> <a href="javascript:;"> <div class="media bg-success"><i class="fa fa-thumb-tack"></i></div> <div class="message"><p class="desc">Approve documents in outbox.</p></div> <div class="option read" data-toggle="tooltip" data-title="Mark as Unread" data-click="set-message-status" data-status="read" data-container="body"><i class="fa fa-circle-o"></i></div> </a> </li> <li class="notification-item"> <a href="javascript:;"> <div class="media"><i class="fa fa-calendar-plus-o"></i></div> <div class="message"><p class="desc">New event posted.</p></div> <div class="option" data-toggle="tooltip" data-title="Mark as Read" data-click="set-message-status" data-status="read" data-container="body"><i class="fa fa-circle-o"></i></div> </a> </li> </ul> </li> </ul> </header> </div> 

Select the closest .notification-item ancestor based on the clicked element by using the .closest() method . Which would be $(this).closest('.notification-item').find('.media') .

You can also chain the attr() method after the .addClass() / .removeClass() methods as well:

Updated Example

if (status === 'read') {
    $(this).removeClass('read').attr('data-status', 'unread');
    $(this).closest('.notification-item').find('.media').removeClass('bg-success').attr('data-status', 'unread');
} else {
    $(this).addClass('read').attr('data-status', 'read');
    $(this).closest('.notification-item').find('.media').addClass('bg-success').attr('data-status', 'read');
    tooltipText = 'Mark as Unread';
}

As a side note, you could also use $(this).prevAll('.media').first() in order to select the previous .media element:

Updated Example

if (status === 'read') {
    $(this).removeClass('read').attr('data-status', 'unread');
    $(this).prevAll('.media').first().removeClass('bg-success').attr('data-status', 'unread');
} else {
    $(this).addClass('read').attr('data-status', 'read');
    $(this).prevAll('.media').first().addClass('bg-success').attr('data-status', 'read');
    tooltipText = 'Mark as Unread';
}

You can also shorten the logic by using .toggleClass() in place of .addClass() / .removeClass() .

Updated Example

var tooltipText = status === 'read' ? 'Mark as Unread' : 'Mark as Read';
var newStatus = status === 'read' ? 'unread' : 'read';
$(this).toggleClass('read', status !== 'read').attr('data-status', newStatus);
$(this).prevAll('.media').first().toggleClass('bg-success', status !== 'read').attr('data-status', newStatus);

If your html structure is unlikely to change, then, given this:

<li class="notification-item">
    <a href="javascript:;">
        <div class="media"><i class="fa fa-exclamation-triangle"></i></div>
        <div class="message"><p class="desc">Server down on 1/24/2016.</p></div>
        <div class="option" data-toggle="tooltip" data-title="Mark as Read" data-click="set-message-status" data-status="unread" data-container="body"><i class="fa fa-circle-o"></i></div>
    </a>
</li>

and

$('[data-click="set-message-status"]').on('click', function (e) {

then $(this) is the div.option so to get to the i.fa you can either go across to .media then down to i.fa :

 var fa = $(this).siblings(".media").find("i.fa")

or, to give a bit more flexibility to your html, go up to the best-fit container (the li not the a ) then down to the icon:

var fa = $(this).closest("li.notification-item").find(".media > i.fa")

you need the extra .media > as there are two i.fa and this will give you specifically the first one.

Alternatively, you can just change both at the same time

var fa = $(this).closest("li.notification-item").find("i.fa")

I think you navigate up until the the "a" element and then do the find from there, but to make sure you get just the right element you should star from the event target, like this, for example:

$(this).parent().find(".media").removeClass('bg-success');

In this case the $(this) referers to the item defined on the observer, the div with the data-click attribute where the clicking ocurred.

You could change the $(this) for $(e.target) , and the " .parent() " for " .closest('a') " or " .closest('li') "

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM