Last active
August 29, 2015 13:58
-
-
Save azybler/9977709 to your computer and use it in GitHub Desktop.
Pooling-based Notification sample JavaScript code.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var baseUrl = 'http://www.test.com/'; | |
var Notification = { | |
ajaxFrontendLock: false, // to block user-triggered ajax call. | |
ajaxBackendLock: false, // to block backend-triggered ajax call. | |
ajaxTimeout: 5000, // 5 seconds. | |
getListUrl: baseUrl + 'notifications/get-list/', | |
getUnreadCountUrl: baseUrl + 'notifications/get-unread-count/', | |
getNewCountPoolingInterval: 10000), // 10 seconds. | |
markAsReadUrl: baseUrl + 'notifications/mark-as-read/', | |
notificationBtn: 'a#notification-popover-toggle', | |
selectAllBtn: 'a#notification-select-all', | |
selectNoneBtn: 'a#notification-select-none', | |
markSelectedCbx: '.notification-mark-selected', | |
loadingLbl: '.popover-container ul li.loading-label', | |
isEmptyLbl: '.popover-container ul li.isempty-label', | |
markAllAsReadBtn: 'a#notification-mark-all-as-read', | |
optionLbl: '.popover-container ul li.options-label', | |
setup: function() { | |
// Select all notifications. | |
$(Notification.selectAllBtn).bind({ | |
click: function() { | |
$(markSelectedCbx).prop('checked', true); | |
Notification.onSelectionChange(); | |
} | |
}); | |
// Unselects all notifications. | |
$(selectNoneBtn).bind({ | |
click: function() { | |
$(markSelectedCbx).prop('checked', false); | |
Notification.onSelectionChange(); | |
} | |
}); | |
// Handle click on Notification link to load notifications. | |
$(notificationBtn).bind({ | |
click: function() { | |
if (!$(this).hasClass('over')) { | |
// Populate notification pop over with top x notifications. | |
Notification.getList(); | |
} | |
} | |
}); | |
// Update UI to show "? new notifications" based on new count with an | |
// interval. | |
(function poll() { | |
setTimeout(function() { | |
Notification.getUnreadCount(function() { | |
// Setup the next poll recursively | |
poll(); | |
}); | |
}, Notification.getNewCountPoolingInterval); | |
})(); | |
}, | |
updateUiBeginLoading: function() { | |
// Show the loading icon. | |
$(loadingLbl).css({ 'display': 'block' }); | |
// Remove all li elements after the first one with the class | |
// 'loading-label' | |
$(loadingLbl).nextAll('li.item').remove(); | |
// Hides the "there is no notification" message. | |
$(isEmptyLbl).css({ 'display': 'none' }); | |
// Hides the top options bar on the notification pop over. | |
$(optionLbl).css({ 'display': 'none' }); | |
}, | |
updateUiEndLoading: function() { | |
// Hides the loading icon. | |
$(loadingLbl).css({ 'display': 'none' }); | |
}, | |
markAllOrSelectedToRead: function(e) { | |
var nids = [], | |
notifications = e.data.notifications || []; | |
notifications.forEach(function(notification) { | |
if (notification.is(':checked')) { | |
nids.push(notification.data('id')); | |
} | |
}); | |
if (0 === nids.length) { | |
notifications.forEach(function(notification) { | |
nids.push(notification.data('id')); | |
}); | |
} | |
if (0 === nids.length) { | |
nids = 'none'; | |
} | |
if (Notification.ajaxFrontendLock) return; | |
Notification.ajaxFrontendLock = true; | |
// indicate Ui that ajax call has started. | |
Notification.updateUiBeginLoading(); | |
$.ajax({ | |
type: 'POST', | |
url: Notification.markAsReadUrl, | |
data: { 'nids[]': nids }, | |
timeout: Notification.ajaxTimeout, | |
success: function(response) { | |
Notification.ajaxFrontendLock = false; | |
// No need to call updateUiEndLoading(), after getList() has ended, it | |
// will call updateUiEndLoading() for us. | |
if (200 == response.status) { | |
Notification.getList(); | |
} | |
}, | |
error: function(jqXHR, textStatus, errorThrown) { | |
Notification.ajaxFrontendLock = false; | |
// indicate Ui that ajax call has ended. | |
Notification.updateUiEndLoading(); | |
}, | |
dataType: 'json' | |
}); | |
}, | |
getUnreadCount: function(callback) { | |
if (!Notification.ajaxFrontendLock) { | |
Notification.ajaxBackendLock = true; | |
$.ajax({ | |
type: 'GET', | |
url: Notification.getUnreadCountUrl, | |
data: { }, | |
timeout: Notification.ajaxTimeout, | |
success: function(response) { | |
Notification.ajaxBackendLock = false; | |
if (200 == response.status) { | |
Notification.updateUiWithUnreadCount(response.count); | |
} | |
if (callback) { | |
callback(); | |
} | |
}, | |
error: function(jqXHR, textStatus, errorThrown) { | |
Notification.ajaxBackendLock = false; | |
if (callback) { | |
callback(); | |
} | |
}, | |
dataType: 'json' | |
}); | |
} else { | |
if (callback) { | |
callback(); | |
} | |
} | |
}, | |
updateUiWithUnreadCount: function(count) { | |
if (0 === count) { | |
$(notificationBtn).removeClass('hasNew'); | |
$(notificationBtn).text('Notifications'); | |
} else if (1 === count) { | |
$(notificationBtn).addClass('hasNew'); | |
$(notificationBtn).text('1 New Notification'); | |
} else if (count >= 2) { | |
$(notificationBtn).addClass('hasNew'); | |
$(notificationBtn).text(count + ' New Notifications'); | |
} | |
}, | |
isAllSelectableChecked: function() { | |
// Check if all the notification is selected. | |
return $(markSelectedCbx).is(':checked').length === | |
$(markSelectedCbx).length; | |
}, | |
isAllSelectableUnchecked: function() { | |
// Check if all the notification is not selected. | |
return $(markSelectedCbx).not(':checked').length === | |
$(markSelectedCbx).length; | |
}, | |
onSelectionChange: function() { | |
if (Notification.isAllSelectableChecked()) { | |
// All notifications are checked. | |
$(Notification.selectAllBtn).css({ 'display': 'none' }); | |
} else { | |
// There are some checked notifications. | |
$(Notification.selectAllBtn).css({ 'display': '' }); | |
} | |
if (Notification.isAllSelectableUnchecked()) { | |
// All notifications are unchecked. | |
$(selectNoneBtn).css({ 'display': 'none' }); | |
$(markAllAsReadBtn).text('Mark all as read'); | |
} else { | |
// There are some unchecked notifications. | |
$(selectNoneBtn).css({ 'display': '' }); | |
$(markAllAsReadBtn).text('Mark selected as read'); | |
} | |
}, | |
getList: function() { | |
if (Notification.ajaxFrontendLock) return; | |
Notification.ajaxFrontendLock = true; | |
// indicate Ui that ajax call has started. | |
Notification.updateUiBeginLoading(); | |
$.ajax({ | |
type: 'GET', | |
url: Notification.getListUrl, | |
data: { }, | |
timeout: Notification.ajaxTimeout, | |
success: function(response) { | |
Notification.ajaxFrontendLock = false; | |
// indicate Ui that ajax call has ended. | |
Notification.updateUiEndLoading(); | |
if (200 == response.status) { | |
Notification.updateUiWithUnreadCount(response.total_count); | |
Notification.updateUiWithNotifications(response.notifications); | |
} | |
}, | |
error: function(jqXHR, textStatus, errorThrown) { | |
Notification.ajaxFrontendLock = false; | |
// indicate Ui that ajax call has ended. | |
Notification.updateUiEndLoading(); | |
}, | |
dataType: 'json' | |
}); | |
}, | |
updateUiWithNotifications: function(result) { | |
var partialHtml = ''; | |
result = result || []; | |
if (result.length > 0) { | |
for (var i in result) { | |
partialHtml += '<li class="item'; | |
// Add class name 'read' if the notification has been read by the user. | |
if (null != result[i].read_on) { | |
partialHtml += ' read'; | |
} | |
partialHtml += '">'; | |
partialHtml += '<input type="checkbox" '; | |
partialHtml += 'class="notification-mark-selected notification-mark" '; | |
partialHtml += 'data-id="' + result[i].id + '">'; | |
partialHtml += '<a href="' + baseUrl + result[i].url + '">'; | |
partialHtml += result[i].message; | |
partialHtml += '</a>'; | |
partialHtml += '</li>'; | |
} | |
$(loadingLbl).after(partialHtml); | |
$(isEmptyLbl).css({ 'display': 'none' }); | |
$(optionLbl).css({ 'display': 'block' }); | |
// bind the checkbox to perform mark one notification as read. | |
$(markSelectedCbx).unbind(); | |
$(markSelectedCbx).bind({ | |
click: Notification.onSelectionChange | |
}); | |
var notifications = $(markSelectedCbx).map(function(i, n) { | |
return $(n); | |
}).get(); //converts it to an array | |
// Handle ajax logic: mark all notifications as read | |
$(markAllAsReadBtn).unbind(); | |
$(markAllAsReadBtn).bind('click', | |
{ notifications: notifications }, | |
Notification.markAllOrSelectedToRead); | |
Notification.onSelectionChange(); | |
} else { | |
$(isEmptyLbl).css({ 'display': 'block' }); | |
} | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment