if notification count is zero I want what I have right now(box) but if it's not zero I want box to be changed to badge with notification count - javascript

I have a notification system that works. Right now, when there's no notification or not, the notification appears in a <span class='glyphicon glyphicon-inbox' aria-hidden="true"></span> just like stackoverflow. but my desire is when there's a notification, I want the box to be turned into a
<span class="badge badge-notify" style="red">notification count</span>
again just like a stack overflow.
So I tried removing a particular class that changes the form of the box when if count == 0 and adding the class when count is not zero. I tried setting set interval as well but it just won't work.
Can you please help me?
below is what I have in navbar, I have the notification box and the badge set up.
<li class="dropdown">
<a href="#" class="dropdown-toggle notification-toggle" data-toggle="dropdown" role="button" aria-expanded="false" id="button">
<span class='glyphicon glyphicon-inbox' aria-hidden="true"></span>
<span class="caret"></span>
<span class="badge badge-notify">notification count</span></a>
<ul class="dropdown-menu" role="menu" id='notification_dropdown'>
</ul>
</li>
below is my ajax function to disply notification
<script>
$(document).ready(function(){
$(".notification-toggle").click(function(e){
e.preventDefault();
$.ajax({
type: "POST",
url: "{% url 'get_notifications_ajax' %}",
data: {
csrfmiddlewaretoken: "{{ csrf_token }}",
},
success: function(data){
$("#notification_dropdown").html(' <li role="presentation" class="dropdown-header">alarm</li>');
var count = data.count
console.log(count)
if (count == 0) {
$("#notification_dropdown").removeClass('notification');
var url = '{% url "notifications_all" %}'
$("#notification_dropdown").append("<li><a href='" + url+ "'>view all</a></li>")
} else {
$("#notification_dropdown").addClass('notification');
$(data.notifications).each(function(){
var link = this;
$("#notification_dropdown").append("<li>" + link + "</li>")
})
}
console.log(data.notifications);
},
error: function(rs, e) {
console.log(rs);
console.log(e);
}
})
})
})
</script>
so what I kinda tried was this,
<style>
{% block style %}
#notification_dropdown{
}
#notification_dropdown.notification{
color: red;
}
{% endblock %}
</style>
and
<script>
setTimeout(function(){
$("#notification_dropdown:visible").addClass('notification');
}, 2000);
</script>
maybe I set the id wrong...those did nothing unfortunately.
not sure if this is needed, I'll also add function for notification(ajax)
def get_notifications_ajax(request):
if request.is_ajax() and request.method == "POST":
notifications = Notification.objects.all_for_user(MyProfile.objects.get(user=request.user)).recent()
count = notifications.count()
notes = []
for note in notifications:
notes.append(note.get_link.encode('utf-8'))
data = {
"notifications": notes,
"count": count,
}
print data
json_data = json.dumps(data)
print json_data
return HttpResponse(json_data, content_type='application/json')
else:
raise Http404
So my question)
1) what did I do wrong that the form/color of notification box didn't change when notification is not zero, and how do I achieve what I want which is box to be turned into a
<span class="badge badge-notify" style="red">notification count</span>
2) I'm able to display count of notification in console with console.log(count), how do I display this count in the navbar?

It looks like all the changes you are doing in AJAX success are on #notification_dropdown but in your navbar HTML the <span> elements you want to toggle are never touched. It's the same in your CSS:
<style>
{% block style %}
#notification_dropdown{
}
#notification_dropdown.notification{
color: red;
}
{% endblock %}
</style>
The CSS selectors used (#notification_dropdown) do not apply the CSS properties to the <span> elements which matter.
One of the ways to fix this -
Change your navbar HTML to:
<li class="dropdown">
<a href="#" class="dropdown-toggle notification-toggle" data-toggle="dropdown" role="button" aria-expanded="false" id="button">
<span id="no_notify" class='glyphicon glyphicon-inbox' aria-hidden="true"></span>
<span class="caret"></span>
<span id="notify_count" class="badge badge-notify">notification count</span></a>
<ul class="dropdown-menu" role="menu" id='notification_dropdown'>
</ul>
</li>
Change: added id attribute to both no notify and notify count badge span elements.
And
Change your Ajax script to:
<script>
$(document).ready(function(){
$(".notification-toggle").click(function(e){
e.preventDefault();
$.ajax({
type: "POST",
url: "{% url 'get_notifications_ajax' %}",
data: {
csrfmiddlewaretoken: "{{ csrf_token }}",
},
success: function(data){
$("#notification_dropdown").html(' <li role="presentation" class="dropdown-header">alarm</li>');
var count = data.count
console.log(count)
if (count == 0) {
$("#notify_count").html(count).hide();
$("#no_notify").show();
$("#notification_dropdown").removeClass('notification');
var url = '{% url "notifications_all" %}'
$("#notification_dropdown").append("<li><a href='" + url+ "'>view all</a></li>")
} else {
$("#no_notify").hide();
$("#notify_count").html(count).show();
$("#notification_dropdown").addClass('notification');
$(data.notifications).each(function(){
var link = this;
$("#notification_dropdown").append("<li>" + link + "</li>")
})
}
console.log(data.notifications);
},
error: function(rs, e) {
console.log(rs);
console.log(e);
}
})
})
})
</script>
Change: added $("#no_notify") and $("#notify_count") related lines to show()/hide() those spans based on count
And change your setTimeout to:
<script>
setTimeout(function(){
$(".notification-toggle").click();
}, 2000);
</script>
$(".notification-toggle").click(); triggers a click on <a> in navbar, which does the Ajax call. If the count from Ajax response is zero we hide notify_count span and show no_notify else do the reverse.
Triggering a click on the <a> tag seems like a good idea. If in future you want the count update to happen only on user action (a click on anchor tag) and do not want the call to happen periodically all you have to do is get rid of setTimeout logic.
It is a best practice to add an error callback too for your AJAX call, just in case if the POST call to get_notifications_ajax fails.

One simple way to accomplish this is to use setInterval() to query the server every few seconds for new notifications. The code would look something like this:
HTML
<li class="dropdown">
<a href="#" class="dropdown-toggle notification-toggle" data-toggle="dropdown" role="button" aria-expanded="false" id="button">
<div id='inbox-wrapper'><span class='glyphicon glyphicon-inbox' aria-hidden="true"></span><div>
<span class="caret"></span>
<span class="badge badge-notify">notification count</span></a>
<ul class="dropdown-menu" role="menu" id='notification_dropdown'></ul>
</li>
JS
<script>
setInterval(function(){
$.ajax({
type: "POST",
url: "{% url 'get_notifications_ajax' %}",
data: {
csrfmiddlewaretoken: "{{ csrf_token }}",
},
success: function(data){
$("#notification_dropdown").html(' <li role="presentation" class="dropdown-header">alarm</li>');
var count = data.count
console.log(count)
if (count == 0) {
$("#notification_dropdown").removeClass('notification');
var url = '{% url "notifications_all" %}'
$("#notification_dropdown").append("<li><a href='" + url+ "'>view all</a></li>")
// here we change the inbox appearance
$("#inbox-wrapper").html("<span class='glyphicon glyphicon-inbox' aria-hidden='true'></span>");
} else {
$("#notification_dropdown").addClass('notification');
$(data.notifications).each(function(){
var link = this;
$("#notification_dropdown").append("<li>" + link + "</li>")
// change the inbox appearance
$("#inbox-wrapper").html("<span class='badge badge-notify' style='background-color:red'>" + count + "</span>");
})
}
console.log(data.notifications);
},
error: function(rs, e) {
console.log(rs);
console.log(e);
}
});
}, 5000);
</script>
I made the following changes to your code:
1) I added a div with an id to wrap the inbox, in order to make HTML swapping simpler (as well I fixed the style attribute for the 'active' inbox span)
2) I move the code from the inbox click event to a setInterval function.
That way, you don't have to send the AJAX request when opening the inbox drop-down, because you already have done so, every 5 seconds!
3) I added the notification count to the inbox element

Related

Laravel - Favourite / Un-Favourite button

I'm trying to create a favourite / un-favourite button for items. The button needs to be toggable so that when the user first clicks it, the item is added to favourites, the next time they click it the item should be un-favourited. It should also remember all the items the user has already favourited and display the button differently.
Here is what I currently have, I loop through all the items and display the delete or add button depending if they have the item favourited:
#foreach($items as $item)
#if($item->isFavourited)
<button id="deletefavourite{{$item->id}}" onClick="deleteFromFavourites({{$item->id}}, {{ Auth::user()->id }})" name="addfavourite" class="btn btn-lg"><i class="fas fa-heartbeat"></i></button>
#else
<button id="addfavourites{{$item->id}}" onClick="addToFavourites({{$item->id}}, {{ Auth::user()->id }})" name="deletefavourite" class="btn btn-lg"><i class="fas fa-heart" ></i></button>
#endif
#endforeach
My Javascript function to add/remove favourite items using AJAX request:
function addToFavourites(itemid, userid) {
var user_id = userid;
var item_id = itemid;
$.ajax({
type: 'post',
url: 'api/addfavourite',
data: {
'user_id': user_id,
'item_id': item_id,
},
success: function () {
$('#addfavourites' + item_id).css({
'color': '#ad1707'
});
},
error: function (XMLHttpRequest) {
// handle error
}
});
}
Function deleteFromFavourites is the same, but just doing a DELETE ajax
request to remove the item
The problem is that the button does not toggle between favourite and un-favourite not unless I refresh the page. How can I do this without having to refresh the page?
PHP is server side code, so it's completely rendered before it ever leaves the server. That means the other button never exists on the client machine.
You could instead allow both buttons to be sent to the client, but initially hide one from view with CSS.
#foreach($items as $item)
<!-- set color and hide if not favourited -->
<button id="deletefavourite{{$item->id}}"
onClick="deleteFromFavourites({{$item->id}}, {{ Auth::user()->id }})"
name="addfavourite"
class="btn btn-lg"
style="color: #ad1707; {{ $item->isFavourited ? '' : 'display: none;' }}">
<i class="fas fa-heartbeat"></i>
</button>
<!-- hide if favourited -->
<button id="addfavourites{{$item->id}}"
onClick="addToFavourites({{$item->id}}, {{ Auth::user()->id }})"
name="deletefavourite"
class="btn btn-lg"
style="{{ $item->isFavourited ? 'display: none;' : '' }}">
<i class="fas fa-heart" ></i>
</button>
#endforeach
Then in your JavaScript, you can show or hide the buttons as you make changes.
function addToFavourites(itemid, userid) {
var user_id = userid;
var item_id = itemid;
$.ajax({
type: 'post',
url: 'api/addfavourite',
data: {
'user_id': user_id,
'item_id': item_id,
},
success: function () {
// hide add button
$('#addfavourites' + item_id).hide();
// show delete button
$('#deletefavourite' + item_id).show();
},
error: function (XMLHttpRequest) {
// handle error
}
});
}
// and so on for the other function
// ...
// show add button
$('#addfavourites' + item_id).show();
// hide delete button
$('#deletefavourite' + item_id).hide();
// ...

Deleting href when clicked on a link (a delete icon) beside it (Javascript help)

I have a link <a href="#"> and beside that there is a delete png icon (which is also <a href="#"> link.
So what I want is, when clicked on that delete icon, the link <a href="#"> should get deleted with a confirmation window.
So far I have got like,
html:
<ul>
<li>link <a class="delete" href="#" data-request="POST" >....</a></li>
</ul>
My javascript for data-request
var join_request = function(evnt){
evnt.preventDefault();
var $a = $(this);
var request = $a.data('request') || 'POST';
if (confirm("Are you sure want to delete it?")) {
$.ajax($a.attr('href'), {
type: request,
context: $a,
success: join_request_success
});
}
return false;
};
var join_request_success = function(data, a, b){
this.trigger('executed');
};
$(document).ready(function(){
$('a[data-request]').bind('click', join_request);
}
This doesn't seem to be working! When I am clicking on the delete icon, it is displaying the confirmation window but not doing anything.
Is there any other simple way of achieving this? If not, can anyone tell me where am I going wrong?
Thanks.
var join_request = function(evnt){
evnt.preventDefault();
var $a = $(this);
var request = $a.data('request') || 'POST';
if (confirm("Are you sure want to delete it?")) {
$.ajax($a.attr('href'), {
type: request,
context: $a,
error: join_request_success
});
}
return false;
};
var join_request_success = function(data, a, b){
this.trigger('executed');
this.prev().remove();
};
$(document).ready(function(){
$('a[data-request]').bind('click', join_request);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<ul>
<li>link <a class="delete" href="#" data-request="POST" >....</a></li>
</ul>
Note that I had to change success: to error: for demonstration.

Double buffering divs flicker when refreshing in Ajax

I have code that refreshes a div running on local server without flickering, but when hosting it on a webserver, it does flicker (disappear to background) when refreshing:
<script>
setTimeout(function() {
$.ajax({
url: "",
context: document.body,
success: function(s,x){
$(this).html(s);
}
});
}, 1000);
</script>
I've had a good look around SO and the web, and it seems I want to double buffer the div table I am refreshing - have one hidden, refresh that, then swap the display style of the two divs
I started with How to avoid blinking when updating page from ajax
moved on to http://www.brightcherry.co.uk/scribbles/jquery-auto-refresh-div-every-x-seconds/
and Trouble with dynamic refreshing div
And got some good ideas from:How to toggle between two divs
The code I am trying to get to work may be too complicated. I feels like it should work, and the tables refresh, but they flicker with a long time between display.
Divs;
<div id="id1" style="display: none";>
<div id="allTable1" class = "tableCenter">
<div id="hiTable" class = "table">
{% for entry in high_entry_list %}
<li>
<a href="/entries/{{ entry.id }}/">
<div class = "high" style = "text-align: left";>
{{ entry.text }}
<div style="float: right">
{{ entry.score }}
</div>
</div>
</a>
</li>
{% endfor %}
</div>
....and two more tables as hiTable above...
</div>
</div>
<div id="id2" style="display: block";>
<div id="allTable2" class = "tableCenter">
<div id="hiTable" class = "table">
{% for entry in high_entry_list %}
<li>
<a href="/entries/{{ entry.id }}/">
<div class = "high" style = "text-align: left";>
{{ entry.text }}
<div style="float: right">
{{ entry.score }}
</div>
</div>
</a>
</li>
{% endfor %}
</div>
....and two more tables as hiTable above...
</div>
</div>
Script:
<script>
var visible_id = 'id2';
setInterval(function() {
if(visible_id == 'id2') {
document.getElementById('id1').style.display = 'block';
document.getElementById('id2').style.display = 'none';
$.ajax({
url: "/index",
context: document.getElementById('allTable2'),
success: function (s) {
$("#allTable2").html(s).load;
}
});
visible_id = 'id1';
} else {
document.getElementById('id1').style.display = 'none';
document.getElementById('id2').style.display = 'block';
$.ajax({
url: "/index",
context: document.getElementById('allTable1'),
success: function (s) {
$("#allTable1").html(s).load;
}
});
visible_id = 'id2';
}
}, 1000);
</script>
So I have div wrappers for the two copies of three tables (one hidden, one shown), the javascript checks the visibility, swaps display style for the two wrappers, and updates the hidden one with an ajax refresh (which works). Is there an obvious logic or coding flaw that may be causing the flicker?
AJAX requests can take significantly longer than a second. You are toggling between the tables whether or not a particular AJAX request has finished, but the AJAX will still execute (perhaps 1.5 seconds later), giving you that undesired flickering behavior.
Rather than setting an interval which will execute whether or not the AJAX request has finished, set a timeout from the AJAX callback. Something like this (you'll probably need to fiddle with it some):
<script>
(function(){
var visible_id = 'id2';
function toggleDisplay(){
// toggle displayed table
document.getElementById('id1').style.display = visible_id === 'id2' ? 'block' : 'none';
document.getElementById('id2').style.display = visible_id === 'id2' ? 'none' : 'block';
var tableId = visible_id === 'id2' ? 'allTable1' : 'allTable2';
$.ajax({
url: "/index",
context: document.getElementById(tableId),
success: function (s) {
$("#" + tableId).html(s).load;
// when the ajax request has finished, initiate the next ajax request
// after a 1 second delay
window.setTimeout( toggleDisplay, 1000 );
}
});
visible_id = visible_id === 'id2' ? 'id1' : 'id2';
}
})();
</script>

How to get which link has been clicked in jquery

Good day...
I have multiple links as below:
<li>Save</li>
<li>Save As</li>
<li>Save And Exit</li>
I wanna know which link has been clicked
I tried something like this:
if ($("#mmSaveForm").click() == "true") {
//do something
}
else if ($("mmSaveAs").click() == "true") {
//Do something
}
else if ($("#mmSaveExit").click() == "true") {
//Do something
}
I tried these links, questions & answers but they are not helping:
How can I get the button that caused the submit from the form submit event?
jQuery: how to get which button was clicked upon form submission?
how to detect which button is clicked using jQuery
jQuery - how to determine which link was clicked
I've been trying this the whole night, please help...
Thank you in advanced...
Why don't you target the class instead, grab the id and then use a switch statement.
$('.itemDisabled').on('click', function () {
var id = this.id;
switch(id) {
case 'mmSaveForm':
// code
break;
case 'mmSaveAs':
// code
break;
case 'mmSaveExit':
// code
break;
}
});
Try to use .is(selector) to identify the element which has been clicked,
$('a.noTxtSelect1').click(function(e){
e.preventDefault();
if($(this).is("#mmSaveForm")){
} else if($(this).is("#mmSaveAs")) {
} else if($(this).is("#mmSaveExit")) {
}
});
If your links have id attributes all starting with 'mm' you could use:
$('a[id^=mm]').on('click', function(){
console.log(this.id);
});
Or on one or more classes:
$('a.itemDisabled').on('click', function(){
-or-
$('a.itemDisabled.noTxtSelect1').on('click', function(){
In the click event, you can use switch to determine the link clicked, which you can fetch using this or $(this)
e.g.:
Demo Fiddle
$('a[id^=mm]').on('click', function () {
switch (this.id) {
case "mmSaveForm":
alert(this.id);
break;
case "mmSaveAs":
alert(this.id);
break;
case "mmSaveExit":
alert(this.id);
break;
}
});
You can use the [attr^="value"] ["starts with"] selector:
$('[id^="mmSave"]').click(function(event){
event.preventDefault();
var action = this.id;
// do your business
});
You're thinking about this the wrong way. In your
$(document).ready(function() {})
you register for click events. So something like
$(document).ready(function() {
$("#mmSaveForm").click(function() {
// handle the click
});
});
may be you can try this
$(function(){
$('.linkclass').click(function(){
var link_text = $(this).text();
alert('the clicked link text is '+ link_text);
});
});
Use common class like a itemDisabled for click event and get id ,
$(".itemDisabled").click(function (e) {
e.preventDefault();
var id = this.id;
if (id === "mmSaveForm") {
} else if (id === "mmSaveExit") {
} else {}
});
No need jquery please look this code
<!DOCTYPE html >
<html >
<head>
<script>
function clickbtn(t)
{
alert(t.id);
/*if(t.id==...)
{
dosomething();
}
else
{
dootherthing();
}
*/
}
</script>
</head>
<ul>
<li>Save</li>
<li>Save As</li>
<li>Save And Exit</li>
</ul>
<body>
</body>
</html>
It work ok .
Hope this help!
This is my html page (Django template):
<div class="col">
{% for blog in blogs %}
<div class="post">
<h3>{{ blog.title }}</h3>
<div class="date">
<p>Created: {{blog.date_created|date:'d M Y'}}</p>
</div>
<p>{{ blog.brief|safe }}</p>
<ul class="nav justify-content-end">
<li class="nav-item">
<a class="nav-link active" href="{% url 'blog:edit' pk=blog.pk %}">Edit</a>
</li>
<li class="nav-item">
<a class="nav-link" id="publish" href="{{blog.pk}}">Publish</a>
</li>
<li class="nav-item">
<a class="btn btn-danger" id="remove" href="{{blog.pk}}">Remove</a>
</li>
</ul>
<br>
</div>
{% endfor %}
</div>
In my javascript file, this is what have and it works.
$(document).ready(function() {
console.log("document is ready!!!")
$('#id_bloglist').on("click", 'a#publish,a#remove', function(e) {
e.preventDefault()
var pk = $(this).attr("href")
if ($(this)[0].id == 'remove'){
console.log("remove link clicked, calling deleteBlog with pk = " + pk)
}
else if ($(this)[0].id == 'publish'){
console.log("publish link clicked, calling publishBlog with pk = " + pk)
}
return false;
});
});

JQuery Closest Method to change HTML

I am working on a project, i have two anchors in my View(for voting functionality),
I have a div inside which i am having a <ul> and in 3 <li> i am having anchor for upvote,vote count (in <h2>) and anchor downvote respectively
I want functionality that when i click on any anchor, the h2 html show the vote count, i've implemented the functionality but because of i am unable to do this,
this is my View
<div class="voting" style="margin-left:20px;">
<ul>
<li class="addvote"><a href="#" class="voteAnswer" answerid="#answer.AnswerID" name="Voted">
Up</a></li>
<li class="votecounter">
<h2>
#answer.AnswerLikes.Where(a => a.IsActive == true).Count()</h2>
</li>
<li class="subvote"><a href="#" class="voteAnswer" answerid="#answer.AnswerID" name="Voted">
Down</a></li>
</ul>
</div>
and this is my JS
$(".voteAnswer").click(function (event) {
var answerid = $(this).attr('answerid');
var name = $(this).attr('name');
var id = $(this).attr('id');
var output = $(this);
$.ajax({
url: ResourceAjaxUrl.VoteUnvoteTheAnswer,
type: "POST",
data: JSON.stringify({ answerID: answerid }),
dataType: "html",
contentType: "application/json; charset-utf-8",
success: function (Result) {
alert("Voted");
// $(output).html("Voted (" + Result + ")");
$(output).closest("li").find("h2").html(Result);
$(output).attr("name", "Voted");
},
error: function (msg) {
alert("Unable to Vote answer: " + msg);
}
});
event.preventDefault();
});
i have tried using $(output).closest("li").find(".votecounter") but its still not working
The UL is the closest common ancestor.
Try:
$(output).closest("UL").find(".votecounter")
there are some problems in your code .
here
$(".voteAnswer").click(function (event) {
var id = $(this).attr('id');
there is no attribute id in .voteAnswer
and also how do you differentiate upvote and downvote .
you have to check the anchor's parent li tag's class and check it is upvote or down vote .
also you can select the .votecounter
simply by
$(".votecounter").find("h2").html(Result);
or
$(output).closest("ul").find(".votecounter");

Categories