You are on page 1of 5

BuildingusefulnotificationswithHTML5APIs

ArnoSlatiusOct28,2014

Manyuserskeeploadsoftabsopenintheirbrowsersthesedays.Stuffthey'reworkingon,thingsthey
wanttoreadlater,Twitterfeeds.Howisyoursiteorapplicationgoingtostandoutanymore?Whatif
youreallywanttodrawausersattention?HTML5suppliesuswithafewJavaScriptAPIadditionsthat
canhelp.

ThePageVisibilityAPIisthefirst.Thisallowsyoutogeteventsifyourapplicationtabismovedaway
fromtheuserbutremainsactive.

TheWebNotificationAPIisthenext.Thisallowsyoutocreateapopupthatinformstheuserwithyour
message.

ThirdistheVibrationAPI.It'satinyAPIbutitaddsaphysicalaspecttonotifications.
Ifyoulookatthesupportedplatformsyou'llseethatthePageVisibilityissupportedonmostcurrent
platforms.Webnotificationsarewidelysupportedondesktopbrowsers,butmobilebrowsers
unfortunatelylackinsupport.OnlythelatestAndroidBrowsersupportsit(notevenChromefor
Android).Somewhatdisappointing,Iagree.ThevibrationAPIisbettersupportedbrowserwise
(althoughnotbyiOS...)butasyouprobablyimaginedit'salostcauseonmostdesktopsandlaptops.
Supportmayvary,butthatcanonlyimproveovertime.Solet'sseehowwecanmakethemostoutofit.
First,I'llshowyouhowtousetheindividualAPIs.

VibrationAPI
I'llfirstblowyouwaywiththisawesomeAPI.Itallowsyoutomakeauser'sdevicevibrate
//Makeitvibratefor300ms
window.navigator.vibrate(300);

//Butyoucandefinepatternsaswell...on,off,ontimesinsequence
window.navigator.vibrate([300,100,300])

Insultinglysimple,Iagree.Onethingtonoteonthepatternsthough:I'vefoundthatforAndroidatleast,
thefirstbuzzisn'talwaystreatedcorrectly.Ifyouusethepatterninmyexample,youmightnoticethat
thefirstvibrationisconsiderablyshorterthanthesecondone.Youmightwanttoexperimentabitwith
ittogettheresultyou'reafter.

PageVisibilityAPI
NextisamoreinterestingAPI.Byregisteringyoureventhandlertothisyoucangetasignalwhetheror
notyourpageisvisibletotheuser.TheexamplebelowispartiallyborrowedfromMDN,butItriedto
showwhichpartsyou'llneedforwhichwebbrowser.
//Currentlydifferentbrowsershavedifferentevents
varhidden,visibilityChange;
if(typeofdocument.hidden!=='undefined'){
//Opera12.10,Firefox>=18,Chrome>=31,IE11
hidden='hidden';
visibilityChangeEvent='visibilitychange';
}elseif(typeofdocument.mozHidden!=='undefined'){
//Olderfirefox
hidden='mozHidden';
visibilityChangeEvent='mozvisibilitychange';
}elseif(typeofdocument.msHidden!=='undefined'){
//IE10
hidden='msHidden';
visibilityChangeEvent='msvisibilitychange';
}elseif(typeofdocument.webkitHidden!=='undefined'){
//Chrome<31andAndroidbrowser(4.4+!)
hidden='webkitHidden';
visibilityChangeEvent='webkitvisibilitychange';
}

//Eventhandler:logchangetobrowserconsole
functionvisibleChangeHandler(){
if(document[hidden]){
console.log('Pageisnotvisible\n');
}else{
console.log('Pageisvisible\n');
}
}

//Registereventhandler
if(typeofdocument.addEventListener==='undefined'||
typeofdocument[hidden]==='undefined'){
console.log('PageVisibilityAPIisn'tsupported,sorry!');
}else{
document.addEventListener(visibilityChangeEvent,visibleChangeHandler,false);
}

0.
1.
2.
3.
4.
5.
6.
7.
8.
9.
0.
1.
2.
3.
4.
5.
6.
7.
8.
9.
0.
1.
2.
3.
4.
5.
6.

Thisexamplewillsupportalmostallversionsofbrowsersthathaveimplementedtheevent.Ifyou're
lookingtosupportonlythemostcurrentbrowsersthenyoucandoitmucheasierbyregistering
thevisibilitychangeevent.YoucanmakeiteveneasieronyourselfbyusingtheVisibility.jswrapper
librarywhichaddsahacktosupportolderwebbrowsers,shouldyouneedto.
AswiththepreviousAPI,therearesomenotestobemade;desktopbrowserswillfiretheeventnicely
whenyourtablosesfocus.Unfortunately,youcan'tdependontheeventifyouruserswitchestoan
otherapplicationthanthewebbrowser.SwitchingappsonAndroidfirestheeventinChrome,Firefox
andOpera(sorry,noiOSforme).

WebNotificationAPI
ThefirstthingtonotewhenyouapplythewebnotificationsAPIisthatyou'llneeduserconsenttoshow
anotification.Thisisprobablybetterbecauseyouralertscouldbecomeannoyingprettyfast,sorespect
youruserbymakingsurenotificationsbenefit,anddon'tpester,them.
UsingtheAPIrequiresustolookfordifferentwindowelementsbecauseolderbrowsersmighthavethis
implementedinaprefixedmanner:
//Determinethecorrectobjecttouse
varnotification=window.Notification||window.mozNotification||window.webkitNotification;

//Theuserneedstoallowthis
if('undefined'===typeofnotification)
alert('Webnotificationnotsupported');
else
notification.requestPermission(function(permission){});

//Afunctionhandler
functionNotify(titleText,bodyText)
{
if('undefined'===typeofnotification)
returnfalse;//Notsupported....
varnoty=newnotification(
titleText,{
body:bodyText,
dir:'auto',//orltr,rtl
lang:'EN',//langusedwithinthenotification.
tag:'notificationPopup',//AnelementIDtoget/setthecontent
icon:''//TheURLofanimagetobeusedasanicon
}
);
noty.onclick=function(){
console.log('notification.Click');
};
noty.onerror=function(){
console.log('notification.Error');
};
noty.onshow=function(){
console.log('notification.Show');
};
noty.onclose=function(){
console.log('notification.Close');
};
returntrue;
}

0.
1.
2.
3.
4.
5.
6.
7.
8.
9.
0.
1.
2.
3.
4.
5.
6.
7.
8.
9.
0.
1.
2.
3.
4.
5.
6.
7.

Here'swhatyou'llseewhenyousupplysometextandaniconURL:

Combiningthemall
Let'sseehowwecancombinetheseAPIstogether.Isuggestthefollowingscenario:

I'llassumeyoualreadyhavesomesortofnotificationqueueinyourapplicationthatyoucanquery.

Weperiodicallyquerythebackendfornotificationstoshow.

Weonlypushanotificationifthepageisn'tvisibleandcombineitwithvibration,otherwisesome
foregroundnotificationqueueisassumedtoshowthenotification.

Ifwecan'tsendthenotification,wefallbacktochangingthetabtitlesothatwemightgetauser's
attention.
Here'sthecode:
//Registereventandrequestspermission
document.addEventListener('visibilitychange',visibleChangeHandler,false);
varnotification=window.Notification||window.mozNotification||window.webkitNotification;
notification.requestPermission(function(permission){});

//Pollourbackendfornotifications,setsomereasonabletimeoutforyourapplication
window.setInterval(function(){
console.log('poll...');
jQuery.ajax({
url:'site/notifyQueue',
dataType:'json',
data:{userid:'1234',token:'otherdata'},//Includeyourowndata,thinkaboutCSRF!
success:function(data,status){
notificationPoster(data,status);
}
});
},5000);//pollevery5secs.

varoriginalTitle='',messageCount=0;
functionnotificationPoster(data,status)
{
if(document['hidden']){
console.log('pagenotvisible,usenotificationandvibrate');
//Vibrateandtrytosendnotification
window.navigator.vibrate(500);
if(false==Notify(data.title,data.body)){
//Fallbacksignalingwhichupdatesthetabtitle
if(''==originalTitle)
originalTitle=document.title;
messageCount++;
document.title='('+messageCount+'messages!)'+originalTitle;
}else{
//Notificationwasshown
}
}
else{
console.log('pagevisible,pushtonormalnotificationqueue');

0.
1.
2.
3.
4.
5.
6.
7.
8.
9.
0.
1.
2.
3.
4.
5.
6.
7.
8.
9.
0.
1.
2.
3.
4.
5.
6.
7.

8.
9.
0.
1.
2.
3.
4.
5.
6.

doYourOwnSignaling(data);

//Resetfallbackhandling
messageCount=0;
if(''!=originalTitle)
document.title=originalTitle;
originalTitle='';
}
}

Obviously,I'veleftouttheactualnotificationimplementationifthepageisvisible.That'soutsideofthe
scopeofthistutorial.Ido,ofcourse,havesomesuggestionsforthat:

noty.js,whichisavailablehereonBinpress,hasasimpleinterfacewhichyoucansendyourmessageto
immediately.

AlternativelyNotifier.jsimplementsaverynicestylethatresemblesthebrowsertypenotificationson
screen.

TryGoogle,therearesomanyoutthere....
It'suptoyoureally,youcanimplementityourselforuseoneofthemanylibrariesoutthere.
IhopetheseexamplesgiveyousomeinspirationtoimplementtheseAPIsinyourownapplication.Do
letusknowifthisworkedforyou,orbetteryet,howyou'veimprovedit.Goodluck!