dom manipulation - go make things

43

Upload: others

Post on 30-Nov-2021

3 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: DOM Manipulation - Go Make Things
Page 2: DOM Manipulation - Go Make Things

DOMManipulationByChrisFerdinandiGoMakeThings,LLCv4.0.0

Copyright2021ChrisFerdinandiandGoMakeThings,LLC.AllRightsReserved.

Page 3: DOM Manipulation - Go Make Things

TableofContents

1. Intro

AquickwordaboutbrowsercompatibilityUsingthecodeinthisguide

2. Selectors

document.querySelectorAll()document.querySelector()Element.matches()Type-specificselectormethods

3. Loops

forfor…offor…inSkippingandendingloopsArray.forEach()andNodeList.forEach()

4. Classes

Element.classListElement.className

5. Styles

InlineStylesComputedStyles

6. Attributes&Properties

Element.getAttribute(),Element.setAttribute(),Element.removeAttribute(),andElement.hasAttribute()Properties

Page 4: DOM Manipulation - Go Make Things

Attributesvs.Properties

7. EventListeners

EventTarget.addEventListener()MultipleTargetsCapturingeventsthatdon’tbubbleMultipleEvents

8. Puttingitalltogether

GettingSetupListeningforclicksDeterminingwhethertoshoworhidepasswordsShowingandhidingpasswordsStylingthebutton

9. AbouttheAuthor

Page 5: DOM Manipulation - Go Make Things

Intro

Inthisguide,you’lllearn:

HowtogetelementsintheDOM.Howtoloopthrougharrays,objects,NodeLists,andotheriterableitems.Howtoget,set,andremoveclasses.Howtomanipulate,remove,andupdatestyles.Howtoget,set,andremoveattributes.HowtolistenforeventsintheDOM.Techniquesforimprovingeventlistenerperformance.

Aquickwordaboutbrowsercompatibility

ThisguidefocusesonmethodsandAPIsthataresupportedinallmodernbrowsers.ThatmeansthelatestversionsofEdge,Chrome,Firefox,Opera,Safari,andthelatestmobilebrowsersforAndroidandiOS.

Usingthecodeinthisguide

Unlessotherwisenoted,allofthecodeinthisbookisfreetouseundertheMITlicense.Youcanviewofcopyofthelicenseathttps://gomakethings.com/mit.

Let’sgetstarted!

Page 6: DOM Manipulation - Go Make Things

Selectors

HowtogetelementsintheDOM.

document.querySelectorAll()

Findallmatchingelementsonapage.YoucanuseanyvalidCSSselector.

document.querySelector()

Findthefirstmatchingelementonapage.

//Getallbuttonelementsletbuttons=document.querySelectorAll('button');

//Getallelementswiththe.bg-redclassletelemsRed=document.querySelectorAll('.bg-red');

//Getallelementswiththe[data-snack]attributeletelemsSnacks=document.querySelectorAll('[data-snack]');

Page 7: DOM Manipulation - Go Make Things

Ifanelementisn’tfound,querySelector()returnsnull.If

youtrytodosomethingwiththenonexistentelement,anerrorwillgetthrown.Youshouldcheckthatamatchingelementwasfoundbeforeusingit.

Element.matches()

//Thefirstbuttonletbutton=document.querySelector('button');

//Thefirstelementwiththe.bg-redclass

letred=document.querySelector('.bg-red');

//Thefirstelementwithadataattributeofsnackequaltocarrotsletcarrots=document.querySelector('[data-snack="carrots"]');

//Anelementthatdoesn'texistletnone=document.querySelector('.bg-orange');

//Verifyelementexistsbeforedoinganythingwithit

if(none){

//Dosomething...

}

Page 8: DOM Manipulation - Go Make Things

Checkifanelementwouldbeselectedbyaparticularselectororsetofselectors.Returnstrueiftheelementisamatch,and

falsewhenit’snot.

Type-specificselectormethods

Thereareotherselectormethodsthattargetelementsbyspecifictype.

Thedocument.getElementById()methodgetselementsby

theirID,predatesIE6.Thedocument.getElementsByName()methodreturnsa

NodeListofelementswithmatching[name]attributes.Italso

hasdeepbackwardscompatibility.

Ifyouwantedtogetallelementsofacertaintype,youcouldusedocument.getElementsByTagName(),whichworks

backtoIE6.Andthenewkidontheblock,

//Checkifthefirst.bg-redelementhasthe[data-snackattribute]

letred=document.querySelector('.bg-red');

if(red.matches('[data-snack]')){

console.log('Yummysnack!');

}else{

console.log('Nosnacks');

}

Page 9: DOM Manipulation - Go Make Things

document.getElementsByClassName(),getsallelements

thatmatchaspecificclass.ItworksinIE9andup.

Idon’trecommendusinganyofthem.

I’mlazy.Idon’tliketothinkaboutwhichselectoristherightonetouse.Thedocument.querySelector()and

document.querySelectorAll()methodsdoeverything

thoseothermethodsdoandmore.

ThetoughestdecisionIhavetomakeiswhetherIneedallmatchingelementsorjustthefirstone.

Page 10: DOM Manipulation - Go Make Things

Loops

Howtoloopthrougharrays,objects,andarray-likeobjects.

for

Loopthrougharrays,NodeLists,andotherarray-likeobjects.

Inthefirstpartoftheloop,beforethefirstsemicolon,wesetacountervariable(typicallyi,butitcanbeanything)

to0.

Thesecondpart,betweenthetwosemicolons,isthetestwecheckagainstaftereachiterationoftheloop.Inthiscase,wewanttomakesurethecountervalueislessthanthetotalnumberofitemsinourarray.Wedothisbycheckingthe.lengthofourarray.

Finally,afterthesecondsemicolon,wespecifywhattorun

letsandwiches=['turkey','tuna','ham','pb&j'];

//logs0,"tuna",1,"ham",2,"turkey",3,"pb&j"for(leti=0;i<sandwiches.length;i++){

console.log(i);//index

console.log(sandwiches[i]);//value

}

Page 11: DOM Manipulation - Go Make Things

aftereachloop.Inthiscase,we’readding1tothevalueof

iwithi++.

Wecanthenuseitograbthecurrentitemintheloopfromour

array.

for…of

Loopoveriterableobjects.Thatincludesstrings,arrays,andotherarray-likeobjectssuchasNodeLists,HTMLCollections,andHTMLFormControlsCollection,butnotplainobjects({}).

Inafor...ofloop,youdefineavariabletorepresentthe

currentitemoftheiterablethatyou’reloopingthrough.Inside

theblock(thestuffbetweencurlybrackets),youcanusethatvariabletoreferencethecurrentitem.

for…in

letsandwiches=['turkey','tuna','ham','pb&j'];

//logs"tuna","ham","turkey","pb&j"

for(letsandwichofsandwiches){

console.log(sandwich);

}

Page 12: DOM Manipulation - Go Make Things

Loopoverplainobjects({}).

Thefirstpart,key,isavariablethatgetsassignedtotheobject

keyoneachloop.Thesecondpart(intheexamplebelow,lunch),istheobjecttoloopover.

Inafor...inloop,youdefineavariabletorepresentthekey

intheobjectthatyou’reloopingthrough.Insidetheblock(the

stuffbetweencurlybrackets),youcanusethatvariabletogetthekeynameandthevalueofthatkey.

letlunch={

sandwich:'ham',

snack:'chips',

drink:'soda',

desert:'cookie',

guests:3,

alcohol:false,

};

//logs"sandwich","ham","snack","chips","drink","soda","desert","cookie","guests",3,"alcohol",false

for(letkeyinlunch){

console.log(key);//key

console.log(lunch[key]);//value

}

Page 13: DOM Manipulation - Go Make Things

Skippingandendingloops

Youcanskiptothenextiteminaloopusingcontinue,orend

theloopaltogetherwithbreak.Theseworkwithfor,

for...of,andfor...inloops.

/**

*Skippingaloop

*/letsandwiches=['turkey','tuna','ham','pb&j'];

//logs"turkey","tuna","turkey","pb&j"

for(letsandwichofsandwiches){

//Skiptothenextitemintheloop

if(sandwich==='ham')continue;

console.log(sandwich);

}

/**

*Breakingaloop

*/

letlunch={

sandwich:'ham',

snack:'chips',

drink:'soda',

desert:'cookie',

Page 14: DOM Manipulation - Go Make Things

Array.forEach()andNodeList.forEach()

TheArray.forEach()andNodeList.forEach()methods

provideasimplerwaytoiterateoverarraysandNodeListswhilestillhavingaccesstotheindex.

YoupassacallbackfunctionintotheforEach()method.The

callbackitselfacceptsthreearguments:thecurrentitemintheloop,theindexofthecurrentitemintheloop,andthearrayitself.Allthreeareoptional,andyoucannamethemanythingyouwant.

desert:'cookie',

guests:3,

alcohol:false,

};

//logs"sandwich","ham","snack","chips"

for(letkeyinlunch){

if(key==='drink')break;

console.log(lunch[key]);

}

Page 15: DOM Manipulation - Go Make Things

Unlikewithfor,for...of,andfor...inloops,youcan’t

endaforEach()callbackfunctionbeforeit’sloopedthrough

allitems.Youcanreturntoendthecurrentloop(likeyou

wouldwithcontinue),butthere’snowaytobreaktheloop.

Becauseofthat,Igenerallypreferusingafor...ofloop

unlessIexplicitlyneedtheindex.

letsandwiches=['turkey','tuna','ham','pb&j'];

//logs0,"tuna",1,"ham",2,"turkey",3,"pb&j"sandwiches.forEach(function(sandwich,index){

console.log(index);//index

console.log(sandwich);//value

});

//Skip"ham"

//logs0,"tuna",2,"turkey",3,"pb&j"sandwiches.forEach(function(sandwich,index){

if(sandwich==='ham')return;

console.log(index);//index

console.log(sandwich);//value

});

Page 16: DOM Manipulation - Go Make Things

Classes

Howtoadd,remove,toggle,andcheckforclassesonanelement.

Element.classList

TheElement.classListAPIprovidesasimplewaytoadd,

remove,toggle,andcheckforclassesonanelement.

Usetheadd()methodtoaddaclass,theremove()methodto

removeaclass,thetoggle()methodtotoggleaclassonor

off,andthecontains()methodtocheckifaclassexists.

Page 17: DOM Manipulation - Go Make Things

Element.className

Getalloftheclassesonanelementasastring,addaclassorclasses,orcompletelyreplaceorremoveallclasses.

letelem=document.querySelector('#sandwich');

//Addthe.turkeyclass

elem.classList.add('turkey');

//Removethe.tunaclass

elem.classList.remove('tuna');

//Togglethe.tomatoclassonoroff//(Addtheclassifit'snotalreadyontheelement,removeitifitis.)

elem.classList.toggle('tomato');

//Checkifanelementhasthe.mayoclass

if(elem.classList.contains('mayo')){

console.log('addmayo!');

}

Page 18: DOM Manipulation - Go Make Things

letelem=document.querySelector('div');

//Getalloftheclassesonanelement

letelemClasses=elem.className;

//Addaclasstoanelement

elem.className+='vanilla-js';

//Completelyreplaceallclassesonanelement

elem.className='new-class';

Page 19: DOM Manipulation - Go Make Things

Styles

Howtogetandsetstyles(asin,CSS)foranelement.

VanillaJavaScriptusescamelcasedversionsoftheattributesyouwoulduseinCSS.TheMozillaDeveloperNetworkprovidesacomprehensivelistofavailableattributesandtheirJavaScriptcounterparts.

InlineStyles

GetandsetinlinestylesforanelementwiththeElement.styleproperty.

TheElement.stylepropertyisaread-onlyobject.Youcan

getandsetindividualstylepropertiesonitusingcamelCasestylenamesaspropertiesontheElement.styleobject.

<pid="sandwich"style="background-color:green;color:white;">

Sandwich

</p>

Page 20: DOM Manipulation - Go Make Things

Youcanalsogetandsetastringrepresentationoftheentireinlinestylepropertyontheelementitselfwiththe

Element.style.cssTextproperty.

letsandwich=document.querySelector('#sandwich');

//Getastyle//Ifthisstyleisnotsetasaninlinestyledirectlyontheelement,itreturnsanemptystringletbgColor=sandwich.style.backgroundColor;//thiswillreturn"green"letfontWeight=sandwich.style.fontWeight;//thiswillreturn""

//Setthebackground-colorstyleproperty

sandwich.style.backgroundColor='purple';

Page 21: DOM Manipulation - Go Make Things

ComputedStyles

Thewindow.getComputedStyle()methodgetstheactual

computedstyleofanelement.Thisfactorsinbrowserdefaultstylesheetsaswellasexternalstylesbeingusedonthepage.

//Getthestylesonanelement//returns"background-color:green;color:white;"

letstyles=sandwich.style.cssText;

//Completelyreplacetheinlinestylesonanelementsandwich.style.cssText='font-size:2em;font-weight:bold;';

//Addadditionalstyles

sandwich.style.cssText+='color:purple;';

letsandwich=document.querySelector('#sandwich');letbgColor=window.getComputedStyle(sandwich).backgroundColor;

Page 22: DOM Manipulation - Go Make Things

Attributes&Properties

Howtoget,set,andremoveattributesforanelement.

Element.getAttribute(),Element.setAttribute(),Element.removeAttribute(),andElement.hasAttribute()

Get,set,remove,andcheckfortheexistenceofattributes(includingdataattributes)onanelement.

Ifanattributedoesnotexistonanelement,theElement.getAttribute()methodreturnsnull.

Page 23: DOM Manipulation - Go Make Things

Properties

HTMLelementshavedozensofpropertiesthatyoucanaccessdirectly.

Someofthemarereadonly,meaningyoucangettheirvaluebutnotsetit.Otherscanbeusedtobothreadandsetvalues.YoucanfindafulllistontheMozillaDeveloperNetwork.

letelem=document.querySelector('#lunch');

//Getthevalueofthe[data-sandwich]attributeletsandwich=elem.getAttribute('data-sandwich');

//Setavalueforthe[data-sandwich]attributeelem.setAttribute('data-sandwich','turkey');

//Removethe[data-chips]attribute

elem.removeAttribute('data-chips');

//Checkifanelementhasthe`[data-drink]`attribute

if(elem.hasAttribute('data-drink')){

console.log('Addadrink!');

}

Page 24: DOM Manipulation - Go Make Things

Attributesvs.Properties

InJavaScript,anelementhasattributesandproperties.Thetermsareoftenusedinterchangeably,butthey’reactuallytwoseparatethings.

AnattributeistheinitialstatewhenrenderedintheDOM.Apropertyisthecurrentstate.

Inmostcases,attributesandpropertiesarekeptin-syncautomatically.Forexample,whenyouusesetAttribute()

toupdateanIDattribute,theidpropertyisupdatedaswell.

letelem=document.querySelector('#main');

//GettheIDoftheelement

//returns"main"

letid=elem.id;

//SettheIDoftheelement

elem.id='secondary';

//GettheparentNodeoftheelement

//Thispropertyisread-only

letparent=elem.parentNode;

<p>Hello</p>

Page 25: DOM Manipulation - Go Make Things

However,user-changeableformproperties—noteably,value,

checked,andselected—arenotautomaticallysynced.

letp=document.querySelector('p');

//UpdatetheID

p.setAttribute('id','first-paragraph');

//Thesebothreturn"first-paragraph"

letid1=p.getAttribute('id');

letid2=p.id;

<labelfor="greeting">Greeting</label>

<inputtype="text"id="greeting">

Page 26: DOM Manipulation - Go Make Things

Ifyoutrytoupdatethevaluepropertydirectly,thatwill

updatetheUI.

Thisallowsyoutochoosedifferentapproachesdependingonwhetheryouwanttooverwriteuserupdatesornot.

Ifyouwanttoupdateafield,butonlyiftheuserhasn’tmadeanychanges,useElement.setAttribute().Ifyouwantto

overwriteanythingthey’vedone,usethevalueproperty.

letgreeting=document.querySelector('#greeting');

//Updatethevaluegreeting.setAttribute('value','Hellothere!');

//Ifyouhaven'tmadeanyupdatestothefield,thesebothreturn"Hellothere!"//IfyouHAVEupdatedthefield,val1returnswhateverwastypedinthefieldinstead

letval1=greeting.value;

letval2=greeting.getAttribute('value');

greeting.value='Hellothere!';

Page 27: DOM Manipulation - Go Make Things

EventListeners

Howtolistenforbrowsereventsandruncallbackfunctionswhentheyhappen.

EventTarget.addEventListener()

Listenforeventsonanelement.YoucanfindafulllistofavailableeventsontheMozillaDeveloperNetwork.

RuntheEventTarget.addEventListener()methodon

theelementyouwanttolistenforeventson.Itacceptstwoarguments:theeventtolistenfor,andacallbackfunctiontorunwhentheeventhappens.

Youcanpasstheeventintothecallbackfunctionasan

argument.Theevent.targetpropertyistheelementthat

triggeredtheevent.Theeventobjecthasotherpropertiesas

well,manyofthemspecifictothetypeofeventthatoccurred.

Page 28: DOM Manipulation - Go Make Things

MultipleTargets

TheEventTarget.addEventListener()methodonlybe

attachedtoanindividualelement.Youcan’tattachittoanarrayornodelistofmatchingelementslikeyoumightinjQueryorotherframeworks.

letbtn=document.querySelector('#click-me');

btn.addEventListener('click',function(event){

console.log(event);//Theeventdetailsconsole.log(event.target);//Theclickedelement

});

//Thiswon'twork!letbtns=document.querySelectorAll('.click-me');

btns.addEventListener('click',function(event){

console.log(event);//Theeventdetailsconsole.log(event.target);//Theclickedelement

});

Page 29: DOM Manipulation - Go Make Things

Forperformancereasons,youalsoshouldnotloopovereachelementandattachanevenlistenertoit.

Fortunately,there’sareallyeasyandperformantwaytogetajQuery-likeexperience:eventdelegationoreventbubbling.

Insteadoflisteningforaneventonspecificelements,youattachyourlistenertoaparentelementthatyourelementsarecontainedwithin,suchasthewindowordocument.Events

thathappensonelementsinsideitbubbleup.Wecanthenchecktoseeiftheitemthattriggeredtheeventhasamatchingselector.

/**

*Thisworks,butit'sbadforperformance

*DON'TDOIT!

*/letbtns=document.querySelectorAll('.click-me');

for(letbtnofbtns){btn.addEventListener('click',function(event){console.log(event);//Theeventdetailsconsole.log(event.target);//Theclickedelement

});

}

Page 30: DOM Manipulation - Go Make Things

Yes,itisactuallybetterforperformancetolistentoallclicksonthedocumentthanhaveabunchofindividualeventlisteners.

Asasidebenefit,youcandynamicallyloadmatchingelementstotheDOMaftertheeventlistenerisalreadysetupanditwillstillwork.

Capturingeventsthatdon’tbubble

Certainevents,likefocus,don’tbubble.Inordertouseevent

delegationwitheventsthatdon’tbubble,youcansetanoptionalthirdargumentontheEventTarget.addEventListener()method,called

useCapture,totrue.

//Listenforclicksontheentirewindowdocument.addEventListener('click',function(event){

//Iftheclickedelementhasthe`.click-me`class,it'samatch!

if(event.target.matches('.click-me')){

//Dosomething...

}

});

Page 31: DOM Manipulation - Go Make Things

YoucandetermineifuseCaptureshouldbesettotrueor

falsebylookingattheeventdetailspageontheMozilla

DeveloperNetwork(likethisoneforthefocusevent).

IfBubblesinthechartatthetopofthepageis“No,”youneedtosetuseCapturetotruetouseeventdelegation.

MultipleEvents

InvanillaJavaScript,eacheventtyperequiresit’sowneventlistener.Unfortunately,youcan’tpassinmultipleeventstoasinglelistenerlikeyoumightinjQueryandotherframeworks.

//Listenforallfocuseventsinthedocumentdocument.addEventListener('focus',function(event){//Runfunctionswheneveranelementinthedocumentcomesintofocus

},true);

Page 32: DOM Manipulation - Go Make Things

Instead,createanamedfunctionandpassthatintoyoureventlistener.Thisletsyouavoidwritingthesamecodeoverandoveragain,andkeepsyourcodemoreDRY.

Fornamedcallbackfunctions,donotincludetheparentheses(())onthefunction.

Theeventobjectisautomaticallypassedinasanargument.

Youcandeterminewhichtypeofeventtriggeredthecallbackfunctionwiththeevent.typeproperty.

/**

*Thiswon'twork!

*/window.addEventListener('click,scroll',function(event){

console.log(event);//Theeventdetailsconsole.log(event.target);//Theclickedelement

});

Page 33: DOM Manipulation - Go Make Things

//Setupourfunctiontorunonvariousevents

functionlogTheEvent(event){console.log('Thefollowingeventhappened:'+event.type);

}

//Addoureventlistenersdocument.addEventListener('click',logTheEvent);window.addEventListener('scroll',logTheEvent);

Page 34: DOM Manipulation - Go Make Things

Puttingitalltogether

Tomakethisalltangible,let’sworkonaprojecttogether.We’llbuildascriptthatlet’suserstogglethevisibilityofpasswordfieldsinaform.

GettingSetup

Thetemplatehassomestartingmarkup:aformwithtwopasswordfieldsandsomebuttons.

Intheform,there’sabuttonwiththe[data-password]

attributethatwillbeusedtotogglethepasswordfieldvisibility.Thatbuttonhastwoadditionalattributes.

The[type="button"]attributepreventsthebuttonfrom

submittingtheformwhenclicked.

Page 35: DOM Manipulation - Go Make Things

I’vealsoaddedsomedefaultCSSsothatwecanfocusontheJavaScript.

Alright,let’sgetstarted.

Listeningforclicks

Thefirstthingwewanttodoisdetectclicksonour[data-

password]button.Let’susethe

document.querySelector()methodtogetbuttonandsave

ittothetogglevariable.

<form>

<labelfor="current-pw">CurrentPassword</label>

<inputtype="password"id="current-pw">

<labelfor="new-pw">NewPassword</label>

<inputtype="password"id="new-pw">

<p><buttontype="button"data-password>ShowPasswords</button></p>

<p><button>ChangePassword</button></p>

</form>

Page 36: DOM Manipulation - Go Make Things

Next,we’llusetheaddEventListener()methodtolistenfor

clickeventsonit,anddothingswhenthebuttonisclicked.

Determiningwhethertoshoworhidepasswords

Whenthebuttonisclicked,weneedtodetermineifweshouldshoworhidepasswords.Onesimplewaytodothatistocheckifthebuttoniscurrentlyselectedornot.

The[aria-pressed]attributeisusedtotellscreenreaders

(softwarethatpeoplewithvisualimpairmentsusetointeractwithwebpages)ifastate-basedbuttonlikethisoneispressed

//Getthepasswordtogglelettoggle=document.querySelector('[data-password]');

//Getthepasswordtogglelettoggle=document.querySelector('[data-password]');

//Listenforclicksonthetogglebuttontoggle.addEventListener('click',function(event){

//Dostuff...

});

Page 37: DOM Manipulation - Go Make Things

ornot.It’sexactlywhatweneed!

The[aria-pressed]attributehasavalueoftruewhenthe

buttonisselected,andfalsewhenit’snot.Let’sstartby

addingittoourbutton.

Insideoureventlistener’scallbackfunction,wecancheckthevalueofthe[aria-pressed]attributetodetermineifthe

buttoniscurrentlyactiveornot.

We’llusetheevent.targettogetthebuttonthattriggered

theclickevent.Wecoulduseourtogglevariable,butIwant

toshowthedifferentoptionsyouhave.

We’llusethegetAttribute()methodtogetthevalueof

[aria-pressed].

<buttontype="button"data-passwordaria-pressed="false">ShowPasswords</button>

//Listenforclicksonthetogglebuttontoggle.addEventListener('click',function(event){

//Getthevalueofthe[aria-pressed]attributeletpressed=event.target.getAttribute('aria-pressed');

});

Page 38: DOM Manipulation - Go Make Things

Next,we’llusethestrictequalsoperator(===)tocheckif

pressedhasavalueoffalse.

Ifitdoes,weneedtoshowthepasswordfieldsandupdatethevalueof[aria-pressed]totrue.Ifnot,weneedtohidethe

fieldsandchangethevaluetofalse.

WecanusethesetAttribute()methodtosetthe[aria-

pressed]attribute.

Page 39: DOM Manipulation - Go Make Things

Showingandhidingpasswords

//Listenforclicksonthetogglebuttontoggle.addEventListener('click',function(event){

//Getthevalueofthe[aria-pressed]attributeletpressed=event.target.getAttribute('aria-pressed');

//Ifbuttonisn'tpressedyet,pressitandshowfields//Otherwise,unpressitandhidethefields

if(pressed==='false'){event.target.setAttribute('aria-pressed','true');

//Showthefields...

}else{event.target.setAttribute('aria-pressed','false');

//Hidethefields...

}

});

Page 40: DOM Manipulation - Go Make Things

Now,we’rereadytoactuallyshowandhideourpasswordfields.Let’susethedocument.querySelectorAll()methodto

getallfieldswiththe[type="password"]attribute.

We’lluseafor...oflooptoloopthrougheachofour

fields,andthetypepropertytoupdatethefieldtypeas

needed.

Ifthepasswordshouldbevisible,we’llchangethetypeto

text.Ifitshouldbehidden,we’llchangeitbacktopassword.

//Getthepasswordtoggleandpasswordfieldslettoggle=document.querySelector('[data-password]');letfields=document.querySelectorAll('[type="password"]');

Page 41: DOM Manipulation - Go Make Things

//Listenforclicksonthetogglebuttontoggle.addEventListener('click',function(event){

//Getthevalueofthe[aria-pressed]attributeletpressed=event.target.getAttribute('aria-pressed');

//Ifbuttonisn'tpressedyet,pressitandshowfields//Otherwise,unpressitandhidethefields

if(pressed==='false'){event.target.setAttribute('aria-pressed','true');

for(letfieldoffields){

field.type='text';

}

}else{event.target.setAttribute('aria-pressed','false');

for(letfieldoffields){

field.type='password';

}

}

});

Page 42: DOM Manipulation - Go Make Things

Now,thepasswordswillshoworhidebasedonthebuttonstate.

There’sjustonelastthingtodo:stylethebuttonsouserscanvisuallytellifit’sselectedornot.

Stylingthebutton

OnereallycoolthingaboutattributesisthattheycanbeusedtostyleelementsjustlikeclassesandIDs.

Sincethe[aria-pressed]attributealreadyholds

informationaboutwhetherornotthebuttonisselected,itmakessensetouseittostylethebuttonvisuallyaswell.Let’sgiveabluebackgroundwithwhitetextwhenit’sactive.

Congratulations!YoujustcreatedashowpasswordscriptusingavarietyofDOMmanipulationtechniques.

/**

*ActiveButtonStyle

*/

[aria-pressed="true"]{

background-color:#0088cc;

color:#ffffff;

}

Page 43: DOM Manipulation - Go Make Things

AbouttheAuthor

Hi,I’mChrisFerdinandi.Ibelievethere’sasimpler,moreresilientwaytomakethingsfortheweb.

I’mtheauthoroftheVanillaJSPocketGuideseries,creatoroftheVanillaJSAcademytrainingprogram,andhostoftheVanillaJSPodcast.Mydevelopertipsnewsletterisreadbythousandsofdeveloperseachweekday.

Ilovepirates,puppies,andPixarmovies,andlivenearhorsefarmsinruralMassachusetts.

Youcanfindme:

OnmywebsiteatGoMakeThings.com.Byemailatchris@gomakethings.com.OnTwitterat@ChrisFerdinandi.