voice.js 116 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070
  1. /**
  2. * Copyright (c) 2006-2015, JGraph Ltd
  3. * Copyright (c) 2006-2015, Gaudenz Alder
  4. */
  5. /**
  6. * Voice plugin for draw.io
  7. *
  8. * Documentation:
  9. *
  10. * https://support.draw.io/questions/9666655/how-to-use-the-voice-plugin
  11. *
  12. * TODO: Use grammer https://msdn.microsoft.com/en-us/library/ee800145.aspx
  13. */
  14. Draw.loadPlugin(function(ui) {
  15. var micImage = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAA5UlEQVR4Xr3SMYrCQBTGcSfIQiAgRIS9hOANBCurPUAuIAp7A7FVsFkIbLGYA9gKtoKNYG3jll5AFNKG518YMD6SISD4wY9J4MvkMYwRkZqOMSZkifGFe1b4pnvW3TqK8oMo14twxUgXPRSlDxU7TcUNPqATlG7wCi93cA2Iq2x7l7IJsgofB6UTiEjKklFqsabQSdFA5jqDAzrYQGeNNv5d9yDBEAME6NreFmP8Yuma4A8hFpiLSFNAYYYYn0jwCIUnxMcER4h1whS+7hseXKcu9ifGeQ+qeO8GjN7DPve+Q6+oewPhmE63Qfsb6AAAAABJRU5ErkJggg==';
  16. // Speech recognition never supported without synthesis
  17. if (!('speechSynthesis' in window))
  18. {
  19. ui.showError('Error', 'Speech output not supported in this browser.', 'OK');
  20. return;
  21. }
  22. else
  23. {
  24. // Triggers loading of voices
  25. speechSynthesis.getVoices();
  26. }
  27. // Do no use in chromeless mode
  28. if (ui.editor.chromeless || ui.menubar == null)
  29. {
  30. return;
  31. }
  32. // Mic PNG image
  33. var outputImage = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpBNDU1RDkxODcxREIxMUU0OTU3Qjg3REYyOTYxQzc0QiIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpBNDU1RDkxOTcxREIxMUU0OTU3Qjg3REYyOTYxQzc0QiI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkE0NTVEOTE2NzFEQjExRTQ5NTdCODdERjI5NjFDNzRCIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkE0NTVEOTE3NzFEQjExRTQ5NTdCODdERjI5NjFDNzRCIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+QsVUnQAAAX5JREFUeNqck00oRFEUx+eNyYSFUj7KgpfPBUlJWZgFw3IWihpRFpZia4e1hZSlNDsLopSNfBTFQqSwkKmZ5SA2ylfq+Z3pXL15ehlu/fqf9849555777mW4ziBfEZ9rd2InEEsmU4dmP/WHxKEkT1oglaSZOR/0DvRssIVUOQKjEASsxoGoQDmjT/oDUaOdRUzbkASrsMdzMIwSe2cBASXIjtQpyvHYQvzGeLQDkOwDG8w8p2A4GJEJre5Vk5DFBbZ7yG6D+PYL3oW0WwCgh/Re4i4t8PEE2QOxqikDN2AbuwQKr4WU4E4S3wOfw1CWtktFEI5ZDTu5y34DMvPIQl24dTHL9f2CRfQAB/wAFXwlE3gOO990Im95GmcLmQGEpyHTB6AI2xJKL4r7xYmYdX1betpT0kzoT1yhdhyY71aeW4rcyNySJswTVWXWkklcq5N1AETsCAuqkn9+hZ09RXoh1e4hm2CR//7mJqlB8xjCgXyHzXaDzETLONLgAEAxwd5e6Mz+S4AAAAASUVORK5CYII=';
  34. // True if we're on ChromOs
  35. var chromeOs = /\bCrOS\b/.test(navigator.userAgent);
  36. // Maximum length of message to speak
  37. var maxMessageLength = 1000;
  38. // Maximum length of the label before the cell
  39. // is called by its shapename
  40. var maxLabelLength = 15;
  41. // Maximum length of output queue.
  42. var maxQueueLength = 3;
  43. // Specifies if speech output is enabled.
  44. var speechOutputEnabled = true;
  45. // Specifies if speech output is enabled.
  46. var speechInputEnabled = true;
  47. // Last message is never repeated
  48. var lastMessage = null;
  49. // Timestamp of last message
  50. var lastMessageTimestamp = null;
  51. // Sets global recognition language
  52. var lang = 'en-US';
  53. // Caches action names
  54. var actions = null;
  55. var actionList = null;
  56. // Caches shape names
  57. var shapeList = null;
  58. // Last inserted cell
  59. var lastInserted = null;
  60. // Current voice
  61. var currentVoice = 10;
  62. // Current recognition thread
  63. var recognizing = null;
  64. // Adds menu
  65. mxResources.parse('voiceType=Voice Type');
  66. mxResources.parse('speechOutput=Speech Output');
  67. mxResources.parse('speechListen=Listen');
  68. mxResources.parse('speechInstalled=Start with draw.io');
  69. mxResources.parse('speechListenContinuous=Start/Stop Listen');
  70. mxResources.parse('speechHint=Hint');
  71. mxResources.parse('speechHelp=Help');
  72. mxResources.parse('speechQuit=Quit');
  73. // Installs footer click handler
  74. function getOrCreateVoiceButton(ui)
  75. {
  76. if (ui.voiceButton == null)
  77. {
  78. ui.voiceButton = document.createElement('div');
  79. ui.voiceButton.className = 'geBtn';
  80. ui.voiceButton.style.width = '140px';
  81. ui.voiceButton.style.minWidth = '140px';
  82. ui.voiceButton.style.textOverflow = 'ellipsis';
  83. ui.voiceButton.style.overflowX = 'hidden';
  84. ui.voiceButton.style.fontWeight = 'bold';
  85. ui.voiceButton.style.textAlign = 'center';
  86. ui.voiceButton.style.display = 'inline-block';
  87. ui.voiceButton.style.padding = '0 10px 0 10px';
  88. ui.voiceButton.style.marginTop = '-4px';
  89. ui.voiceButton.style.height = '28px';
  90. ui.voiceButton.style.lineHeight = '28px';
  91. ui.voiceButton.style.color = '#235695';
  92. if (ui.buttonContainer.firstChild != null)
  93. {
  94. ui.buttonContainer.insertBefore(ui.voiceButton, ui.buttonContainer.firstChild);
  95. }
  96. else
  97. {
  98. ui.buttonContainer.appendChild(ui.voiceButton);
  99. }
  100. }
  101. return ui.voiceButton;
  102. };
  103. var td = getOrCreateVoiceButton(ui);
  104. if (td != null)
  105. {
  106. // Installs listener for start/stop listen
  107. mxEvent.addListener(td, 'click', function(evt)
  108. {
  109. if (speechSynthesis.speaking)
  110. {
  111. speechSynthesis.cancel();
  112. }
  113. App.listen(true);
  114. });
  115. }
  116. function setPluginInstalled(value)
  117. {
  118. if (mxSettings != null)
  119. {
  120. var plugins = mxSettings.getPlugins();
  121. var installed = mxUtils.indexOf(plugins, '/plugins/voice.js') >= 0;
  122. if (value != installed)
  123. {
  124. if (installed)
  125. {
  126. mxUtils.remove('/plugins/voice.js', plugins);
  127. }
  128. else
  129. {
  130. plugins.push('/plugins/voice.js');
  131. }
  132. mxSettings.setPlugins(plugins);
  133. mxSettings.save();
  134. }
  135. }
  136. };
  137. // Shows initial status message if only output is enable
  138. if (!('webkitSpeechRecognition' in window))
  139. {
  140. if (td != null)
  141. {
  142. td.innerHTML = '<img style="margin-right:4px;" align="absmiddle" border="0" src="' + outputImage + '"/> Ready';
  143. td.style.color = '#235695';
  144. }
  145. }
  146. function updateStatusMessage()
  147. {
  148. if ('webkitSpeechRecognition' in window)
  149. {
  150. if (td != null)
  151. {
  152. if (recognizing != null)
  153. {
  154. td.innerHTML = '<img style="margin-right:4px;" align="absmiddle" border="0" src="' + micImage + '"/> Listening...';
  155. td.setAttribute('title', 'Click to Stop (Ctrl+O)');
  156. td.style.color = 'darkGray';
  157. }
  158. else
  159. {
  160. td.innerHTML = '<img style="margin-right:4px;" align="absmiddle" border="0" src="' + micImage + '"/> Click to Speak';
  161. td.setAttribute('title', 'Click to Speak (Ctrl+O)');
  162. td.style.color = '#235695';
  163. }
  164. }
  165. }
  166. };
  167. updateStatusMessage();
  168. var action = ui.actions.addAction('speechOutput', function()
  169. {
  170. speechOutputEnabled = !speechOutputEnabled;
  171. }, null, null, 'Ctrl/AltGr+Shift+Esc');
  172. action.setToggleAction(true);
  173. action.setSelectedCallback(function() { return speechOutputEnabled; });
  174. var action = ui.actions.addAction('speechInstalled', function()
  175. {
  176. setPluginInstalled();
  177. });
  178. action.setToggleAction(true);
  179. action.setSelectedCallback(function() { return mxUtils.indexOf(mxSettings.getPlugins(), '/plugins/voice.js') >= 0; });
  180. ui.actions.addAction('speechListen', function()
  181. {
  182. App.listen();
  183. }, null, null, 'Ctrl/AltGr+Esc');
  184. ui.actions.addAction('speechListenContinuous', function()
  185. {
  186. App.listen(true);
  187. }, null, null, 'Ctrl+O');
  188. ui.actions.addAction('speechHint', function()
  189. {
  190. App.sayHint();
  191. }, null, null, 'Shift+Esc');
  192. ui.actions.addAction('speechHelp', function()
  193. {
  194. window.open('https://support.draw.io/questions/9666655/how-to-use-the-voice-plugin');
  195. });
  196. // Hijacks the settings for storing current voice
  197. if (mxSettings != null)
  198. {
  199. var tmp = mxSettings.settings.voice;
  200. if (tmp != null)
  201. {
  202. currentVoice = parseInt(tmp);
  203. }
  204. }
  205. ui.menus.put('voiceType', new Menu(mxUtils.bind(this, function(menu, parent)
  206. {
  207. var voices = speechSynthesis.getVoices();
  208. if (voices.length == 0)
  209. {
  210. menu.addItem('Loading...', null, function() {}, parent, null, false);
  211. }
  212. else
  213. {
  214. for (var i = 0; i < voices.length; i++)
  215. {
  216. (function(index)
  217. {
  218. var item = menu.addItem(voices[index].name + ' (' + voices[i].lang + ')', null, function()
  219. {
  220. currentVoice = index;
  221. App.say('hello');
  222. if (mxSettings != null)
  223. {
  224. mxSettings.settings.voice = currentVoice;
  225. mxSettings.save();
  226. }
  227. }, parent);
  228. if (index == currentVoice)
  229. {
  230. menu.addCheckmark(item, Editor.checkmarkImage);
  231. }
  232. })(i);
  233. }
  234. if (!mxClient.IS_QUIRKS)
  235. {
  236. parent.div.style.overflowX = 'hidden';
  237. parent.div.style.overflowY = 'auto';
  238. parent.div.style.maxHeight = '100%';
  239. // Workaround for document scrollbars with 100% max height in Chrome
  240. parent.div.style.marginBottom = '-20px';
  241. }
  242. }
  243. })));
  244. ui.actions.addAction('speechQuit', function()
  245. {
  246. // Hides UI
  247. speechOutputEnabled = false;
  248. menu.style.display = 'none';
  249. td.style.display = 'none';
  250. });
  251. var menu = ui.menubar.addMenu('Voice', function(menu, parent)
  252. {
  253. ui.menus.addSubmenu('voiceType', menu, parent);
  254. ui.menus.addMenuItems(menu, ['-', 'speechOutput', 'speechHint', '-', 'speechListen',
  255. 'speechListenContinuous', '-', 'speechInstalled',
  256. 'speechHelp', '-', 'speechQuit']);
  257. });
  258. // Inserts voice menu before help menu
  259. var menu = menu.parentNode.insertBefore(menu, menu.previousSibling.previousSibling.previousSibling);
  260. function insertShape(shape, done)
  261. {
  262. var searchTerm = mxUtils.trim(shape);
  263. ui.sidebar.searchEntries(searchTerm, 1, 0, function(results, len, more)
  264. {
  265. if (results.length > 0)
  266. {
  267. var elt = results[0]();
  268. // Click is blocked, must use mousedown/-up sequence
  269. // LATER: Use touchstart or pointerEvents depending on system
  270. dispatchEvent(elt, mouseEvent('mousedown', 1, 50, 1, 50));
  271. dispatchEvent(document.body, mouseEvent('mouseup', 1, 50, 1, 50));
  272. }
  273. else
  274. {
  275. App.say('{1} not found', [searchTerm]);
  276. }
  277. if (done != null)
  278. {
  279. done();
  280. }
  281. });
  282. };
  283. // http://stackoverflow.com/questions/11919065/sort-an-array-by-the-levenshtein-distance-with-best-performance-in-javascript
  284. //http://www.merriampark.com/ld.htm, http://www.mgilleland.com/ld/ldjavascript.htm, Damerau–Levenshtein distance (Wikipedia)
  285. var levenshteinDist = function(s, t) {
  286. var d = []; //2d matrix
  287. // Step 1
  288. var n = s.length;
  289. var m = t.length;
  290. if (n == 0) return m;
  291. if (m == 0) return n;
  292. //Create an array of arrays in javascript (a descending loop is quicker)
  293. for (var i = n; i >= 0; i--) d[i] = [];
  294. // Step 2
  295. for (var i = n; i >= 0; i--) d[i][0] = i;
  296. for (var j = m; j >= 0; j--) d[0][j] = j;
  297. // Step 3
  298. for (var i = 1; i <= n; i++) {
  299. var s_i = s.charAt(i - 1);
  300. // Step 4
  301. for (var j = 1; j <= m; j++) {
  302. //Check the jagged ld total so far
  303. if (i == j && d[i][j] > 4) return n;
  304. var t_j = t.charAt(j - 1);
  305. var cost = (s_i == t_j) ? 0 : 1; // Step 5
  306. //Calculate the minimum
  307. var mi = d[i - 1][j] + 1;
  308. var b = d[i][j - 1] + 1;
  309. var c = d[i - 1][j - 1] + cost;
  310. if (b < mi) mi = b;
  311. if (c < mi) mi = c;
  312. d[i][j] = mi; // Step 6
  313. //Damerau transposition
  314. if (i > 1 && j > 1 && s_i == t.charAt(j - 2) && s.charAt(i - 2) == t_j) {
  315. d[i][j] = Math.min(d[i][j], d[i - 2][j - 2] + cost);
  316. }
  317. }
  318. }
  319. // Step 7
  320. return d[n][m];
  321. }
  322. function naiveHammingDistance(str1, str2) {
  323. var dist = 0;
  324. str1 = str1.toLowerCase();
  325. str2 = str2.toLowerCase();
  326. for(var i = 0; i < str1.length; i++)
  327. {
  328. if (str2[i] && str2[i] !== str1[i])
  329. {
  330. dist += Math.abs(str1.charCodeAt(i) - str2.charCodeAt(i)) + Math.abs(str2.indexOf( str1[i] )) * 2;
  331. }
  332. else if (!str2[i])
  333. {
  334. // If there's no letter in the comparing string
  335. dist += dist;
  336. }
  337. }
  338. return dist;
  339. };
  340. function getBestWord(str1, words, useLevenshteinDist)
  341. {
  342. useLevenshteinDist = (useLevenshteinDist != null) ? useLevenshteinDist : true;
  343. var bestWord = words[0];
  344. var minDist = ((useLevenshteinDist) ? levenshteinDist(str1, bestWord) :
  345. naiveHammingDistance(str1, bestWord));
  346. for (var i = 1; i < words.length; i++)
  347. {
  348. var tmp = ((useLevenshteinDist) ? levenshteinDist(str1, words[i]) :
  349. ((str1 == words[i]) ? 0 : naiveHammingDistance(str1, words[i])));
  350. if (tmp < minDist || (tmp == minDist &&
  351. str1.length > bestWord.length &&
  352. bestWord.length < words[i].length))
  353. {
  354. bestWord = words[i];
  355. minDist = tmp;
  356. }
  357. if (bestWord == str1)
  358. {
  359. break;
  360. }
  361. }
  362. return bestWord;
  363. }
  364. function mouseEvent(type, sx, sy, cx, cy, shift)
  365. {
  366. var evt;
  367. var e = {
  368. bubbles: true,
  369. cancelable: (type != "mousemove"),
  370. view: window,
  371. detail: 0,
  372. screenX: sx,
  373. screenY: sy,
  374. clientX: cx,
  375. clientY: cy,
  376. ctrlKey: false,
  377. altKey: false,
  378. shiftKey: (shift != null) ? shift : false,
  379. metaKey: false,
  380. button: 0,
  381. relatedTarget: undefined
  382. };
  383. if (typeof( document.createEvent ) == "function")
  384. {
  385. evt = document.createEvent("MouseEvents");
  386. evt.initMouseEvent(type,
  387. e.bubbles, e.cancelable, e.view, e.detail,
  388. e.screenX, e.screenY, e.clientX, e.clientY,
  389. e.ctrlKey, e.altKey, e.shiftKey, e.metaKey,
  390. e.button, document.body.parentNode);
  391. }
  392. else if (document.createEventObject)
  393. {
  394. evt = document.createEventObject();
  395. for (prop in e)
  396. {
  397. evt[prop] = e[prop];
  398. }
  399. evt.button = { 0:1, 1:4, 2:2 }[evt.button] || evt.button;
  400. }
  401. return evt;
  402. };
  403. function dispatchEvent (el, evt)
  404. {
  405. if (el.dispatchEvent)
  406. {
  407. el.dispatchEvent(evt);
  408. }
  409. else if (el.fireEvent)
  410. {
  411. el.fireEvent('on' + type, evt);
  412. }
  413. return evt;
  414. };
  415. var keyHandlerEscape = ui.keyHandler.escape;
  416. ui.keyHandler.escape = function(evt)
  417. {
  418. if ((!mxClient.IS_MAC && mxEvent.isAltDown(evt)) ||
  419. ((mxClient.IS_MAC || chromeOs) && mxEvent.isControlDown(evt)))
  420. {
  421. if (speechOutputEnabled)
  422. {
  423. App.say('Speech output disabled');
  424. }
  425. speechOutputEnabled = !speechOutputEnabled;
  426. if (speechOutputEnabled)
  427. {
  428. App.say('Speech output enabled');
  429. }
  430. mxEvent.consume(evt);
  431. }
  432. else if (mxEvent.isShiftDown(evt))
  433. {
  434. App.sayHint();
  435. mxEvent.consume(evt);
  436. }
  437. else
  438. {
  439. keyHandlerEscape.apply(this, arguments);
  440. }
  441. };
  442. ui.keyHandler.bindAction(32, true, 'speechListen'); // Ctrl+SPACE
  443. ui.keyHandler.bindAction(79, true, 'speechListenContinuous'); // Ctrl+O
  444. /**
  445. * Plays a beep.
  446. */
  447. var beep = new Audio('data:audio/wav;base64,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qJrx4KOQjahZxWbcZgztj2c49nKmkId44S71j0c8eV9yDK6uPRzx5X18eDvjvQ6yKo9ZSS6l//8elePK/Lf//IInrOF/FvDoADYAGBMGb7FtErm5MXMlmPAJQVgWta7Zx2go+8xJ0UiCb8LHHdftWyLJE0QIAIsI+UbXu67dZMjmgDGCGl1H+vpF4NSDckSIkk7Vd+sxEhBQMRU8j/12UIRhzSaUdQ+rQU5kGeFxm+hb1oh6pWWmv3uvmReDl0UnvtapVaIzo1jZbf/pD6ElLqSX+rUmOQNpJFa/r+sa4e/pBlAABoAAAAA3CUgShLdGIxsY7AUABPRrgCABdDuQ5GC7DqPQCgbbJUAoRSUj+NIEig0YfyWUho1VBBBA//uQZB4ABZx5zfMakeAAAAmwAAAAF5F3P0w9GtAAACfAAAAAwLhMDmAYWMgVEG1U0FIGCBgXBXAtfMH10000EEEEEECUBYln03TTTdNBDZopopYvrTTdNa325mImNg3TTPV9q3pmY0xoO6bv3r00y+IDGid/9aaaZTGMuj9mpu9Mpio1dXrr5HERTZSmqU36A3CumzN/9Robv/Xx4v9ijkSRSNLQhAWumap82WRSBUqXStV/YcS+XVLnSS+WLDroqArFkMEsAS+eWmrUzrO0oEmE40RlMZ5+ODIkAyKAGUwZ3mVKmcamcJnMW26MRPgUw6j+LkhyHGVGYjSUUKNpuJUQoOIAyDvEyG8S5yfK6dhZc0Tx1KI/gviKL6qvvFs1+bWtaz58uUNnryq6kt5RzOCkPWlVqVX2a/EEBUdU1KrXLf40GoiiFXK///qpoiDXrOgqDR38JB0bw7SoL+ZB9o1RCkQjQ2CBYZKd/+VJxZRRZlqSkKiws0WFxUyCwsKiMy7hUVFhIaCrNQsKkTIsLivwKKigsj8XYlwt/WKi2N4d//uQRCSAAjURNIHpMZBGYiaQPSYyAAABLAAAAAAAACWAAAAApUF/Mg+0aohSIRobBAsMlO//Kk4soosy1JSFRYWaLC4qZBYWFRGZdwqKiwkNBVmoWFSJkWFxX4FFRQWR+LsS4W/rFRb/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////VEFHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU291bmRib3kuZGUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMjAwNGh0dHA6Ly93d3cuc291bmRib3kuZGUAAAAAAAAAACU=');
  448. var beep2 = new Audio('data:audio/wav;base64,UklGRg8VAABXQVZFZm10IBAAAAABAAEAESsAACJWAAACABAAZGF0YesUAAAAAAAAAAAAAAAAAAAAAAAAAAA1/0/+xP05/Vr8jfoy9uT0gvWY96/4xfnc+vP7jv0w/yoBnQSUBiII4wlrEPsT8BVkF3kTTxAhDvQLxgigBegCLwCQ+8z2QvRZ8+vwMO0D6/LpMOuG77Pxy/QZ+HX6+fyvAEIFbwevCrUObRNbFkIZABvTGAgWIRMOEFcL7AcUBVwC2/zR+Or1A/NQ7jTqTedm5ILlaehQ6zfuh/J99zX6E/0fAaAGhwluDCsQ+RUjGQoc1R16GUAWexJyDYsKowftA/L9r/rg98L09O5T62zoheUP5ErlMegY637w5vTI94H6dv9BBCgHPAqADh0TBBbrGCkbRRxeGXcWoRLTDMIJ2wZpA5z9J/pA9zv0J++L623ozOSA5BLmculA737yLvUs+Cj+IgL9BLUH3Qz/EOYTzRboG2QefRuWGN8TyA7hC/oIvQRt/4b8wfkQ9p/wqu3D6mDnTOLz49rm+uls7xDz9/Xe+In+qwKSBXkIdA3HEa4UlRd6G5wdtRocFRoRgA6ZC2QGywHj/s37C/dK8r/v4ex06GXjq+K85MXoie4T8djzcfcR/UwAMwNvBg8MqA+PEnYVOxuAHdQc7RmMFEsQuA3QCtMFAgEc/jX7nPZ68fDuGezk547iSOOH52vsUu+L8cD1B/vu/dQA9wSiCokNcBAvFP0ZJh25HZcbyRU9EnsP4AxAB2EDegCU/UP4BvQf8TjuIelq5IPh8+IY5zPsGu8B8jr2lPuq/p0BiAVWC1IOyhDAE44Z7hwqHEMXXBR1EdkNxQjABdkCZf+X+SX2PvMt8F/qieai47vg2uUV6vzs4+8T9Z75WPw//+wDzAizC0cOghLoF88ath1EHXsXlBStEQwOPgggBToC1f4H+V31uPKL8M7qwOaq5GTl9ufd6v/tcPMS9/n54PyNAq0GlAl7DHkRyRWwGJcbgBuaGbMWzBN9D3UKYAdvBFEApPrs9xT1dPED7N/o+OXU4wHmvuil65buB/S994H6aP0GA3UHXApDDRASkRZ5GWAcuBvRGOoV1xCcDLUJzgbPAQH9Gvoz987y5e3+6hfohOW445/mhukf7TPyO/U9+NL7oAEXBeoHygqYEHMUWhdBGtQb8BoJGCIVPxDUC+4INQZ+AXn8kvmB9jbyHe026h3lDeKA42jmkOsI8TbzBPZV+tL/uAKfBYwJWg+fEaoUxRiTHg8dKBoCFzQR9g2MC6UI0AKY/rr7AfnE8zvvVOxt6YzkYuFJ5DDnrev+8OXzzPbS+lkAQAMJBoMJ9A4cEgMVVRgjHkcdQBl5E5EQqg0HCjkE9QAP/tD6AvXk8XPvjOwT5p/iKuIR5XDqs+5G8S30KPn7/eEA9QOECIQNDhDlEhgXmRwNHn4crxjhEskP4gx/Cd8DbQCH/YL64vRQ8avuxOs55h7jZOMy6cDsg+8c8ur33fvE/qoBIgd4C1MO3RDaFZQaex2AHe0ZzxToEVEPNAuzBcwC5v/9+y/2MfOA8EXtd+cV5NXi9ePD6YntUvDc8k/4ZfxM/zICTQfAC6cOjhFrFlwbQx6AGu4WBxQgETsM0gfrBAQCO/02+E/1aPIy7hrpM+ZM43Djg+hq61HuwvHW9gb67fwnAPUFoQmIDG8PLRU9GSQcCx+aGiYWPhNXEKMLGQdgBHsBBf3u9wf1IPLy7VLoa+WA5GTlS+gy67LvAPXn96n6vf6bBIIHaQrtDQITHxYGGYAbgBu1GF0VbxJbDagJwQbaA2j+Dfom9z/0L+9x6orno+Rj5CzmE+n660LwxPV9+Ff7O/8IBd4HsgofDpAT5xZ1GkoeYxt8GKoU3A7HC/oIsgXl/0b8RflE9i/xkO2p6sLnMeQO5PXm3Om97irzEfb4+L39xQKsBZMIxQzhEcgUrxeWGn0dmxq0FzAUvw5/C4EIJwWI/+P7/PgV9rbwx+xA6XLjHOPW5Pnnx+1K8fLz2faA/IwAVgNrBmsLcg+pEZAUbxkQHZ0b0xhXFCMP9gw2CkUG6gAy/lv7tfcV8o3v/+yw6eHjKeSe5onp+u6Z8iP1rfcQ/VcBEATJBoML6Q9zEnsXQBsCHdUalRVPEcUOOgyfBxcDXgCm/Vv5bPSF8eruP+tQ5mnjf+RM6Bruh/Ab82z2r/vs/qMBdgS5CS4NuA9DEsIXRBsQHCkZlBSkEHQOjQslB4sC0/8b/Rv5L/Sl8fDss+iG5hDlneda7PvvDvJu9Ub6//yW/+8C1AdzCv0M/A+0FOkX1BkeGgoVehHODqEM5AdSBMgBPv/O+hL34PRW8pTupuq/5yvo2Oro7nLxtPPV9lD7q/0GAPgCgQdDCrsNyhH4EyUWZxaAE1IRJQ9wDBUInQVwAwEBefzL+bz3jvX38TTvB+3Z6vHsV+8w8V3z0vY3+mX8kv7iAaIFoQfGCW0MoQ/OEfsTnhS3EXwPTw3bCgwHrAStApwAoPzx+Zj3VPQL8g7wZu6s7SvvWPGJ8yr3iPlC+0H9rABmAzcFBwfrCcoM9w7JEIARABHTDvUMdQpYB7YF8wOGAeb9A/xO+lf4E/UB84TxgPCA8MHxdfPo9A74afoL/K39wQBwAxIFtAZNCQUM1Q2mD+sPuA7oDEAK2gc4BpYEBgJT/7H9OPwI+lH33fUk9FTyg/CV8R7zMfUY+MD5SvsS/SYADQKAA/QEdQdbCc4KQgwDDlYO4gxvCxgJyAZUBeEDtQE7/8f9VPxo+u33efZK9IDygPKA85L1LvhE+aT6m/xL/70AEwKwAzoGeQe/CFkK4wyADfIMfQvzCDQH7wWqBEsCSQDc/pf9Qfsd+Qf4lfZ69JXy8vI69C/2nfji+Sf75/yg//UAOgLJA4EG5AeeCRcMig2ADTgMrgknCOYGiAXPAj0B+f+m/u77Kvrl+KD3ifW986nywPP09e33BflK+l38lP7Z/x0BBQNnBawGzwdtCfcLbg0dDWkL3wiSB2UGAQV2AtYAkv9N/s/7A/p6+PD1mvSD86/yOfUC90r4Mvmi+3b9xP42AIoCigTNBeMG0wjrCl8MKQ3yC1QJPQgnB44FOAPzAa4AIP/E/GD7G/q3+Ir26fTe84HzCfat98T42vkx/Af+I/9nAJkCoQS4BQoIpQnQCkMMlguACmEJ7gf4BRYE0QK4Ac//g/09/Pj6Ovnx9tr1xPRU9Gv1gfax9yT5gPsA/Ub+k//uAZQD2QQeBgoIkAm0CicMZAvxCX4IlgfEBa4DaQJNAZb/W/0W/Cb6TPgH9+/1EPW/9Nb1O/fw+N76I/xH/cr+JQF2ArsDJgUlB7EI+wkGC2ILwAqpCZMITQalBIcDQgIeAEz+M/3u+w/6Mfgb97D1MvWq9cH22PdK+Ub7i/yy/R3/eAG1AlgEXQZFB5UITQp6DGsLVQryCJYGUQU6BAMDpwA3/yH+Cv26+jj5Rvgw9zH1f/SV9az2pfiZ+rD7x/yU/rMAygHgAm4EjQakB7sICArYCwAL6gmfCEQG5gTPA7IChAAM/6v9fftI+kn5NvgI9jr1avWA9n/47vkE+xv8I/7I/94A9QHXA6IFuQaiB0wJFAtxC5UK/gjoBtEFuwRJAxsB+P/h/pX9Z/sd+gf53/ey9QD1VfVs9oT4Gfow+0b8Of7z/xMBQAO2BM0F5AahCBEK8gqVCtUIJgc9BlUFoAPFAd0Azf8s/iX8Pfsy+rb4ifbK9bn1dfZ0+Ib5hPq1++L9J/8eADQBVgPGBLgFzwZ/CPwJ8wo5Cr8IKAcSBicFigOWAa4Aov8V/vT73vpL+bD3mvaD9Sn2JPgM+fT5S/tG/Vz+Vf+GAIQCtgO1BLsFiwfQCOcJ/grWCI0HvQanBcgDUAJjAUwAjv7w/Aj88/pu+cX3r/bm9X/2j/hJ+UT6pfuk/Zz+nv/fAN4C+wNcBUwHNAg8CeQJhwmACIIHZQY4BAkDDgLyACP/6v31/N77IfrJ+Nr3xPYO99n3wfjY+WP7+vzi/cr+OgAaAgIDDARlBTUHIwjvCFYJnQi8B9MG1wUGBNsC4wHNAAb/u/2c/J36gvmv+O/32PY/9zn48/iw+hr8KP0R/tb/YAFIAjADsgROBmUHJwiwCOQIKghNBwoGPQRUA2wCSAF5/3X+jP2I/Lj6lPm9+AP4pffy97b4nvlN+6/8l/1//g0AjwF3Aj4EhwVvBlgHAAmsCesI1QdeBvYEDgQmA7wBFQAu/0b++/w2+036ZflH+KX2Kvf99wn52fr1+938yv1s/5UAfQFlAvIDNgUeBgYHeggXCQAIdQcgBogEnwPfAp8B6P8A/5D9L/xH+4z6SPnY9x/3nPfW+JD6Sfsk/Ff9KP8bAOkA2AGoA5YEZAVXBvkHvgjICA4IfgZBBWEEpwMSAqAAu/8B/5H9AfwY+1r6QPnz95f3Mvhh+QL7u/uS/Kn9S/8hAE4B2gLDA4gElgU4ByMIgAghCIAGogXoBBoEeAJaAXIAi//x/dX8G/xi++n5rvgA+AD4IPl6+jT77fso/an+kf9UAG8BCQPxA7sEtgVYBygITgjBBx8GMAV2BLkDFwIJARMAcv6d/eP8Evyf+pP5vPgC+BX5D/rs+qb7//wZ/tj+wP8MAU8COAPzAxoFZgYgBwEI7AeuBsYF/gQJBJYCpQHXAPz/iP6F/bH87vt6+mT5mPgM+Cr5PfoX+6L7B/1e/kr/vAC4AXECKwNhBF8FGAbSBgAHuQYABkYFGATSAhgCXwFKAOz+Mv55/X38CvtL+pL5C/k5+d35lvpg+9P8xP19/jf/oACqAWMCHQNvBJEFSwYEBwAHhwbNBRQF9AOgAuYBmgB0/7r+AP7N/I370/oZ+kf5qfi/+Y/6fvvC/Hz9Nv4T/1cAIgHcAaYC6wPJBIMFPQb2Bs8GFQZbBSsEKANuArQBlwCC/8j+Dv4E/dv7Iftn+sL5TfkH+sH6pvvr/K79tf7i/5oAVAFJAogDQQT7BN0FIgcVB50GxwVTBHADyAI5AvQACABc/9H+of2i/O/7Y/tN+qP5APqL+on7ovwt/eD93f4TAMwAZQEwAnUDBgStBIUFygaLBgAGZgUhBD0DkwIHAs0A1/8E/779EP1w/K/7avqi+Wr59fkr+yX81/xi/X/+jP9DAM8AtQGlAjED5gPPBNMFXgYWBkQF/wN0A+gCLwLqAEYAvP8c/9f9Gv2P/AT88Pot+ur5o/qs+4H8Ef3L/cb+r/85AHUBUALbAmYDigR9BQIGMQaBBZUECgRTA2YCaAHcACwATf87/rD9Jf1l/CD7g/oo+jD6dftP/Pf8hP2b/ln/5P9vAHQBRQLQAlwDTwQyBb4FwAUWBR8ElAMJAzsCMgGnALj/0f5G/rr93vzk+1j7zfrU+ov7Fvyh/Fj9b/4D/47/MgBJAe8BewIKA/MDnQQ1Be8FLAV1BOoDXgNnAogB/ABxAKv/2/5Q/sX9Cv0u/KP7GPsY+wD8i/z6/IT9mv4R/8f/zgBaAcMBYQJ4AwcEdwTKBPgEiwQABG0DhALeAVIBxwDl/zH/pv4b/kT9hPz7+577gPuc+/n7gfw//Rj+o/4u/+D/xABPAbwBPwIoA7wDMASABIAEFQScAz4DVgKoAQUBHQCw/zz/pv69/Tz9zvxD/Ir7lfsV/HL8Rf0C/on+5v6m/24A+QBYAQYC2wJnA8wDUgT2BGsEAAR4A48C/gGMARcBLwCR/xr/t/7P/ST9pvxJ/ML7svsV/KH8dP03/sP+ff8YAJgA9ACjAS4CkQIcA8oDQARABOMDMQNqAg0CsAEnAXIA5/99//H+CP6n/Ur92vwg/AD8K/yS/Hr9Af5e/rv+m/80AJEA7gC7AWcCxAIhA9wDcgRDBOoDQwNxAhQCSgGaAD0A4f9I/6j+S/7u/WH9tPxX/GT8x/yA/d39Ov6u/mj/0f8tAJQATgHDASACfQI1A7cD9QPHA/wCVQL8Ac0BPAGhAEQA6P9W/6/+Uv71/W/9u/xe/ID8+fyz/Rb+pv5Q/63/CQCMAEMBoAH8AXMCLQOTA9gD5QMrA7gCSgK+ATMBxQBoAAsAh/8S/7X+Wf7Z/V/9Av3T/DH9y/36/U/+2P6F/7P/AgB+ADgBbAG1ASUC3wImA1QDcwO5Al8CBQJMAekApgBeAKb/Nv/t/rj+//2D/TP9Bf0r/XL9z/0s/qz+Jf+C/9//WQDMAPoAUgHGAUUCdALFAt0CgAJRAgYCngETAdgAkwAxAKf/X/8g/8P+Ov7l/a39UP2O/ev9S/7X/iH/Xv+7/0MAmgDRAC4BsAEUAkQCoQLAArICgwIqArQBOAEKAbcARwC//5H/RP/0/sX+bf4p/gD+AP4k/lL+gf4M/17/jP+6/zkAlgDFAPMAZgHQAf4BLQJAAjUCBwLYAX8B+wDNAH4AIQDF/5T/MP+3/on+Wv4Y/sP98v0g/mv+9v4s/1r/mP8jAGQAkwDFAFABngHNAfsBUwJnAjkCCgKUAS0B/gChAEUA9f/G/5j/Uv/7/sz+nv5w/kH+bv6d/tb+M/9o/63/BAAyAGEAnwD8ACwBWwGTAfABAALrAbkBXAEfAfEAwgBoACYA+P/K/3b/Lf/+/tD+gv5A/kD+a/6y/gj/Nv9l/6b/AQAvAF0AjAC6AOkAFwFGAXQBgAFuAUABEQHjALQAhgBXACkA/P/N/5//cP9C/xP/5f7A/sD+Dv9A/0T/c//C/wAAAAArAHQAwADAAOUAKAGAAYABgAFkAQcBAAHmALAAUwBAACwA/v+h/4D/dP9F/0D/QP9A/0D/ZP+A/4H/r//e/wAAAAAoAFYAgACAAKIA0AD/AAAB4wDAAMAAmABqAEAAQAAeAPH/w//A/6b/gP+A/1r/QP9E/3L/gP+P/73/7P8AAAgANgBlAIAAgQCwAN4AAAEAAQAB5wDAAMAAnABtAEAAQAAiAAAAAAAAAOn/wP/A/8D/wP/A/8D/wP/L//r/AAAAAAQAMwBAAEAAQABsAIAAgACAAIAAgACAAIAAXwBAAEAAQAAlAAAAAAAAAO3/wP/A/8D/wP/A/8D/2f8AAAAAAAASAEAAQABAADMABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACM');
  449. App.beep = function(wav)
  450. {
  451. wav = (wav != null) ? wav : beep;
  452. wav.play();
  453. };
  454. // Thread to reset the label
  455. var resetStatus = null;
  456. /**
  457. *
  458. * Static method for speech output.
  459. */
  460. App.say = function(message, params)
  461. {
  462. if ('speechSynthesis' in window && message != null)
  463. {
  464. var text = mxResources.replacePlaceholders(message, params || []);
  465. lastMessageTimestamp = null;
  466. lastMessage = text;
  467. if (text != null && text.length > 0)
  468. {
  469. if (td != null)
  470. {
  471. var tmp = text;
  472. // Capitalize string
  473. if (tmp != null && tmp.length > 1)
  474. {
  475. tmp = tmp.charAt(0).toUpperCase() + tmp.slice(1);
  476. }
  477. td.innerHTML = ((speechOutputEnabled) ? '<img style="margin-right:4px;" align="absmiddle" border="0" src="' +
  478. outputImage + '"/>' : '') + ' ' + tmp;
  479. td.style.color = '#235695';
  480. if (resetStatus != null)
  481. {
  482. window.clearTimeout(resetStatus);
  483. resetStatus = null;
  484. }
  485. resetStatus = window.setTimeout(function()
  486. {
  487. updateStatusMessage();
  488. }, (recognizing != null) ? 1000 : 3000);
  489. }
  490. // Workaround for talking too much
  491. if (speechOutputEnabled && (!speechSynthesis.speaking || !speechSynthesis.pending))
  492. {
  493. if (text.length < maxMessageLength)
  494. {
  495. var msg = new SpeechSynthesisUtterance();
  496. // Picks random voice with same main locale
  497. var voices = speechSynthesis.getVoices();
  498. // Say "again" for same last message except more than 10 secs ago or shorter than again
  499. if (lastMessageTimestamp != null && text == lastMessage && text != null &&
  500. text.length > 5 && lastMessage != 'again')
  501. {
  502. if (lastMessageTimestamp != null &&
  503. new Date().getTime() - lastMessageTimestamp.getTime() < 10000)
  504. {
  505. text = 'repeat';
  506. }
  507. }
  508. msg.voice = voices[currentVoice];
  509. msg.voiceURI = 'native';
  510. //msg.lang = lang;
  511. msg.text = text;
  512. console.log('App.say speak:', msg.text);
  513. speechSynthesis.speak(msg);
  514. lastMessageTimestamp = new Date();
  515. }
  516. else
  517. {
  518. console.log('App.say ignored:', text);
  519. }
  520. }
  521. else
  522. {
  523. console.log('App.say skipped:', message);
  524. }
  525. }
  526. }
  527. };
  528. /**
  529. * Static method for speech output.
  530. */
  531. App.listen = function(continuous)
  532. {
  533. if ('webkitSpeechRecognition' in window && speechInputEnabled)
  534. {
  535. if (recognizing != null)
  536. {
  537. recognizing.stop();
  538. }
  539. else
  540. {
  541. var recognition = new webkitSpeechRecognition();
  542. recognition.interimResults = true;
  543. // TODO: Should use grammar instead of trying more alternatives
  544. recognition.maxAlternatives = 5;
  545. recognition.lang = lang;
  546. if (continuous != null)
  547. {
  548. recognition.continuous = continuous;
  549. }
  550. recognition.onstart = function(event)
  551. {
  552. updateStatusMessage();
  553. App.beep();
  554. };
  555. recognition.onresult = function(event)
  556. {
  557. for (var i = event.resultIndex; i < event.results.length; ++i)
  558. {
  559. if (td != null)
  560. {
  561. td.innerHTML = '<img style="margin-right:4px;" align="absmiddle" border="0" src="' + micImage +
  562. '"/> ' + event.results[i][0].transcript;
  563. td.style.color = (event.results[i].isFinal) ? '#235695' : 'darkGray';
  564. }
  565. if (event.results[i].isFinal)
  566. {
  567. var ok = false;
  568. for (var j = 0; j < event.results[i].length; j++)
  569. {
  570. if (App.executeVoiceCommand(event.results[i][j].transcript, recognition))
  571. {
  572. ok = true;
  573. break;
  574. }
  575. }
  576. if (!ok)
  577. {
  578. App.say('{1} not found', [event.results[i][0].transcript]);
  579. }
  580. if (td != null)
  581. {
  582. if (resetStatus != null)
  583. {
  584. window.clearTimeout(resetStatus);
  585. resetStatus = null;
  586. }
  587. resetStatus = window.setTimeout(function()
  588. {
  589. updateStatusMessage();
  590. }, 1000);
  591. }
  592. }
  593. }
  594. };
  595. recognition.onend = function(event)
  596. {
  597. // Overrides footer
  598. recognizing = null;
  599. updateStatusMessage();
  600. App.beep(beep2);
  601. };
  602. recognition.start();
  603. recognizing = recognition;
  604. }
  605. }
  606. else
  607. {
  608. speechOutputEnabled = !speechOutputEnabled;
  609. lastMessageTimestamp = null;
  610. App.say(lastMessage || 'Ready');
  611. lastMessageTimestamp = null;
  612. }
  613. };
  614. /**
  615. * Executes the given voice command.
  616. */
  617. App.executeVoiceCommand = function(command, recognition)
  618. {
  619. console.log('App.execute:', mxUtils.trim(command));
  620. var tokens = mxUtils.trim(command).split(' ');
  621. if (tokens.length > 0 && graph.isEnabled())
  622. {
  623. // Ask for Mic permissions
  624. // FIXME: Dialog seems to be hidden until tab is changed
  625. function resolveStylename(token, styles)
  626. {
  627. var tmp = token.toLowerCase().replace(/ /g, '');
  628. var style = null;
  629. for (var i = 0; i < styles.length; i++)
  630. {
  631. if (styles[i].toLowerCase() == tmp)
  632. {
  633. style = styles[i];
  634. break;
  635. }
  636. }
  637. return style;
  638. };
  639. // Main command
  640. tokens[0] = tokens[0].toLowerCase();
  641. // TODO: Use hamming distance for best match command but include all possible actions
  642. // which might be too slow
  643. // console.log('connect', naiveHammingDistance(tokens[0], 'connect'), naiveHammingDistance('disable', 'connect'), naiveHammingDistance('change', 'connect'));
  644. if (graph.isEditing())
  645. {
  646. if (tokens.length == 1 && tokens[0] == 'apply')
  647. {
  648. graph.stopEditing();
  649. }
  650. else if (tokens.length == 1 && tokens[0] == 'undo')
  651. {
  652. document.execCommand('undo', false, null);
  653. }
  654. else if (tokens.length == 1 && tokens[0] == 'redo')
  655. {
  656. document.execCommand('redo', false, null);
  657. }
  658. else
  659. {
  660. document.execCommand('insertHTML', false, command);
  661. }
  662. return true;
  663. }
  664. else if (tokens[0] == 'edit' && tokens[1] == 'text')
  665. {
  666. var cells = graph.getSelectionCells();
  667. if (cells.length == 1)
  668. {
  669. graph.startEditingAtCell(cells[0]);
  670. }
  671. return true;
  672. }
  673. else if (tokens[0] == 'hello' || tokens[0] == 'hi')
  674. {
  675. App.say('Hello! Try "Help", "Help Topic" or "Quick Start".');
  676. return true;
  677. }
  678. else if (tokens[0] == 'help')
  679. {
  680. var wnd = window.open('https://support.draw.io/questions/9666655/how-to-use-the-voice-plugin');
  681. if (wnd == null)
  682. {
  683. App.say('Popup blocked');
  684. }
  685. else if (tokens.length > 1)
  686. {
  687. // Just used to check if popup windows are allowed
  688. wnd.close();
  689. var searchTerm = mxUtils.trim(command.substring(tokens[0].length));
  690. if (searchTerm != null && searchTerm.length > 0)
  691. {
  692. var form = document.createElement('div');
  693. form.style.display = 'inline';
  694. form.innerHTML = ':<form style="display:inline;margin-left:8px;" id="rw_search_form"' +
  695. 'target="_blank" method="get" action="https://support.draw.io/dosearchsite.action">' +
  696. '<input id="rw_search_query" type="text" name="queryString" size="25"></form>';
  697. var realForm = form.getElementsByTagName('form')[0]
  698. var input = form.getElementsByTagName('input')[0];
  699. input.setAttribute('value', searchTerm);
  700. realForm.submit();
  701. App.say(command);
  702. }
  703. }
  704. else
  705. {
  706. App.say('help');
  707. }
  708. return true;
  709. }
  710. else if ((tokens[0] == 'info' && tokens.length == 1) || mxUtils.trim(command).toLowerCase() == 'what\'s this')
  711. {
  712. App.sayHint();
  713. return true;
  714. }
  715. else if (tokens[0] == 'install' && tokens.length == 1)
  716. {
  717. setPluginInstalled(true);
  718. App.say('Installed');
  719. return true;
  720. }
  721. else if (tokens[0] == 'uninstall' && tokens.length == 1)
  722. {
  723. setPluginInstalled(false);
  724. App.say('Uninstalled');
  725. return true;
  726. }
  727. else if (tokens[0] == 'quick' && tokens.length > 0 && tokens[1].toLowerCase() == 'start')
  728. {
  729. var wnd = window.open('https://youtu.be/8OaMWa4R1SE?t=1');
  730. if (wnd == null)
  731. {
  732. App.say('Popup blocked');
  733. }
  734. return true;
  735. }
  736. else if (tokens[0] == 'search' && tokens.length > 1)
  737. {
  738. var searchToken = tokens.slice(1, tokens.length).join(' ').toLowerCase();
  739. var wnd = window.open('https://www.google.ch/search?q=' + encodeURIComponent(searchToken) + '&tbm=isch', 'voicePluginSearchResult');
  740. if (wnd == null)
  741. {
  742. App.say('Popup blocked');
  743. }
  744. return true;
  745. }
  746. else if (tokens[0] == 'shrink')
  747. {
  748. var cell = graph.getSelectionCell();
  749. var geo = graph.getCellGeometry(cell);
  750. if (graph.getModel().isVertex(cell) && geo != null)
  751. {
  752. geo = geo.clone();
  753. if (tokens.length == 1 || tokens[1] == 'height')
  754. {
  755. geo.height = graph.snap(Math.round(geo.height * 0.5));
  756. }
  757. if (tokens.length == 1 || tokens[1] != 'height')
  758. {
  759. geo.width = graph.snap(Math.round(geo.width * 0.5));
  760. }
  761. if (geo.width > graph.tolerance && geo.height > graph.tolerance)
  762. {
  763. graph.getModel().setGeometry(cell, geo);
  764. App.say('Resized');
  765. }
  766. else
  767. {
  768. App.say('Too small');
  769. }
  770. }
  771. else
  772. {
  773. App.say('No cell to resize');
  774. }
  775. return true;
  776. }
  777. else if (tokens[0] == 'double')
  778. {
  779. var cell = graph.getSelectionCell();
  780. var geo = graph.getCellGeometry(cell);
  781. if (graph.getModel().isVertex(cell) && geo != null)
  782. {
  783. geo = geo.clone();
  784. if (tokens.length == 1 || tokens[1] == 'height')
  785. {
  786. geo.height *= 2;
  787. }
  788. if (tokens.length == 1 || tokens[1] != 'height')
  789. {
  790. geo.width *= 2;
  791. }
  792. if (geo.width > graph.tolerance && geo.height > graph.tolerance)
  793. {
  794. graph.getModel().setGeometry(cell, geo);
  795. App.say('Resized');
  796. }
  797. else
  798. {
  799. App.say('Too small');
  800. }
  801. }
  802. else
  803. {
  804. App.say('No cell to resize');
  805. }
  806. return true;
  807. }
  808. else if (tokens[0] == 'width' || tokens[0] == 'with' || tokens[0] == 'height')
  809. {
  810. // Try numeric stylename if last token is numeric
  811. var lastToken = tokens[tokens.length - 1].toLowerCase();
  812. // Fixes some special cases for recoginition of short phrases
  813. // like "stroke width 2" where it tries to be clever
  814. if (lastToken == 'tool' || lastToken == 'tune' || lastToken == 'tomb' || lastToken == 'tube')
  815. {
  816. lastToken = '2';
  817. }
  818. else if (lastToken == 'd3')
  819. {
  820. lastToken = '3';
  821. }
  822. else if (lastToken == 'v')
  823. {
  824. lastToken = '5';
  825. }
  826. else
  827. {
  828. // Converts numeric words to numbers (system only seems to return written numbers for <= 4)
  829. var numbers = ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine'];
  830. var tmpIndex = mxUtils.indexOf(numbers, lastToken);
  831. if (tmpIndex >= 0)
  832. {
  833. lastToken = tmpIndex;
  834. }
  835. }
  836. var lastValue = parseFloat(tokens[1].toLowerCase());
  837. if (tokens.length >= 2 && !isNaN(lastValue))
  838. {
  839. var cell = graph.getSelectionCell();
  840. var geo = graph.getCellGeometry(cell);
  841. if (graph.getModel().isVertex(cell) && geo != null)
  842. {
  843. geo = geo.clone();
  844. if (tokens[0] == 'height')
  845. {
  846. geo.height = lastValue;
  847. }
  848. else
  849. {
  850. geo.width = lastValue;
  851. }
  852. graph.getModel().setGeometry(cell, geo);
  853. App.say('Resized');
  854. }
  855. else
  856. {
  857. App.say('No cell to resize');
  858. }
  859. }
  860. return true;
  861. }
  862. else if (tokens[0] == 'insert' && tokens.length > 1)
  863. {
  864. // Fixes some common mistakes
  865. if (tokens[1].toLowerCase() == 'edits')
  866. {
  867. tokens[1] = 'ellipse';
  868. }
  869. var searchTerm = mxUtils.trim(tokens.slice(1, tokens.length).join(' '));
  870. var current = graph.getSelectionCell();
  871. // Clears selection to disable built-in connecting
  872. graph.clearSelection();
  873. insertShape(searchTerm, function()
  874. {
  875. var cell = graph.getSelectionCell();
  876. // Connects dangling edge of previously selected edge and moves cell
  877. if (graph.model.isVertex(cell) && graph.model.isEdge(current) &&
  878. (graph.model.getTerminal(current, true) == null ||
  879. graph.model.getTerminal(current, false) == null))
  880. {
  881. var edgeState = graph.view.getState(current);
  882. var vertexState = graph.view.getState(cell);
  883. if (vertexState != null && edgeState != null && edgeState.absolutePoints != null &&
  884. edgeState.absolutePoints.length > 1)
  885. {
  886. var source = graph.model.getTerminal(current, true) == null;
  887. var pts = edgeState.absolutePoints;
  888. var pt = pts[(source) ? 0 : pts.length - 1];
  889. var loc = new mxPoint(vertexState.getCenterX(), vertexState.getCenterY());
  890. if (loc != null && edgeState != null)
  891. {
  892. var s = graph.view.scale;
  893. var dx = pt.x - loc.x;
  894. var dy = pt.y - loc.y;
  895. // TODO: Should add insert to transaction but need absolute position
  896. graph.model.beginUpdate();
  897. try
  898. {
  899. graph.moveCells(graph.getSelectionCells(), dx / s, dy / s);
  900. graph.model.setTerminal(current, cell, source);
  901. }
  902. finally
  903. {
  904. graph.model.endUpdate();
  905. }
  906. }
  907. }
  908. }
  909. });
  910. return true;
  911. }
  912. else if (tokens[0] == 'connect' || tokens[0] == 'kinect' || (tokens[0] == 'clone' && tokens.length > 1))
  913. {
  914. var cell = graph.getSelectionCell();
  915. if (graph.getModel().isVertex(cell))
  916. {
  917. // Uses east direction if token not understood
  918. var direction = mxConstants.DIRECTION_EAST;
  919. if (tokens.length > 1)
  920. {
  921. tokens[1] = tokens[1].toLowerCase();
  922. // Guessing direction based on minimum hamming distance for given set
  923. var guess = getBestWord(tokens[1], ['up', 'left', 'down', 'right', 'north', 'south', 'east', 'west']);
  924. if (guess == 'up' || guess == mxConstants.DIRECTION_NORTH)
  925. {
  926. direction = mxConstants.DIRECTION_NORTH;
  927. }
  928. else if (guess == 'left' || guess == mxConstants.DIRECTION_WEST)
  929. {
  930. direction = mxConstants.DIRECTION_WEST;
  931. }
  932. else if (guess == 'down' || guess == mxConstants.DIRECTION_SOUTH)
  933. {
  934. direction = mxConstants.DIRECTION_SOUTH;
  935. }
  936. }
  937. var length = graph.defaultEdgeLength;
  938. var cloneSource = tokens[0] == 'clone';
  939. var evt = mouseEvent('click', 1, 50, 1, 50, !cloneSource);
  940. var cells = graph.connectVertex(cell, direction, length, evt);
  941. graph.selectCellsForConnectVertex(cells, evt, ui.hoverIcons);
  942. }
  943. return true;
  944. }
  945. // Fixes drive and ride common mistakes for right
  946. else if (mxUtils.indexOf(['and', 'drive', 'ride', 'move', 'up', 'left', 'down', 'right', 'north', 'south', 'east', 'west', 'downright'], tokens[0]) >= 0)
  947. {
  948. var cell = graph.getSelectionCell();
  949. if (!graph.isSelectionEmpty())
  950. {
  951. // Uses east direction if token not understood
  952. var dx = 0;
  953. var dy = 0;
  954. for (var i = 0; i < tokens.length; i++)
  955. {
  956. tokens[i] = tokens[i].toLowerCase();
  957. var direction = null;
  958. // Downright is a single word needs special handling
  959. if (tokens[i].toLowerCase() == 'downright')
  960. {
  961. dx += graph.defaultEdgeLength;
  962. dy += graph.defaultEdgeLength;
  963. }
  964. else
  965. {
  966. var guess = null;
  967. // Guessing direction based on minimum hamming distance for given set
  968. // Handle some common cases
  969. if (tokens[i] == 'drive' || tokens[i] == 'ride')
  970. {
  971. guess = 'right';
  972. }
  973. else
  974. {
  975. guess = getBestWord(tokens[i], ['move', 'and', 'up', 'left', 'right', 'north', 'south', 'east', 'west', 'down', 'downright']);
  976. }
  977. if (guess == 'up' || guess == mxConstants.DIRECTION_NORTH)
  978. {
  979. direction = mxConstants.DIRECTION_NORTH;
  980. }
  981. else if (guess == 'left' || guess == mxConstants.DIRECTION_WEST)
  982. {
  983. direction = mxConstants.DIRECTION_WEST;
  984. }
  985. else if (guess == 'down' || guess == mxConstants.DIRECTION_SOUTH)
  986. {
  987. direction = mxConstants.DIRECTION_SOUTH;
  988. }
  989. else if (guess == 'right' || guess == mxConstants.DIRECTION_EAST)
  990. {
  991. direction = mxConstants.DIRECTION_EAST;
  992. }
  993. if (direction != null)
  994. {
  995. if (direction == mxConstants.DIRECTION_NORTH)
  996. {
  997. dy += -graph.defaultEdgeLength;
  998. }
  999. else if (direction == mxConstants.DIRECTION_WEST)
  1000. {
  1001. dx += -graph.defaultEdgeLength;
  1002. }
  1003. else if (direction == mxConstants.DIRECTION_SOUTH)
  1004. {
  1005. dy += graph.defaultEdgeLength;
  1006. }
  1007. else if (direction == mxConstants.DIRECTION_EAST)
  1008. {
  1009. dx += graph.defaultEdgeLength;
  1010. }
  1011. }
  1012. }
  1013. }
  1014. if (dx != 0 || dy != null)
  1015. {
  1016. graph.moveCells(graph.getSelectionCells(), dx, dy);
  1017. App.say('Moved');
  1018. }
  1019. return true;
  1020. }
  1021. }
  1022. else if (tokens[0] == 'text')
  1023. {
  1024. var cells = graph.getSelectionCells();
  1025. if (cells.length == 0 && graph.model.contains(lastInserted))
  1026. {
  1027. cells = [lastInserted];
  1028. }
  1029. if (cells.length == 0)
  1030. {
  1031. App.say('No cell for text');
  1032. }
  1033. else if (tokens[0].length >= 2)
  1034. {
  1035. var value = tokens.slice(1, tokens.length).join(' ');
  1036. if (value.length > 0)
  1037. {
  1038. // Capitalize string
  1039. if (value.length > 1)
  1040. {
  1041. value = value.charAt(0).toUpperCase() + value.slice(1);
  1042. }
  1043. graph.labelChanged(cells[0], value);
  1044. }
  1045. }
  1046. return true;
  1047. }
  1048. else if (tokens[0] == 'disconnect' && tokens.length == 1)
  1049. {
  1050. var cells = graph.getAllEdges(graph.getSelectionCells());
  1051. if (cells.length == 0)
  1052. {
  1053. App.say('No cell to disconnect');
  1054. }
  1055. else
  1056. {
  1057. graph.removeCells(cells);
  1058. }
  1059. return true;
  1060. }
  1061. else if (tokens[0] == 'deselect' && tokens.length == 1)
  1062. {
  1063. graph.clearSelection();
  1064. return true;
  1065. }
  1066. else if (tokens[0] === 'select' && (tokens.length == 1 || mxUtils.indexOf(
  1067. ['vertices', 'edges', 'none', 'all'], tokens[1].toLowerCase()) < 0))
  1068. {
  1069. // Handles some other shortcuts
  1070. if (tokens.length == 1 || mxUtils.indexOf(['last'], tokens[1].toLowerCase()) >= 0)
  1071. {
  1072. if (graph.model.contains(lastInserted))
  1073. {
  1074. graph.setSelectionCell(lastInserted);
  1075. App.say('{1} selected', [graph.getWordForCell(lastInserted).replace(/([A-Z])/g, ' $1')]);
  1076. return true;
  1077. }
  1078. }
  1079. // Handles alternative cases of edges
  1080. else if (mxUtils.indexOf(['connection', 'connections', 'inches'], tokens[1].toLowerCase()) >= 0)
  1081. {
  1082. var edges = graph.getAllEdges(graph.getSelectionCells());
  1083. if (edges.length > 0)
  1084. {
  1085. graph.setSelectionCells(edges);
  1086. }
  1087. else
  1088. {
  1089. ui.actions.get('selectEdges').funct();
  1090. }
  1091. App.sayHint();
  1092. return true;
  1093. }
  1094. // Handles alternative version of vertices
  1095. else if (mxUtils.indexOf(['shapes'], tokens[1].toLowerCase()) >= 0)
  1096. {
  1097. ui.actions.get('selectVertices').funct();
  1098. App.sayHint();
  1099. return true;
  1100. }
  1101. else if (mxUtils.indexOf(['previous'], tokens[1].toLowerCase()) >= 0)
  1102. {
  1103. if (graph.isSelectionEmpty())
  1104. {
  1105. // Selects the first vertex
  1106. var parent = graph.getDefaultParent();
  1107. var childCount = graph.model.getChildCount(parent);
  1108. for (var i = childCount - 1; i >= 0; i--)
  1109. {
  1110. var child = graph.model.getChildAt(parent, i);
  1111. if (graph.model.isVertex(child))
  1112. {
  1113. graph.setSelectionCell(child);
  1114. App.say('{1} selected', [graph.getWordForCell(child).replace(/([A-Z])/g, ' $1')]);
  1115. return true;
  1116. }
  1117. }
  1118. }
  1119. else
  1120. {
  1121. var cell = graph.getSelectionCell();
  1122. var model = graph.getModel();
  1123. var index = model.getParent(cell).getIndex(cell);
  1124. var childCount = model.getChildCount(model.getParent(cell));
  1125. if (index >= 0)
  1126. {
  1127. var next = model.getParent(cell).getChildAt(((index == 0) ? childCount : index) - 1);
  1128. if (next != null)
  1129. {
  1130. graph.setSelectionCell(next);
  1131. App.say('{1} selected', [graph.getWordForCell(next)]);
  1132. return true;
  1133. }
  1134. }
  1135. App.say('Previous not found');
  1136. }
  1137. }
  1138. else if (mxUtils.indexOf(['source', 'target'], tokens[1].toLowerCase()) >= 0)
  1139. {
  1140. var cell = graph.getSelectionCell();
  1141. if (graph.model.isEdge(cell))
  1142. {
  1143. var terminal = graph.model.getTerminal(cell, tokens[1].toLowerCase() == 'source');
  1144. if (terminal != null)
  1145. {
  1146. graph.setSelectionCell(terminal);
  1147. return true;
  1148. }
  1149. }
  1150. }
  1151. else if (mxUtils.indexOf(['next'], tokens[1].toLowerCase()) >= 0)
  1152. {
  1153. if (graph.isSelectionEmpty())
  1154. {
  1155. // Selects the first vertex
  1156. var parent = graph.getDefaultParent();
  1157. var childCount = graph.model.getChildCount(parent);
  1158. for (var i = 0; i < childCount; i++)
  1159. {
  1160. var child = graph.model.getChildAt(parent, i);
  1161. if (graph.model.isVertex(child))
  1162. {
  1163. graph.setSelectionCell(child);
  1164. App.say('{1} selected', [graph.getWordForCell(child).replace(/([A-Z])/g, ' $1')]);
  1165. return true;
  1166. }
  1167. }
  1168. }
  1169. else
  1170. {
  1171. var cell = graph.getSelectionCell();
  1172. var model = graph.getModel();
  1173. var index = model.getParent(cell).getIndex(cell);
  1174. var childCount = model.getChildCount(model.getParent(cell));
  1175. if (index < childCount)
  1176. {
  1177. var next = model.getParent(cell).getChildAt(((index == childCount - 1) ? 0 : index + 1));
  1178. if (next != null)
  1179. {
  1180. graph.setSelectionCell(next);
  1181. App.say('{1} selected', [graph.getWordForCell(next).replace(/([A-Z])/g, ' $1')]);
  1182. return true;
  1183. }
  1184. }
  1185. }
  1186. }
  1187. else
  1188. {
  1189. var states = graph.view.states.getValues();
  1190. var token = tokens[1].toLowerCase();
  1191. var searchToken = tokens.slice(1, tokens.length).join('').toLowerCase();
  1192. for (var i = states.length - 1; i > 0; i--)
  1193. {
  1194. // Simple matching for shape name or label
  1195. if (!graph.isCellSelected(states[i].cell))
  1196. {
  1197. // Tries label search first
  1198. var lab = graph.getLabel(states[i].cell);
  1199. if (lab != null && lab.length > 0)
  1200. {
  1201. lab = lab.toLowerCase().replace(/ /g, '');
  1202. // Some common mistakes
  1203. if (lab.charAt(lab.length - 1) == '2' && tokens[tokens.length - 1].toLowerCase() == 'to')
  1204. {
  1205. lab = lab.substring(0, lab.length - 1) + 'to';
  1206. }
  1207. var min = Math.min(searchToken.length, lab.length);
  1208. if (searchToken.substring(0, min) == lab.substring(0, min))
  1209. {
  1210. graph.setSelectionCell(states[i].cell);
  1211. App.say('{1} selected', [graph.getWordForCell(states[i].cell)]);
  1212. return true;
  1213. }
  1214. }
  1215. // Then tries shapename search
  1216. if (tokens.length == 2)
  1217. {
  1218. // Some common names
  1219. if (mxUtils.indexOf(['circle'], token) >= 0)
  1220. {
  1221. searchToken = 'ellipse';
  1222. }
  1223. else if (mxUtils.indexOf(['condition', 'decision'], token) >= 0)
  1224. {
  1225. searchToken = 'rhombus';
  1226. }
  1227. else if (mxUtils.indexOf(['preparation'], token) >= 0)
  1228. {
  1229. searchToken = 'hexagon';
  1230. }
  1231. else if (mxUtils.indexOf(['trapez'], token) >= 0)
  1232. {
  1233. searchToken = 'parallelogram';
  1234. }
  1235. }
  1236. var wrd = graph.getWordForCell(states[i].cell, true);
  1237. var min = Math.min(wrd.length, searchToken.length);
  1238. if (searchToken.substring(0, min) == wrd.substring(0, min))
  1239. {
  1240. graph.setSelectionCell(states[i].cell);
  1241. App.say('{1} selected', [graph.getWordForCell(states[i].cell)]);
  1242. return true;
  1243. }
  1244. }
  1245. }
  1246. }
  1247. }
  1248. else if (tokens[0] === 'remove')
  1249. {
  1250. var cells = graph.getSelectionCells();
  1251. if (cells.length == 0 && graph.model.contains(lastInserted))
  1252. {
  1253. cells = [lastInserted];
  1254. }
  1255. if (cells.length == 0)
  1256. {
  1257. App.say('No cells');
  1258. }
  1259. else if (tokens[1].toLowerCase() == 'text')
  1260. {
  1261. graph.labelChanged(cells[0], '');
  1262. }
  1263. else
  1264. {
  1265. // Remove style
  1266. var styleToken = mxUtils.trim(tokens.slice(1, tokens.length).join(' ').toLowerCase());
  1267. // Fixes common recognition errors
  1268. styleToken = styleToken.replace(/a line/g, 'align')
  1269. // Merges to single word
  1270. styleToken = styleToken.replace(/ /g, '')
  1271. // Fixes common speech errors that make no sense in the context
  1272. var keys = [mxConstants.STYLE_FILLCOLOR, mxConstants.STYLE_GRADIENTCOLOR,
  1273. mxConstants.STYLE_STROKECOLOR, mxConstants.STYLE_FONTCOLOR,
  1274. mxConstants.STYLE_LABEL_BACKGROUNDCOLOR, mxConstants.STYLE_LABEL_BORDERCOLOR,
  1275. mxConstants.STYLE_STROKEWIDTH, mxConstants.STYLE_FONTSIZE, mxConstants.STYLE_SPACING,
  1276. mxConstants.STYLE_SPACING_TOP, mxConstants.STYLE_SPACING_LEFT, mxConstants.STYLE_SPACING_RIGHT,
  1277. mxConstants.STYLE_SPACING_BOTTOM, mxConstants.STYLE_PERIMETER_SPACING,
  1278. mxConstants.STYLE_STARTSIZE, mxConstants.STYLE_ENDSIZE, mxConstants.STYLE_OPACITY,
  1279. mxConstants.STYLE_TEXT_OPACITY, mxConstants.STYLE_ROTATION,
  1280. mxConstants.STYLE_ALIGN, mxConstants.STYLE_VERTICAL_ALIGN, mxConstants.STYLE_FONTFAMILY,
  1281. mxConstants.STYLE_LABEL_POSITION, mxConstants.STYLE_VERTICAL_LABEL_POSITION,
  1282. mxConstants.STYLE_GRADIENT_DIRECTION];
  1283. // Guesses best word
  1284. var style = getBestWord(styleToken, keys);
  1285. if (style != null)
  1286. {
  1287. graph.setCellStyles(style, null, cells);
  1288. ui.fireEvent(new mxEventObject('styleChanged', 'keys', [style], 'values', [null], 'cells', cells));
  1289. }
  1290. else
  1291. {
  1292. App.say('Unknown style {1}', [changeTokens[0]]);
  1293. }
  1294. }
  1295. return true;
  1296. }
  1297. else
  1298. {
  1299. var cells = graph.getSelectionCells();
  1300. if (cells.length == 0 && graph.model.contains(lastInserted))
  1301. {
  1302. cells = [lastInserted];
  1303. }
  1304. // Try numeric stylename if last token is numeric
  1305. var lastToken = tokens[tokens.length - 1].toLowerCase();
  1306. // Fixes some special cases for recoginition of short phrases
  1307. // like "stroke width 2" where it tries to be clever
  1308. if (lastToken == 'tool' || lastToken == 'tune' || lastToken == 'tomb' || lastToken == 'tube')
  1309. {
  1310. lastToken = '2';
  1311. }
  1312. else if (lastToken == 'd3')
  1313. {
  1314. lastToken = '3';
  1315. }
  1316. else if (lastToken == 'v')
  1317. {
  1318. lastToken = '5';
  1319. }
  1320. else
  1321. {
  1322. // Converts numeric words to numbers (system only seems to return written numbers for <= 4)
  1323. var numbers = ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine'];
  1324. var tmpIndex = mxUtils.indexOf(numbers, lastToken);
  1325. if (tmpIndex >= 0)
  1326. {
  1327. lastToken = tmpIndex;
  1328. }
  1329. }
  1330. // If last token is numeric
  1331. var lastValue = parseFloat(lastToken);
  1332. if (tokens.length >= 2 && !isNaN(lastValue))
  1333. {
  1334. var styleToken = tokens.slice(0, tokens.length - 1).join('').toLowerCase();
  1335. // Numeric styles
  1336. var keys = [mxConstants.STYLE_STROKEWIDTH, mxConstants.STYLE_FONTSIZE, mxConstants.STYLE_SPACING,
  1337. mxConstants.STYLE_SPACING_TOP, mxConstants.STYLE_SPACING_LEFT, mxConstants.STYLE_SPACING_RIGHT,
  1338. mxConstants.STYLE_SPACING_BOTTOM, mxConstants.STYLE_PERIMETER_SPACING,
  1339. mxConstants.STYLE_STARTSIZE, mxConstants.STYLE_ENDSIZE, mxConstants.STYLE_OPACITY,
  1340. mxConstants.STYLE_TEXT_OPACITY, mxConstants.STYLE_ROTATION]
  1341. var style = null;
  1342. // Workaround for problem with "font size" is to say "size" ("font" is near "phone")
  1343. if (styleToken == 'size')
  1344. {
  1345. style = mxConstants.STYLE_FONTSIZE;
  1346. }
  1347. else
  1348. {
  1349. // Guesses best word
  1350. style = getBestWord(styleToken, keys);
  1351. }
  1352. if (style != null)
  1353. {
  1354. if (cells.length == 0)
  1355. {
  1356. App.say('No cell for {1}', [style]);
  1357. }
  1358. // Plausibility check
  1359. else if (lastValue <= 400)
  1360. {
  1361. graph.setCellStyles(style, lastValue, cells);
  1362. ui.fireEvent(new mxEventObject('styleChanged', 'keys', [style], 'values', [lastValue], 'cells', cells));
  1363. }
  1364. else
  1365. {
  1366. App.say('{1} ignored', [lastValue]);
  1367. }
  1368. // Terminate
  1369. return true;
  1370. }
  1371. }
  1372. // If "color" appears in the command
  1373. if (tokens.length >= 2)
  1374. {
  1375. // Replaces GB spelling with US spelling for internal lookups
  1376. var colorCommand = mxUtils.trim(command.toLowerCase().replace(/colour/g, 'color'));
  1377. var colorIndex = colorCommand.indexOf('color');
  1378. // "Color" (word alone) matches to fill color
  1379. if (colorIndex >= 0)
  1380. {
  1381. // Text from first space after color* word
  1382. var colorToken = mxUtils.trim(colorCommand.substring(
  1383. colorCommand.indexOf(' ', colorIndex))).replace(/ /g, '');
  1384. var color = null;
  1385. // Checks for color code of token using ntc
  1386. for (var i = 0; i < ntc.names.length; i++)
  1387. {
  1388. if (ntc.names[i][1].toLowerCase().replace(/ /g, '') == colorToken)
  1389. {
  1390. color = '#' + ntc.names[i][0];
  1391. break;
  1392. }
  1393. }
  1394. // Color is known
  1395. if (color != null)
  1396. {
  1397. var styleToken = colorCommand.substring(0, colorIndex + 'color'.length).replace(/ /g, '');
  1398. keys = [mxConstants.STYLE_GRADIENTCOLOR,
  1399. mxConstants.STYLE_STROKECOLOR, mxConstants.STYLE_FONTCOLOR,
  1400. mxConstants.STYLE_LABEL_BACKGROUNDCOLOR, mxConstants.STYLE_LABEL_BORDERCOLOR,
  1401. mxConstants.STYLE_FILLCOLOR];
  1402. var style = null;
  1403. // Handles some special cases
  1404. if (styleToken == 'thecolor' || styleToken == 'color')
  1405. {
  1406. if (graph.model.isEdge(graph.getSelectionCell()))
  1407. {
  1408. style = mxConstants.STYLE_STROKECOLOR;
  1409. }
  1410. else
  1411. {
  1412. style = mxConstants.STYLE_FILLCOLOR;
  1413. }
  1414. }
  1415. else
  1416. {
  1417. // Guesses best word
  1418. style = getBestWord(styleToken, keys);
  1419. }
  1420. if (style != null)
  1421. {
  1422. if (cells.length == 0)
  1423. {
  1424. App.say('No cell for {1}', [style]);
  1425. }
  1426. else
  1427. {
  1428. graph.setCellStyles(style, color, cells);
  1429. ui.fireEvent(new mxEventObject('styleChanged', 'keys', [style], 'values', [color], 'cells', cells));
  1430. }
  1431. // Terminate
  1432. return true;
  1433. }
  1434. }
  1435. }
  1436. }
  1437. // If the first token is a general stylename
  1438. if (tokens.length >= 2)
  1439. {
  1440. var keys = [mxConstants.STYLE_ALIGN, mxConstants.STYLE_VERTICAL_ALIGN,
  1441. mxConstants.STYLE_FONTFAMILY, mxConstants.STYLE_LABEL_POSITION,
  1442. mxConstants.STYLE_VERTICAL_LABEL_POSITION,
  1443. mxConstants.STYLE_GRADIENT_DIRECTION];
  1444. var styleToken = mxUtils.trim(tokens.slice(0, tokens.length - 1).join(' ').toLowerCase());
  1445. // Fixes common recognition errors
  1446. styleToken = styleToken.replace(/a line/g, 'align')
  1447. // Merges to single word
  1448. styleToken = styleToken.replace(/ /g, '')
  1449. var style = resolveStylename(styleToken, keys);
  1450. var value = mxUtils.trim(tokens[tokens.length - 1].toLowerCase());
  1451. if (style != null && value != null && value.length > 0)
  1452. {
  1453. if (cells.length == 0)
  1454. {
  1455. App.say('No cell for {1}', [style]);
  1456. }
  1457. else
  1458. {
  1459. graph.setCellStyles(style, value, cells);
  1460. ui.fireEvent(new mxEventObject('styleChanged', 'keys', [style], 'values', [value], 'cells', cells));
  1461. }
  1462. // Terminate
  1463. return true;
  1464. }
  1465. }
  1466. // Checks if the command is a shape name
  1467. var vertices = [];
  1468. for (var i = 0; i < cells.length; i++)
  1469. {
  1470. var cell = cells[i];
  1471. if (graph.model.isVertex(cell))
  1472. {
  1473. vertices.push(cell);
  1474. }
  1475. }
  1476. var shapenameToken = mxUtils.trim(tokens.join('')).toLowerCase();
  1477. // Searches for registered shape names
  1478. // LATER: Using search like insert requires access to
  1479. // the cells of the search result items
  1480. if (shapeList == null)
  1481. {
  1482. shapeList = [];
  1483. for (var tmp in mxCellRenderer.prototype.defaultShapes)
  1484. {
  1485. shapeList.push(tmp.toLowerCase());
  1486. }
  1487. }
  1488. // Only exact matches allowed here
  1489. // LATER: Support rounded style
  1490. var shape = null;
  1491. // Some common mappings
  1492. if (mxUtils.indexOf(['cirlce', 'event', 'start', 'end'], shapenameToken) >= 0)
  1493. {
  1494. shapenameToken = shape = 'ellipse';
  1495. }
  1496. else if (mxUtils.indexOf(['condition', 'decision'], shapenameToken) >= 0)
  1497. {
  1498. shapenameToken = shape = 'rhombus';
  1499. }
  1500. else if (mxUtils.indexOf(['preparation'], shapenameToken) >= 0)
  1501. {
  1502. shapenameToken = shape = 'hexagon';
  1503. }
  1504. else if (mxUtils.indexOf(['trapez'], shapenameToken) >= 0)
  1505. {
  1506. shapenameToken = shape = 'parallelogram';
  1507. }
  1508. else
  1509. {
  1510. shape = getBestWord(shapenameToken, shapeList);
  1511. }
  1512. // LATER: Ignore all edge shapes
  1513. if (shape != null && shape.toLowerCase() == shapenameToken && shape != 'connector' &&
  1514. shape != 'arrow' && shape != 'flexarrow' && shape != 'arrowconnector' &&
  1515. shape != 'link')
  1516. {
  1517. if (cells.length == 0)
  1518. {
  1519. App.say('No cell for {1}', [shape]);
  1520. }
  1521. else if (vertices.length == 0)
  1522. {
  1523. App.say('Connections ignored');
  1524. }
  1525. else
  1526. {
  1527. // LATER: Add perimeter style etc
  1528. graph.setCellStyles(mxConstants.STYLE_SHAPE, shapenameToken, vertices);
  1529. ui.fireEvent(new mxEventObject('styleChanged', 'keys', [mxConstants.STYLE_SHAPE],
  1530. 'values', [shapenameToken], 'cells', vertices));
  1531. // Terminate
  1532. return true;
  1533. }
  1534. }
  1535. // Lazy creation of cache for action names
  1536. if (actions == null)
  1537. {
  1538. actions = {};
  1539. actionList = [];
  1540. for (var name in ui.actions.actions)
  1541. {
  1542. var shortname = mxUtils.trim(name).toLowerCase().replace(/ /g, '');
  1543. actions[shortname] = ui.actions.actions[name];
  1544. actionList.push(shortname);
  1545. }
  1546. }
  1547. var name = mxUtils.trim(command).toLowerCase().replace(/ /g, '');
  1548. if (urlParams['dev'] == '1')
  1549. {
  1550. var guess = getBestWord(name, actionList, true);
  1551. console.log('App.say guess:', name, '=>', guess, '(' +
  1552. naiveHammingDistance(name, guess) + ', ' +
  1553. levenshteinDist(name, guess) +
  1554. ')');
  1555. }
  1556. // Some common redirects and mistakes
  1557. if (tokens[0] == 'back')
  1558. {
  1559. command = name = 'undo';
  1560. }
  1561. else if (tokens[0] == 'restore')
  1562. {
  1563. command = name = 'redo';
  1564. }
  1565. else if (tokens[0] == 'clone')
  1566. {
  1567. command = name = 'duplicate';
  1568. }
  1569. else if (mxUtils.indexOf(['all', 'small', 'wall', 'call'], name) >= 0)
  1570. {
  1571. command = name = 'selectall';
  1572. }
  1573. else if (mxUtils.indexOf(['both', 'boat', 'phone', 'don\'t', 'food', 'bolt', 'bull'], tokens[0]) >= 0)
  1574. {
  1575. command = name = 'bold';
  1576. }
  1577. var action = actions[name];
  1578. if (action != null)
  1579. {
  1580. if (action.isEnabled())
  1581. {
  1582. App.say(name);
  1583. action.funct();
  1584. }
  1585. else
  1586. {
  1587. // Cannot use name here as it has no spaces
  1588. App.say('{1} disabled', [command]);
  1589. }
  1590. return true;
  1591. }
  1592. return false;
  1593. }
  1594. }
  1595. };
  1596. if ('speechSynthesis' in window)
  1597. {
  1598. // Shows dialog for mic access
  1599. if (navigator.webkitGetUserMedia)
  1600. {
  1601. window.addEventListener('load', function()
  1602. {
  1603. navigator.webkitGetUserMedia({audio:true}, function()
  1604. {
  1605. //console.log('access to mic ok');
  1606. }, function(e)
  1607. {
  1608. //alert('Error getting audio');
  1609. console.log(e);
  1610. });
  1611. });
  1612. }
  1613. // Installs helper methods and listeners for speech output
  1614. var graph = ui.editor.graph;
  1615. App.reloadVoicePlugin = function()
  1616. {
  1617. // Shows UI
  1618. speechOutputEnabled = true;
  1619. menu.style.display = '';
  1620. td.style.display = 'inline-block';
  1621. };
  1622. App.sayHint = function()
  1623. {
  1624. if (graph.getSelectionCount() == 0)
  1625. {
  1626. App.say('No cell selected.' + ((ui.isDiagramEmpty()) ? ' Diagram is empty.' : ''));
  1627. }
  1628. else if (graph.getSelectionCount() == 1)
  1629. {
  1630. var cell = graph.getSelectionCell();
  1631. if (graph.getModel().isVertex(cell))
  1632. {
  1633. var geo = graph.getCellGeometry(cell)
  1634. if (geo != null)
  1635. {
  1636. App.say('{1} at {2} and {3} is {4} times {5} pixels', [graph.getWordForCell(cell, true),
  1637. geo.x, geo.y, geo.width, geo.height]);
  1638. }
  1639. }
  1640. else
  1641. {
  1642. App.say('One connection selected');
  1643. }
  1644. var lab = mxUtils.trim(graph.getLabel(cell));
  1645. if (lab != null && lab.length > 0 && lab.length < 20)
  1646. {
  1647. App.say('Label is {1}', [lab]);
  1648. }
  1649. }
  1650. else
  1651. {
  1652. var cells = graph.getSelectionCells();
  1653. var vertexCount = 0;
  1654. var edgeCount = 0;
  1655. for (var i = 0; i < cells.length; i++)
  1656. {
  1657. var cell = cells[i];
  1658. if (graph.model.isEdge(cell))
  1659. {
  1660. edgeCount++;
  1661. }
  1662. else if (graph.model.isVertex(cell))
  1663. {
  1664. vertexCount++;
  1665. }
  1666. }
  1667. if (vertexCount > 0 && edgeCount > 0)
  1668. {
  1669. var tmp = '';
  1670. if (vertexCount == 1)
  1671. {
  1672. tmp += 'One shape';
  1673. }
  1674. else
  1675. {
  1676. tmp += '{1} shapes';
  1677. }
  1678. tmp += ' and ';
  1679. if (edgeCount == 1)
  1680. {
  1681. tmp += 'one connection';
  1682. }
  1683. else
  1684. {
  1685. tmp += '{2} connections';
  1686. }
  1687. App.say(tmp + ' selected', [vertexCount, edgeCount]);
  1688. }
  1689. else if (vertexCount > 0)
  1690. {
  1691. App.say('{1} shapes selected', [vertexCount]);
  1692. }
  1693. else
  1694. {
  1695. App.say('{1} connections selected', [edgeCount]);
  1696. }
  1697. }
  1698. };
  1699. // Can return more than first word
  1700. function firstWord(value)
  1701. {
  1702. // TODO Use regex
  1703. if (value != null && value.length > maxLabelLength)
  1704. {
  1705. var space = value.indexOf(' ');
  1706. // Add second word if label is short
  1707. var tmp = value.indexOf(' ', space + 1);
  1708. if (tmp >= 0 && tmp <= maxLabelLength)
  1709. {
  1710. space = tmp;
  1711. // Add third word if label is short
  1712. var tmp = value.indexOf(' ', space + 1);
  1713. if (tmp >= 0 && tmp <= maxLabelLength)
  1714. {
  1715. space = tmp;
  1716. }
  1717. }
  1718. if (space >= 0)
  1719. {
  1720. value = value.substring(0, space);
  1721. }
  1722. }
  1723. return value;
  1724. };
  1725. graph.getWordForCell = function(cell, ignoreLabel)
  1726. {
  1727. var label = 'no';
  1728. if (cell != null)
  1729. {
  1730. label = (ignoreLabel) ? null : firstWord(this.getLabel(cell));
  1731. if (label == null || label.length == 0 || label.length > maxLabelLength || mxUtils.isNumeric(label))
  1732. {
  1733. var state = this.view.getState(cell);
  1734. var style = (state != null) ? state.style : this.getCellStyle(cell);
  1735. var tmp = style[mxConstants.STYLE_SHAPE];
  1736. if (tmp == 'label')
  1737. {
  1738. label = 'rectangle';
  1739. }
  1740. else if (tmp != null)
  1741. {
  1742. var dot = tmp.lastIndexOf('.');
  1743. if (dot >= 0)
  1744. {
  1745. tmp = tmp.substring(dot + 1);
  1746. }
  1747. label = tmp
  1748. }
  1749. }
  1750. var div = document.createElement('div');
  1751. div.innerHTML = label;
  1752. label = div.innerText;
  1753. }
  1754. return label;
  1755. };
  1756. ui.addListener('styleChanged', function(sender, evt)
  1757. {
  1758. //console.log('styleChanged', evt, evt.getProperty('keys'));
  1759. var cells = evt.getProperty('cells');
  1760. var keys = evt.getProperty('keys');
  1761. var values = evt.getProperty('values');
  1762. if (cells != null && keys != null && keys.length == 1 && values.length == 1)
  1763. {
  1764. var tmp = values[0];
  1765. if (typeof tmp === 'string' && tmp.charAt(0) == '#')
  1766. {
  1767. var n_match = ntc.name(tmp);
  1768. //if (n_match[2]) /* exact match */
  1769. {
  1770. tmp = n_match[1];
  1771. }
  1772. }
  1773. if (tmp == mxConstants.NONE || tmp == null)
  1774. {
  1775. App.say('Removed {1}', [keys[0]]);
  1776. }
  1777. else
  1778. {
  1779. // Replaces camel case notation with spaces
  1780. var key = keys[0].replace(/([A-Z])/g, ' $1')
  1781. App.say('{1} {2}', [key, tmp]);
  1782. }
  1783. }
  1784. });
  1785. graph.addListener(mxEvent.LABEL_CHANGED, function(sender, evt)
  1786. {
  1787. //console.log('CELL_CONNECTED', evt);
  1788. var cell = evt.getProperty('cell');
  1789. var old = evt.getProperty('old');
  1790. // Resolves placeholders in new label
  1791. var value = this.getLabel(cell);
  1792. if ((value != null && value.length > 20) ||
  1793. (old != null && old.length > 20))
  1794. {
  1795. App.say('Label changed');
  1796. }
  1797. else if (value != null && value.length == 0)
  1798. {
  1799. App.say('Label removed');
  1800. }
  1801. else if (value != null)
  1802. {
  1803. App.say('{1}', [value]);
  1804. }
  1805. });
  1806. graph.addListener(mxEvent.CELL_CONNECTED, function(sender, evt)
  1807. {
  1808. // console.log('CELL_CONNECTED', evt);
  1809. // var edge = evt.getProperty('edge');
  1810. // var terminal = evt.getProperty('terminal');
  1811. // var other = graph.model.getTerminal(edge, !evt.getProperty('source'));
  1812. //
  1813. // if (other != null && terminal != null)
  1814. // {
  1815. // App.say('connected {1} to {2}', [getWordForCell(other), getWordForCell(terminal)]);
  1816. // }
  1817. });
  1818. graph.addListener(mxEvent.CELLS_ADDED, function(sender, evt)
  1819. {
  1820. //console.log('CELLS_ADDED', evt);
  1821. var cells = evt.getProperty('cells');
  1822. if (cells.length > 1)
  1823. {
  1824. var vertexCount = 0;
  1825. var edgeCount = 0;
  1826. for (var i = 0; i < cells.length; i++)
  1827. {
  1828. var cell = cells[i];
  1829. if (graph.model.isEdge(cell))
  1830. {
  1831. edgeCount++;
  1832. }
  1833. else if (graph.model.isVertex(cell))
  1834. {
  1835. vertexCount++;
  1836. }
  1837. }
  1838. if (vertexCount > 0 && edgeCount > 0)
  1839. {
  1840. var tmp = '';
  1841. if (vertexCount == 1)
  1842. {
  1843. tmp += 'One shape';
  1844. }
  1845. else
  1846. {
  1847. tmp += '{1} shapes';
  1848. }
  1849. tmp += ' and ';
  1850. if (edgeCount == 1)
  1851. {
  1852. tmp += 'one connection';
  1853. }
  1854. else
  1855. {
  1856. tmp += '{2} connections';
  1857. }
  1858. App.say(tmp + ' inserted', [vertexCount, edgeCount]);
  1859. }
  1860. else if (vertexCount > 0)
  1861. {
  1862. App.say('{1} shapes', [vertexCount]);
  1863. }
  1864. else
  1865. {
  1866. App.say('{1} connections', [edgeCount]);
  1867. }
  1868. }
  1869. else
  1870. {
  1871. cell = cells[0];
  1872. if (graph.model.isEdge(cell) && graph.model.getTerminal(cell, true) != null &&
  1873. graph.model.getTerminal(cell, false) != null)
  1874. {
  1875. if (graph.getWordForCell(graph.model.getTerminal(cell, true)) ==
  1876. graph.getWordForCell(graph.model.getTerminal(cell, false)))
  1877. {
  1878. App.say('Connected');
  1879. }
  1880. else
  1881. {
  1882. App.say('{1} connected to {2}', [graph.getWordForCell(graph.model.getTerminal(cell, true)),
  1883. graph.getWordForCell(graph.model.getTerminal(cell, false))]);
  1884. }
  1885. }
  1886. else if (graph.model.isVertex(cell))
  1887. {
  1888. lastInserted = cell;
  1889. // Replaces camel case notation with spaces
  1890. var word = graph.getWordForCell(cell).replace(/([A-Z])/g, ' $1');
  1891. App.say('{1}', [word]);
  1892. }
  1893. }
  1894. });
  1895. graph.addListener(mxEvent.CELLS_REMOVED, function(sender, evt)
  1896. {
  1897. //console.log('CELLS_REMOVED', evt);
  1898. var cells = evt.getProperty('cells');
  1899. if (cells.length > 1)
  1900. {
  1901. App.say('{1} cells deleted', [cells.length]);
  1902. }
  1903. else
  1904. {
  1905. cell = cells[0];
  1906. App.say('{1} deleted', [graph.getWordForCell(cell)]);
  1907. }
  1908. });
  1909. }
  1910. });
  1911. /** Code for color to voice based on ntc (name that color)
  1912. /*
  1913. +-----------------------------------------------------------------+
  1914. | Created by Chirag Mehta - http://chir.ag/projects/ntc |
  1915. |-----------------------------------------------------------------|
  1916. | ntc js (Name that Color JavaScript) |
  1917. +-----------------------------------------------------------------+
  1918. All the functions, code, lists etc. have been written specifically
  1919. for the Name that Color JavaScript by Chirag Mehta unless otherwise
  1920. specified.
  1921. This script is released under the: Creative Commons License:
  1922. Attribution 2.5 http://creativecommons.org/licenses/by/2.5/
  1923. Sample Usage:
  1924. <script type="text/javascript" src="ntc.js"></script>
  1925. <script type="text/javascript">
  1926. var n_match = ntc.name("#6195ED");
  1927. n_rgb = n_match[0]; // This is the RGB value of the closest matching color
  1928. n_name = n_match[1]; // This is the text string for the name of the match
  1929. n_exactmatch = n_match[2]; // True if exact color match, False if close-match
  1930. alert(n_match);
  1931. </script>
  1932. */
  1933. var ntc = {
  1934. init: function() {
  1935. var color, rgb, hsl;
  1936. for(var i = 0; i < ntc.names.length; i++)
  1937. {
  1938. color = "#" + ntc.names[i][0];
  1939. rgb = ntc.rgb(color);
  1940. hsl = ntc.hsl(color);
  1941. ntc.names[i].push(rgb[0], rgb[1], rgb[2], hsl[0], hsl[1], hsl[2]);
  1942. }
  1943. },
  1944. name: function(color) {
  1945. color = color.toUpperCase();
  1946. if(color.length < 3 || color.length > 7)
  1947. return ["#000000", "Invalid Color: " + color, false];
  1948. if(color.length % 3 == 0)
  1949. color = "#" + color;
  1950. if(color.length == 4)
  1951. color = "#" + color.substr(1, 1) + color.substr(1, 1) + color.substr(2, 1) + color.substr(2, 1) + color.substr(3, 1) + color.substr(3, 1);
  1952. var rgb = ntc.rgb(color);
  1953. var r = rgb[0], g = rgb[1], b = rgb[2];
  1954. var hsl = ntc.hsl(color);
  1955. var h = hsl[0], s = hsl[1], l = hsl[2];
  1956. var ndf1 = 0; ndf2 = 0; ndf = 0;
  1957. var cl = -1, df = -1;
  1958. for(var i = 0; i < ntc.names.length; i++)
  1959. {
  1960. if(color == "#" + ntc.names[i][0])
  1961. return ["#" + ntc.names[i][0], ntc.names[i][1], true];
  1962. ndf1 = Math.pow(r - ntc.names[i][2], 2) + Math.pow(g - ntc.names[i][3], 2) + Math.pow(b - ntc.names[i][4], 2);
  1963. ndf2 = Math.pow(h - ntc.names[i][5], 2) + Math.pow(s - ntc.names[i][6], 2) + Math.pow(l - ntc.names[i][7], 2);
  1964. ndf = ndf1 + ndf2 * 2;
  1965. if(df < 0 || df > ndf)
  1966. {
  1967. df = ndf;
  1968. cl = i;
  1969. }
  1970. }
  1971. return (cl < 0 ? ["#000000", "Invalid Color: " + color, false] : ["#" + ntc.names[cl][0], ntc.names[cl][1], false]);
  1972. },
  1973. // adopted from: Farbtastic 1.2
  1974. // http://acko.net/dev/farbtastic
  1975. hsl: function (color) {
  1976. var rgb = [parseInt('0x' + color.substring(1, 3)) / 255, parseInt('0x' + color.substring(3, 5)) / 255, parseInt('0x' + color.substring(5, 7)) / 255];
  1977. var min, max, delta, h, s, l;
  1978. var r = rgb[0], g = rgb[1], b = rgb[2];
  1979. min = Math.min(r, Math.min(g, b));
  1980. max = Math.max(r, Math.max(g, b));
  1981. delta = max - min;
  1982. l = (min + max) / 2;
  1983. s = 0;
  1984. if(l > 0 && l < 1)
  1985. s = delta / (l < 0.5 ? (2 * l) : (2 - 2 * l));
  1986. h = 0;
  1987. if(delta > 0)
  1988. {
  1989. if (max == r && max != g) h += (g - b) / delta;
  1990. if (max == g && max != b) h += (2 + (b - r) / delta);
  1991. if (max == b && max != r) h += (4 + (r - g) / delta);
  1992. h /= 6;
  1993. }
  1994. return [parseInt(h * 255), parseInt(s * 255), parseInt(l * 255)];
  1995. },
  1996. // adopted from: Farbtastic 1.2
  1997. // http://acko.net/dev/farbtastic
  1998. rgb: function(color) {
  1999. return [parseInt('0x' + color.substring(1, 3)), parseInt('0x' + color.substring(3, 5)), parseInt('0x' + color.substring(5, 7))];
  2000. },
  2001. names: [
  2002. // Added all standard HTML color names / gaudenz, oct-2015
  2003. ["F0F8FF", "aliceblue"],
  2004. ["FAEBD7", "antiquewhite"],
  2005. ["00FFFF", "aqua"],
  2006. ["7FFFD4", "aquamarine"],
  2007. ["F0FFFF", "azure"],
  2008. ["F5F5DC", "beige"],
  2009. ["FFE4C4", "bisque"],
  2010. ["000000", "black"],
  2011. ["FFEBCD", "blanchedalmond"],
  2012. ["0000FF", "blue"],
  2013. ["8A2BE2", "blueviolet"],
  2014. ["A52A2A", "brown"],
  2015. ["DEB887", "burlywood"],
  2016. ["5F9EA0", "cadetblue"],
  2017. ["7FFF00", "chartreuse"],
  2018. ["D2691E", "chocolate"],
  2019. ["FF7F50", "coral"],
  2020. ["6495ED", "cornflowerblue"],
  2021. ["FFF8DC", "cornsilk"],
  2022. ["DC143C", "crimson"],
  2023. ["00FFFF", "cyan"],
  2024. ["00008B", "darkblue"],
  2025. ["008B8B", "darkcyan"],
  2026. ["B8860B", "darkgoldenrod"],
  2027. ["A9A9A9", "darkgray"],
  2028. ["A9A9A9", "darkgrey"],
  2029. ["006400", "darkgreen"],
  2030. ["BDB76B", "darkkhaki"],
  2031. ["8B008B", "darkmagenta"],
  2032. ["556B2F", "darkolivegreen"],
  2033. ["FF8C00", "darkorange"],
  2034. ["9932CC", "darkorchid"],
  2035. ["8B0000", "darkred"],
  2036. ["E9967A", "darksalmon"],
  2037. ["8FBC8F", "darkseagreen"],
  2038. ["483D8B", "darkslateblue"],
  2039. ["2F4F4F", "darkslategray"],
  2040. ["2F4F4F", "darkslategrey"],
  2041. ["00CED1", "darkturquoise"],
  2042. ["9400D3", "darkviolet"],
  2043. ["FF1493", "deeppink"],
  2044. ["00BFFF", "deepskyblue"],
  2045. ["696969", "dimgray"],
  2046. ["696969", "dimgrey"],
  2047. ["1E90FF", "dodgerblue"],
  2048. ["B22222", "firebrick"],
  2049. ["FFFAF0", "floralwhite"],
  2050. ["228B22", "forestgreen"],
  2051. ["FF00FF", "fuchsia"],
  2052. ["DCDCDC", "gainsboro"],
  2053. ["F8F8FF", "ghostwhite"],
  2054. ["FFD700", "gold"],
  2055. ["DAA520", "goldenrod"],
  2056. ["808080", "gray"],
  2057. ["808080", "grey"],
  2058. ["008000", "green"],
  2059. ["ADFF2F", "greenyellow"],
  2060. ["F0FFF0", "honeydew"],
  2061. ["FF69B4", "hotpink"],
  2062. ["CD5C5C", "indianred "],
  2063. ["4B0082", "indigo "],
  2064. ["FFFFF0", "ivory"],
  2065. ["F0E68C", "khaki"],
  2066. ["E6E6FA", "lavender"],
  2067. ["FFF0F5", "lavenderblush"],
  2068. ["7CFC00", "lawngreen"],
  2069. ["FFFACD", "lemonchiffon"],
  2070. ["ADD8E6", "lightblue"],
  2071. ["F08080", "lightcoral"],
  2072. ["E0FFFF", "lightcyan"],
  2073. ["FAFAD2", "lightgoldenrodyellow"],
  2074. ["D3D3D3", "lightgray"],
  2075. ["D3D3D3", "lightgrey"],
  2076. ["90EE90", "lightgreen"],
  2077. ["FFB6C1", "lightpink"],
  2078. ["FFA07A", "lightsalmon"],
  2079. ["20B2AA", "lightseagreen"],
  2080. ["87CEFA", "lightskyblue"],
  2081. ["778899", "lightslategray"],
  2082. ["778899", "lightslategrey"],
  2083. ["B0C4DE", "lightsteelblue"],
  2084. ["FFFFE0", "lightyellow"],
  2085. ["00FF00", "lime"],
  2086. ["32CD32", "limegreen"],
  2087. ["FAF0E6", "linen"],
  2088. ["FF00FF", "magenta"],
  2089. ["800000", "maroon"],
  2090. ["66CDAA", "mediumaquamarine"],
  2091. ["0000CD", "mediumblue"],
  2092. ["BA55D3", "mediumorchid"],
  2093. ["9370DB", "mediumpurple"],
  2094. ["3CB371", "mediumseagreen"],
  2095. ["7B68EE", "mediumslateblue"],
  2096. ["00FA9A", "mediumspringgreen"],
  2097. ["48D1CC", "mediumturquoise"],
  2098. ["C71585", "mediumvioletred"],
  2099. ["191970", "midnightblue"],
  2100. ["F5FFFA", "mintcream"],
  2101. ["FFE4E1", "mistyrose"],
  2102. ["FFE4B5", "moccasin"],
  2103. ["FFDEAD", "navajowhite"],
  2104. ["000080", "navy"],
  2105. ["FDF5E6", "oldlace"],
  2106. ["808000", "olive"],
  2107. ["6B8E23", "olivedrab"],
  2108. ["FFA500", "orange"],
  2109. ["FF4500", "orangered"],
  2110. ["DA70D6", "orchid"],
  2111. ["EEE8AA", "palegoldenrod"],
  2112. ["98FB98", "palegreen"],
  2113. ["AFEEEE", "paleturquoise"],
  2114. ["DB7093", "palevioletred"],
  2115. ["FFEFD5", "papayawhip"],
  2116. ["FFDAB9", "peachpuff"],
  2117. ["CD853F", "peru"],
  2118. ["FFC0CB", "pink"],
  2119. ["DDA0DD", "plum"],
  2120. ["B0E0E6", "powderblue"],
  2121. ["800080", "purple"],
  2122. ["FF0000", "red"],
  2123. ["BC8F8F", "rosybrown"],
  2124. ["4169E1", "royalblue"],
  2125. ["8B4513", "saddlebrown"],
  2126. ["FA8072", "salmon"],
  2127. ["F4A460", "sandybrown"],
  2128. ["2E8B57", "seagreen"],
  2129. ["FFF5EE", "seashell"],
  2130. ["A0522D", "sienna"],
  2131. ["C0C0C0", "silver"],
  2132. ["87CEEB", "skyblue"],
  2133. ["6A5ACD", "slateblue"],
  2134. ["708090", "slategray"],
  2135. ["708090", "slategrey"],
  2136. ["FFFAFA", "snow"],
  2137. ["00FF7F", "springgreen"],
  2138. ["4682B4", "steelblue"],
  2139. ["D2B48C", "tan"],
  2140. ["008080", "teal"],
  2141. ["D8BFD8", "thistle"],
  2142. ["FF6347", "tomato"],
  2143. ["40E0D0", "turquoise"],
  2144. ["EE82EE", "violet"],
  2145. ["F5DEB3", "wheat"],
  2146. ["FFFFFF", "white"],
  2147. ["F5F5F5", "whitesmoke"],
  2148. ["FFFF00", "yellow"],
  2149. ["9ACD32", "yellowgreen"],
  2150. // Existing table
  2151. ["000000", "Black"],
  2152. ["000080", "Navy Blue"],
  2153. ["0000C8", "Dark Blue"],
  2154. ["0000FF", "Blue"],
  2155. ["000741", "Stratos"],
  2156. ["001B1C", "Swamp"],
  2157. ["002387", "Resolution Blue"],
  2158. ["002900", "Deep Fir"],
  2159. ["002E20", "Burnham"],
  2160. ["002FA7", "International Klein Blue"],
  2161. ["003153", "Prussian Blue"],
  2162. ["003366", "Midnight Blue"],
  2163. ["003399", "Smalt"],
  2164. ["003532", "Deep Teal"],
  2165. ["003E40", "Cyprus"],
  2166. ["004620", "Kaitoke Green"],
  2167. ["0047AB", "Cobalt"],
  2168. ["004816", "Crusoe"],
  2169. ["004950", "Sherpa Blue"],
  2170. ["0056A7", "Endeavour"],
  2171. ["00581A", "Camarone"],
  2172. ["0066CC", "Science Blue"],
  2173. ["0066FF", "Blue Ribbon"],
  2174. ["00755E", "Tropical Rain Forest"],
  2175. ["0076A3", "Allports"],
  2176. ["007BA7", "Deep Cerulean"],
  2177. ["007EC7", "Lochmara"],
  2178. ["007FFF", "Azure Radiance"],
  2179. ["008080", "Teal"],
  2180. ["0095B6", "Bondi Blue"],
  2181. ["009DC4", "Pacific Blue"],
  2182. ["00A693", "Persian Green"],
  2183. ["00A86B", "Jade"],
  2184. ["00CC99", "Caribbean Green"],
  2185. ["00CCCC", "Robin's Egg Blue"],
  2186. ["00FF00", "Green"],
  2187. ["00FF7F", "Spring Green"],
  2188. ["00FFFF", "Cyan / Aqua"],
  2189. ["010D1A", "Blue Charcoal"],
  2190. ["011635", "Midnight"],
  2191. ["011D13", "Holly"],
  2192. ["012731", "Daintree"],
  2193. ["01361C", "Cardin Green"],
  2194. ["01371A", "County Green"],
  2195. ["013E62", "Astronaut Blue"],
  2196. ["013F6A", "Regal Blue"],
  2197. ["014B43", "Aqua Deep"],
  2198. ["015E85", "Orient"],
  2199. ["016162", "Blue Stone"],
  2200. ["016D39", "Fun Green"],
  2201. ["01796F", "Pine Green"],
  2202. ["017987", "Blue Lagoon"],
  2203. ["01826B", "Deep Sea"],
  2204. ["01A368", "Green Haze"],
  2205. ["022D15", "English Holly"],
  2206. ["02402C", "Sherwood Green"],
  2207. ["02478E", "Congress Blue"],
  2208. ["024E46", "Evening Sea"],
  2209. ["026395", "Bahama Blue"],
  2210. ["02866F", "Observatory"],
  2211. ["02A4D3", "Cerulean"],
  2212. ["03163C", "Tangaroa"],
  2213. ["032B52", "Green Vogue"],
  2214. ["036A6E", "Mosque"],
  2215. ["041004", "Midnight Moss"],
  2216. ["041322", "Black Pearl"],
  2217. ["042E4C", "Blue Whale"],
  2218. ["044022", "Zuccini"],
  2219. ["044259", "Teal Blue"],
  2220. ["051040", "Deep Cove"],
  2221. ["051657", "Gulf Blue"],
  2222. ["055989", "Venice Blue"],
  2223. ["056F57", "Watercourse"],
  2224. ["062A78", "Catalina Blue"],
  2225. ["063537", "Tiber"],
  2226. ["069B81", "Gossamer"],
  2227. ["06A189", "Niagara"],
  2228. ["073A50", "Tarawera"],
  2229. ["080110", "Jaguar"],
  2230. ["081910", "Black Bean"],
  2231. ["082567", "Deep Sapphire"],
  2232. ["088370", "Elf Green"],
  2233. ["08E8DE", "Bright Turquoise"],
  2234. ["092256", "Downriver"],
  2235. ["09230F", "Palm Green"],
  2236. ["09255D", "Madison"],
  2237. ["093624", "Bottle Green"],
  2238. ["095859", "Deep Sea Green"],
  2239. ["097F4B", "Salem"],
  2240. ["0A001C", "Black Russian"],
  2241. ["0A480D", "Dark Fern"],
  2242. ["0A6906", "Japanese Laurel"],
  2243. ["0A6F75", "Atoll"],
  2244. ["0B0B0B", "Cod Gray"],
  2245. ["0B0F08", "Marshland"],
  2246. ["0B1107", "Gordons Green"],
  2247. ["0B1304", "Black Forest"],
  2248. ["0B6207", "San Felix"],
  2249. ["0BDA51", "Malachite"],
  2250. ["0C0B1D", "Ebony"],
  2251. ["0C0D0F", "Woodsmoke"],
  2252. ["0C1911", "Racing Green"],
  2253. ["0C7A79", "Surfie Green"],
  2254. ["0C8990", "Blue Chill"],
  2255. ["0D0332", "Black Rock"],
  2256. ["0D1117", "Bunker"],
  2257. ["0D1C19", "Aztec"],
  2258. ["0D2E1C", "Bush"],
  2259. ["0E0E18", "Cinder"],
  2260. ["0E2A30", "Firefly"],
  2261. ["0F2D9E", "Torea Bay"],
  2262. ["10121D", "Vulcan"],
  2263. ["101405", "Green Waterloo"],
  2264. ["105852", "Eden"],
  2265. ["110C6C", "Arapawa"],
  2266. ["120A8F", "Ultramarine"],
  2267. ["123447", "Elephant"],
  2268. ["126B40", "Jewel"],
  2269. ["130000", "Diesel"],
  2270. ["130A06", "Asphalt"],
  2271. ["13264D", "Blue Zodiac"],
  2272. ["134F19", "Parsley"],
  2273. ["140600", "Nero"],
  2274. ["1450AA", "Tory Blue"],
  2275. ["151F4C", "Bunting"],
  2276. ["1560BD", "Denim"],
  2277. ["15736B", "Genoa"],
  2278. ["161928", "Mirage"],
  2279. ["161D10", "Hunter Green"],
  2280. ["162A40", "Big Stone"],
  2281. ["163222", "Celtic"],
  2282. ["16322C", "Timber Green"],
  2283. ["163531", "Gable Green"],
  2284. ["171F04", "Pine Tree"],
  2285. ["175579", "Chathams Blue"],
  2286. ["182D09", "Deep Forest Green"],
  2287. ["18587A", "Blumine"],
  2288. ["19330E", "Palm Leaf"],
  2289. ["193751", "Nile Blue"],
  2290. ["1959A8", "Fun Blue"],
  2291. ["1A1A68", "Lucky Point"],
  2292. ["1AB385", "Mountain Meadow"],
  2293. ["1B0245", "Tolopea"],
  2294. ["1B1035", "Haiti"],
  2295. ["1B127B", "Deep Koamaru"],
  2296. ["1B1404", "Acadia"],
  2297. ["1B2F11", "Seaweed"],
  2298. ["1B3162", "Biscay"],
  2299. ["1B659D", "Matisse"],
  2300. ["1C1208", "Crowshead"],
  2301. ["1C1E13", "Rangoon Green"],
  2302. ["1C39BB", "Persian Blue"],
  2303. ["1C402E", "Everglade"],
  2304. ["1C7C7D", "Elm"],
  2305. ["1D6142", "Green Pea"],
  2306. ["1E0F04", "Creole"],
  2307. ["1E1609", "Karaka"],
  2308. ["1E1708", "El Paso"],
  2309. ["1E385B", "Cello"],
  2310. ["1E433C", "Te Papa Green"],
  2311. ["1E90FF", "Dodger Blue"],
  2312. ["1E9AB0", "Eastern Blue"],
  2313. ["1F120F", "Night Rider"],
  2314. ["1FC2C2", "Java"],
  2315. ["20208D", "Jacksons Purple"],
  2316. ["202E54", "Cloud Burst"],
  2317. ["204852", "Blue Dianne"],
  2318. ["211A0E", "Eternity"],
  2319. ["220878", "Deep Blue"],
  2320. ["228B22", "Forest Green"],
  2321. ["233418", "Mallard"],
  2322. ["240A40", "Violet"],
  2323. ["240C02", "Kilamanjaro"],
  2324. ["242A1D", "Log Cabin"],
  2325. ["242E16", "Black Olive"],
  2326. ["24500F", "Green House"],
  2327. ["251607", "Graphite"],
  2328. ["251706", "Cannon Black"],
  2329. ["251F4F", "Port Gore"],
  2330. ["25272C", "Shark"],
  2331. ["25311C", "Green Kelp"],
  2332. ["2596D1", "Curious Blue"],
  2333. ["260368", "Paua"],
  2334. ["26056A", "Paris M"],
  2335. ["261105", "Wood Bark"],
  2336. ["261414", "Gondola"],
  2337. ["262335", "Steel Gray"],
  2338. ["26283B", "Ebony Clay"],
  2339. ["273A81", "Bay of Many"],
  2340. ["27504B", "Plantation"],
  2341. ["278A5B", "Eucalyptus"],
  2342. ["281E15", "Oil"],
  2343. ["283A77", "Astronaut"],
  2344. ["286ACD", "Mariner"],
  2345. ["290C5E", "Violent Violet"],
  2346. ["292130", "Bastille"],
  2347. ["292319", "Zeus"],
  2348. ["292937", "Charade"],
  2349. ["297B9A", "Jelly Bean"],
  2350. ["29AB87", "Jungle Green"],
  2351. ["2A0359", "Cherry Pie"],
  2352. ["2A140E", "Coffee Bean"],
  2353. ["2A2630", "Baltic Sea"],
  2354. ["2A380B", "Turtle Green"],
  2355. ["2A52BE", "Cerulean Blue"],
  2356. ["2B0202", "Sepia Black"],
  2357. ["2B194F", "Valhalla"],
  2358. ["2B3228", "Heavy Metal"],
  2359. ["2C0E8C", "Blue Gem"],
  2360. ["2C1632", "Revolver"],
  2361. ["2C2133", "Bleached Cedar"],
  2362. ["2C8C84", "Lochinvar"],
  2363. ["2D2510", "Mikado"],
  2364. ["2D383A", "Outer Space"],
  2365. ["2D569B", "St Tropaz"],
  2366. ["2E0329", "Jacaranda"],
  2367. ["2E1905", "Jacko Bean"],
  2368. ["2E3222", "Rangitoto"],
  2369. ["2E3F62", "Rhino"],
  2370. ["2E8B57", "Sea Green"],
  2371. ["2EBFD4", "Scooter"],
  2372. ["2F270E", "Onion"],
  2373. ["2F3CB3", "Governor Bay"],
  2374. ["2F519E", "Sapphire"],
  2375. ["2F5A57", "Spectra"],
  2376. ["2F6168", "Casal"],
  2377. ["300529", "Melanzane"],
  2378. ["301F1E", "Cocoa Brown"],
  2379. ["302A0F", "Woodrush"],
  2380. ["304B6A", "San Juan"],
  2381. ["30D5C8", "Turquoise"],
  2382. ["311C17", "Eclipse"],
  2383. ["314459", "Pickled Bluewood"],
  2384. ["315BA1", "Azure"],
  2385. ["31728D", "Calypso"],
  2386. ["317D82", "Paradiso"],
  2387. ["32127A", "Persian Indigo"],
  2388. ["32293A", "Blackcurrant"],
  2389. ["323232", "Mine Shaft"],
  2390. ["325D52", "Stromboli"],
  2391. ["327C14", "Bilbao"],
  2392. ["327DA0", "Astral"],
  2393. ["33036B", "Christalle"],
  2394. ["33292F", "Thunder"],
  2395. ["33CC99", "Shamrock"],
  2396. ["341515", "Tamarind"],
  2397. ["350036", "Mardi Gras"],
  2398. ["350E42", "Valentino"],
  2399. ["350E57", "Jagger"],
  2400. ["353542", "Tuna"],
  2401. ["354E8C", "Chambray"],
  2402. ["363050", "Martinique"],
  2403. ["363534", "Tuatara"],
  2404. ["363C0D", "Waiouru"],
  2405. ["36747D", "Ming"],
  2406. ["368716", "La Palma"],
  2407. ["370202", "Chocolate"],
  2408. ["371D09", "Clinker"],
  2409. ["37290E", "Brown Tumbleweed"],
  2410. ["373021", "Birch"],
  2411. ["377475", "Oracle"],
  2412. ["380474", "Blue Diamond"],
  2413. ["381A51", "Grape"],
  2414. ["383533", "Dune"],
  2415. ["384555", "Oxford Blue"],
  2416. ["384910", "Clover"],
  2417. ["394851", "Limed Spruce"],
  2418. ["396413", "Dell"],
  2419. ["3A0020", "Toledo"],
  2420. ["3A2010", "Sambuca"],
  2421. ["3A2A6A", "Jacarta"],
  2422. ["3A686C", "William"],
  2423. ["3A6A47", "Killarney"],
  2424. ["3AB09E", "Keppel"],
  2425. ["3B000B", "Temptress"],
  2426. ["3B0910", "Aubergine"],
  2427. ["3B1F1F", "Jon"],
  2428. ["3B2820", "Treehouse"],
  2429. ["3B7A57", "Amazon"],
  2430. ["3B91B4", "Boston Blue"],
  2431. ["3C0878", "Windsor"],
  2432. ["3C1206", "Rebel"],
  2433. ["3C1F76", "Meteorite"],
  2434. ["3C2005", "Dark Ebony"],
  2435. ["3C3910", "Camouflage"],
  2436. ["3C4151", "Bright Gray"],
  2437. ["3C4443", "Cape Cod"],
  2438. ["3C493A", "Lunar Green"],
  2439. ["3D0C02", "Bean "],
  2440. ["3D2B1F", "Bistre"],
  2441. ["3D7D52", "Goblin"],
  2442. ["3E0480", "Kingfisher Daisy"],
  2443. ["3E1C14", "Cedar"],
  2444. ["3E2B23", "English Walnut"],
  2445. ["3E2C1C", "Black Marlin"],
  2446. ["3E3A44", "Ship Gray"],
  2447. ["3EABBF", "Pelorous"],
  2448. ["3F2109", "Bronze"],
  2449. ["3F2500", "Cola"],
  2450. ["3F3002", "Madras"],
  2451. ["3F307F", "Minsk"],
  2452. ["3F4C3A", "Cabbage Pont"],
  2453. ["3F583B", "Tom Thumb"],
  2454. ["3F5D53", "Mineral Green"],
  2455. ["3FC1AA", "Puerto Rico"],
  2456. ["3FFF00", "Harlequin"],
  2457. ["401801", "Brown Pod"],
  2458. ["40291D", "Cork"],
  2459. ["403B38", "Masala"],
  2460. ["403D19", "Thatch Green"],
  2461. ["405169", "Fiord"],
  2462. ["40826D", "Viridian"],
  2463. ["40A860", "Chateau Green"],
  2464. ["410056", "Ripe Plum"],
  2465. ["411F10", "Paco"],
  2466. ["412010", "Deep Oak"],
  2467. ["413C37", "Merlin"],
  2468. ["414257", "Gun Powder"],
  2469. ["414C7D", "East Bay"],
  2470. ["4169E1", "Royal Blue"],
  2471. ["41AA78", "Ocean Green"],
  2472. ["420303", "Burnt Maroon"],
  2473. ["423921", "Lisbon Brown"],
  2474. ["427977", "Faded Jade"],
  2475. ["431560", "Scarlet Gum"],
  2476. ["433120", "Iroko"],
  2477. ["433E37", "Armadillo"],
  2478. ["434C59", "River Bed"],
  2479. ["436A0D", "Green Leaf"],
  2480. ["44012D", "Barossa"],
  2481. ["441D00", "Morocco Brown"],
  2482. ["444954", "Mako"],
  2483. ["454936", "Kelp"],
  2484. ["456CAC", "San Marino"],
  2485. ["45B1E8", "Picton Blue"],
  2486. ["460B41", "Loulou"],
  2487. ["462425", "Crater Brown"],
  2488. ["465945", "Gray Asparagus"],
  2489. ["4682B4", "Steel Blue"],
  2490. ["480404", "Rustic Red"],
  2491. ["480607", "Bulgarian Rose"],
  2492. ["480656", "Clairvoyant"],
  2493. ["481C1C", "Cocoa Bean"],
  2494. ["483131", "Woody Brown"],
  2495. ["483C32", "Taupe"],
  2496. ["49170C", "Van Cleef"],
  2497. ["492615", "Brown Derby"],
  2498. ["49371B", "Metallic Bronze"],
  2499. ["495400", "Verdun Green"],
  2500. ["496679", "Blue Bayoux"],
  2501. ["497183", "Bismark"],
  2502. ["4A2A04", "Bracken"],
  2503. ["4A3004", "Deep Bronze"],
  2504. ["4A3C30", "Mondo"],
  2505. ["4A4244", "Tundora"],
  2506. ["4A444B", "Gravel"],
  2507. ["4A4E5A", "Trout"],
  2508. ["4B0082", "Pigment Indigo"],
  2509. ["4B5D52", "Nandor"],
  2510. ["4C3024", "Saddle"],
  2511. ["4C4F56", "Abbey"],
  2512. ["4D0135", "Blackberry"],
  2513. ["4D0A18", "Cab Sav"],
  2514. ["4D1E01", "Indian Tan"],
  2515. ["4D282D", "Cowboy"],
  2516. ["4D282E", "Livid Brown"],
  2517. ["4D3833", "Rock"],
  2518. ["4D3D14", "Punga"],
  2519. ["4D400F", "Bronzetone"],
  2520. ["4D5328", "Woodland"],
  2521. ["4E0606", "Mahogany"],
  2522. ["4E2A5A", "Bossanova"],
  2523. ["4E3B41", "Matterhorn"],
  2524. ["4E420C", "Bronze Olive"],
  2525. ["4E4562", "Mulled Wine"],
  2526. ["4E6649", "Axolotl"],
  2527. ["4E7F9E", "Wedgewood"],
  2528. ["4EABD1", "Shakespeare"],
  2529. ["4F1C70", "Honey Flower"],
  2530. ["4F2398", "Daisy Bush"],
  2531. ["4F69C6", "Indigo"],
  2532. ["4F7942", "Fern Green"],
  2533. ["4F9D5D", "Fruit Salad"],
  2534. ["4FA83D", "Apple"],
  2535. ["504351", "Mortar"],
  2536. ["507096", "Kashmir Blue"],
  2537. ["507672", "Cutty Sark"],
  2538. ["50C878", "Emerald"],
  2539. ["514649", "Emperor"],
  2540. ["516E3D", "Chalet Green"],
  2541. ["517C66", "Como"],
  2542. ["51808F", "Smalt Blue"],
  2543. ["52001F", "Castro"],
  2544. ["520C17", "Maroon Oak"],
  2545. ["523C94", "Gigas"],
  2546. ["533455", "Voodoo"],
  2547. ["534491", "Victoria"],
  2548. ["53824B", "Hippie Green"],
  2549. ["541012", "Heath"],
  2550. ["544333", "Judge Gray"],
  2551. ["54534D", "Fuscous Gray"],
  2552. ["549019", "Vida Loca"],
  2553. ["55280C", "Cioccolato"],
  2554. ["555B10", "Saratoga"],
  2555. ["556D56", "Finlandia"],
  2556. ["5590D9", "Havelock Blue"],
  2557. ["56B4BE", "Fountain Blue"],
  2558. ["578363", "Spring Leaves"],
  2559. ["583401", "Saddle Brown"],
  2560. ["585562", "Scarpa Flow"],
  2561. ["587156", "Cactus"],
  2562. ["589AAF", "Hippie Blue"],
  2563. ["591D35", "Wine Berry"],
  2564. ["592804", "Brown Bramble"],
  2565. ["593737", "Congo Brown"],
  2566. ["594433", "Millbrook"],
  2567. ["5A6E9C", "Waikawa Gray"],
  2568. ["5A87A0", "Horizon"],
  2569. ["5B3013", "Jambalaya"],
  2570. ["5C0120", "Bordeaux"],
  2571. ["5C0536", "Mulberry Wood"],
  2572. ["5C2E01", "Carnaby Tan"],
  2573. ["5C5D75", "Comet"],
  2574. ["5D1E0F", "Redwood"],
  2575. ["5D4C51", "Don Juan"],
  2576. ["5D5C58", "Chicago"],
  2577. ["5D5E37", "Verdigris"],
  2578. ["5D7747", "Dingley"],
  2579. ["5DA19F", "Breaker Bay"],
  2580. ["5E483E", "Kabul"],
  2581. ["5E5D3B", "Hemlock"],
  2582. ["5F3D26", "Irish Coffee"],
  2583. ["5F5F6E", "Mid Gray"],
  2584. ["5F6672", "Shuttle Gray"],
  2585. ["5FA777", "Aqua Forest"],
  2586. ["5FB3AC", "Tradewind"],
  2587. ["604913", "Horses Neck"],
  2588. ["605B73", "Smoky"],
  2589. ["606E68", "Corduroy"],
  2590. ["6093D1", "Danube"],
  2591. ["612718", "Espresso"],
  2592. ["614051", "Eggplant"],
  2593. ["615D30", "Costa Del Sol"],
  2594. ["61845F", "Glade Green"],
  2595. ["622F30", "Buccaneer"],
  2596. ["623F2D", "Quincy"],
  2597. ["624E9A", "Butterfly Bush"],
  2598. ["625119", "West Coast"],
  2599. ["626649", "Finch"],
  2600. ["639A8F", "Patina"],
  2601. ["63B76C", "Fern"],
  2602. ["6456B7", "Blue Violet"],
  2603. ["646077", "Dolphin"],
  2604. ["646463", "Storm Dust"],
  2605. ["646A54", "Siam"],
  2606. ["646E75", "Nevada"],
  2607. ["6495ED", "Cornflower Blue"],
  2608. ["64CCDB", "Viking"],
  2609. ["65000B", "Rosewood"],
  2610. ["651A14", "Cherrywood"],
  2611. ["652DC1", "Purple Heart"],
  2612. ["657220", "Fern Frond"],
  2613. ["65745D", "Willow Grove"],
  2614. ["65869F", "Hoki"],
  2615. ["660045", "Pompadour"],
  2616. ["660099", "Purple"],
  2617. ["66023C", "Tyrian Purple"],
  2618. ["661010", "Dark Tan"],
  2619. ["66B58F", "Silver Tree"],
  2620. ["66FF00", "Bright Green"],
  2621. ["66FF66", "Screamin' Green"],
  2622. ["67032D", "Black Rose"],
  2623. ["675FA6", "Scampi"],
  2624. ["676662", "Ironside Gray"],
  2625. ["678975", "Viridian Green"],
  2626. ["67A712", "Christi"],
  2627. ["683600", "Nutmeg Wood Finish"],
  2628. ["685558", "Zambezi"],
  2629. ["685E6E", "Salt Box"],
  2630. ["692545", "Tawny Port"],
  2631. ["692D54", "Finn"],
  2632. ["695F62", "Scorpion"],
  2633. ["697E9A", "Lynch"],
  2634. ["6A442E", "Spice"],
  2635. ["6A5D1B", "Himalaya"],
  2636. ["6A6051", "Soya Bean"],
  2637. ["6B2A14", "Hairy Heath"],
  2638. ["6B3FA0", "Royal Purple"],
  2639. ["6B4E31", "Shingle Fawn"],
  2640. ["6B5755", "Dorado"],
  2641. ["6B8BA2", "Bermuda Gray"],
  2642. ["6B8E23", "Olive Drab"],
  2643. ["6C3082", "Eminence"],
  2644. ["6CDAE7", "Turquoise Blue"],
  2645. ["6D0101", "Lonestar"],
  2646. ["6D5E54", "Pine Cone"],
  2647. ["6D6C6C", "Dove Gray"],
  2648. ["6D9292", "Juniper"],
  2649. ["6D92A1", "Gothic"],
  2650. ["6E0902", "Red Oxide"],
  2651. ["6E1D14", "Moccaccino"],
  2652. ["6E4826", "Pickled Bean"],
  2653. ["6E4B26", "Dallas"],
  2654. ["6E6D57", "Kokoda"],
  2655. ["6E7783", "Pale Sky"],
  2656. ["6F440C", "Cafe Royale"],
  2657. ["6F6A61", "Flint"],
  2658. ["6F8E63", "Highland"],
  2659. ["6F9D02", "Limeade"],
  2660. ["6FD0C5", "Downy"],
  2661. ["701C1C", "Persian Plum"],
  2662. ["704214", "Sepia"],
  2663. ["704A07", "Antique Bronze"],
  2664. ["704F50", "Ferra"],
  2665. ["706555", "Coffee"],
  2666. ["708090", "Slate Gray"],
  2667. ["711A00", "Cedar Wood Finish"],
  2668. ["71291D", "Metallic Copper"],
  2669. ["714693", "Affair"],
  2670. ["714AB2", "Studio"],
  2671. ["715D47", "Tobacco Brown"],
  2672. ["716338", "Yellow Metal"],
  2673. ["716B56", "Peat"],
  2674. ["716E10", "Olivetone"],
  2675. ["717486", "Storm Gray"],
  2676. ["718080", "Sirocco"],
  2677. ["71D9E2", "Aquamarine Blue"],
  2678. ["72010F", "Venetian Red"],
  2679. ["724A2F", "Old Copper"],
  2680. ["726D4E", "Go Ben"],
  2681. ["727B89", "Raven"],
  2682. ["731E8F", "Seance"],
  2683. ["734A12", "Raw Umber"],
  2684. ["736C9F", "Kimberly"],
  2685. ["736D58", "Crocodile"],
  2686. ["737829", "Crete"],
  2687. ["738678", "Xanadu"],
  2688. ["74640D", "Spicy Mustard"],
  2689. ["747D63", "Limed Ash"],
  2690. ["747D83", "Rolling Stone"],
  2691. ["748881", "Blue Smoke"],
  2692. ["749378", "Laurel"],
  2693. ["74C365", "Mantis"],
  2694. ["755A57", "Russett"],
  2695. ["7563A8", "Deluge"],
  2696. ["76395D", "Cosmic"],
  2697. ["7666C6", "Blue Marguerite"],
  2698. ["76BD17", "Lima"],
  2699. ["76D7EA", "Sky Blue"],
  2700. ["770F05", "Dark Burgundy"],
  2701. ["771F1F", "Crown of Thorns"],
  2702. ["773F1A", "Walnut"],
  2703. ["776F61", "Pablo"],
  2704. ["778120", "Pacifika"],
  2705. ["779E86", "Oxley"],
  2706. ["77DD77", "Pastel Green"],
  2707. ["780109", "Japanese Maple"],
  2708. ["782D19", "Mocha"],
  2709. ["782F16", "Peanut"],
  2710. ["78866B", "Camouflage Green"],
  2711. ["788A25", "Wasabi"],
  2712. ["788BBA", "Ship Cove"],
  2713. ["78A39C", "Sea Nymph"],
  2714. ["795D4C", "Roman Coffee"],
  2715. ["796878", "Old Lavender"],
  2716. ["796989", "Rum"],
  2717. ["796A78", "Fedora"],
  2718. ["796D62", "Sandstone"],
  2719. ["79DEEC", "Spray"],
  2720. ["7A013A", "Siren"],
  2721. ["7A58C1", "Fuchsia Blue"],
  2722. ["7A7A7A", "Boulder"],
  2723. ["7A89B8", "Wild Blue Yonder"],
  2724. ["7AC488", "De York"],
  2725. ["7B3801", "Red Beech"],
  2726. ["7B3F00", "Cinnamon"],
  2727. ["7B6608", "Yukon Gold"],
  2728. ["7B7874", "Tapa"],
  2729. ["7B7C94", "Waterloo "],
  2730. ["7B8265", "Flax Smoke"],
  2731. ["7B9F80", "Amulet"],
  2732. ["7BA05B", "Asparagus"],
  2733. ["7C1C05", "Kenyan Copper"],
  2734. ["7C7631", "Pesto"],
  2735. ["7C778A", "Topaz"],
  2736. ["7C7B7A", "Concord"],
  2737. ["7C7B82", "Jumbo"],
  2738. ["7C881A", "Trendy Green"],
  2739. ["7CA1A6", "Gumbo"],
  2740. ["7CB0A1", "Acapulco"],
  2741. ["7CB7BB", "Neptune"],
  2742. ["7D2C14", "Pueblo"],
  2743. ["7DA98D", "Bay Leaf"],
  2744. ["7DC8F7", "Malibu"],
  2745. ["7DD8C6", "Bermuda"],
  2746. ["7E3A15", "Copper Canyon"],
  2747. ["7F1734", "Claret"],
  2748. ["7F3A02", "Peru Tan"],
  2749. ["7F626D", "Falcon"],
  2750. ["7F7589", "Mobster"],
  2751. ["7F76D3", "Moody Blue"],
  2752. ["7FFF00", "Chartreuse"],
  2753. ["7FFFD4", "Aquamarine"],
  2754. ["800000", "Maroon"],
  2755. ["800B47", "Rose Bud Cherry"],
  2756. ["801818", "Falu Red"],
  2757. ["80341F", "Red Robin"],
  2758. ["803790", "Vivid Violet"],
  2759. ["80461B", "Russet"],
  2760. ["807E79", "Friar Gray"],
  2761. ["808000", "Olive"],
  2762. ["808080", "Gray"],
  2763. ["80B3AE", "Gulf Stream"],
  2764. ["80B3C4", "Glacier"],
  2765. ["80CCEA", "Seagull"],
  2766. ["81422C", "Nutmeg"],
  2767. ["816E71", "Spicy Pink"],
  2768. ["817377", "Empress"],
  2769. ["819885", "Spanish Green"],
  2770. ["826F65", "Sand Dune"],
  2771. ["828685", "Gunsmoke"],
  2772. ["828F72", "Battleship Gray"],
  2773. ["831923", "Merlot"],
  2774. ["837050", "Shadow"],
  2775. ["83AA5D", "Chelsea Cucumber"],
  2776. ["83D0C6", "Monte Carlo"],
  2777. ["843179", "Plum"],
  2778. ["84A0A0", "Granny Smith"],
  2779. ["8581D9", "Chetwode Blue"],
  2780. ["858470", "Bandicoot"],
  2781. ["859FAF", "Bali Hai"],
  2782. ["85C4CC", "Half Baked"],
  2783. ["860111", "Red Devil"],
  2784. ["863C3C", "Lotus"],
  2785. ["86483C", "Ironstone"],
  2786. ["864D1E", "Bull Shot"],
  2787. ["86560A", "Rusty Nail"],
  2788. ["868974", "Bitter"],
  2789. ["86949F", "Regent Gray"],
  2790. ["871550", "Disco"],
  2791. ["87756E", "Americano"],
  2792. ["877C7B", "Hurricane"],
  2793. ["878D91", "Oslo Gray"],
  2794. ["87AB39", "Sushi"],
  2795. ["885342", "Spicy Mix"],
  2796. ["886221", "Kumera"],
  2797. ["888387", "Suva Gray"],
  2798. ["888D65", "Avocado"],
  2799. ["893456", "Camelot"],
  2800. ["893843", "Solid Pink"],
  2801. ["894367", "Cannon Pink"],
  2802. ["897D6D", "Makara"],
  2803. ["8A3324", "Burnt Umber"],
  2804. ["8A73D6", "True V"],
  2805. ["8A8360", "Clay Creek"],
  2806. ["8A8389", "Monsoon"],
  2807. ["8A8F8A", "Stack"],
  2808. ["8AB9F1", "Jordy Blue"],
  2809. ["8B00FF", "Electric Violet"],
  2810. ["8B0723", "Monarch"],
  2811. ["8B6B0B", "Corn Harvest"],
  2812. ["8B8470", "Olive Haze"],
  2813. ["8B847E", "Schooner"],
  2814. ["8B8680", "Natural Gray"],
  2815. ["8B9C90", "Mantle"],
  2816. ["8B9FEE", "Portage"],
  2817. ["8BA690", "Envy"],
  2818. ["8BA9A5", "Cascade"],
  2819. ["8BE6D8", "Riptide"],
  2820. ["8C055E", "Cardinal Pink"],
  2821. ["8C472F", "Mule Fawn"],
  2822. ["8C5738", "Potters Clay"],
  2823. ["8C6495", "Trendy Pink"],
  2824. ["8D0226", "Paprika"],
  2825. ["8D3D38", "Sanguine Brown"],
  2826. ["8D3F3F", "Tosca"],
  2827. ["8D7662", "Cement"],
  2828. ["8D8974", "Granite Green"],
  2829. ["8D90A1", "Manatee"],
  2830. ["8DA8CC", "Polo Blue"],
  2831. ["8E0000", "Red Berry"],
  2832. ["8E4D1E", "Rope"],
  2833. ["8E6F70", "Opium"],
  2834. ["8E775E", "Domino"],
  2835. ["8E8190", "Mamba"],
  2836. ["8EABC1", "Nepal"],
  2837. ["8F021C", "Pohutukawa"],
  2838. ["8F3E33", "El Salva"],
  2839. ["8F4B0E", "Korma"],
  2840. ["8F8176", "Squirrel"],
  2841. ["8FD6B4", "Vista Blue"],
  2842. ["900020", "Burgundy"],
  2843. ["901E1E", "Old Brick"],
  2844. ["907874", "Hemp"],
  2845. ["907B71", "Almond Frost"],
  2846. ["908D39", "Sycamore"],
  2847. ["92000A", "Sangria"],
  2848. ["924321", "Cumin"],
  2849. ["926F5B", "Beaver"],
  2850. ["928573", "Stonewall"],
  2851. ["928590", "Venus"],
  2852. ["9370DB", "Medium Purple"],
  2853. ["93CCEA", "Cornflower"],
  2854. ["93DFB8", "Algae Green"],
  2855. ["944747", "Copper Rust"],
  2856. ["948771", "Arrowtown"],
  2857. ["950015", "Scarlett"],
  2858. ["956387", "Strikemaster"],
  2859. ["959396", "Mountain Mist"],
  2860. ["960018", "Carmine"],
  2861. ["964B00", "Brown"],
  2862. ["967059", "Leather"],
  2863. ["9678B6", "Purple Mountain's Majesty"],
  2864. ["967BB6", "Lavender Purple"],
  2865. ["96A8A1", "Pewter"],
  2866. ["96BBAB", "Summer Green"],
  2867. ["97605D", "Au Chico"],
  2868. ["9771B5", "Wisteria"],
  2869. ["97CD2D", "Atlantis"],
  2870. ["983D61", "Vin Rouge"],
  2871. ["9874D3", "Lilac Bush"],
  2872. ["98777B", "Bazaar"],
  2873. ["98811B", "Hacienda"],
  2874. ["988D77", "Pale Oyster"],
  2875. ["98FF98", "Mint Green"],
  2876. ["990066", "Fresh Eggplant"],
  2877. ["991199", "Violet Eggplant"],
  2878. ["991613", "Tamarillo"],
  2879. ["991B07", "Totem Pole"],
  2880. ["996666", "Copper Rose"],
  2881. ["9966CC", "Amethyst"],
  2882. ["997A8D", "Mountbatten Pink"],
  2883. ["9999CC", "Blue Bell"],
  2884. ["9A3820", "Prairie Sand"],
  2885. ["9A6E61", "Toast"],
  2886. ["9A9577", "Gurkha"],
  2887. ["9AB973", "Olivine"],
  2888. ["9AC2B8", "Shadow Green"],
  2889. ["9B4703", "Oregon"],
  2890. ["9B9E8F", "Lemon Grass"],
  2891. ["9C3336", "Stiletto"],
  2892. ["9D5616", "Hawaiian Tan"],
  2893. ["9DACB7", "Gull Gray"],
  2894. ["9DC209", "Pistachio"],
  2895. ["9DE093", "Granny Smith Apple"],
  2896. ["9DE5FF", "Anakiwa"],
  2897. ["9E5302", "Chelsea Gem"],
  2898. ["9E5B40", "Sepia Skin"],
  2899. ["9EA587", "Sage"],
  2900. ["9EA91F", "Citron"],
  2901. ["9EB1CD", "Rock Blue"],
  2902. ["9EDEE0", "Morning Glory"],
  2903. ["9F381D", "Cognac"],
  2904. ["9F821C", "Reef Gold"],
  2905. ["9F9F9C", "Star Dust"],
  2906. ["9FA0B1", "Santas Gray"],
  2907. ["9FD7D3", "Sinbad"],
  2908. ["9FDD8C", "Feijoa"],
  2909. ["A02712", "Tabasco"],
  2910. ["A1750D", "Buttered Rum"],
  2911. ["A1ADB5", "Hit Gray"],
  2912. ["A1C50A", "Citrus"],
  2913. ["A1DAD7", "Aqua Island"],
  2914. ["A1E9DE", "Water Leaf"],
  2915. ["A2006D", "Flirt"],
  2916. ["A23B6C", "Rouge"],
  2917. ["A26645", "Cape Palliser"],
  2918. ["A2AAB3", "Gray Chateau"],
  2919. ["A2AEAB", "Edward"],
  2920. ["A3807B", "Pharlap"],
  2921. ["A397B4", "Amethyst Smoke"],
  2922. ["A3E3ED", "Blizzard Blue"],
  2923. ["A4A49D", "Delta"],
  2924. ["A4A6D3", "Wistful"],
  2925. ["A4AF6E", "Green Smoke"],
  2926. ["A50B5E", "Jazzberry Jam"],
  2927. ["A59B91", "Zorba"],
  2928. ["A5CB0C", "Bahia"],
  2929. ["A62F20", "Roof Terracotta"],
  2930. ["A65529", "Paarl"],
  2931. ["A68B5B", "Barley Corn"],
  2932. ["A69279", "Donkey Brown"],
  2933. ["A6A29A", "Dawn"],
  2934. ["A72525", "Mexican Red"],
  2935. ["A7882C", "Luxor Gold"],
  2936. ["A85307", "Rich Gold"],
  2937. ["A86515", "Reno Sand"],
  2938. ["A86B6B", "Coral Tree"],
  2939. ["A8989B", "Dusty Gray"],
  2940. ["A899E6", "Dull Lavender"],
  2941. ["A8A589", "Tallow"],
  2942. ["A8AE9C", "Bud"],
  2943. ["A8AF8E", "Locust"],
  2944. ["A8BD9F", "Norway"],
  2945. ["A8E3BD", "Chinook"],
  2946. ["A9A491", "Gray Olive"],
  2947. ["A9ACB6", "Aluminium"],
  2948. ["A9B2C3", "Cadet Blue"],
  2949. ["A9B497", "Schist"],
  2950. ["A9BDBF", "Tower Gray"],
  2951. ["A9BEF2", "Perano"],
  2952. ["A9C6C2", "Opal"],
  2953. ["AA375A", "Night Shadz"],
  2954. ["AA4203", "Fire"],
  2955. ["AA8B5B", "Muesli"],
  2956. ["AA8D6F", "Sandal"],
  2957. ["AAA5A9", "Shady Lady"],
  2958. ["AAA9CD", "Logan"],
  2959. ["AAABB7", "Spun Pearl"],
  2960. ["AAD6E6", "Regent St Blue"],
  2961. ["AAF0D1", "Magic Mint"],
  2962. ["AB0563", "Lipstick"],
  2963. ["AB3472", "Royal Heath"],
  2964. ["AB917A", "Sandrift"],
  2965. ["ABA0D9", "Cold Purple"],
  2966. ["ABA196", "Bronco"],
  2967. ["AC8A56", "Limed Oak"],
  2968. ["AC91CE", "East Side"],
  2969. ["AC9E22", "Lemon Ginger"],
  2970. ["ACA494", "Napa"],
  2971. ["ACA586", "Hillary"],
  2972. ["ACA59F", "Cloudy"],
  2973. ["ACACAC", "Silver Chalice"],
  2974. ["ACB78E", "Swamp Green"],
  2975. ["ACCBB1", "Spring Rain"],
  2976. ["ACDD4D", "Conifer"],
  2977. ["ACE1AF", "Celadon"],
  2978. ["AD781B", "Mandalay"],
  2979. ["ADBED1", "Casper"],
  2980. ["ADDFAD", "Moss Green"],
  2981. ["ADE6C4", "Padua"],
  2982. ["ADFF2F", "Green Yellow"],
  2983. ["AE4560", "Hippie Pink"],
  2984. ["AE6020", "Desert"],
  2985. ["AE809E", "Bouquet"],
  2986. ["AF4035", "Medium Carmine"],
  2987. ["AF4D43", "Apple Blossom"],
  2988. ["AF593E", "Brown Rust"],
  2989. ["AF8751", "Driftwood"],
  2990. ["AF8F2C", "Alpine"],
  2991. ["AF9F1C", "Lucky"],
  2992. ["AFA09E", "Martini"],
  2993. ["AFB1B8", "Bombay"],
  2994. ["AFBDD9", "Pigeon Post"],
  2995. ["B04C6A", "Cadillac"],
  2996. ["B05D54", "Matrix"],
  2997. ["B05E81", "Tapestry"],
  2998. ["B06608", "Mai Tai"],
  2999. ["B09A95", "Del Rio"],
  3000. ["B0E0E6", "Powder Blue"],
  3001. ["B0E313", "Inch Worm"],
  3002. ["B10000", "Bright Red"],
  3003. ["B14A0B", "Vesuvius"],
  3004. ["B1610B", "Pumpkin Skin"],
  3005. ["B16D52", "Santa Fe"],
  3006. ["B19461", "Teak"],
  3007. ["B1E2C1", "Fringy Flower"],
  3008. ["B1F4E7", "Ice Cold"],
  3009. ["B20931", "Shiraz"],
  3010. ["B2A1EA", "Biloba Flower"],
  3011. ["B32D29", "Tall Poppy"],
  3012. ["B35213", "Fiery Orange"],
  3013. ["B38007", "Hot Toddy"],
  3014. ["B3AF95", "Taupe Gray"],
  3015. ["B3C110", "La Rioja"],
  3016. ["B43332", "Well Read"],
  3017. ["B44668", "Blush"],
  3018. ["B4CFD3", "Jungle Mist"],
  3019. ["B57281", "Turkish Rose"],
  3020. ["B57EDC", "Lavender"],
  3021. ["B5A27F", "Mongoose"],
  3022. ["B5B35C", "Olive Green"],
  3023. ["B5D2CE", "Jet Stream"],
  3024. ["B5ECDF", "Cruise"],
  3025. ["B6316C", "Hibiscus"],
  3026. ["B69D98", "Thatch"],
  3027. ["B6B095", "Heathered Gray"],
  3028. ["B6BAA4", "Eagle"],
  3029. ["B6D1EA", "Spindle"],
  3030. ["B6D3BF", "Gum Leaf"],
  3031. ["B7410E", "Rust"],
  3032. ["B78E5C", "Muddy Waters"],
  3033. ["B7A214", "Sahara"],
  3034. ["B7A458", "Husk"],
  3035. ["B7B1B1", "Nobel"],
  3036. ["B7C3D0", "Heather"],
  3037. ["B7F0BE", "Madang"],
  3038. ["B81104", "Milano Red"],
  3039. ["B87333", "Copper"],
  3040. ["B8B56A", "Gimblet"],
  3041. ["B8C1B1", "Green Spring"],
  3042. ["B8C25D", "Celery"],
  3043. ["B8E0F9", "Sail"],
  3044. ["B94E48", "Chestnut"],
  3045. ["B95140", "Crail"],
  3046. ["B98D28", "Marigold"],
  3047. ["B9C46A", "Wild Willow"],
  3048. ["B9C8AC", "Rainee"],
  3049. ["BA0101", "Guardsman Red"],
  3050. ["BA450C", "Rock Spray"],
  3051. ["BA6F1E", "Bourbon"],
  3052. ["BA7F03", "Pirate Gold"],
  3053. ["BAB1A2", "Nomad"],
  3054. ["BAC7C9", "Submarine"],
  3055. ["BAEEF9", "Charlotte"],
  3056. ["BB3385", "Medium Red Violet"],
  3057. ["BB8983", "Brandy Rose"],
  3058. ["BBD009", "Rio Grande"],
  3059. ["BBD7C1", "Surf"],
  3060. ["BCC9C2", "Powder Ash"],
  3061. ["BD5E2E", "Tuscany"],
  3062. ["BD978E", "Quicksand"],
  3063. ["BDB1A8", "Silk"],
  3064. ["BDB2A1", "Malta"],
  3065. ["BDB3C7", "Chatelle"],
  3066. ["BDBBD7", "Lavender Gray"],
  3067. ["BDBDC6", "French Gray"],
  3068. ["BDC8B3", "Clay Ash"],
  3069. ["BDC9CE", "Loblolly"],
  3070. ["BDEDFD", "French Pass"],
  3071. ["BEA6C3", "London Hue"],
  3072. ["BEB5B7", "Pink Swan"],
  3073. ["BEDE0D", "Fuego"],
  3074. ["BF5500", "Rose of Sharon"],
  3075. ["BFB8B0", "Tide"],
  3076. ["BFBED8", "Blue Haze"],
  3077. ["BFC1C2", "Silver Sand"],
  3078. ["BFC921", "Key Lime Pie"],
  3079. ["BFDBE2", "Ziggurat"],
  3080. ["BFFF00", "Lime"],
  3081. ["C02B18", "Thunderbird"],
  3082. ["C04737", "Mojo"],
  3083. ["C08081", "Old Rose"],
  3084. ["C0C0C0", "Silver"],
  3085. ["C0D3B9", "Pale Leaf"],
  3086. ["C0D8B6", "Pixie Green"],
  3087. ["C1440E", "Tia Maria"],
  3088. ["C154C1", "Fuchsia Pink"],
  3089. ["C1A004", "Buddha Gold"],
  3090. ["C1B7A4", "Bison Hide"],
  3091. ["C1BAB0", "Tea"],
  3092. ["C1BECD", "Gray Suit"],
  3093. ["C1D7B0", "Sprout"],
  3094. ["C1F07C", "Sulu"],
  3095. ["C26B03", "Indochine"],
  3096. ["C2955D", "Twine"],
  3097. ["C2BDB6", "Cotton Seed"],
  3098. ["C2CAC4", "Pumice"],
  3099. ["C2E8E5", "Jagged Ice"],
  3100. ["C32148", "Maroon Flush"],
  3101. ["C3B091", "Indian Khaki"],
  3102. ["C3BFC1", "Pale Slate"],
  3103. ["C3C3BD", "Gray Nickel"],
  3104. ["C3CDE6", "Periwinkle Gray"],
  3105. ["C3D1D1", "Tiara"],
  3106. ["C3DDF9", "Tropical Blue"],
  3107. ["C41E3A", "Cardinal"],
  3108. ["C45655", "Fuzzy Wuzzy Brown"],
  3109. ["C45719", "Orange Roughy"],
  3110. ["C4C4BC", "Mist Gray"],
  3111. ["C4D0B0", "Coriander"],
  3112. ["C4F4EB", "Mint Tulip"],
  3113. ["C54B8C", "Mulberry"],
  3114. ["C59922", "Nugget"],
  3115. ["C5994B", "Tussock"],
  3116. ["C5DBCA", "Sea Mist"],
  3117. ["C5E17A", "Yellow Green"],
  3118. ["C62D42", "Brick Red"],
  3119. ["C6726B", "Contessa"],
  3120. ["C69191", "Oriental Pink"],
  3121. ["C6A84B", "Roti"],
  3122. ["C6C3B5", "Ash"],
  3123. ["C6C8BD", "Kangaroo"],
  3124. ["C6E610", "Las Palmas"],
  3125. ["C7031E", "Monza"],
  3126. ["C71585", "Red Violet"],
  3127. ["C7BCA2", "Coral Reef"],
  3128. ["C7C1FF", "Melrose"],
  3129. ["C7C4BF", "Cloud"],
  3130. ["C7C9D5", "Ghost"],
  3131. ["C7CD90", "Pine Glade"],
  3132. ["C7DDE5", "Botticelli"],
  3133. ["C88A65", "Antique Brass"],
  3134. ["C8A2C8", "Lilac"],
  3135. ["C8A528", "Hokey Pokey"],
  3136. ["C8AABF", "Lily"],
  3137. ["C8B568", "Laser"],
  3138. ["C8E3D7", "Edgewater"],
  3139. ["C96323", "Piper"],
  3140. ["C99415", "Pizza"],
  3141. ["C9A0DC", "Light Wisteria"],
  3142. ["C9B29B", "Rodeo Dust"],
  3143. ["C9B35B", "Sundance"],
  3144. ["C9B93B", "Earls Green"],
  3145. ["C9C0BB", "Silver Rust"],
  3146. ["C9D9D2", "Conch"],
  3147. ["C9FFA2", "Reef"],
  3148. ["C9FFE5", "Aero Blue"],
  3149. ["CA3435", "Flush Mahogany"],
  3150. ["CABB48", "Turmeric"],
  3151. ["CADCD4", "Paris White"],
  3152. ["CAE00D", "Bitter Lemon"],
  3153. ["CAE6DA", "Skeptic"],
  3154. ["CB8FA9", "Viola"],
  3155. ["CBCAB6", "Foggy Gray"],
  3156. ["CBD3B0", "Green Mist"],
  3157. ["CBDBD6", "Nebula"],
  3158. ["CC3333", "Persian Red"],
  3159. ["CC5500", "Burnt Orange"],
  3160. ["CC7722", "Ochre"],
  3161. ["CC8899", "Puce"],
  3162. ["CCCAA8", "Thistle Green"],
  3163. ["CCCCFF", "Periwinkle"],
  3164. ["CCFF00", "Electric Lime"],
  3165. ["CD5700", "Tenn"],
  3166. ["CD5C5C", "Chestnut Rose"],
  3167. ["CD8429", "Brandy Punch"],
  3168. ["CDF4FF", "Onahau"],
  3169. ["CEB98F", "Sorrell Brown"],
  3170. ["CEBABA", "Cold Turkey"],
  3171. ["CEC291", "Yuma"],
  3172. ["CEC7A7", "Chino"],
  3173. ["CFA39D", "Eunry"],
  3174. ["CFB53B", "Old Gold"],
  3175. ["CFDCCF", "Tasman"],
  3176. ["CFE5D2", "Surf Crest"],
  3177. ["CFF9F3", "Humming Bird"],
  3178. ["CFFAF4", "Scandal"],
  3179. ["D05F04", "Red Stage"],
  3180. ["D06DA1", "Hopbush"],
  3181. ["D07D12", "Meteor"],
  3182. ["D0BEF8", "Perfume"],
  3183. ["D0C0E5", "Prelude"],
  3184. ["D0F0C0", "Tea Green"],
  3185. ["D18F1B", "Geebung"],
  3186. ["D1BEA8", "Vanilla"],
  3187. ["D1C6B4", "Soft Amber"],
  3188. ["D1D2CA", "Celeste"],
  3189. ["D1D2DD", "Mischka"],
  3190. ["D1E231", "Pear"],
  3191. ["D2691E", "Hot Cinnamon"],
  3192. ["D27D46", "Raw Sienna"],
  3193. ["D29EAA", "Careys Pink"],
  3194. ["D2B48C", "Tan"],
  3195. ["D2DA97", "Deco"],
  3196. ["D2F6DE", "Blue Romance"],
  3197. ["D2F8B0", "Gossip"],
  3198. ["D3CBBA", "Sisal"],
  3199. ["D3CDC5", "Swirl"],
  3200. ["D47494", "Charm"],
  3201. ["D4B6AF", "Clam Shell"],
  3202. ["D4BF8D", "Straw"],
  3203. ["D4C4A8", "Akaroa"],
  3204. ["D4CD16", "Bird Flower"],
  3205. ["D4D7D9", "Iron"],
  3206. ["D4DFE2", "Geyser"],
  3207. ["D4E2FC", "Hawkes Blue"],
  3208. ["D54600", "Grenadier"],
  3209. ["D591A4", "Can Can"],
  3210. ["D59A6F", "Whiskey"],
  3211. ["D5D195", "Winter Hazel"],
  3212. ["D5F6E3", "Granny Apple"],
  3213. ["D69188", "My Pink"],
  3214. ["D6C562", "Tacha"],
  3215. ["D6CEF6", "Moon Raker"],
  3216. ["D6D6D1", "Quill Gray"],
  3217. ["D6FFDB", "Snowy Mint"],
  3218. ["D7837F", "New York Pink"],
  3219. ["D7C498", "Pavlova"],
  3220. ["D7D0FF", "Fog"],
  3221. ["D84437", "Valencia"],
  3222. ["D87C63", "Japonica"],
  3223. ["D8BFD8", "Thistle"],
  3224. ["D8C2D5", "Maverick"],
  3225. ["D8FCFA", "Foam"],
  3226. ["D94972", "Cabaret"],
  3227. ["D99376", "Burning Sand"],
  3228. ["D9B99B", "Cameo"],
  3229. ["D9D6CF", "Timberwolf"],
  3230. ["D9DCC1", "Tana"],
  3231. ["D9E4F5", "Link Water"],
  3232. ["D9F7FF", "Mabel"],
  3233. ["DA3287", "Cerise"],
  3234. ["DA5B38", "Flame Pea"],
  3235. ["DA6304", "Bamboo"],
  3236. ["DA6A41", "Red Damask"],
  3237. ["DA70D6", "Orchid"],
  3238. ["DA8A67", "Copperfield"],
  3239. ["DAA520", "Golden Grass"],
  3240. ["DAECD6", "Zanah"],
  3241. ["DAF4F0", "Iceberg"],
  3242. ["DAFAFF", "Oyster Bay"],
  3243. ["DB5079", "Cranberry"],
  3244. ["DB9690", "Petite Orchid"],
  3245. ["DB995E", "Di Serria"],
  3246. ["DBDBDB", "Alto"],
  3247. ["DBFFF8", "Frosted Mint"],
  3248. ["DC143C", "Crimson"],
  3249. ["DC4333", "Punch"],
  3250. ["DCB20C", "Galliano"],
  3251. ["DCB4BC", "Blossom"],
  3252. ["DCD747", "Wattle"],
  3253. ["DCD9D2", "Westar"],
  3254. ["DCDDCC", "Moon Mist"],
  3255. ["DCEDB4", "Caper"],
  3256. ["DCF0EA", "Swans Down"],
  3257. ["DDD6D5", "Swiss Coffee"],
  3258. ["DDF9F1", "White Ice"],
  3259. ["DE3163", "Cerise Red"],
  3260. ["DE6360", "Roman"],
  3261. ["DEA681", "Tumbleweed"],
  3262. ["DEBA13", "Gold Tips"],
  3263. ["DEC196", "Brandy"],
  3264. ["DECBC6", "Wafer"],
  3265. ["DED4A4", "Sapling"],
  3266. ["DED717", "Barberry"],
  3267. ["DEE5C0", "Beryl Green"],
  3268. ["DEF5FF", "Pattens Blue"],
  3269. ["DF73FF", "Heliotrope"],
  3270. ["DFBE6F", "Apache"],
  3271. ["DFCD6F", "Chenin"],
  3272. ["DFCFDB", "Lola"],
  3273. ["DFECDA", "Willow Brook"],
  3274. ["DFFF00", "Chartreuse Yellow"],
  3275. ["E0B0FF", "Mauve"],
  3276. ["E0B646", "Anzac"],
  3277. ["E0B974", "Harvest Gold"],
  3278. ["E0C095", "Calico"],
  3279. ["E0FFFF", "Baby Blue"],
  3280. ["E16865", "Sunglo"],
  3281. ["E1BC64", "Equator"],
  3282. ["E1C0C8", "Pink Flare"],
  3283. ["E1E6D6", "Periglacial Blue"],
  3284. ["E1EAD4", "Kidnapper"],
  3285. ["E1F6E8", "Tara"],
  3286. ["E25465", "Mandy"],
  3287. ["E2725B", "Terracotta"],
  3288. ["E28913", "Golden Bell"],
  3289. ["E292C0", "Shocking"],
  3290. ["E29418", "Dixie"],
  3291. ["E29CD2", "Light Orchid"],
  3292. ["E2D8ED", "Snuff"],
  3293. ["E2EBED", "Mystic"],
  3294. ["E2F3EC", "Apple Green"],
  3295. ["E30B5C", "Razzmatazz"],
  3296. ["E32636", "Alizarin Crimson"],
  3297. ["E34234", "Cinnabar"],
  3298. ["E3BEBE", "Cavern Pink"],
  3299. ["E3F5E1", "Peppermint"],
  3300. ["E3F988", "Mindaro"],
  3301. ["E47698", "Deep Blush"],
  3302. ["E49B0F", "Gamboge"],
  3303. ["E4C2D5", "Melanie"],
  3304. ["E4CFDE", "Twilight"],
  3305. ["E4D1C0", "Bone"],
  3306. ["E4D422", "Sunflower"],
  3307. ["E4D5B7", "Grain Brown"],
  3308. ["E4D69B", "Zombie"],
  3309. ["E4F6E7", "Frostee"],
  3310. ["E4FFD1", "Snow Flurry"],
  3311. ["E52B50", "Amaranth"],
  3312. ["E5841B", "Zest"],
  3313. ["E5CCC9", "Dust Storm"],
  3314. ["E5D7BD", "Stark White"],
  3315. ["E5D8AF", "Hampton"],
  3316. ["E5E0E1", "Bon Jour"],
  3317. ["E5E5E5", "Mercury"],
  3318. ["E5F9F6", "Polar"],
  3319. ["E64E03", "Trinidad"],
  3320. ["E6BE8A", "Gold Sand"],
  3321. ["E6BEA5", "Cashmere"],
  3322. ["E6D7B9", "Double Spanish White"],
  3323. ["E6E4D4", "Satin Linen"],
  3324. ["E6F2EA", "Harp"],
  3325. ["E6F8F3", "Off Green"],
  3326. ["E6FFE9", "Hint of Green"],
  3327. ["E6FFFF", "Tranquil"],
  3328. ["E77200", "Mango Tango"],
  3329. ["E7730A", "Christine"],
  3330. ["E79F8C", "Tonys Pink"],
  3331. ["E79FC4", "Kobi"],
  3332. ["E7BCB4", "Rose Fog"],
  3333. ["E7BF05", "Corn"],
  3334. ["E7CD8C", "Putty"],
  3335. ["E7ECE6", "Gray Nurse"],
  3336. ["E7F8FF", "Lily White"],
  3337. ["E7FEFF", "Bubbles"],
  3338. ["E89928", "Fire Bush"],
  3339. ["E8B9B3", "Shilo"],
  3340. ["E8E0D5", "Pearl Bush"],
  3341. ["E8EBE0", "Green White"],
  3342. ["E8F1D4", "Chrome White"],
  3343. ["E8F2EB", "Gin"],
  3344. ["E8F5F2", "Aqua Squeeze"],
  3345. ["E96E00", "Clementine"],
  3346. ["E97451", "Burnt Sienna"],
  3347. ["E97C07", "Tahiti Gold"],
  3348. ["E9CECD", "Oyster Pink"],
  3349. ["E9D75A", "Confetti"],
  3350. ["E9E3E3", "Ebb"],
  3351. ["E9F8ED", "Ottoman"],
  3352. ["E9FFFD", "Clear Day"],
  3353. ["EA88A8", "Carissma"],
  3354. ["EAAE69", "Porsche"],
  3355. ["EAB33B", "Tulip Tree"],
  3356. ["EAC674", "Rob Roy"],
  3357. ["EADAB8", "Raffia"],
  3358. ["EAE8D4", "White Rock"],
  3359. ["EAF6EE", "Panache"],
  3360. ["EAF6FF", "Solitude"],
  3361. ["EAF9F5", "Aqua Spring"],
  3362. ["EAFFFE", "Dew"],
  3363. ["EB9373", "Apricot"],
  3364. ["EBC2AF", "Zinnwaldite"],
  3365. ["ECA927", "Fuel Yellow"],
  3366. ["ECC54E", "Ronchi"],
  3367. ["ECC7EE", "French Lilac"],
  3368. ["ECCDB9", "Just Right"],
  3369. ["ECE090", "Wild Rice"],
  3370. ["ECEBBD", "Fall Green"],
  3371. ["ECEBCE", "Aths Special"],
  3372. ["ECF245", "Starship"],
  3373. ["ED0A3F", "Red Ribbon"],
  3374. ["ED7A1C", "Tango"],
  3375. ["ED9121", "Carrot Orange"],
  3376. ["ED989E", "Sea Pink"],
  3377. ["EDB381", "Tacao"],
  3378. ["EDC9AF", "Desert Sand"],
  3379. ["EDCDAB", "Pancho"],
  3380. ["EDDCB1", "Chamois"],
  3381. ["EDEA99", "Primrose"],
  3382. ["EDF5DD", "Frost"],
  3383. ["EDF5F5", "Aqua Haze"],
  3384. ["EDF6FF", "Zumthor"],
  3385. ["EDF9F1", "Narvik"],
  3386. ["EDFC84", "Honeysuckle"],
  3387. ["EE82EE", "Lavender Magenta"],
  3388. ["EEC1BE", "Beauty Bush"],
  3389. ["EED794", "Chalky"],
  3390. ["EED9C4", "Almond"],
  3391. ["EEDC82", "Flax"],
  3392. ["EEDEDA", "Bizarre"],
  3393. ["EEE3AD", "Double Colonial White"],
  3394. ["EEEEE8", "Cararra"],
  3395. ["EEEF78", "Manz"],
  3396. ["EEF0C8", "Tahuna Sands"],
  3397. ["EEF0F3", "Athens Gray"],
  3398. ["EEF3C3", "Tusk"],
  3399. ["EEF4DE", "Loafer"],
  3400. ["EEF6F7", "Catskill White"],
  3401. ["EEFDFF", "Twilight Blue"],
  3402. ["EEFF9A", "Jonquil"],
  3403. ["EEFFE2", "Rice Flower"],
  3404. ["EF863F", "Jaffa"],
  3405. ["EFEFEF", "Gallery"],
  3406. ["EFF2F3", "Porcelain"],
  3407. ["F091A9", "Mauvelous"],
  3408. ["F0D52D", "Golden Dream"],
  3409. ["F0DB7D", "Golden Sand"],
  3410. ["F0DC82", "Buff"],
  3411. ["F0E2EC", "Prim"],
  3412. ["F0E68C", "Khaki"],
  3413. ["F0EEFD", "Selago"],
  3414. ["F0EEFF", "Titan White"],
  3415. ["F0F8FF", "Alice Blue"],
  3416. ["F0FCEA", "Feta"],
  3417. ["F18200", "Gold Drop"],
  3418. ["F19BAB", "Wewak"],
  3419. ["F1E788", "Sahara Sand"],
  3420. ["F1E9D2", "Parchment"],
  3421. ["F1E9FF", "Blue Chalk"],
  3422. ["F1EEC1", "Mint Julep"],
  3423. ["F1F1F1", "Seashell"],
  3424. ["F1F7F2", "Saltpan"],
  3425. ["F1FFAD", "Tidal"],
  3426. ["F1FFC8", "Chiffon"],
  3427. ["F2552A", "Flamingo"],
  3428. ["F28500", "Tangerine"],
  3429. ["F2C3B2", "Mandys Pink"],
  3430. ["F2F2F2", "Concrete"],
  3431. ["F2FAFA", "Black Squeeze"],
  3432. ["F34723", "Pomegranate"],
  3433. ["F3AD16", "Buttercup"],
  3434. ["F3D69D", "New Orleans"],
  3435. ["F3D9DF", "Vanilla Ice"],
  3436. ["F3E7BB", "Sidecar"],
  3437. ["F3E9E5", "Dawn Pink"],
  3438. ["F3EDCF", "Wheatfield"],
  3439. ["F3FB62", "Canary"],
  3440. ["F3FBD4", "Orinoco"],
  3441. ["F3FFD8", "Carla"],
  3442. ["F400A1", "Hollywood Cerise"],
  3443. ["F4A460", "Sandy brown"],
  3444. ["F4C430", "Saffron"],
  3445. ["F4D81C", "Ripe Lemon"],
  3446. ["F4EBD3", "Janna"],
  3447. ["F4F2EE", "Pampas"],
  3448. ["F4F4F4", "Wild Sand"],
  3449. ["F4F8FF", "Zircon"],
  3450. ["F57584", "Froly"],
  3451. ["F5C85C", "Cream Can"],
  3452. ["F5C999", "Manhattan"],
  3453. ["F5D5A0", "Maize"],
  3454. ["F5DEB3", "Wheat"],
  3455. ["F5E7A2", "Sandwisp"],
  3456. ["F5E7E2", "Pot Pourri"],
  3457. ["F5E9D3", "Albescent White"],
  3458. ["F5EDEF", "Soft Peach"],
  3459. ["F5F3E5", "Ecru White"],
  3460. ["F5F5DC", "Beige"],
  3461. ["F5FB3D", "Golden Fizz"],
  3462. ["F5FFBE", "Australian Mint"],
  3463. ["F64A8A", "French Rose"],
  3464. ["F653A6", "Brilliant Rose"],
  3465. ["F6A4C9", "Illusion"],
  3466. ["F6F0E6", "Merino"],
  3467. ["F6F7F7", "Black Haze"],
  3468. ["F6FFDC", "Spring Sun"],
  3469. ["F7468A", "Violet Red"],
  3470. ["F77703", "Chilean Fire"],
  3471. ["F77FBE", "Persian Pink"],
  3472. ["F7B668", "Rajah"],
  3473. ["F7C8DA", "Azalea"],
  3474. ["F7DBE6", "We Peep"],
  3475. ["F7F2E1", "Quarter Spanish White"],
  3476. ["F7F5FA", "Whisper"],
  3477. ["F7FAF7", "Snow Drift"],
  3478. ["F8B853", "Casablanca"],
  3479. ["F8C3DF", "Chantilly"],
  3480. ["F8D9E9", "Cherub"],
  3481. ["F8DB9D", "Marzipan"],
  3482. ["F8DD5C", "Energy Yellow"],
  3483. ["F8E4BF", "Givry"],
  3484. ["F8F0E8", "White Linen"],
  3485. ["F8F4FF", "Magnolia"],
  3486. ["F8F6F1", "Spring Wood"],
  3487. ["F8F7DC", "Coconut Cream"],
  3488. ["F8F7FC", "White Lilac"],
  3489. ["F8F8F7", "Desert Storm"],
  3490. ["F8F99C", "Texas"],
  3491. ["F8FACD", "Corn Field"],
  3492. ["F8FDD3", "Mimosa"],
  3493. ["F95A61", "Carnation"],
  3494. ["F9BF58", "Saffron Mango"],
  3495. ["F9E0ED", "Carousel Pink"],
  3496. ["F9E4BC", "Dairy Cream"],
  3497. ["F9E663", "Portica"],
  3498. ["F9EAF3", "Amour"],
  3499. ["F9F8E4", "Rum Swizzle"],
  3500. ["F9FF8B", "Dolly"],
  3501. ["F9FFF6", "Sugar Cane"],
  3502. ["FA7814", "Ecstasy"],
  3503. ["FA9D5A", "Tan Hide"],
  3504. ["FAD3A2", "Corvette"],
  3505. ["FADFAD", "Peach Yellow"],
  3506. ["FAE600", "Turbo"],
  3507. ["FAEAB9", "Astra"],
  3508. ["FAECCC", "Champagne"],
  3509. ["FAF0E6", "Linen"],
  3510. ["FAF3F0", "Fantasy"],
  3511. ["FAF7D6", "Citrine White"],
  3512. ["FAFAFA", "Alabaster"],
  3513. ["FAFDE4", "Hint of Yellow"],
  3514. ["FAFFA4", "Milan"],
  3515. ["FB607F", "Brink Pink"],
  3516. ["FB8989", "Geraldine"],
  3517. ["FBA0E3", "Lavender Rose"],
  3518. ["FBA129", "Sea Buckthorn"],
  3519. ["FBAC13", "Sun"],
  3520. ["FBAED2", "Lavender Pink"],
  3521. ["FBB2A3", "Rose Bud"],
  3522. ["FBBEDA", "Cupid"],
  3523. ["FBCCE7", "Classic Rose"],
  3524. ["FBCEB1", "Apricot Peach"],
  3525. ["FBE7B2", "Banana Mania"],
  3526. ["FBE870", "Marigold Yellow"],
  3527. ["FBE96C", "Festival"],
  3528. ["FBEA8C", "Sweet Corn"],
  3529. ["FBEC5D", "Candy Corn"],
  3530. ["FBF9F9", "Hint of Red"],
  3531. ["FBFFBA", "Shalimar"],
  3532. ["FC0FC0", "Shocking Pink"],
  3533. ["FC80A5", "Tickle Me Pink"],
  3534. ["FC9C1D", "Tree Poppy"],
  3535. ["FCC01E", "Lightning Yellow"],
  3536. ["FCD667", "Goldenrod"],
  3537. ["FCD917", "Candlelight"],
  3538. ["FCDA98", "Cherokee"],
  3539. ["FCF4D0", "Double Pearl Lusta"],
  3540. ["FCF4DC", "Pearl Lusta"],
  3541. ["FCF8F7", "Vista White"],
  3542. ["FCFBF3", "Bianca"],
  3543. ["FCFEDA", "Moon Glow"],
  3544. ["FCFFE7", "China Ivory"],
  3545. ["FCFFF9", "Ceramic"],
  3546. ["FD0E35", "Torch Red"],
  3547. ["FD5B78", "Wild Watermelon"],
  3548. ["FD7B33", "Crusta"],
  3549. ["FD7C07", "Sorbus"],
  3550. ["FD9FA2", "Sweet Pink"],
  3551. ["FDD5B1", "Light Apricot"],
  3552. ["FDD7E4", "Pig Pink"],
  3553. ["FDE1DC", "Cinderella"],
  3554. ["FDE295", "Golden Glow"],
  3555. ["FDE910", "Lemon"],
  3556. ["FDF5E6", "Old Lace"],
  3557. ["FDF6D3", "Half Colonial White"],
  3558. ["FDF7AD", "Drover"],
  3559. ["FDFEB8", "Pale Prim"],
  3560. ["FDFFD5", "Cumulus"],
  3561. ["FE28A2", "Persian Rose"],
  3562. ["FE4C40", "Sunset Orange"],
  3563. ["FE6F5E", "Bittersweet"],
  3564. ["FE9D04", "California"],
  3565. ["FEA904", "Yellow Sea"],
  3566. ["FEBAAD", "Melon"],
  3567. ["FED33C", "Bright Sun"],
  3568. ["FED85D", "Dandelion"],
  3569. ["FEDB8D", "Salomie"],
  3570. ["FEE5AC", "Cape Honey"],
  3571. ["FEEBF3", "Remy"],
  3572. ["FEEFCE", "Oasis"],
  3573. ["FEF0EC", "Bridesmaid"],
  3574. ["FEF2C7", "Beeswax"],
  3575. ["FEF3D8", "Bleach White"],
  3576. ["FEF4CC", "Pipi"],
  3577. ["FEF4DB", "Half Spanish White"],
  3578. ["FEF4F8", "Wisp Pink"],
  3579. ["FEF5F1", "Provincial Pink"],
  3580. ["FEF7DE", "Half Dutch White"],
  3581. ["FEF8E2", "Solitaire"],
  3582. ["FEF8FF", "White Pointer"],
  3583. ["FEF9E3", "Off Yellow"],
  3584. ["FEFCED", "Orange White"],
  3585. ["FF0000", "Red"],
  3586. ["FF007F", "Rose"],
  3587. ["FF00CC", "Purple Pizzazz"],
  3588. ["FF00FF", "Magenta / Fuchsia"],
  3589. ["FF2400", "Scarlet"],
  3590. ["FF3399", "Wild Strawberry"],
  3591. ["FF33CC", "Razzle Dazzle Rose"],
  3592. ["FF355E", "Radical Red"],
  3593. ["FF3F34", "Red Orange"],
  3594. ["FF4040", "Coral Red"],
  3595. ["FF4D00", "Vermilion"],
  3596. ["FF4F00", "International Orange"],
  3597. ["FF6037", "Outrageous Orange"],
  3598. ["FF6600", "Blaze Orange"],
  3599. ["FF66FF", "Pink Flamingo"],
  3600. ["FF681F", "Orange"],
  3601. ["FF69B4", "Hot Pink"],
  3602. ["FF6B53", "Persimmon"],
  3603. ["FF6FFF", "Blush Pink"],
  3604. ["FF7034", "Burning Orange"],
  3605. ["FF7518", "Pumpkin"],
  3606. ["FF7D07", "Flamenco"],
  3607. ["FF7F00", "Flush Orange"],
  3608. ["FF7F50", "Coral"],
  3609. ["FF8C69", "Salmon"],
  3610. ["FF9000", "Pizazz"],
  3611. ["FF910F", "West Side"],
  3612. ["FF91A4", "Pink Salmon"],
  3613. ["FF9933", "Neon Carrot"],
  3614. ["FF9966", "Atomic Tangerine"],
  3615. ["FF9980", "Vivid Tangerine"],
  3616. ["FF9E2C", "Sunshade"],
  3617. ["FFA000", "Orange Peel"],
  3618. ["FFA194", "Mona Lisa"],
  3619. ["FFA500", "Web Orange"],
  3620. ["FFA6C9", "Carnation Pink"],
  3621. ["FFAB81", "Hit Pink"],
  3622. ["FFAE42", "Yellow Orange"],
  3623. ["FFB0AC", "Cornflower Lilac"],
  3624. ["FFB1B3", "Sundown"],
  3625. ["FFB31F", "My Sin"],
  3626. ["FFB555", "Texas Rose"],
  3627. ["FFB7D5", "Cotton Candy"],
  3628. ["FFB97B", "Macaroni and Cheese"],
  3629. ["FFBA00", "Selective Yellow"],
  3630. ["FFBD5F", "Koromiko"],
  3631. ["FFBF00", "Amber"],
  3632. ["FFC0A8", "Wax Flower"],
  3633. ["FFC0CB", "Pink"],
  3634. ["FFC3C0", "Your Pink"],
  3635. ["FFC901", "Supernova"],
  3636. ["FFCBA4", "Flesh"],
  3637. ["FFCC33", "Sunglow"],
  3638. ["FFCC5C", "Golden Tainoi"],
  3639. ["FFCC99", "Peach Orange"],
  3640. ["FFCD8C", "Chardonnay"],
  3641. ["FFD1DC", "Pastel Pink"],
  3642. ["FFD2B7", "Romantic"],
  3643. ["FFD38C", "Grandis"],
  3644. ["FFD700", "Gold"],
  3645. ["FFD800", "School bus Yellow"],
  3646. ["FFD8D9", "Cosmos"],
  3647. ["FFDB58", "Mustard"],
  3648. ["FFDCD6", "Peach Schnapps"],
  3649. ["FFDDAF", "Caramel"],
  3650. ["FFDDCD", "Tuft Bush"],
  3651. ["FFDDCF", "Watusi"],
  3652. ["FFDDF4", "Pink Lace"],
  3653. ["FFDEAD", "Navajo White"],
  3654. ["FFDEB3", "Frangipani"],
  3655. ["FFE1DF", "Pippin"],
  3656. ["FFE1F2", "Pale Rose"],
  3657. ["FFE2C5", "Negroni"],
  3658. ["FFE5A0", "Cream Brulee"],
  3659. ["FFE5B4", "Peach"],
  3660. ["FFE6C7", "Tequila"],
  3661. ["FFE772", "Kournikova"],
  3662. ["FFEAC8", "Sandy Beach"],
  3663. ["FFEAD4", "Karry"],
  3664. ["FFEC13", "Broom"],
  3665. ["FFEDBC", "Colonial White"],
  3666. ["FFEED8", "Derby"],
  3667. ["FFEFA1", "Vis Vis"],
  3668. ["FFEFC1", "Egg White"],
  3669. ["FFEFD5", "Papaya Whip"],
  3670. ["FFEFEC", "Fair Pink"],
  3671. ["FFF0DB", "Peach Cream"],
  3672. ["FFF0F5", "Lavender blush"],
  3673. ["FFF14F", "Gorse"],
  3674. ["FFF1B5", "Buttermilk"],
  3675. ["FFF1D8", "Pink Lady"],
  3676. ["FFF1EE", "Forget Me Not"],
  3677. ["FFF1F9", "Tutu"],
  3678. ["FFF39D", "Picasso"],
  3679. ["FFF3F1", "Chardon"],
  3680. ["FFF46E", "Paris Daisy"],
  3681. ["FFF4CE", "Barley White"],
  3682. ["FFF4DD", "Egg Sour"],
  3683. ["FFF4E0", "Sazerac"],
  3684. ["FFF4E8", "Serenade"],
  3685. ["FFF4F3", "Chablis"],
  3686. ["FFF5EE", "Seashell Peach"],
  3687. ["FFF5F3", "Sauvignon"],
  3688. ["FFF6D4", "Milk Punch"],
  3689. ["FFF6DF", "Varden"],
  3690. ["FFF6F5", "Rose White"],
  3691. ["FFF8D1", "Baja White"],
  3692. ["FFF9E2", "Gin Fizz"],
  3693. ["FFF9E6", "Early Dawn"],
  3694. ["FFFACD", "Lemon Chiffon"],
  3695. ["FFFAF4", "Bridal Heath"],
  3696. ["FFFBDC", "Scotch Mist"],
  3697. ["FFFBF9", "Soapstone"],
  3698. ["FFFC99", "Witch Haze"],
  3699. ["FFFCEA", "Buttery White"],
  3700. ["FFFCEE", "Island Spice"],
  3701. ["FFFDD0", "Cream"],
  3702. ["FFFDE6", "Chilean Heath"],
  3703. ["FFFDE8", "Travertine"],
  3704. ["FFFDF3", "Orchid White"],
  3705. ["FFFDF4", "Quarter Pearl Lusta"],
  3706. ["FFFEE1", "Half and Half"],
  3707. ["FFFEEC", "Apricot White"],
  3708. ["FFFEF0", "Rice Cake"],
  3709. ["FFFEF6", "Black White"],
  3710. ["FFFEFD", "Romance"],
  3711. ["FFFF00", "Yellow"],
  3712. ["FFFF66", "Laser Lemon"],
  3713. ["FFFF99", "Pale Canary"],
  3714. ["FFFFB4", "Portafino"],
  3715. ["FFFFF0", "Ivory"],
  3716. ["FFFFFF", "White"]
  3717. ]
  3718. }
  3719. ntc.init();