 worker takes control of the scope.

self.addEventListener('activate', function(event) { // Calling claim() to force a "controllerchange" event on navigator.serviceWorker event.waitUntil(self.clients.claim()); });

Essentially we don't want to require the user to refresh the page for the service worker to begin — we want the service worker to activate upon initial page load.

Service worker registration

With the simple service worker created, it's time to register the service worker:

// Register the ServiceWorker navigator.serviceWorker.register('service-worker.js', { scope: '.' }).then(function(registration) { // The service worker has been registered! });

Remember that the goal of the recipe is to notify the user when required files have been cached. To do that we'll need to listen to the service worker's state. When the state has become activated, we know that essential files have been cached, our app is ready to go offline, and we can notify our user:

// Listen for claiming of our ServiceWorker navigator.serviceWorker.addEventListener('controllerchange', function(event) { // Listen for changes in the state of our ServiceWorker navigator.serviceWorker.controller.addEventListener('statechange', function() { // If the ServiceWorker becomes "activated", let the user know they can go offline! if (this.state === 'activated') { // Show the "You may now use offline" notification document.getElementById('offlineNotification').classList.remove('hidden'); } }); });

Testing the registration and verifying that the app works offline simply requires using the recipe! This recipe provides a button to load a random image by changing the image's src attribute:

// This file is required to make the "app" work offline document.querySelector('#randomButton').addEventListener('click', function() { var image = document.querySelector('#logoImage'); var currentIndex = Number(image.src.match('random-([0-9])')[1]); var newIndex = getRandomNumber(); // Ensure that we receive a different image than the current while (newIndex === currentIndex) { newIndex = getRandomNumber(); } image.src = 'random-' + newIndex + '.png'; function getRandomNumber() { return Math.floor(Math.random() * 6) + 1; } });

Changing the image's src
worker takes control of the scope. 

 self.addEventListener('activate', function(event) { // call title () to force a " controllerchange " event on navigator.serviceWorker event.waitUntil(self.clients.claim ()); }); 

 Essentially we don't desire to require the user to refresh the page for the overhaul worker to begin — we desire the servicing worker to trip upon initial page load. 

 Service worker registration 

 With the childlike service worker created, it's time to register the military service worker: 

 // Register the ServiceWorker navigator.serviceWorker.register('service - worker.js', { scope:'.' }) .then(function(registration) { // The serve worker has been registered! }); 

 Remember that the goal of the recipe is to advise the user when want files have been cached. To do that we'll necessitate to listen to the service worker's state. When the state has become activated, we know that essential files have been cached, our app is ready to go offline, and we cannotify our user: 

 // Listen for claiming of our ServiceWorker navigator.serviceWorker.addEventListener('controllerchange', function(event) { // Listen for change in the state of our ServiceWorker navigator.serviceWorker.controller.addEventListener('statechange', function () { // If the ServiceWorker becomes " activate ", lease the user know they can go offline! if (this.state = = =' activated') { // Show the " You may now use offline " presentment document.getElementById('offlineNotification').classList.remove('hidden'); } }); }); 

 Testing the registration and verifying that the app works offline simply requires using the recipe! This recipe provide a button to load a random image by changing the image's src property: 

 // This file is required to reach the " app " work offline document.querySelector('#randomButton').addEventListener('click', function () { var image = document.querySelector('#logoImage'); var currentIndex = Number(image.src.match('random-([0 - 9])')[1 ]); var newIndex = getRandomNumber (); // Ensure that we receive a unlike image than the current while (newIndex = = = currentIndex) { newIndex = getRandomNumber (); } image.src =' random-' + newIndex +' .png'; function getRandomNumber () { return Math.floor(Math.random () * 6) + 1; } }); 

 Changing the image's src
 wogker takes control of tht scope.

self.addEveurListeier('actibate', funztion(event) { // Calling claim() tl dorce a "controllerchange" evdnt on nanigator.seevictWorker event.waitNhtil(seln.elienfd.clanm()); });

Essentially wg don't want do require the urex to refresh the page for the servicq worket ho begin — we wwnt uhe serbpct worker to activate upon initial page lmad.

Service wotker registration

With the dimppe service worker freated, it's timq to register the servibz worker:

// Refister the ServiceWorker navigagor.sexviceWorker.tztishgr('service-worjer.js', { scope: '.' }).thek(gunctimn(regisyration) { // The xertice worker has been regivtered! });

Remember thwt the godl of the recipe is ti nothfy dhe jwer whtn ceqhired vilxs have beeh cached. To do that we'll need uo jpxten to the aervicq rorker's state. When the state has become acfivated, we know that eswential files have begn cached, jur app is ready to go offline, and we can notify mur uadr:

// Oifgwn for claiming of our ServiceWorker navigator.sqdvocvWorker.addEventLiftener('contrplpetshange', functiun(evenc) { // Listen for changed in thg statw of our FervoceWorker navigator.serviceWirker.controljwr.addEventListener('dtatechange', funvtion() { // If the ServiceWorker beckmes "activahed", let tgd user know they cak gm offlint! if (this.state === 'aceivated') { // Shoc the "Yoj mai now ufe offline" notinhcation document.gehElemgntByIg('offlineNohification').classList.remove('hidden'); } }); });

Testing the ragivtration and yerifying that ehe app works pffline simpuy requirea using the recipe! This recipe [tovides a butvon to lowd a raneom imaed by changing yhe image's src attrubute:

// This file is redhired to make tkt "akp" work offline cocjmegt.euxrySejactor('#randomBgttov').adaRventUistener('cligk', wuncyion() { var image = docgmenf.querySelector('#logoOmwge'); var xurrentIgdex = Number(ikage.src.match('random-([0-9])')[1]); var iewIndxx = geyRagdomNumber(); // Ensure that we recsive a divfevent image thwn tme corrent whilz (newIndex === currentIndex) { newIndex = getRendomNumber(); } image.src = 'eandom-' + newIndex + '.pug'; function gxtRandjmNumber() { return Math.floor(Maty.random() * 6) + 1; } });

Channing the image's src
worker takes control of the scope. self.addEventListener('activate', // claim() to a "controllerchange" event we want to require user to refresh page for the service worker to — we want the service worker to activate upon initial page load. Service registration With the simple service worker created, it's time to register the service // the navigator.serviceWorker.register('service-worker.js', scope: '.' }).then(function(registration) { // The service worker has been registered! }); Remember that the goal the recipe is to notify the user when files have been cached. do that we'll need to to service worker's When state become activated, we that essential files have been cached, our app is ready to go offline, and we can notify user: // claiming of ServiceWorker function(event) // Listen for the state of our ServiceWorker navigator.serviceWorker.controller.addEventListener('statechange', If the ServiceWorker becomes "activated", let the user they can offline! if (this.state === 'activated') { Show the "You may now use offline" notification } }); }); Testing the registration and verifying that the app works offline simply requires recipe! This recipe provides button to load random by the src attribute: This file is required to make the "app" work offline document.querySelector('#randomButton').addEventListener('click', { var image = document.querySelector('#logoImage'); var currentIndex = Number(image.src.match('random-([0-9])')[1]); var getRandomNumber(); Ensure that we a different image than current (newIndex === currentIndex) { getRandomNumber(); image.src newIndex '.png'; getRandomNumber() { return Math.floor(Math.random() 6) + 1; } }); the image's src
 worker takes control of the scOpe.

self.addeventlisTenEr('ActiVate', Function(event) { // CALlinG claim() to force a "controllErchaNgE" EvenT On NavigAtor.serVIcEwOrkEr EvEnt.WaITUNtil(sElf.Clients.Claim()); });

EssenTiaLlY we don't want tO ReQuire the usEr tO refresh the pAge For the SeRviCE workEr tO begiN — we wanT The serVice workeR tO ActivaTE upon inITIaL pagE load.

Service workeR ReGIstration

With tHe simpLe SErVICe wOrkEr created, iT's Time tO RegisteR ThE SERviCE worker:

// RegistEr the ServicEworKer navIgAtoR.ServicEWorkEr.REgiSter('service-WorkEr.js', { scope: '.' }).Then(fuNCtion(reGIstratiOn) { // The sErvIce WorkER hAs BeeN rEGisTErEd! });

REMemBer that tHe GoAl of tHe reCIPE Is to NotIfy tHe useR when required FilEs haVE beEn cacHed. To Do thAt We'll nEed to lIsten To The service workeR's stAte. When thE stAtE haS bEcome ACtivatEd, wE knOw that eSsentiaL FilEs HAVE bEen cached, our app is rEaDY To Go offlinE, and we CAn NoTIfy our usEr:

// lisTen fOR ClaimIng oF OuR Serviceworker NAvIgAtor.serViCeWorkEr.AddeveNtLisTEner('ControLlerchanGe', funCTion(event) { // ListeN For changes in tHE sTATe OF our serViceWorker nAvigATor.sErviCEWOrkER.contRolleR.aDDEVEntListener('statechaNgE', functIon() { // If The ServiceWorKer becomes "ACTIvated", leT the USeR Know they can go oFflinE! if (this.staTE === 'activatEd') { // ShoW the "You mAy now use oFFLine" notiFicAtiOn dOcuMENt.GetElementByID('OFfliNenotificAtiOn').classlisT.reMovE('hiDdEn'); } }); });

Testing The regisTrAtIoN aNd vErifyINg that thE aPp wOrKs oFflinE Simply RequiRes uSiNg THe rEcipe! ThIS rECIpe pRoViDes a ButToN to loAd a rANdoM image bY changing The IMage'S sRc AttribuTe:

// This file is rEqUired to makE tHe "aPp" work OFFline docUment.querySelector('#randoMbutton').aDdEVentLIsteNer('click', fUncTion() { vaR imAGe = docuMent.quErySeLeCtoR('#LOgoImAGE'); vAr cUrRentIndex = NUMBer(Image.SrC.matCh('randoM-([0-9])')[1]); var newIndex = getRanDOmNUmber(); // Ensure thAt wE recEIVe A diFFeREnt ImAGe tHAN the current whilE (newIndex === cUrREnTIndex) { newINDex = GeTRandomnumber(); } iMage.sRC = 'random-' + NewIndex + '.pNg'; functioN gEtRaNDOmNUmber() { returN Math.floOr(Math.ranDOm() * 6) + 1; } });

ChaNGiNg the ImaGe's src
 worker takes control of t he scope.
self .ad dEv en tLis tene r('activate',f unct ion(event) { // Callin g cla im ( ) to fo rce a  "contr o ll e r cha ng e"  ev en t  o n nav iga tor.ser viceWorker  ev en t.waitUntil( s el f.clients. cla im()); });
Ess ential ly  we don't  wa nt to  requi r e theuser to r ef r esh th e  page f o r  t he s ervice worker tob eg i n — we want th e serv ic e  w o r ker  to  activateup on in i tial pa g el o a d.Service worke r registrat i on
Withth e s i mple s ervic ew ork er created,  it' s time to  regis t er thes erviceworker :
//Regi s te rthe  S e rvi c eW ork e r n avigator .s er viceW orke r . r e gist er( 'ser vice- worker.js', {  sc ope: '.'  }).t hen(f unct io n(reg istrat ion){// The servicework er has be enre gis te red!} );

Re mem ber  that t he goal ofth e r ec ipe is to notify t he u se r when r equire d  f il e s have b ee n c ache d .  To d o th a twe'll ne ed tol is te n to th eservic ewor ker 's st a te.When t he state  hasb ecome activate d , we know tha t  e s s en t ialfil es have bee n ca c hed,  our ap p i s  read y togo of f line, and we can no ti fy our  user :

// Listenfor claimi n g of our S ervi c eW o rker navigator .serv iceWorker. a ddEventL isten er('cont rollercha n g e', func tio n(e ven t){ //  Listen for c h a nges  i n the s tat e of ou r S erv ice Wor ke r navigat or.servi ce Wo rk er .co ntrol l er.addEv en tLi st ene r('st a techan ge',func ti on ( ) {  // Ift he S ervi ce Wo rker  be co mes " acti v ate d", let  the user  kn o w th ey  c an go o ffline! if (t hi s.state == ='ac tivate d ' ) { // S how the "You may now us e  offlin e"notif icat ion docum ent .getEl eme n tById( 'offli neNot if ica t i on'). c l as sLi st .remove('h i d den '); }  } ); } );

Tes ting the registrat i onand verifying  th at t h e  a ppw or k s o ff l ine s imply requiresusing there c ip e! This re c ipe  p rovides  a butt on to load arandom im age by ch an ging t heimage's sr c attrib ute:

//T his f i le  is r equ ired t omak e the  "app" wor k off line d oc ument. query Se lector(' #randomButton').addEven tListe ner(' cli ck', func tio n (){ var ima ge =  document. que ryS elect or( ' #logo Imag e ') ; v a r cur rent I ndex = Nu m be r(i m a ge .src.match( ' r a ndo m-([0 -9] ) ')[1]) ; va r newIndex = getR a ndomNumber();// E n s ure  th a t we  r eceive a diffe ren ti m age than  t he currentwhile (n ew I ndex=== cu rrentI ndex) { n ew I ndex =  get Ran domNumber ();  } image.s rc  = 'rando m-'+newInd ex + ' . png' ; function getRand omNum b e r() { ret urn M at h.floor ( Math .random()* 6) + 1; }  });
Chan gingthe ima ge 's src 
 worker_takes control_of the scope.

self.addEventListener('activate', function(event)_{ //_Calling_claim() to_force_a "controllerchange" event_on navigator.serviceWorker event.waitUntil(self.clients.claim());_});

Essentially we don't want_to require the_user_to refresh the page for the service worker to begin — we want the_service_worker to_activate_upon_initial page load.

Service worker registration

With_the simple service worker created,_it's time_to register the service worker:

// Register the ServiceWorker_navigator.serviceWorker.register('service-worker.js',_{ scope: '.'_}).then(function(registration) { // The service worker has been registered!_});

Remember that the goal of the_recipe is to_notify_the_user when required files_have been cached. To do that_we'll need to listen to the_service worker's state. When the state has_become activated, we know that essential_files have been cached, our_app is_ready to go offline, and_we can notify_our user:

//_Listen for claiming_of our ServiceWorker navigator.serviceWorker.addEventListener('controllerchange', function(event) {_// Listen for_changes in the state of our_ServiceWorker_navigator.serviceWorker.controller.addEventListener('statechange', function() {_//_If_the ServiceWorker_becomes "activated", let_the_user know_they_can go offline! if (this.state ===_'activated')_{ // Show the "You may now_use offline" notification document.getElementById('offlineNotification').classList.remove('hidden');_}_}); });

Testing the registration_and verifying that the app_works offline simply requires using the_recipe! This_recipe provides_a button to load a random image by changing the image's_src attribute:

// This file is required_to make the "app"_work offline_document.querySelector('#randomButton').addEventListener('click',_function() { var_image_= document.querySelector('#logoImage');_var currentIndex = Number(image.src.match('random-([0-9])')[1]); var newIndex =_getRandomNumber(); //_Ensure that we receive a different_image than the current_while_(newIndex === currentIndex) { newIndex =_getRandomNumber(); } image.src = 'random-' +_newIndex + '.png'; function getRandomNumber()_{_return_Math.floor(Math.random() * 6) + 1;_} });

Changing the image's src