luci.js.html 137 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>Source: luci.js</title>
  6. <script src="scripts/prettify/prettify.js"></script>
  7. <script src="scripts/prettify/lang-css.js"></script>
  8. <script src="scripts/jquery.min.js"></script>
  9. <!--[if lt IE 9]>
  10. <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
  11. <![endif]-->
  12. <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
  13. <link type="text/css" rel="stylesheet" href="styles/bootstrap.min.css">
  14. <link type="text/css" rel="stylesheet" href="styles/jaguar.css">
  15. <script>
  16. var config = {"monospaceLinks":true,"cleverLinks":true,"default":{"outputSourceFiles":true}};
  17. </script>
  18. </head>
  19. <body>
  20. <div id="wrap" class="clearfix">
  21. <div class="navigation">
  22. <h3 class="applicationName"><a href="index.html"></a></h3>
  23. <div class="search">
  24. <input id="search" type="text" class="form-control input-sm" placeholder="Search Documentations">
  25. </div>
  26. <ul class="list">
  27. <li class="item" data-name="LuCI">
  28. <span class="title">
  29. <a href="LuCI.html">LuCI</a>
  30. </span>
  31. <ul class="members itemMembers">
  32. <span class="subtitle">Members</span>
  33. <li data-name="LuCI#env"><a href="LuCI.html#env">env</a></li>
  34. </ul>
  35. <ul class="typedefs itemMembers">
  36. <span class="subtitle">Typedefs</span>
  37. <li data-name="LuCI.requestCallbackFn"><a href="LuCI.html#.requestCallbackFn">requestCallbackFn</a></li>
  38. </ul>
  39. <ul class="typedefs itemMembers">
  40. </ul>
  41. <ul class="methods itemMembers">
  42. <span class="subtitle">Methods</span>
  43. <li data-name="LuCI#bind"><a href="LuCI.html#bind">bind</a></li>
  44. <li data-name="LuCI#error"><a href="LuCI.html#error">error</a></li>
  45. <li data-name="LuCI#get"><a href="LuCI.html#get">get</a></li>
  46. <li data-name="LuCI#halt"><a href="LuCI.html#halt">halt</a></li>
  47. <li data-name="LuCI#hasSystemFeature"><a href="LuCI.html#hasSystemFeature">hasSystemFeature</a></li>
  48. <li data-name="LuCI#isObject"><a href="LuCI.html#isObject">isObject</a></li>
  49. <li data-name="LuCI#location"><a href="LuCI.html#location">location</a></li>
  50. <li data-name="LuCI#path"><a href="LuCI.html#path">path</a></li>
  51. <li data-name="LuCI#poll"><a href="LuCI.html#poll">poll</a></li>
  52. <li data-name="LuCI#post"><a href="LuCI.html#post">post</a></li>
  53. <li data-name="LuCI#raise"><a href="LuCI.html#raise">raise</a></li>
  54. <li data-name="LuCI#require"><a href="LuCI.html#require">require</a></li>
  55. <li data-name="LuCI#resolveDefault"><a href="LuCI.html#resolveDefault">resolveDefault</a></li>
  56. <li data-name="LuCI#resource"><a href="LuCI.html#resource">resource</a></li>
  57. <li data-name="LuCI#run"><a href="LuCI.html#run">run</a></li>
  58. <li data-name="LuCI#sortedKeys"><a href="LuCI.html#sortedKeys">sortedKeys</a></li>
  59. <li data-name="LuCI#stop"><a href="LuCI.html#stop">stop</a></li>
  60. <li data-name="LuCI#toArray"><a href="LuCI.html#toArray">toArray</a></li>
  61. <li data-name="LuCI#url"><a href="LuCI.html#url">url</a></li>
  62. </ul>
  63. <ul class="events itemMembers">
  64. </ul>
  65. </li>
  66. <li class="item" data-name="LuCI.Class">
  67. <span class="title">
  68. <a href="LuCI.Class.html">LuCI.Class</a>
  69. </span>
  70. <ul class="members itemMembers">
  71. </ul>
  72. <ul class="typedefs itemMembers">
  73. </ul>
  74. <ul class="typedefs itemMembers">
  75. </ul>
  76. <ul class="methods itemMembers">
  77. <span class="subtitle">Methods</span>
  78. <li data-name="LuCI.Class.extend"><a href="LuCI.Class.html#.extend">extend</a></li>
  79. <li data-name="LuCI.Class.instantiate"><a href="LuCI.Class.html#.instantiate">instantiate</a></li>
  80. <li data-name="LuCI.Class.isSubclass"><a href="LuCI.Class.html#.isSubclass">isSubclass</a></li>
  81. <li data-name="LuCI.Class.singleton"><a href="LuCI.Class.html#.singleton">singleton</a></li>
  82. <li data-name="LuCI.Class#super"><a href="LuCI.Class.html#super">super</a></li>
  83. <li data-name="LuCI.Class#varargs"><a href="LuCI.Class.html#varargs">varargs</a></li>
  84. </ul>
  85. <ul class="events itemMembers">
  86. </ul>
  87. </li>
  88. <li class="item" data-name="LuCI.dom">
  89. <span class="title">
  90. <a href="LuCI.dom.html">LuCI.dom</a>
  91. </span>
  92. <ul class="members itemMembers">
  93. </ul>
  94. <ul class="typedefs itemMembers">
  95. <span class="subtitle">Typedefs</span>
  96. <li data-name="LuCI.dom~ignoreCallbackFn"><a href="LuCI.dom.html#~ignoreCallbackFn">ignoreCallbackFn</a></li>
  97. </ul>
  98. <ul class="typedefs itemMembers">
  99. </ul>
  100. <ul class="methods itemMembers">
  101. <span class="subtitle">Methods</span>
  102. <li data-name="LuCI.dom#append"><a href="LuCI.dom.html#append">append</a></li>
  103. <li data-name="LuCI.dom#attr"><a href="LuCI.dom.html#attr">attr</a></li>
  104. <li data-name="LuCI.dom#bindClassInstance"><a href="LuCI.dom.html#bindClassInstance">bindClassInstance</a></li>
  105. <li data-name="LuCI.dom#callClassMethod"><a href="LuCI.dom.html#callClassMethod">callClassMethod</a></li>
  106. <li data-name="LuCI.dom#content"><a href="LuCI.dom.html#content">content</a></li>
  107. <li data-name="LuCI.dom#create"><a href="LuCI.dom.html#create">create</a></li>
  108. <li data-name="LuCI.dom#data"><a href="LuCI.dom.html#data">data</a></li>
  109. <li data-name="LuCI.dom#elem"><a href="LuCI.dom.html#elem">elem</a></li>
  110. <li data-name="LuCI.dom#findClassInstance"><a href="LuCI.dom.html#findClassInstance">findClassInstance</a></li>
  111. <li data-name="LuCI.dom#isEmpty"><a href="LuCI.dom.html#isEmpty">isEmpty</a></li>
  112. <li data-name="LuCI.dom#matches"><a href="LuCI.dom.html#matches">matches</a></li>
  113. <li data-name="LuCI.dom#parent"><a href="LuCI.dom.html#parent">parent</a></li>
  114. <li data-name="LuCI.dom#parse"><a href="LuCI.dom.html#parse">parse</a></li>
  115. </ul>
  116. <ul class="events itemMembers">
  117. </ul>
  118. </li>
  119. <li class="item" data-name="LuCI.fs">
  120. <span class="title">
  121. <a href="LuCI.fs.html">LuCI.fs</a>
  122. </span>
  123. <ul class="members itemMembers">
  124. </ul>
  125. <ul class="typedefs itemMembers">
  126. <span class="subtitle">Typedefs</span>
  127. <li data-name="LuCI.fs.FileExecResult"><a href="LuCI.fs.html#.FileExecResult">FileExecResult</a></li>
  128. <li data-name="LuCI.fs.FileStatEntry"><a href="LuCI.fs.html#.FileStatEntry">FileStatEntry</a></li>
  129. </ul>
  130. <ul class="typedefs itemMembers">
  131. </ul>
  132. <ul class="methods itemMembers">
  133. <span class="subtitle">Methods</span>
  134. <li data-name="LuCI.fs#exec"><a href="LuCI.fs.html#exec">exec</a></li>
  135. <li data-name="LuCI.fs#lines"><a href="LuCI.fs.html#lines">lines</a></li>
  136. <li data-name="LuCI.fs#list"><a href="LuCI.fs.html#list">list</a></li>
  137. <li data-name="LuCI.fs#read"><a href="LuCI.fs.html#read">read</a></li>
  138. <li data-name="LuCI.fs#remove"><a href="LuCI.fs.html#remove">remove</a></li>
  139. <li data-name="LuCI.fs#stat"><a href="LuCI.fs.html#stat">stat</a></li>
  140. <li data-name="LuCI.fs#trimmed"><a href="LuCI.fs.html#trimmed">trimmed</a></li>
  141. <li data-name="LuCI.fs#write"><a href="LuCI.fs.html#write">write</a></li>
  142. </ul>
  143. <ul class="events itemMembers">
  144. </ul>
  145. </li>
  146. <li class="item" data-name="LuCI.Headers">
  147. <span class="title">
  148. <a href="LuCI.Headers.html">LuCI.Headers</a>
  149. </span>
  150. <ul class="members itemMembers">
  151. </ul>
  152. <ul class="typedefs itemMembers">
  153. </ul>
  154. <ul class="typedefs itemMembers">
  155. </ul>
  156. <ul class="methods itemMembers">
  157. <span class="subtitle">Methods</span>
  158. <li data-name="LuCI.Headers#get"><a href="LuCI.Headers.html#get">get</a></li>
  159. <li data-name="LuCI.Headers#has"><a href="LuCI.Headers.html#has">has</a></li>
  160. </ul>
  161. <ul class="events itemMembers">
  162. </ul>
  163. </li>
  164. <li class="item" data-name="LuCI.Network">
  165. <span class="title">
  166. <a href="LuCI.Network.html">LuCI.Network</a>
  167. </span>
  168. <ul class="members itemMembers">
  169. </ul>
  170. <ul class="typedefs itemMembers">
  171. <span class="subtitle">Typedefs</span>
  172. <li data-name="LuCI.Network.SwitchTopology"><a href="LuCI.Network.html#.SwitchTopology">SwitchTopology</a></li>
  173. <li data-name="LuCI.Network.WifiEncryption"><a href="LuCI.Network.html#.WifiEncryption">WifiEncryption</a></li>
  174. <li data-name="LuCI.Network.WifiPeerEntry"><a href="LuCI.Network.html#.WifiPeerEntry">WifiPeerEntry</a></li>
  175. <li data-name="LuCI.Network.WifiRateEntry"><a href="LuCI.Network.html#.WifiRateEntry">WifiRateEntry</a></li>
  176. <li data-name="LuCI.Network.WifiScanResult"><a href="LuCI.Network.html#.WifiScanResult">WifiScanResult</a></li>
  177. </ul>
  178. <ul class="typedefs itemMembers">
  179. </ul>
  180. <ul class="methods itemMembers">
  181. <span class="subtitle">Methods</span>
  182. <li data-name="LuCI.Network#addNetwork"><a href="LuCI.Network.html#addNetwork">addNetwork</a></li>
  183. <li data-name="LuCI.Network#addWifiNetwork"><a href="LuCI.Network.html#addWifiNetwork">addWifiNetwork</a></li>
  184. <li data-name="LuCI.Network#deleteNetwork"><a href="LuCI.Network.html#deleteNetwork">deleteNetwork</a></li>
  185. <li data-name="LuCI.Network#deleteWifiNetwork"><a href="LuCI.Network.html#deleteWifiNetwork">deleteWifiNetwork</a></li>
  186. <li data-name="LuCI.Network#flushCache"><a href="LuCI.Network.html#flushCache">flushCache</a></li>
  187. <li data-name="LuCI.Network#formatWifiEncryption"><a href="LuCI.Network.html#formatWifiEncryption">formatWifiEncryption</a></li>
  188. <li data-name="LuCI.Network#getDevice"><a href="LuCI.Network.html#getDevice">getDevice</a></li>
  189. <li data-name="LuCI.Network#getDevices"><a href="LuCI.Network.html#getDevices">getDevices</a></li>
  190. <li data-name="LuCI.Network#getDSLModemType"><a href="LuCI.Network.html#getDSLModemType">getDSLModemType</a></li>
  191. <li data-name="LuCI.Network#getHostHints"><a href="LuCI.Network.html#getHostHints">getHostHints</a></li>
  192. <li data-name="LuCI.Network#getIfnameOf"><a href="LuCI.Network.html#getIfnameOf">getIfnameOf</a></li>
  193. <li data-name="LuCI.Network#getNetwork"><a href="LuCI.Network.html#getNetwork">getNetwork</a></li>
  194. <li data-name="LuCI.Network#getNetworks"><a href="LuCI.Network.html#getNetworks">getNetworks</a></li>
  195. <li data-name="LuCI.Network#getProtocol"><a href="LuCI.Network.html#getProtocol">getProtocol</a></li>
  196. <li data-name="LuCI.Network#getProtocols"><a href="LuCI.Network.html#getProtocols">getProtocols</a></li>
  197. <li data-name="LuCI.Network#getSwitchTopologies"><a href="LuCI.Network.html#getSwitchTopologies">getSwitchTopologies</a></li>
  198. <li data-name="LuCI.Network#getWAN6Networks"><a href="LuCI.Network.html#getWAN6Networks">getWAN6Networks</a></li>
  199. <li data-name="LuCI.Network#getWANNetworks"><a href="LuCI.Network.html#getWANNetworks">getWANNetworks</a></li>
  200. <li data-name="LuCI.Network#getWifiDevice"><a href="LuCI.Network.html#getWifiDevice">getWifiDevice</a></li>
  201. <li data-name="LuCI.Network#getWifiDevices"><a href="LuCI.Network.html#getWifiDevices">getWifiDevices</a></li>
  202. <li data-name="LuCI.Network#getWifiNetwork"><a href="LuCI.Network.html#getWifiNetwork">getWifiNetwork</a></li>
  203. <li data-name="LuCI.Network#getWifiNetworks"><a href="LuCI.Network.html#getWifiNetworks">getWifiNetworks</a></li>
  204. <li data-name="LuCI.Network#isIgnoredDevice"><a href="LuCI.Network.html#isIgnoredDevice">isIgnoredDevice</a></li>
  205. <li data-name="LuCI.Network#maskToPrefix"><a href="LuCI.Network.html#maskToPrefix">maskToPrefix</a></li>
  206. <li data-name="LuCI.Network#prefixToMask"><a href="LuCI.Network.html#prefixToMask">prefixToMask</a></li>
  207. <li data-name="LuCI.Network#registerErrorCode"><a href="LuCI.Network.html#registerErrorCode">registerErrorCode</a></li>
  208. <li data-name="LuCI.Network#registerPatternVirtual"><a href="LuCI.Network.html#registerPatternVirtual">registerPatternVirtual</a></li>
  209. <li data-name="LuCI.Network#registerProtocol"><a href="LuCI.Network.html#registerProtocol">registerProtocol</a></li>
  210. <li data-name="LuCI.Network#renameNetwork"><a href="LuCI.Network.html#renameNetwork">renameNetwork</a></li>
  211. </ul>
  212. <ul class="events itemMembers">
  213. </ul>
  214. </li>
  215. <li class="item" data-name="LuCI.Network.Device">
  216. <span class="title">
  217. <a href="LuCI.Network.Device.html">LuCI.Network.Device</a>
  218. </span>
  219. <ul class="members itemMembers">
  220. </ul>
  221. <ul class="typedefs itemMembers">
  222. </ul>
  223. <ul class="typedefs itemMembers">
  224. </ul>
  225. <ul class="methods itemMembers">
  226. <span class="subtitle">Methods</span>
  227. <li data-name="LuCI.Network.Device#getBridgeID"><a href="LuCI.Network.Device.html#getBridgeID">getBridgeID</a></li>
  228. <li data-name="LuCI.Network.Device#getBridgeSTP"><a href="LuCI.Network.Device.html#getBridgeSTP">getBridgeSTP</a></li>
  229. <li data-name="LuCI.Network.Device#getI18n"><a href="LuCI.Network.Device.html#getI18n">getI18n</a></li>
  230. <li data-name="LuCI.Network.Device#getIP6Addrs"><a href="LuCI.Network.Device.html#getIP6Addrs">getIP6Addrs</a></li>
  231. <li data-name="LuCI.Network.Device#getIPAddrs"><a href="LuCI.Network.Device.html#getIPAddrs">getIPAddrs</a></li>
  232. <li data-name="LuCI.Network.Device#getMAC"><a href="LuCI.Network.Device.html#getMAC">getMAC</a></li>
  233. <li data-name="LuCI.Network.Device#getMTU"><a href="LuCI.Network.Device.html#getMTU">getMTU</a></li>
  234. <li data-name="LuCI.Network.Device#getName"><a href="LuCI.Network.Device.html#getName">getName</a></li>
  235. <li data-name="LuCI.Network.Device#getNetwork"><a href="LuCI.Network.Device.html#getNetwork">getNetwork</a></li>
  236. <li data-name="LuCI.Network.Device#getNetworks"><a href="LuCI.Network.Device.html#getNetworks">getNetworks</a></li>
  237. <li data-name="LuCI.Network.Device#getPorts"><a href="LuCI.Network.Device.html#getPorts">getPorts</a></li>
  238. <li data-name="LuCI.Network.Device#getRXBytes"><a href="LuCI.Network.Device.html#getRXBytes">getRXBytes</a></li>
  239. <li data-name="LuCI.Network.Device#getRXPackets"><a href="LuCI.Network.Device.html#getRXPackets">getRXPackets</a></li>
  240. <li data-name="LuCI.Network.Device#getShortName"><a href="LuCI.Network.Device.html#getShortName">getShortName</a></li>
  241. <li data-name="LuCI.Network.Device#getTXBytes"><a href="LuCI.Network.Device.html#getTXBytes">getTXBytes</a></li>
  242. <li data-name="LuCI.Network.Device#getTXPackets"><a href="LuCI.Network.Device.html#getTXPackets">getTXPackets</a></li>
  243. <li data-name="LuCI.Network.Device#getType"><a href="LuCI.Network.Device.html#getType">getType</a></li>
  244. <li data-name="LuCI.Network.Device#getTypeI18n"><a href="LuCI.Network.Device.html#getTypeI18n">getTypeI18n</a></li>
  245. <li data-name="LuCI.Network.Device#getWifiNetwork"><a href="LuCI.Network.Device.html#getWifiNetwork">getWifiNetwork</a></li>
  246. <li data-name="LuCI.Network.Device#isBridge"><a href="LuCI.Network.Device.html#isBridge">isBridge</a></li>
  247. <li data-name="LuCI.Network.Device#isBridgePort"><a href="LuCI.Network.Device.html#isBridgePort">isBridgePort</a></li>
  248. <li data-name="LuCI.Network.Device#isUp"><a href="LuCI.Network.Device.html#isUp">isUp</a></li>
  249. </ul>
  250. <ul class="events itemMembers">
  251. </ul>
  252. </li>
  253. <li class="item" data-name="LuCI.Network.Hosts">
  254. <span class="title">
  255. <a href="LuCI.Network.Hosts.html">LuCI.Network.Hosts</a>
  256. </span>
  257. <ul class="members itemMembers">
  258. </ul>
  259. <ul class="typedefs itemMembers">
  260. </ul>
  261. <ul class="typedefs itemMembers">
  262. </ul>
  263. <ul class="methods itemMembers">
  264. <span class="subtitle">Methods</span>
  265. <li data-name="LuCI.Network.Hosts#getHostnameByIP6Addr"><a href="LuCI.Network.Hosts.html#getHostnameByIP6Addr">getHostnameByIP6Addr</a></li>
  266. <li data-name="LuCI.Network.Hosts#getHostnameByIPAddr"><a href="LuCI.Network.Hosts.html#getHostnameByIPAddr">getHostnameByIPAddr</a></li>
  267. <li data-name="LuCI.Network.Hosts#getHostnameByMACAddr"><a href="LuCI.Network.Hosts.html#getHostnameByMACAddr">getHostnameByMACAddr</a></li>
  268. <li data-name="LuCI.Network.Hosts#getIP6AddrByMACAddr"><a href="LuCI.Network.Hosts.html#getIP6AddrByMACAddr">getIP6AddrByMACAddr</a></li>
  269. <li data-name="LuCI.Network.Hosts#getIPAddrByMACAddr"><a href="LuCI.Network.Hosts.html#getIPAddrByMACAddr">getIPAddrByMACAddr</a></li>
  270. <li data-name="LuCI.Network.Hosts#getMACAddrByIP6Addr"><a href="LuCI.Network.Hosts.html#getMACAddrByIP6Addr">getMACAddrByIP6Addr</a></li>
  271. <li data-name="LuCI.Network.Hosts#getMACAddrByIPAddr"><a href="LuCI.Network.Hosts.html#getMACAddrByIPAddr">getMACAddrByIPAddr</a></li>
  272. <li data-name="LuCI.Network.Hosts#getMACHints"><a href="LuCI.Network.Hosts.html#getMACHints">getMACHints</a></li>
  273. </ul>
  274. <ul class="events itemMembers">
  275. </ul>
  276. </li>
  277. <li class="item" data-name="LuCI.Network.Protocol">
  278. <span class="title">
  279. <a href="LuCI.Network.Protocol.html">LuCI.Network.Protocol</a>
  280. </span>
  281. <ul class="members itemMembers">
  282. </ul>
  283. <ul class="typedefs itemMembers">
  284. </ul>
  285. <ul class="typedefs itemMembers">
  286. </ul>
  287. <ul class="methods itemMembers">
  288. <span class="subtitle">Methods</span>
  289. <li data-name="LuCI.Network.Protocol#addDevice"><a href="LuCI.Network.Protocol.html#addDevice">addDevice</a></li>
  290. <li data-name="LuCI.Network.Protocol#containsDevice"><a href="LuCI.Network.Protocol.html#containsDevice">containsDevice</a></li>
  291. <li data-name="LuCI.Network.Protocol#deleteDevice"><a href="LuCI.Network.Protocol.html#deleteDevice">deleteDevice</a></li>
  292. <li data-name="LuCI.Network.Protocol#get"><a href="LuCI.Network.Protocol.html#get">get</a></li>
  293. <li data-name="LuCI.Network.Protocol#getDevice"><a href="LuCI.Network.Protocol.html#getDevice">getDevice</a></li>
  294. <li data-name="LuCI.Network.Protocol#getDevices"><a href="LuCI.Network.Protocol.html#getDevices">getDevices</a></li>
  295. <li data-name="LuCI.Network.Protocol#getDNS6Addrs"><a href="LuCI.Network.Protocol.html#getDNS6Addrs">getDNS6Addrs</a></li>
  296. <li data-name="LuCI.Network.Protocol#getDNSAddrs"><a href="LuCI.Network.Protocol.html#getDNSAddrs">getDNSAddrs</a></li>
  297. <li data-name="LuCI.Network.Protocol#getErrors"><a href="LuCI.Network.Protocol.html#getErrors">getErrors</a></li>
  298. <li data-name="LuCI.Network.Protocol#getExpiry"><a href="LuCI.Network.Protocol.html#getExpiry">getExpiry</a></li>
  299. <li data-name="LuCI.Network.Protocol#getGateway6Addr"><a href="LuCI.Network.Protocol.html#getGateway6Addr">getGateway6Addr</a></li>
  300. <li data-name="LuCI.Network.Protocol#getGatewayAddr"><a href="LuCI.Network.Protocol.html#getGatewayAddr">getGatewayAddr</a></li>
  301. <li data-name="LuCI.Network.Protocol#getI18n"><a href="LuCI.Network.Protocol.html#getI18n">getI18n</a></li>
  302. <li data-name="LuCI.Network.Protocol#getIfname"><a href="LuCI.Network.Protocol.html#getIfname">getIfname</a></li>
  303. <li data-name="LuCI.Network.Protocol#getIP6Addr"><a href="LuCI.Network.Protocol.html#getIP6Addr">getIP6Addr</a></li>
  304. <li data-name="LuCI.Network.Protocol#getIP6Addrs"><a href="LuCI.Network.Protocol.html#getIP6Addrs">getIP6Addrs</a></li>
  305. <li data-name="LuCI.Network.Protocol#getIP6Prefix"><a href="LuCI.Network.Protocol.html#getIP6Prefix">getIP6Prefix</a></li>
  306. <li data-name="LuCI.Network.Protocol#getIPAddr"><a href="LuCI.Network.Protocol.html#getIPAddr">getIPAddr</a></li>
  307. <li data-name="LuCI.Network.Protocol#getIPAddrs"><a href="LuCI.Network.Protocol.html#getIPAddrs">getIPAddrs</a></li>
  308. <li data-name="LuCI.Network.Protocol#getL2Device"><a href="LuCI.Network.Protocol.html#getL2Device">getL2Device</a></li>
  309. <li data-name="LuCI.Network.Protocol#getL3Device"><a href="LuCI.Network.Protocol.html#getL3Device">getL3Device</a></li>
  310. <li data-name="LuCI.Network.Protocol#getMetric"><a href="LuCI.Network.Protocol.html#getMetric">getMetric</a></li>
  311. <li data-name="LuCI.Network.Protocol#getName"><a href="LuCI.Network.Protocol.html#getName">getName</a></li>
  312. <li data-name="LuCI.Network.Protocol#getNetmask"><a href="LuCI.Network.Protocol.html#getNetmask">getNetmask</a></li>
  313. <li data-name="LuCI.Network.Protocol#getOpkgPackage"><a href="LuCI.Network.Protocol.html#getOpkgPackage">getOpkgPackage</a></li>
  314. <li data-name="LuCI.Network.Protocol#getProtocol"><a href="LuCI.Network.Protocol.html#getProtocol">getProtocol</a></li>
  315. <li data-name="LuCI.Network.Protocol#getType"><a href="LuCI.Network.Protocol.html#getType">getType</a></li>
  316. <li data-name="LuCI.Network.Protocol#getUptime"><a href="LuCI.Network.Protocol.html#getUptime">getUptime</a></li>
  317. <li data-name="LuCI.Network.Protocol#getZoneName"><a href="LuCI.Network.Protocol.html#getZoneName">getZoneName</a></li>
  318. <li data-name="LuCI.Network.Protocol#isAlias"><a href="LuCI.Network.Protocol.html#isAlias">isAlias</a></li>
  319. <li data-name="LuCI.Network.Protocol#isBridge"><a href="LuCI.Network.Protocol.html#isBridge">isBridge</a></li>
  320. <li data-name="LuCI.Network.Protocol#isDynamic"><a href="LuCI.Network.Protocol.html#isDynamic">isDynamic</a></li>
  321. <li data-name="LuCI.Network.Protocol#isEmpty"><a href="LuCI.Network.Protocol.html#isEmpty">isEmpty</a></li>
  322. <li data-name="LuCI.Network.Protocol#isFloating"><a href="LuCI.Network.Protocol.html#isFloating">isFloating</a></li>
  323. <li data-name="LuCI.Network.Protocol#isInstalled"><a href="LuCI.Network.Protocol.html#isInstalled">isInstalled</a></li>
  324. <li data-name="LuCI.Network.Protocol#isUp"><a href="LuCI.Network.Protocol.html#isUp">isUp</a></li>
  325. <li data-name="LuCI.Network.Protocol#isVirtual"><a href="LuCI.Network.Protocol.html#isVirtual">isVirtual</a></li>
  326. <li data-name="LuCI.Network.Protocol#set"><a href="LuCI.Network.Protocol.html#set">set</a></li>
  327. </ul>
  328. <ul class="events itemMembers">
  329. </ul>
  330. </li>
  331. <li class="item" data-name="LuCI.Network.WifiDevice">
  332. <span class="title">
  333. <a href="LuCI.Network.WifiDevice.html">LuCI.Network.WifiDevice</a>
  334. </span>
  335. <ul class="members itemMembers">
  336. </ul>
  337. <ul class="typedefs itemMembers">
  338. </ul>
  339. <ul class="typedefs itemMembers">
  340. </ul>
  341. <ul class="methods itemMembers">
  342. <span class="subtitle">Methods</span>
  343. <li data-name="LuCI.Network.WifiDevice#addWifiNetwork"><a href="LuCI.Network.WifiDevice.html#addWifiNetwork">addWifiNetwork</a></li>
  344. <li data-name="LuCI.Network.WifiDevice#deleteWifiNetwork"><a href="LuCI.Network.WifiDevice.html#deleteWifiNetwork">deleteWifiNetwork</a></li>
  345. <li data-name="LuCI.Network.WifiDevice#get"><a href="LuCI.Network.WifiDevice.html#get">get</a></li>
  346. <li data-name="LuCI.Network.WifiDevice#getHTModes"><a href="LuCI.Network.WifiDevice.html#getHTModes">getHTModes</a></li>
  347. <li data-name="LuCI.Network.WifiDevice#getHWModes"><a href="LuCI.Network.WifiDevice.html#getHWModes">getHWModes</a></li>
  348. <li data-name="LuCI.Network.WifiDevice#getI18n"><a href="LuCI.Network.WifiDevice.html#getI18n">getI18n</a></li>
  349. <li data-name="LuCI.Network.WifiDevice#getName"><a href="LuCI.Network.WifiDevice.html#getName">getName</a></li>
  350. <li data-name="LuCI.Network.WifiDevice#getScanList"><a href="LuCI.Network.WifiDevice.html#getScanList">getScanList</a></li>
  351. <li data-name="LuCI.Network.WifiDevice#getWifiNetwork"><a href="LuCI.Network.WifiDevice.html#getWifiNetwork">getWifiNetwork</a></li>
  352. <li data-name="LuCI.Network.WifiDevice#getWifiNetworks"><a href="LuCI.Network.WifiDevice.html#getWifiNetworks">getWifiNetworks</a></li>
  353. <li data-name="LuCI.Network.WifiDevice#isDisabled"><a href="LuCI.Network.WifiDevice.html#isDisabled">isDisabled</a></li>
  354. <li data-name="LuCI.Network.WifiDevice#isUp"><a href="LuCI.Network.WifiDevice.html#isUp">isUp</a></li>
  355. <li data-name="LuCI.Network.WifiDevice#set"><a href="LuCI.Network.WifiDevice.html#set">set</a></li>
  356. </ul>
  357. <ul class="events itemMembers">
  358. </ul>
  359. </li>
  360. <li class="item" data-name="LuCI.Network.WifiNetwork">
  361. <span class="title">
  362. <a href="LuCI.Network.WifiNetwork.html">LuCI.Network.WifiNetwork</a>
  363. </span>
  364. <ul class="members itemMembers">
  365. </ul>
  366. <ul class="typedefs itemMembers">
  367. </ul>
  368. <ul class="typedefs itemMembers">
  369. </ul>
  370. <ul class="methods itemMembers">
  371. <span class="subtitle">Methods</span>
  372. <li data-name="LuCI.Network.WifiNetwork#disconnectClient"><a href="LuCI.Network.WifiNetwork.html#disconnectClient">disconnectClient</a></li>
  373. <li data-name="LuCI.Network.WifiNetwork#get"><a href="LuCI.Network.WifiNetwork.html#get">get</a></li>
  374. <li data-name="LuCI.Network.WifiNetwork#getActiveBSSID"><a href="LuCI.Network.WifiNetwork.html#getActiveBSSID">getActiveBSSID</a></li>
  375. <li data-name="LuCI.Network.WifiNetwork#getActiveEncryption"><a href="LuCI.Network.WifiNetwork.html#getActiveEncryption">getActiveEncryption</a></li>
  376. <li data-name="LuCI.Network.WifiNetwork#getActiveMode"><a href="LuCI.Network.WifiNetwork.html#getActiveMode">getActiveMode</a></li>
  377. <li data-name="LuCI.Network.WifiNetwork#getActiveModeI18n"><a href="LuCI.Network.WifiNetwork.html#getActiveModeI18n">getActiveModeI18n</a></li>
  378. <li data-name="LuCI.Network.WifiNetwork#getActiveSSID"><a href="LuCI.Network.WifiNetwork.html#getActiveSSID">getActiveSSID</a></li>
  379. <li data-name="LuCI.Network.WifiNetwork#getAssocList"><a href="LuCI.Network.WifiNetwork.html#getAssocList">getAssocList</a></li>
  380. <li data-name="LuCI.Network.WifiNetwork#getBitRate"><a href="LuCI.Network.WifiNetwork.html#getBitRate">getBitRate</a></li>
  381. <li data-name="LuCI.Network.WifiNetwork#getBSSID"><a href="LuCI.Network.WifiNetwork.html#getBSSID">getBSSID</a></li>
  382. <li data-name="LuCI.Network.WifiNetwork#getChannel"><a href="LuCI.Network.WifiNetwork.html#getChannel">getChannel</a></li>
  383. <li data-name="LuCI.Network.WifiNetwork#getCountryCode"><a href="LuCI.Network.WifiNetwork.html#getCountryCode">getCountryCode</a></li>
  384. <li data-name="LuCI.Network.WifiNetwork#getDevice"><a href="LuCI.Network.WifiNetwork.html#getDevice">getDevice</a></li>
  385. <li data-name="LuCI.Network.WifiNetwork#getFrequency"><a href="LuCI.Network.WifiNetwork.html#getFrequency">getFrequency</a></li>
  386. <li data-name="LuCI.Network.WifiNetwork#getI18n"><a href="LuCI.Network.WifiNetwork.html#getI18n">getI18n</a></li>
  387. <li data-name="LuCI.Network.WifiNetwork#getID"><a href="LuCI.Network.WifiNetwork.html#getID">getID</a></li>
  388. <li data-name="LuCI.Network.WifiNetwork#getIfname"><a href="LuCI.Network.WifiNetwork.html#getIfname">getIfname</a></li>
  389. <li data-name="LuCI.Network.WifiNetwork#getMeshID"><a href="LuCI.Network.WifiNetwork.html#getMeshID">getMeshID</a></li>
  390. <li data-name="LuCI.Network.WifiNetwork#getMode"><a href="LuCI.Network.WifiNetwork.html#getMode">getMode</a></li>
  391. <li data-name="LuCI.Network.WifiNetwork#getName"><a href="LuCI.Network.WifiNetwork.html#getName">getName</a></li>
  392. <li data-name="LuCI.Network.WifiNetwork#getNetwork"><a href="LuCI.Network.WifiNetwork.html#getNetwork">getNetwork</a></li>
  393. <li data-name="LuCI.Network.WifiNetwork#getNetworkNames"><a href="LuCI.Network.WifiNetwork.html#getNetworkNames">getNetworkNames</a></li>
  394. <li data-name="LuCI.Network.WifiNetwork#getNetworks"><a href="LuCI.Network.WifiNetwork.html#getNetworks">getNetworks</a></li>
  395. <li data-name="LuCI.Network.WifiNetwork#getNoise"><a href="LuCI.Network.WifiNetwork.html#getNoise">getNoise</a></li>
  396. <li data-name="LuCI.Network.WifiNetwork#getShortName"><a href="LuCI.Network.WifiNetwork.html#getShortName">getShortName</a></li>
  397. <li data-name="LuCI.Network.WifiNetwork#getSignal"><a href="LuCI.Network.WifiNetwork.html#getSignal">getSignal</a></li>
  398. <li data-name="LuCI.Network.WifiNetwork#getSignalLevel"><a href="LuCI.Network.WifiNetwork.html#getSignalLevel">getSignalLevel</a></li>
  399. <li data-name="LuCI.Network.WifiNetwork#getSignalPercent"><a href="LuCI.Network.WifiNetwork.html#getSignalPercent">getSignalPercent</a></li>
  400. <li data-name="LuCI.Network.WifiNetwork#getSSID"><a href="LuCI.Network.WifiNetwork.html#getSSID">getSSID</a></li>
  401. <li data-name="LuCI.Network.WifiNetwork#getTXPower"><a href="LuCI.Network.WifiNetwork.html#getTXPower">getTXPower</a></li>
  402. <li data-name="LuCI.Network.WifiNetwork#getTXPowerOffset"><a href="LuCI.Network.WifiNetwork.html#getTXPowerOffset">getTXPowerOffset</a></li>
  403. <li data-name="LuCI.Network.WifiNetwork#getWifiDevice"><a href="LuCI.Network.WifiNetwork.html#getWifiDevice">getWifiDevice</a></li>
  404. <li data-name="LuCI.Network.WifiNetwork#getWifiDeviceName"><a href="LuCI.Network.WifiNetwork.html#getWifiDeviceName">getWifiDeviceName</a></li>
  405. <li data-name="LuCI.Network.WifiNetwork#isClientDisconnectSupported"><a href="LuCI.Network.WifiNetwork.html#isClientDisconnectSupported">isClientDisconnectSupported</a></li>
  406. <li data-name="LuCI.Network.WifiNetwork#isDisabled"><a href="LuCI.Network.WifiNetwork.html#isDisabled">isDisabled</a></li>
  407. <li data-name="LuCI.Network.WifiNetwork#isUp"><a href="LuCI.Network.WifiNetwork.html#isUp">isUp</a></li>
  408. <li data-name="LuCI.Network.WifiNetwork#set"><a href="LuCI.Network.WifiNetwork.html#set">set</a></li>
  409. </ul>
  410. <ul class="events itemMembers">
  411. </ul>
  412. </li>
  413. <li class="item" data-name="LuCI.Poll">
  414. <span class="title">
  415. <a href="LuCI.Poll.html">LuCI.Poll</a>
  416. </span>
  417. <ul class="members itemMembers">
  418. </ul>
  419. <ul class="typedefs itemMembers">
  420. </ul>
  421. <ul class="typedefs itemMembers">
  422. </ul>
  423. <ul class="methods itemMembers">
  424. <span class="subtitle">Methods</span>
  425. <li data-name="LuCI.Poll#active"><a href="LuCI.Poll.html#active">active</a></li>
  426. <li data-name="LuCI.Poll#add"><a href="LuCI.Poll.html#add">add</a></li>
  427. <li data-name="LuCI.Poll#remove"><a href="LuCI.Poll.html#remove">remove</a></li>
  428. <li data-name="LuCI.Poll#start"><a href="LuCI.Poll.html#start">start</a></li>
  429. <li data-name="LuCI.Poll#stop"><a href="LuCI.Poll.html#stop">stop</a></li>
  430. </ul>
  431. <ul class="events itemMembers">
  432. </ul>
  433. </li>
  434. <li class="item" data-name="LuCI.Request">
  435. <span class="title">
  436. <a href="LuCI.Request.html">LuCI.Request</a>
  437. </span>
  438. <ul class="members itemMembers">
  439. </ul>
  440. <ul class="typedefs itemMembers">
  441. <span class="subtitle">Typedefs</span>
  442. <li data-name="LuCI.Request.interceptorFn"><a href="LuCI.Request.html#.interceptorFn">interceptorFn</a></li>
  443. <li data-name="LuCI.Request.RequestOptions"><a href="LuCI.Request.html#.RequestOptions">RequestOptions</a></li>
  444. </ul>
  445. <ul class="typedefs itemMembers">
  446. </ul>
  447. <ul class="methods itemMembers">
  448. <span class="subtitle">Methods</span>
  449. <li data-name="LuCI.Request#addInterceptor"><a href="LuCI.Request.html#addInterceptor">addInterceptor</a></li>
  450. <li data-name="LuCI.Request#expandURL"><a href="LuCI.Request.html#expandURL">expandURL</a></li>
  451. <li data-name="LuCI.Request#get"><a href="LuCI.Request.html#get">get</a></li>
  452. <li data-name="LuCI.Request#post"><a href="LuCI.Request.html#post">post</a></li>
  453. <li data-name="LuCI.Request#removeInterceptor"><a href="LuCI.Request.html#removeInterceptor">removeInterceptor</a></li>
  454. <li data-name="LuCI.Request#request"><a href="LuCI.Request.html#request">request</a></li>
  455. </ul>
  456. <ul class="events itemMembers">
  457. </ul>
  458. </li>
  459. <li class="item" data-name="LuCI.Request.poll">
  460. <span class="title">
  461. <a href="LuCI.Request.poll.html">LuCI.Request.poll</a>
  462. </span>
  463. <ul class="members itemMembers">
  464. </ul>
  465. <ul class="typedefs itemMembers">
  466. <span class="subtitle">Typedefs</span>
  467. <li data-name="LuCI.Request.poll~callbackFn"><a href="LuCI.Request.poll.html#~callbackFn">callbackFn</a></li>
  468. </ul>
  469. <ul class="typedefs itemMembers">
  470. </ul>
  471. <ul class="methods itemMembers">
  472. <span class="subtitle">Methods</span>
  473. <li data-name="LuCI.Request.poll#active"><a href="LuCI.Request.poll.html#active">active</a></li>
  474. <li data-name="LuCI.Request.poll#add"><a href="LuCI.Request.poll.html#add">add</a></li>
  475. <li data-name="LuCI.Request.poll#remove"><a href="LuCI.Request.poll.html#remove">remove</a></li>
  476. <li data-name="LuCI.Request.poll#start"><a href="LuCI.Request.poll.html#start">start</a></li>
  477. <li data-name="LuCI.Request.poll#stop"><a href="LuCI.Request.poll.html#stop">stop</a></li>
  478. </ul>
  479. <ul class="events itemMembers">
  480. </ul>
  481. </li>
  482. <li class="item" data-name="LuCI.Response">
  483. <span class="title">
  484. <a href="LuCI.Response.html">LuCI.Response</a>
  485. </span>
  486. <ul class="members itemMembers">
  487. <span class="subtitle">Members</span>
  488. <li data-name="LuCI.Response#duration"><a href="LuCI.Response.html#duration">duration</a></li>
  489. <li data-name="LuCI.Response#headers"><a href="LuCI.Response.html#headers">headers</a></li>
  490. <li data-name="LuCI.Response#ok"><a href="LuCI.Response.html#ok">ok</a></li>
  491. <li data-name="LuCI.Response#status"><a href="LuCI.Response.html#status">status</a></li>
  492. <li data-name="LuCI.Response#statusText"><a href="LuCI.Response.html#statusText">statusText</a></li>
  493. <li data-name="LuCI.Response#url"><a href="LuCI.Response.html#url">url</a></li>
  494. </ul>
  495. <ul class="typedefs itemMembers">
  496. </ul>
  497. <ul class="typedefs itemMembers">
  498. </ul>
  499. <ul class="methods itemMembers">
  500. <span class="subtitle">Methods</span>
  501. <li data-name="LuCI.Response#clone"><a href="LuCI.Response.html#clone">clone</a></li>
  502. <li data-name="LuCI.Response#json"><a href="LuCI.Response.html#json">json</a></li>
  503. <li data-name="LuCI.Response#text"><a href="LuCI.Response.html#text">text</a></li>
  504. </ul>
  505. <ul class="events itemMembers">
  506. </ul>
  507. </li>
  508. <li class="item" data-name="LuCI.rpc">
  509. <span class="title">
  510. <a href="LuCI.rpc.html">LuCI.rpc</a>
  511. </span>
  512. <ul class="members itemMembers">
  513. </ul>
  514. <ul class="typedefs itemMembers">
  515. <span class="subtitle">Typedefs</span>
  516. <li data-name="LuCI.rpc.DeclareOptions"><a href="LuCI.rpc.html#.DeclareOptions">DeclareOptions</a></li>
  517. <li data-name="LuCI.rpc~filterFn"><a href="LuCI.rpc.html#~filterFn">filterFn</a></li>
  518. <li data-name="LuCI.rpc~interceptorFn"><a href="LuCI.rpc.html#~interceptorFn">interceptorFn</a></li>
  519. <li data-name="LuCI.rpc~invokeFn"><a href="LuCI.rpc.html#~invokeFn">invokeFn</a></li>
  520. </ul>
  521. <ul class="typedefs itemMembers">
  522. </ul>
  523. <ul class="methods itemMembers">
  524. <span class="subtitle">Methods</span>
  525. <li data-name="LuCI.rpc#addInterceptor"><a href="LuCI.rpc.html#addInterceptor">addInterceptor</a></li>
  526. <li data-name="LuCI.rpc#declare"><a href="LuCI.rpc.html#declare">declare</a></li>
  527. <li data-name="LuCI.rpc#getBaseURL"><a href="LuCI.rpc.html#getBaseURL">getBaseURL</a></li>
  528. <li data-name="LuCI.rpc#getSessionID"><a href="LuCI.rpc.html#getSessionID">getSessionID</a></li>
  529. <li data-name="LuCI.rpc#getStatusText"><a href="LuCI.rpc.html#getStatusText">getStatusText</a></li>
  530. <li data-name="LuCI.rpc#list"><a href="LuCI.rpc.html#list">list</a></li>
  531. <li data-name="LuCI.rpc#removeInterceptor"><a href="LuCI.rpc.html#removeInterceptor">removeInterceptor</a></li>
  532. <li data-name="LuCI.rpc#setBaseURL"><a href="LuCI.rpc.html#setBaseURL">setBaseURL</a></li>
  533. <li data-name="LuCI.rpc#setSessionID"><a href="LuCI.rpc.html#setSessionID">setSessionID</a></li>
  534. </ul>
  535. <ul class="events itemMembers">
  536. </ul>
  537. </li>
  538. <li class="item" data-name="LuCI.uci">
  539. <span class="title">
  540. <a href="LuCI.uci.html">LuCI.uci</a>
  541. </span>
  542. <ul class="members itemMembers">
  543. </ul>
  544. <ul class="typedefs itemMembers">
  545. <span class="subtitle">Typedefs</span>
  546. <li data-name="LuCI.uci.ChangeRecord"><a href="LuCI.uci.html#.ChangeRecord">ChangeRecord</a></li>
  547. <li data-name="LuCI.uci.SectionObject"><a href="LuCI.uci.html#.SectionObject">SectionObject</a></li>
  548. <li data-name="LuCI.uci~sectionsFn"><a href="LuCI.uci.html#~sectionsFn">sectionsFn</a></li>
  549. </ul>
  550. <ul class="typedefs itemMembers">
  551. </ul>
  552. <ul class="methods itemMembers">
  553. <span class="subtitle">Methods</span>
  554. <li data-name="LuCI.uci#add"><a href="LuCI.uci.html#add">add</a></li>
  555. <li data-name="LuCI.uci#apply"><a href="LuCI.uci.html#apply">apply</a></li>
  556. <li data-name="LuCI.uci#changes"><a href="LuCI.uci.html#changes">changes</a></li>
  557. <li data-name="LuCI.uci#createSID"><a href="LuCI.uci.html#createSID">createSID</a></li>
  558. <li data-name="LuCI.uci#get"><a href="LuCI.uci.html#get">get</a></li>
  559. <li data-name="LuCI.uci#get_first"><a href="LuCI.uci.html#get_first">get_first</a></li>
  560. <li data-name="LuCI.uci#load"><a href="LuCI.uci.html#load">load</a></li>
  561. <li data-name="LuCI.uci#move"><a href="LuCI.uci.html#move">move</a></li>
  562. <li data-name="LuCI.uci#remove"><a href="LuCI.uci.html#remove">remove</a></li>
  563. <li data-name="LuCI.uci#resolveSID"><a href="LuCI.uci.html#resolveSID">resolveSID</a></li>
  564. <li data-name="LuCI.uci#save"><a href="LuCI.uci.html#save">save</a></li>
  565. <li data-name="LuCI.uci#sections"><a href="LuCI.uci.html#sections">sections</a></li>
  566. <li data-name="LuCI.uci#set"><a href="LuCI.uci.html#set">set</a></li>
  567. <li data-name="LuCI.uci#set_first"><a href="LuCI.uci.html#set_first">set_first</a></li>
  568. <li data-name="LuCI.uci#unload"><a href="LuCI.uci.html#unload">unload</a></li>
  569. <li data-name="LuCI.uci#unset"><a href="LuCI.uci.html#unset">unset</a></li>
  570. <li data-name="LuCI.uci#unset_first"><a href="LuCI.uci.html#unset_first">unset_first</a></li>
  571. </ul>
  572. <ul class="events itemMembers">
  573. </ul>
  574. </li>
  575. <li class="item" data-name="LuCI.view">
  576. <span class="title">
  577. <a href="LuCI.view.html">LuCI.view</a>
  578. </span>
  579. <ul class="members itemMembers">
  580. </ul>
  581. <ul class="typedefs itemMembers">
  582. </ul>
  583. <ul class="typedefs itemMembers">
  584. </ul>
  585. <ul class="methods itemMembers">
  586. <span class="subtitle">Methods</span>
  587. <li data-name="LuCI.view#addFooter"><a href="LuCI.view.html#addFooter">addFooter</a></li>
  588. <li data-name="LuCI.view#handleReset"><a href="LuCI.view.html#handleReset">handleReset</a></li>
  589. <li data-name="LuCI.view#handleSave"><a href="LuCI.view.html#handleSave">handleSave</a></li>
  590. <li data-name="LuCI.view#handleSaveApply"><a href="LuCI.view.html#handleSaveApply">handleSaveApply</a></li>
  591. <li data-name="LuCI.view#load"><a href="LuCI.view.html#load">load</a></li>
  592. <li data-name="LuCI.view#render"><a href="LuCI.view.html#render">render</a></li>
  593. </ul>
  594. <ul class="events itemMembers">
  595. </ul>
  596. </li>
  597. <li class="item" data-name="LuCI.XHR">
  598. <span class="title">
  599. <a href="LuCI.XHR.html">LuCI.XHR</a>
  600. </span>
  601. <ul class="members itemMembers">
  602. </ul>
  603. <ul class="typedefs itemMembers">
  604. </ul>
  605. <ul class="typedefs itemMembers">
  606. </ul>
  607. <ul class="methods itemMembers">
  608. <span class="subtitle">Methods</span>
  609. <li data-name="LuCI.XHR#abort"><a href="LuCI.XHR.html#abort">abort</a></li>
  610. <li data-name="LuCI.XHR#busy"><a href="LuCI.XHR.html#busy">busy</a></li>
  611. <li data-name="LuCI.XHR#cancel"><a href="LuCI.XHR.html#cancel">cancel</a></li>
  612. <li data-name="LuCI.XHR#get"><a href="LuCI.XHR.html#get">get</a></li>
  613. <li data-name="LuCI.XHR#post"><a href="LuCI.XHR.html#post">post</a></li>
  614. <li data-name="LuCI.XHR#send_form"><a href="LuCI.XHR.html#send_form">send_form</a></li>
  615. </ul>
  616. <ul class="events itemMembers">
  617. </ul>
  618. </li>
  619. </ul>
  620. </div>
  621. <div class="main">
  622. <h1 class="page-title" data-filename="luci.js.html">Source: luci.js</h1>
  623. <section>
  624. <article>
  625. <pre id="source-code" class="prettyprint source "><code>/**
  626. * @class LuCI
  627. * @classdesc
  628. *
  629. * This is the LuCI base class. It is automatically instantiated and
  630. * accessible using the global `L` variable.
  631. *
  632. * @param {Object} env
  633. * The environment settings to use for the LuCI runtime.
  634. */
  635. (function(window, document, undefined) {
  636. 'use strict';
  637. /* Object.assign polyfill for IE */
  638. if (typeof Object.assign !== 'function') {
  639. Object.defineProperty(Object, 'assign', {
  640. value: function assign(target, varArgs) {
  641. if (target == null)
  642. throw new TypeError('Cannot convert undefined or null to object');
  643. var to = Object(target);
  644. for (var index = 1; index &lt; arguments.length; index++)
  645. if (arguments[index] != null)
  646. for (var nextKey in arguments[index])
  647. if (Object.prototype.hasOwnProperty.call(arguments[index], nextKey))
  648. to[nextKey] = arguments[index][nextKey];
  649. return to;
  650. },
  651. writable: true,
  652. configurable: true
  653. });
  654. }
  655. /* Promise.finally polyfill */
  656. if (typeof Promise.prototype.finally !== 'function') {
  657. Promise.prototype.finally = function(fn) {
  658. var onFinally = function(cb) {
  659. return Promise.resolve(fn.call(this)).then(cb);
  660. };
  661. return this.then(
  662. function(result) { return onFinally.call(this, function() { return result }) },
  663. function(reason) { return onFinally.call(this, function() { return Promise.reject(reason) }) }
  664. );
  665. };
  666. }
  667. /*
  668. * Class declaration and inheritance helper
  669. */
  670. var toCamelCase = function(s) {
  671. return s.replace(/(?:^|[\. -])(.)/g, function(m0, m1) { return m1.toUpperCase() });
  672. };
  673. /**
  674. * @class Class
  675. * @hideconstructor
  676. * @memberof LuCI
  677. * @classdesc
  678. *
  679. * `LuCI.Class` is the abstract base class all LuCI classes inherit from.
  680. *
  681. * It provides simple means to create subclasses of given classes and
  682. * implements prototypal inheritance.
  683. */
  684. var superContext = null, Class = Object.assign(function() {}, {
  685. /**
  686. * Extends this base class with the properties described in
  687. * `properties` and returns a new subclassed Class instance
  688. *
  689. * @memberof LuCI.Class
  690. *
  691. * @param {Object&lt;string, *>} properties
  692. * An object describing the properties to add to the new
  693. * subclass.
  694. *
  695. * @returns {LuCI.Class}
  696. * Returns a new LuCI.Class sublassed from this class, extended
  697. * by the given properties and with its prototype set to this base
  698. * class to enable inheritance. The resulting value represents a
  699. * class constructor and can be instantiated with `new`.
  700. */
  701. extend: function(properties) {
  702. var props = {
  703. __base__: { value: this.prototype },
  704. __name__: { value: properties.__name__ || 'anonymous' }
  705. };
  706. var ClassConstructor = function() {
  707. if (!(this instanceof ClassConstructor))
  708. throw new TypeError('Constructor must not be called without "new"');
  709. if (Object.getPrototypeOf(this).hasOwnProperty('__init__')) {
  710. if (typeof(this.__init__) != 'function')
  711. throw new TypeError('Class __init__ member is not a function');
  712. this.__init__.apply(this, arguments)
  713. }
  714. else {
  715. this.super('__init__', arguments);
  716. }
  717. };
  718. for (var key in properties)
  719. if (!props[key] &amp;&amp; properties.hasOwnProperty(key))
  720. props[key] = { value: properties[key], writable: true };
  721. ClassConstructor.prototype = Object.create(this.prototype, props);
  722. ClassConstructor.prototype.constructor = ClassConstructor;
  723. Object.assign(ClassConstructor, this);
  724. ClassConstructor.displayName = toCamelCase(props.__name__.value + 'Class');
  725. return ClassConstructor;
  726. },
  727. /**
  728. * Extends this base class with the properties described in
  729. * `properties`, instantiates the resulting subclass using
  730. * the additional optional arguments passed to this function
  731. * and returns the resulting subclassed Class instance.
  732. *
  733. * This function serves as a convenience shortcut for
  734. * {@link LuCI.Class.extend Class.extend()} and subsequent
  735. * `new`.
  736. *
  737. * @memberof LuCI.Class
  738. *
  739. * @param {Object&lt;string, *>} properties
  740. * An object describing the properties to add to the new
  741. * subclass.
  742. *
  743. * @param {...*} [new_args]
  744. * Specifies arguments to be passed to the subclass constructor
  745. * as-is in order to instantiate the new subclass.
  746. *
  747. * @returns {LuCI.Class}
  748. * Returns a new LuCI.Class instance extended by the given
  749. * properties with its prototype set to this base class to
  750. * enable inheritance.
  751. */
  752. singleton: function(properties /*, ... */) {
  753. return Class.extend(properties)
  754. .instantiate(Class.prototype.varargs(arguments, 1));
  755. },
  756. /**
  757. * Calls the class constructor using `new` with the given argument
  758. * array being passed as variadic parameters to the constructor.
  759. *
  760. * @memberof LuCI.Class
  761. *
  762. * @param {Array&lt;*>} params
  763. * An array of arbitrary values which will be passed as arguments
  764. * to the constructor function.
  765. *
  766. * @param {...*} [new_args]
  767. * Specifies arguments to be passed to the subclass constructor
  768. * as-is in order to instantiate the new subclass.
  769. *
  770. * @returns {LuCI.Class}
  771. * Returns a new LuCI.Class instance extended by the given
  772. * properties with its prototype set to this base class to
  773. * enable inheritance.
  774. */
  775. instantiate: function(args) {
  776. return new (Function.prototype.bind.apply(this,
  777. Class.prototype.varargs(args, 0, null)))();
  778. },
  779. /* unused */
  780. call: function(self, method) {
  781. if (typeof(this.prototype[method]) != 'function')
  782. throw new ReferenceError(method + ' is not defined in class');
  783. return this.prototype[method].apply(self, self.varargs(arguments, 1));
  784. },
  785. /**
  786. * Checks whether the given class value is a subclass of this class.
  787. *
  788. * @memberof LuCI.Class
  789. *
  790. * @param {LuCI.Class} classValue
  791. * The class object to test.
  792. *
  793. * @returns {boolean}
  794. * Returns `true` when the given `classValue` is a subclass of this
  795. * class or `false` if the given value is not a valid class or not
  796. * a subclass of this class'.
  797. */
  798. isSubclass: function(classValue) {
  799. return (classValue != null &amp;&amp;
  800. typeof(classValue) == 'function' &amp;&amp;
  801. classValue.prototype instanceof this);
  802. },
  803. prototype: {
  804. /**
  805. * Extract all values from the given argument array beginning from
  806. * `offset` and prepend any further given optional parameters to
  807. * the beginning of the resulting array copy.
  808. *
  809. * @memberof LuCI.Class
  810. * @instance
  811. *
  812. * @param {Array&lt;*>} args
  813. * The array to extract the values from.
  814. *
  815. * @param {number} offset
  816. * The offset from which to extract the values. An offset of `0`
  817. * would copy all values till the end.
  818. *
  819. * @param {...*} [extra_args]
  820. * Extra arguments to add to prepend to the resultung array.
  821. *
  822. * @returns {Array&lt;*>}
  823. * Returns a new array consisting of the optional extra arguments
  824. * and the values extracted from the `args` array beginning with
  825. * `offset`.
  826. */
  827. varargs: function(args, offset /*, ... */) {
  828. return Array.prototype.slice.call(arguments, 2)
  829. .concat(Array.prototype.slice.call(args, offset));
  830. },
  831. /**
  832. * Walks up the parent class chain and looks for a class member
  833. * called `key` in any of the parent classes this class inherits
  834. * from. Returns the member value of the superclass or calls the
  835. * member as function and returns its return value when the
  836. * optional `callArgs` array is given.
  837. *
  838. * This function has two signatures and is sensitive to the
  839. * amount of arguments passed to it:
  840. * - `super('key')` -
  841. * Returns the value of `key` when found within one of the
  842. * parent classes.
  843. * - `super('key', ['arg1', 'arg2'])` -
  844. * Calls the `key()` method with parameters `arg1` and `arg2`
  845. * when found within one of the parent classes.
  846. *
  847. * @memberof LuCI.Class
  848. * @instance
  849. *
  850. * @param {string} key
  851. * The name of the superclass member to retrieve.
  852. *
  853. * @param {Array&lt;*>} [callArgs]
  854. * An optional array of function call parameters to use. When
  855. * this parameter is specified, the found member value is called
  856. * as function using the values of this array as arguments.
  857. *
  858. * @throws {ReferenceError}
  859. * Throws a `ReferenceError` when `callArgs` are specified and
  860. * the found member named by `key` is not a function value.
  861. *
  862. * @returns {*|null}
  863. * Returns the value of the found member or the return value of
  864. * the call to the found method. Returns `null` when no member
  865. * was found in the parent class chain or when the call to the
  866. * superclass method returned `null`.
  867. */
  868. super: function(key, callArgs) {
  869. for (superContext = Object.getPrototypeOf(superContext ||
  870. Object.getPrototypeOf(this));
  871. superContext &amp;&amp; !superContext.hasOwnProperty(key);
  872. superContext = Object.getPrototypeOf(superContext)) { }
  873. if (!superContext)
  874. return null;
  875. var res = superContext[key];
  876. if (arguments.length > 1) {
  877. if (typeof(res) != 'function')
  878. throw new ReferenceError(key + ' is not a function in base class');
  879. if (typeof(callArgs) != 'object')
  880. callArgs = this.varargs(arguments, 1);
  881. res = res.apply(this, callArgs);
  882. }
  883. superContext = null;
  884. return res;
  885. },
  886. /**
  887. * Returns a string representation of this class.
  888. *
  889. * @returns {string}
  890. * Returns a string representation of this class containing the
  891. * constructor functions `displayName` and describing the class
  892. * members and their respective types.
  893. */
  894. toString: function() {
  895. var s = '[' + this.constructor.displayName + ']', f = true;
  896. for (var k in this) {
  897. if (this.hasOwnProperty(k)) {
  898. s += (f ? ' {\n' : '') + ' ' + k + ': ' + typeof(this[k]) + '\n';
  899. f = false;
  900. }
  901. }
  902. return s + (f ? '' : '}');
  903. }
  904. }
  905. });
  906. /**
  907. * @class
  908. * @memberof LuCI
  909. * @hideconstructor
  910. * @classdesc
  911. *
  912. * The `Headers` class is an internal utility class exposed in HTTP
  913. * response objects using the `response.headers` property.
  914. */
  915. var Headers = Class.extend(/** @lends LuCI.Headers.prototype */ {
  916. __name__: 'LuCI.XHR.Headers',
  917. __init__: function(xhr) {
  918. var hdrs = this.headers = {};
  919. xhr.getAllResponseHeaders().split(/\r\n/).forEach(function(line) {
  920. var m = /^([^:]+):(.*)$/.exec(line);
  921. if (m != null)
  922. hdrs[m[1].trim().toLowerCase()] = m[2].trim();
  923. });
  924. },
  925. /**
  926. * Checks whether the given header name is present.
  927. * Note: Header-Names are case-insensitive.
  928. *
  929. * @instance
  930. * @memberof LuCI.Headers
  931. * @param {string} name
  932. * The header name to check
  933. *
  934. * @returns {boolean}
  935. * Returns `true` if the header name is present, `false` otherwise
  936. */
  937. has: function(name) {
  938. return this.headers.hasOwnProperty(String(name).toLowerCase());
  939. },
  940. /**
  941. * Returns the value of the given header name.
  942. * Note: Header-Names are case-insensitive.
  943. *
  944. * @instance
  945. * @memberof LuCI.Headers
  946. * @param {string} name
  947. * The header name to read
  948. *
  949. * @returns {string|null}
  950. * The value of the given header name or `null` if the header isn't present.
  951. */
  952. get: function(name) {
  953. var key = String(name).toLowerCase();
  954. return this.headers.hasOwnProperty(key) ? this.headers[key] : null;
  955. }
  956. });
  957. /**
  958. * @class
  959. * @memberof LuCI
  960. * @hideconstructor
  961. * @classdesc
  962. *
  963. * The `Response` class is an internal utility class representing HTTP responses.
  964. */
  965. var Response = Class.extend({
  966. __name__: 'LuCI.XHR.Response',
  967. __init__: function(xhr, url, duration, headers, content) {
  968. /**
  969. * Describes whether the response is successful (status codes `200..299`) or not
  970. * @instance
  971. * @memberof LuCI.Response
  972. * @name ok
  973. * @type {boolean}
  974. */
  975. this.ok = (xhr.status >= 200 &amp;&amp; xhr.status &lt;= 299);
  976. /**
  977. * The numeric HTTP status code of the response
  978. * @instance
  979. * @memberof LuCI.Response
  980. * @name status
  981. * @type {number}
  982. */
  983. this.status = xhr.status;
  984. /**
  985. * The HTTP status description message of the response
  986. * @instance
  987. * @memberof LuCI.Response
  988. * @name statusText
  989. * @type {string}
  990. */
  991. this.statusText = xhr.statusText;
  992. /**
  993. * The HTTP headers of the response
  994. * @instance
  995. * @memberof LuCI.Response
  996. * @name headers
  997. * @type {LuCI.Headers}
  998. */
  999. this.headers = (headers != null) ? headers : new Headers(xhr);
  1000. /**
  1001. * The total duration of the HTTP request in milliseconds
  1002. * @instance
  1003. * @memberof LuCI.Response
  1004. * @name duration
  1005. * @type {number}
  1006. */
  1007. this.duration = duration;
  1008. /**
  1009. * The final URL of the request, i.e. after following redirects.
  1010. * @instance
  1011. * @memberof LuCI.Response
  1012. * @name url
  1013. * @type {string}
  1014. */
  1015. this.url = url;
  1016. /* privates */
  1017. this.xhr = xhr;
  1018. if (content != null &amp;&amp; typeof(content) == 'object') {
  1019. this.responseJSON = content;
  1020. this.responseText = null;
  1021. }
  1022. else if (content != null) {
  1023. this.responseJSON = null;
  1024. this.responseText = String(content);
  1025. }
  1026. else {
  1027. this.responseJSON = null;
  1028. this.responseText = xhr.responseText;
  1029. }
  1030. },
  1031. /**
  1032. * Clones the given response object, optionally overriding the content
  1033. * of the cloned instance.
  1034. *
  1035. * @instance
  1036. * @memberof LuCI.Response
  1037. * @param {*} [content]
  1038. * Override the content of the cloned response. Object values will be
  1039. * treated as JSON response data, all other types will be converted
  1040. * using `String()` and treated as response text.
  1041. *
  1042. * @returns {LuCI.Response}
  1043. * The cloned `Response` instance.
  1044. */
  1045. clone: function(content) {
  1046. var copy = new Response(this.xhr, this.url, this.duration, this.headers, content);
  1047. copy.ok = this.ok;
  1048. copy.status = this.status;
  1049. copy.statusText = this.statusText;
  1050. return copy;
  1051. },
  1052. /**
  1053. * Access the response content as JSON data.
  1054. *
  1055. * @instance
  1056. * @memberof LuCI.Response
  1057. * @throws {SyntaxError}
  1058. * Throws `SyntaxError` if the content isn't valid JSON.
  1059. *
  1060. * @returns {*}
  1061. * The parsed JSON data.
  1062. */
  1063. json: function() {
  1064. if (this.responseJSON == null)
  1065. this.responseJSON = JSON.parse(this.responseText);
  1066. return this.responseJSON;
  1067. },
  1068. /**
  1069. * Access the response content as string.
  1070. *
  1071. * @instance
  1072. * @memberof LuCI.Response
  1073. * @returns {string}
  1074. * The response content.
  1075. */
  1076. text: function() {
  1077. if (this.responseText == null &amp;&amp; this.responseJSON != null)
  1078. this.responseText = JSON.stringify(this.responseJSON);
  1079. return this.responseText;
  1080. }
  1081. });
  1082. var requestQueue = [];
  1083. function isQueueableRequest(opt) {
  1084. if (!classes.rpc)
  1085. return false;
  1086. if (opt.method != 'POST' || typeof(opt.content) != 'object')
  1087. return false;
  1088. if (opt.nobatch === true)
  1089. return false;
  1090. var rpcBaseURL = Request.expandURL(classes.rpc.getBaseURL());
  1091. return (rpcBaseURL != null &amp;&amp; opt.url.indexOf(rpcBaseURL) == 0);
  1092. }
  1093. function flushRequestQueue() {
  1094. if (!requestQueue.length)
  1095. return;
  1096. var reqopt = Object.assign({}, requestQueue[0][0], { content: [], nobatch: true }),
  1097. batch = [];
  1098. for (var i = 0; i &lt; requestQueue.length; i++) {
  1099. batch[i] = requestQueue[i];
  1100. reqopt.content[i] = batch[i][0].content;
  1101. }
  1102. requestQueue.length = 0;
  1103. Request.request(rpcBaseURL, reqopt).then(function(reply) {
  1104. var json = null, req = null;
  1105. try { json = reply.json() }
  1106. catch(e) { }
  1107. while ((req = batch.shift()) != null)
  1108. if (Array.isArray(json) &amp;&amp; json.length)
  1109. req[2].call(reqopt, reply.clone(json.shift()));
  1110. else
  1111. req[1].call(reqopt, new Error('No related RPC reply'));
  1112. }).catch(function(error) {
  1113. var req = null;
  1114. while ((req = batch.shift()) != null)
  1115. req[1].call(reqopt, error);
  1116. });
  1117. }
  1118. /**
  1119. * @class
  1120. * @memberof LuCI
  1121. * @hideconstructor
  1122. * @classdesc
  1123. *
  1124. * The `Request` class allows initiating HTTP requests and provides utilities
  1125. * for dealing with responses.
  1126. */
  1127. var Request = Class.singleton(/** @lends LuCI.Request.prototype */ {
  1128. __name__: 'LuCI.Request',
  1129. interceptors: [],
  1130. /**
  1131. * Turn the given relative URL into an absolute URL if necessary.
  1132. *
  1133. * @instance
  1134. * @memberof LuCI.Request
  1135. * @param {string} url
  1136. * The URL to convert.
  1137. *
  1138. * @returns {string}
  1139. * The absolute URL derived from the given one, or the original URL
  1140. * if it already was absolute.
  1141. */
  1142. expandURL: function(url) {
  1143. if (!/^(?:[^/]+:)?\/\//.test(url))
  1144. url = location.protocol + '//' + location.host + url;
  1145. return url;
  1146. },
  1147. /**
  1148. * @typedef {Object} RequestOptions
  1149. * @memberof LuCI.Request
  1150. *
  1151. * @property {string} [method=GET]
  1152. * The HTTP method to use, e.g. `GET` or `POST`.
  1153. *
  1154. * @property {Object&lt;string, Object|string>} [query]
  1155. * Query string data to append to the URL. Non-string values of the
  1156. * given object will be converted to JSON.
  1157. *
  1158. * @property {boolean} [cache=false]
  1159. * Specifies whether the HTTP response may be retrieved from cache.
  1160. *
  1161. * @property {string} [username]
  1162. * Provides a username for HTTP basic authentication.
  1163. *
  1164. * @property {string} [password]
  1165. * Provides a password for HTTP basic authentication.
  1166. *
  1167. * @property {number} [timeout]
  1168. * Specifies the request timeout in seconds.
  1169. *
  1170. * @property {boolean} [credentials=false]
  1171. * Whether to include credentials such as cookies in the request.
  1172. *
  1173. * @property {*} [content]
  1174. * Specifies the HTTP message body to send along with the request.
  1175. * If the value is a function, it is invoked and the return value
  1176. * used as content, if it is a FormData instance, it is used as-is,
  1177. * if it is an object, it will be converted to JSON, in all other
  1178. * cases it is converted to a string.
  1179. *
  1180. * @property {Object&lt;string, string>} [header]
  1181. * Specifies HTTP headers to set for the request.
  1182. *
  1183. * @property {function} [progress]
  1184. * An optional request callback function which receives ProgressEvent
  1185. * instances as sole argument during the HTTP request transfer.
  1186. */
  1187. /**
  1188. * Initiate an HTTP request to the given target.
  1189. *
  1190. * @instance
  1191. * @memberof LuCI.Request
  1192. * @param {string} target
  1193. * The URL to request.
  1194. *
  1195. * @param {LuCI.Request.RequestOptions} [options]
  1196. * Additional options to configure the request.
  1197. *
  1198. * @returns {Promise&lt;LuCI.Response>}
  1199. * The resulting HTTP response.
  1200. */
  1201. request: function(target, options) {
  1202. var state = { xhr: new XMLHttpRequest(), url: this.expandURL(target), start: Date.now() },
  1203. opt = Object.assign({}, options, state),
  1204. content = null,
  1205. contenttype = null,
  1206. callback = this.handleReadyStateChange;
  1207. return new Promise(function(resolveFn, rejectFn) {
  1208. opt.xhr.onreadystatechange = callback.bind(opt, resolveFn, rejectFn);
  1209. opt.method = String(opt.method || 'GET').toUpperCase();
  1210. if ('query' in opt) {
  1211. var q = (opt.query != null) ? Object.keys(opt.query).map(function(k) {
  1212. if (opt.query[k] != null) {
  1213. var v = (typeof(opt.query[k]) == 'object')
  1214. ? JSON.stringify(opt.query[k])
  1215. : String(opt.query[k]);
  1216. return '%s=%s'.format(encodeURIComponent(k), encodeURIComponent(v));
  1217. }
  1218. else {
  1219. return encodeURIComponent(k);
  1220. }
  1221. }).join('&amp;') : '';
  1222. if (q !== '') {
  1223. switch (opt.method) {
  1224. case 'GET':
  1225. case 'HEAD':
  1226. case 'OPTIONS':
  1227. opt.url += ((/\?/).test(opt.url) ? '&amp;' : '?') + q;
  1228. break;
  1229. default:
  1230. if (content == null) {
  1231. content = q;
  1232. contenttype = 'application/x-www-form-urlencoded';
  1233. }
  1234. }
  1235. }
  1236. }
  1237. if (!opt.cache)
  1238. opt.url += ((/\?/).test(opt.url) ? '&amp;' : '?') + (new Date()).getTime();
  1239. if (isQueueableRequest(opt)) {
  1240. requestQueue.push([opt, rejectFn, resolveFn]);
  1241. requestAnimationFrame(flushRequestQueue);
  1242. return;
  1243. }
  1244. if ('username' in opt &amp;&amp; 'password' in opt)
  1245. opt.xhr.open(opt.method, opt.url, true, opt.username, opt.password);
  1246. else
  1247. opt.xhr.open(opt.method, opt.url, true);
  1248. opt.xhr.responseType = 'text';
  1249. if ('overrideMimeType' in opt.xhr)
  1250. opt.xhr.overrideMimeType('application/octet-stream');
  1251. if ('timeout' in opt)
  1252. opt.xhr.timeout = +opt.timeout;
  1253. if ('credentials' in opt)
  1254. opt.xhr.withCredentials = !!opt.credentials;
  1255. if (opt.content != null) {
  1256. switch (typeof(opt.content)) {
  1257. case 'function':
  1258. content = opt.content(xhr);
  1259. break;
  1260. case 'object':
  1261. if (!(opt.content instanceof FormData)) {
  1262. content = JSON.stringify(opt.content);
  1263. contenttype = 'application/json';
  1264. }
  1265. else {
  1266. content = opt.content;
  1267. }
  1268. break;
  1269. default:
  1270. content = String(opt.content);
  1271. }
  1272. }
  1273. if ('headers' in opt)
  1274. for (var header in opt.headers)
  1275. if (opt.headers.hasOwnProperty(header)) {
  1276. if (header.toLowerCase() != 'content-type')
  1277. opt.xhr.setRequestHeader(header, opt.headers[header]);
  1278. else
  1279. contenttype = opt.headers[header];
  1280. }
  1281. if ('progress' in opt &amp;&amp; 'upload' in opt.xhr)
  1282. opt.xhr.upload.addEventListener('progress', opt.progress);
  1283. if (contenttype != null)
  1284. opt.xhr.setRequestHeader('Content-Type', contenttype);
  1285. try {
  1286. opt.xhr.send(content);
  1287. }
  1288. catch (e) {
  1289. rejectFn.call(opt, e);
  1290. }
  1291. });
  1292. },
  1293. handleReadyStateChange: function(resolveFn, rejectFn, ev) {
  1294. var xhr = this.xhr,
  1295. duration = Date.now() - this.start;
  1296. if (xhr.readyState !== 4)
  1297. return;
  1298. if (xhr.status === 0 &amp;&amp; xhr.statusText === '') {
  1299. if (duration >= this.timeout)
  1300. rejectFn.call(this, new Error('XHR request timed out'));
  1301. else
  1302. rejectFn.call(this, new Error('XHR request aborted by browser'));
  1303. }
  1304. else {
  1305. var response = new Response(
  1306. xhr, xhr.responseURL || this.url, duration);
  1307. Promise.all(Request.interceptors.map(function(fn) { return fn(response) }))
  1308. .then(resolveFn.bind(this, response))
  1309. .catch(rejectFn.bind(this));
  1310. }
  1311. },
  1312. /**
  1313. * Initiate an HTTP GET request to the given target.
  1314. *
  1315. * @instance
  1316. * @memberof LuCI.Request
  1317. * @param {string} target
  1318. * The URL to request.
  1319. *
  1320. * @param {LuCI.Request.RequestOptions} [options]
  1321. * Additional options to configure the request.
  1322. *
  1323. * @returns {Promise&lt;LuCI.Response>}
  1324. * The resulting HTTP response.
  1325. */
  1326. get: function(url, options) {
  1327. return this.request(url, Object.assign({ method: 'GET' }, options));
  1328. },
  1329. /**
  1330. * Initiate an HTTP POST request to the given target.
  1331. *
  1332. * @instance
  1333. * @memberof LuCI.Request
  1334. * @param {string} target
  1335. * The URL to request.
  1336. *
  1337. * @param {*} [data]
  1338. * The request data to send, see {@link LuCI.Request.RequestOptions} for details.
  1339. *
  1340. * @param {LuCI.Request.RequestOptions} [options]
  1341. * Additional options to configure the request.
  1342. *
  1343. * @returns {Promise&lt;LuCI.Response>}
  1344. * The resulting HTTP response.
  1345. */
  1346. post: function(url, data, options) {
  1347. return this.request(url, Object.assign({ method: 'POST', content: data }, options));
  1348. },
  1349. /**
  1350. * Interceptor functions are invoked whenever an HTTP reply is received, in the order
  1351. * these functions have been registered.
  1352. * @callback LuCI.Request.interceptorFn
  1353. * @param {LuCI.Response} res
  1354. * The HTTP response object
  1355. */
  1356. /**
  1357. * Register an HTTP response interceptor function. Interceptor
  1358. * functions are useful to perform default actions on incoming HTTP
  1359. * responses, such as checking for expired authentication or for
  1360. * implementing request retries before returning a failure.
  1361. *
  1362. * @instance
  1363. * @memberof LuCI.Request
  1364. * @param {LuCI.Request.interceptorFn} interceptorFn
  1365. * The interceptor function to register.
  1366. *
  1367. * @returns {LuCI.Request.interceptorFn}
  1368. * The registered function.
  1369. */
  1370. addInterceptor: function(interceptorFn) {
  1371. if (typeof(interceptorFn) == 'function')
  1372. this.interceptors.push(interceptorFn);
  1373. return interceptorFn;
  1374. },
  1375. /**
  1376. * Remove an HTTP response interceptor function. The passed function
  1377. * value must be the very same value that was used to register the
  1378. * function.
  1379. *
  1380. * @instance
  1381. * @memberof LuCI.Request
  1382. * @param {LuCI.Request.interceptorFn} interceptorFn
  1383. * The interceptor function to remove.
  1384. *
  1385. * @returns {boolean}
  1386. * Returns `true` if any function has been removed, else `false`.
  1387. */
  1388. removeInterceptor: function(interceptorFn) {
  1389. var oldlen = this.interceptors.length, i = oldlen;
  1390. while (i--)
  1391. if (this.interceptors[i] === interceptorFn)
  1392. this.interceptors.splice(i, 1);
  1393. return (this.interceptors.length &lt; oldlen);
  1394. },
  1395. /**
  1396. * @class
  1397. * @memberof LuCI.Request
  1398. * @hideconstructor
  1399. * @classdesc
  1400. *
  1401. * The `Request.poll` class provides some convience wrappers around
  1402. * {@link LuCI.Poll} mainly to simplify registering repeating HTTP
  1403. * request calls as polling functions.
  1404. */
  1405. poll: {
  1406. /**
  1407. * The callback function is invoked whenever an HTTP reply to a
  1408. * polled request is received or when the polled request timed
  1409. * out.
  1410. *
  1411. * @callback LuCI.Request.poll~callbackFn
  1412. * @param {LuCI.Response} res
  1413. * The HTTP response object.
  1414. *
  1415. * @param {*} data
  1416. * The response JSON if the response could be parsed as such,
  1417. * else `null`.
  1418. *
  1419. * @param {number} duration
  1420. * The total duration of the request in milliseconds.
  1421. */
  1422. /**
  1423. * Register a repeating HTTP request with an optional callback
  1424. * to invoke whenever a response for the request is received.
  1425. *
  1426. * @instance
  1427. * @memberof LuCI.Request.poll
  1428. * @param {number} interval
  1429. * The poll interval in seconds.
  1430. *
  1431. * @param {string} url
  1432. * The URL to request on each poll.
  1433. *
  1434. * @param {LuCI.Request.RequestOptions} [options]
  1435. * Additional options to configure the request.
  1436. *
  1437. * @param {LuCI.Request.poll~callbackFn} [callback]
  1438. * {@link LuCI.Request.poll~callbackFn Callback} function to
  1439. * invoke for each HTTP reply.
  1440. *
  1441. * @throws {TypeError}
  1442. * Throws `TypeError` when an invalid interval was passed.
  1443. *
  1444. * @returns {function}
  1445. * Returns the internally created poll function.
  1446. */
  1447. add: function(interval, url, options, callback) {
  1448. if (isNaN(interval) || interval &lt;= 0)
  1449. throw new TypeError('Invalid poll interval');
  1450. var ival = interval >>> 0,
  1451. opts = Object.assign({}, options, { timeout: ival * 1000 - 5 });
  1452. var fn = function() {
  1453. return Request.request(url, options).then(function(res) {
  1454. if (!Poll.active())
  1455. return;
  1456. try {
  1457. callback(res, res.json(), res.duration);
  1458. }
  1459. catch (err) {
  1460. callback(res, null, res.duration);
  1461. }
  1462. });
  1463. };
  1464. return (Poll.add(fn, ival) ? fn : null);
  1465. },
  1466. /**
  1467. * Remove a polling request that has been previously added using `add()`.
  1468. * This function is essentially a wrapper around
  1469. * {@link LuCI.Poll.remove LuCI.Poll.remove()}.
  1470. *
  1471. * @instance
  1472. * @memberof LuCI.Request.poll
  1473. * @param {function} entry
  1474. * The poll function returned by {@link LuCI.Request.poll#add add()}.
  1475. *
  1476. * @returns {boolean}
  1477. * Returns `true` if any function has been removed, else `false`.
  1478. */
  1479. remove: function(entry) { return Poll.remove(entry) },
  1480. /**
  1481. * Alias for {@link LuCI.Poll.start LuCI.Poll.start()}.
  1482. *
  1483. * @instance
  1484. * @memberof LuCI.Request.poll
  1485. */
  1486. start: function() { return Poll.start() },
  1487. /**
  1488. * Alias for {@link LuCI.Poll.stop LuCI.Poll.stop()}.
  1489. *
  1490. * @instance
  1491. * @memberof LuCI.Request.poll
  1492. */
  1493. stop: function() { return Poll.stop() },
  1494. /**
  1495. * Alias for {@link LuCI.Poll.active LuCI.Poll.active()}.
  1496. *
  1497. * @instance
  1498. * @memberof LuCI.Request.poll
  1499. */
  1500. active: function() { return Poll.active() }
  1501. }
  1502. });
  1503. /**
  1504. * @class
  1505. * @memberof LuCI
  1506. * @hideconstructor
  1507. * @classdesc
  1508. *
  1509. * The `Poll` class allows registering and unregistering poll actions,
  1510. * as well as starting, stopping and querying the state of the polling
  1511. * loop.
  1512. */
  1513. var Poll = Class.singleton(/** @lends LuCI.Poll.prototype */ {
  1514. __name__: 'LuCI.Poll',
  1515. queue: [],
  1516. /**
  1517. * Add a new operation to the polling loop. If the polling loop is not
  1518. * already started at this point, it will be implicitely started.
  1519. *
  1520. * @instance
  1521. * @memberof LuCI.Poll
  1522. * @param {function} fn
  1523. * The function to invoke on each poll interval.
  1524. *
  1525. * @param {number} interval
  1526. * The poll interval in seconds.
  1527. *
  1528. * @throws {TypeError}
  1529. * Throws `TypeError` when an invalid interval was passed.
  1530. *
  1531. * @returns {boolean}
  1532. * Returns `true` if the function has been added or `false` if it
  1533. * already is registered.
  1534. */
  1535. add: function(fn, interval) {
  1536. if (interval == null || interval &lt;= 0)
  1537. interval = window.L ? window.L.env.pollinterval : null;
  1538. if (isNaN(interval) || typeof(fn) != 'function')
  1539. throw new TypeError('Invalid argument to LuCI.Poll.add()');
  1540. for (var i = 0; i &lt; this.queue.length; i++)
  1541. if (this.queue[i].fn === fn)
  1542. return false;
  1543. var e = {
  1544. r: true,
  1545. i: interval >>> 0,
  1546. fn: fn
  1547. };
  1548. this.queue.push(e);
  1549. if (this.tick != null &amp;&amp; !this.active())
  1550. this.start();
  1551. return true;
  1552. },
  1553. /**
  1554. * Remove an operation from the polling loop. If no further operatons
  1555. * are registered, the polling loop is implicitely stopped.
  1556. *
  1557. * @instance
  1558. * @memberof LuCI.Poll
  1559. * @param {function} fn
  1560. * The function to remove.
  1561. *
  1562. * @throws {TypeError}
  1563. * Throws `TypeError` when the given argument isn't a function.
  1564. *
  1565. * @returns {boolean}
  1566. * Returns `true` if the function has been removed or `false` if it
  1567. * wasn't found.
  1568. */
  1569. remove: function(fn) {
  1570. if (typeof(fn) != 'function')
  1571. throw new TypeError('Invalid argument to LuCI.Poll.remove()');
  1572. var len = this.queue.length;
  1573. for (var i = len; i > 0; i--)
  1574. if (this.queue[i-1].fn === fn)
  1575. this.queue.splice(i-1, 1);
  1576. if (!this.queue.length &amp;&amp; this.stop())
  1577. this.tick = 0;
  1578. return (this.queue.length != len);
  1579. },
  1580. /**
  1581. * (Re)start the polling loop. Dispatches a custom `poll-start` event
  1582. * to the `document` object upon successful start.
  1583. *
  1584. * @instance
  1585. * @memberof LuCI.Poll
  1586. * @returns {boolean}
  1587. * Returns `true` if polling has been started (or if no functions
  1588. * where registered) or `false` when the polling loop already runs.
  1589. */
  1590. start: function() {
  1591. if (this.active())
  1592. return false;
  1593. this.tick = 0;
  1594. if (this.queue.length) {
  1595. this.timer = window.setInterval(this.step, 1000);
  1596. this.step();
  1597. document.dispatchEvent(new CustomEvent('poll-start'));
  1598. }
  1599. return true;
  1600. },
  1601. /**
  1602. * Stop the polling loop. Dispatches a custom `poll-stop` event
  1603. * to the `document` object upon successful stop.
  1604. *
  1605. * @instance
  1606. * @memberof LuCI.Poll
  1607. * @returns {boolean}
  1608. * Returns `true` if polling has been stopped or `false` if it din't
  1609. * run to begin with.
  1610. */
  1611. stop: function() {
  1612. if (!this.active())
  1613. return false;
  1614. document.dispatchEvent(new CustomEvent('poll-stop'));
  1615. window.clearInterval(this.timer);
  1616. delete this.timer;
  1617. delete this.tick;
  1618. return true;
  1619. },
  1620. /* private */
  1621. step: function() {
  1622. for (var i = 0, e = null; (e = Poll.queue[i]) != null; i++) {
  1623. if ((Poll.tick % e.i) != 0)
  1624. continue;
  1625. if (!e.r)
  1626. continue;
  1627. e.r = false;
  1628. Promise.resolve(e.fn()).finally((function() { this.r = true }).bind(e));
  1629. }
  1630. Poll.tick = (Poll.tick + 1) % Math.pow(2, 32);
  1631. },
  1632. /**
  1633. * Test whether the polling loop is running.
  1634. *
  1635. * @instance
  1636. * @memberof LuCI.Poll
  1637. * @returns {boolean} - Returns `true` if polling is active, else `false`.
  1638. */
  1639. active: function() {
  1640. return (this.timer != null);
  1641. }
  1642. });
  1643. var dummyElem = null,
  1644. domParser = null,
  1645. originalCBIInit = null,
  1646. rpcBaseURL = null,
  1647. sysFeatures = null,
  1648. classes = {};
  1649. var LuCI = Class.extend(/** @lends LuCI.prototype */ {
  1650. __name__: 'LuCI',
  1651. __init__: function(env) {
  1652. document.querySelectorAll('script[src*="/luci.js"]').forEach(function(s) {
  1653. if (env.base_url == null || env.base_url == '') {
  1654. var m = (s.getAttribute('src') || '').match(/^(.*)\/luci\.js(?:\?v=([^?]+))?$/);
  1655. if (m) {
  1656. env.base_url = m[1];
  1657. env.resource_version = m[2];
  1658. }
  1659. }
  1660. });
  1661. if (env.base_url == null)
  1662. this.error('InternalError', 'Cannot find url of luci.js');
  1663. Object.assign(this.env, env);
  1664. document.addEventListener('poll-start', function(ev) {
  1665. document.querySelectorAll('[id^="xhr_poll_status"]').forEach(function(e) {
  1666. e.style.display = (e.id == 'xhr_poll_status_off') ? 'none' : '';
  1667. });
  1668. });
  1669. document.addEventListener('poll-stop', function(ev) {
  1670. document.querySelectorAll('[id^="xhr_poll_status"]').forEach(function(e) {
  1671. e.style.display = (e.id == 'xhr_poll_status_on') ? 'none' : '';
  1672. });
  1673. });
  1674. var domReady = new Promise(function(resolveFn, rejectFn) {
  1675. document.addEventListener('DOMContentLoaded', resolveFn);
  1676. });
  1677. Promise.all([
  1678. domReady,
  1679. this.require('ui'),
  1680. this.require('rpc'),
  1681. this.require('form'),
  1682. this.probeRPCBaseURL()
  1683. ]).then(this.setupDOM.bind(this)).catch(this.error);
  1684. originalCBIInit = window.cbi_init;
  1685. window.cbi_init = function() {};
  1686. },
  1687. /**
  1688. * Captures the current stack trace and throws an error of the
  1689. * specified type as a new exception. Also logs the exception as
  1690. * error to the debug console if it is available.
  1691. *
  1692. * @instance
  1693. * @memberof LuCI
  1694. *
  1695. * @param {Error|string} [type=Error]
  1696. * Either a string specifying the type of the error to throw or an
  1697. * existing `Error` instance to copy.
  1698. *
  1699. * @param {string} [fmt=Unspecified error]
  1700. * A format string which is used to form the error message, together
  1701. * with all subsequent optional arguments.
  1702. *
  1703. * @param {...*} [args]
  1704. * Zero or more variable arguments to the supplied format string.
  1705. *
  1706. * @throws {Error}
  1707. * Throws the created error object with the captured stack trace
  1708. * appended to the message and the type set to the given type
  1709. * argument or copied from the given error instance.
  1710. */
  1711. raise: function(type, fmt /*, ...*/) {
  1712. var e = null,
  1713. msg = fmt ? String.prototype.format.apply(fmt, this.varargs(arguments, 2)) : null,
  1714. stack = null;
  1715. if (type instanceof Error) {
  1716. e = type;
  1717. if (msg)
  1718. e.message = msg + ': ' + e.message;
  1719. }
  1720. else {
  1721. try { throw new Error('stacktrace') }
  1722. catch (e2) { stack = (e2.stack || '').split(/\n/) }
  1723. e = new (window[type || 'Error'] || Error)(msg || 'Unspecified error');
  1724. e.name = type || 'Error';
  1725. }
  1726. stack = (stack || []).map(function(frame) {
  1727. frame = frame.replace(/(.*?)@(.+):(\d+):(\d+)/g, 'at $1 ($2:$3:$4)').trim();
  1728. return frame ? ' ' + frame : '';
  1729. });
  1730. if (!/^ at /.test(stack[0]))
  1731. stack.shift();
  1732. if (/\braise /.test(stack[0]))
  1733. stack.shift();
  1734. if (/\berror /.test(stack[0]))
  1735. stack.shift();
  1736. if (stack.length)
  1737. e.message += '\n' + stack.join('\n');
  1738. if (window.console &amp;&amp; console.debug)
  1739. console.debug(e);
  1740. throw e;
  1741. },
  1742. /**
  1743. * A wrapper around {@link LuCI#raise raise()} which also renders
  1744. * the error either as modal overlay when `ui.js` is already loaed
  1745. * or directly into the view body.
  1746. *
  1747. * @instance
  1748. * @memberof LuCI
  1749. *
  1750. * @param {Error|string} [type=Error]
  1751. * Either a string specifying the type of the error to throw or an
  1752. * existing `Error` instance to copy.
  1753. *
  1754. * @param {string} [fmt=Unspecified error]
  1755. * A format string which is used to form the error message, together
  1756. * with all subsequent optional arguments.
  1757. *
  1758. * @param {...*} [args]
  1759. * Zero or more variable arguments to the supplied format string.
  1760. *
  1761. * @throws {Error}
  1762. * Throws the created error object with the captured stack trace
  1763. * appended to the message and the type set to the given type
  1764. * argument or copied from the given error instance.
  1765. */
  1766. error: function(type, fmt /*, ...*/) {
  1767. try {
  1768. L.raise.apply(L, Array.prototype.slice.call(arguments));
  1769. }
  1770. catch (e) {
  1771. if (!e.reported) {
  1772. if (L.ui)
  1773. L.ui.addNotification(e.name || _('Runtime error'),
  1774. E('pre', {}, e.message), 'danger');
  1775. else
  1776. L.dom.content(document.querySelector('#maincontent'),
  1777. E('pre', { 'class': 'alert-message error' }, e.message));
  1778. e.reported = true;
  1779. }
  1780. throw e;
  1781. }
  1782. },
  1783. /**
  1784. * Return a bound function using the given `self` as `this` context
  1785. * and any further arguments as parameters to the bound function.
  1786. *
  1787. * @instance
  1788. * @memberof LuCI
  1789. *
  1790. * @param {function} fn
  1791. * The function to bind.
  1792. *
  1793. * @param {*} self
  1794. * The value to bind as `this` context to the specified function.
  1795. *
  1796. * @param {...*} [args]
  1797. * Zero or more variable arguments which are bound to the function
  1798. * as parameters.
  1799. *
  1800. * @returns {function}
  1801. * Returns the bound function.
  1802. */
  1803. bind: function(fn, self /*, ... */) {
  1804. return Function.prototype.bind.apply(fn, this.varargs(arguments, 2, self));
  1805. },
  1806. /**
  1807. * Load an additional LuCI JavaScript class and its dependencies,
  1808. * instantiate it and return the resulting class instance. Each
  1809. * class is only loaded once. Subsequent attempts to load the same
  1810. * class will return the already instantiated class.
  1811. *
  1812. * @instance
  1813. * @memberof LuCI
  1814. *
  1815. * @param {string} name
  1816. * The name of the class to load in dotted notation. Dots will
  1817. * be replaced by spaces and joined with the runtime-determined
  1818. * base URL of LuCI.js to form an absolute URL to load the class
  1819. * file from.
  1820. *
  1821. * @throws {DependencyError}
  1822. * Throws a `DependencyError` when the class to load includes
  1823. * circular dependencies.
  1824. *
  1825. * @throws {NetworkError}
  1826. * Throws `NetworkError` when the underlying {@link LuCI.Request}
  1827. * call failed.
  1828. *
  1829. * @throws {SyntaxError}
  1830. * Throws `SyntaxError` when the loaded class file code cannot
  1831. * be interpreted by `eval`.
  1832. *
  1833. * @throws {TypeError}
  1834. * Throws `TypeError` when the class file could be loaded and
  1835. * interpreted, but when invoking its code did not yield a valid
  1836. * class instance.
  1837. *
  1838. * @returns {Promise&lt;LuCI#Class>}
  1839. * Returns the instantiated class.
  1840. */
  1841. require: function(name, from) {
  1842. var L = this, url = null, from = from || [];
  1843. /* Class already loaded */
  1844. if (classes[name] != null) {
  1845. /* Circular dependency */
  1846. if (from.indexOf(name) != -1)
  1847. L.raise('DependencyError',
  1848. 'Circular dependency: class "%s" depends on "%s"',
  1849. name, from.join('" which depends on "'));
  1850. return Promise.resolve(classes[name]);
  1851. }
  1852. url = '%s/%s.js%s'.format(L.env.base_url, name.replace(/\./g, '/'), (L.env.resource_version ? '?v=' + L.env.resource_version : ''));
  1853. from = [ name ].concat(from);
  1854. var compileClass = function(res) {
  1855. if (!res.ok)
  1856. L.raise('NetworkError',
  1857. 'HTTP error %d while loading class file "%s"', res.status, url);
  1858. var source = res.text(),
  1859. requirematch = /^require[ \t]+(\S+)(?:[ \t]+as[ \t]+([a-zA-Z_]\S*))?$/,
  1860. strictmatch = /^use[ \t]+strict$/,
  1861. depends = [],
  1862. args = '';
  1863. /* find require statements in source */
  1864. for (var i = 0, off = -1, quote = -1, esc = false; i &lt; source.length; i++) {
  1865. var chr = source.charCodeAt(i);
  1866. if (esc) {
  1867. esc = false;
  1868. }
  1869. else if (chr == 92) {
  1870. esc = true;
  1871. }
  1872. else if (chr == quote) {
  1873. var s = source.substring(off, i),
  1874. m = requirematch.exec(s);
  1875. if (m) {
  1876. var dep = m[1], as = m[2] || dep.replace(/[^a-zA-Z0-9_]/g, '_');
  1877. depends.push(L.require(dep, from));
  1878. args += ', ' + as;
  1879. }
  1880. else if (!strictmatch.exec(s)) {
  1881. break;
  1882. }
  1883. off = -1;
  1884. quote = -1;
  1885. }
  1886. else if (quote == -1 &amp;&amp; (chr == 34 || chr == 39)) {
  1887. off = i + 1;
  1888. quote = chr;
  1889. }
  1890. }
  1891. /* load dependencies and instantiate class */
  1892. return Promise.all(depends).then(function(instances) {
  1893. var _factory, _class;
  1894. try {
  1895. _factory = eval(
  1896. '(function(window, document, L%s) { %s })\n\n//# sourceURL=%s\n'
  1897. .format(args, source, res.url));
  1898. }
  1899. catch (error) {
  1900. L.raise('SyntaxError', '%s\n in %s:%s',
  1901. error.message, res.url, error.lineNumber || '?');
  1902. }
  1903. _factory.displayName = toCamelCase(name + 'ClassFactory');
  1904. _class = _factory.apply(_factory, [window, document, L].concat(instances));
  1905. if (!Class.isSubclass(_class))
  1906. L.error('TypeError', '"%s" factory yields invalid constructor', name);
  1907. if (_class.displayName == 'AnonymousClass')
  1908. _class.displayName = toCamelCase(name + 'Class');
  1909. var ptr = Object.getPrototypeOf(L),
  1910. parts = name.split(/\./),
  1911. instance = new _class();
  1912. for (var i = 0; ptr &amp;&amp; i &lt; parts.length - 1; i++)
  1913. ptr = ptr[parts[i]];
  1914. if (ptr)
  1915. ptr[parts[i]] = instance;
  1916. classes[name] = instance;
  1917. return instance;
  1918. });
  1919. };
  1920. /* Request class file */
  1921. classes[name] = Request.get(url, { cache: true }).then(compileClass);
  1922. return classes[name];
  1923. },
  1924. /* DOM setup */
  1925. probeRPCBaseURL: function() {
  1926. if (rpcBaseURL == null) {
  1927. try {
  1928. rpcBaseURL = window.sessionStorage.getItem('rpcBaseURL');
  1929. }
  1930. catch (e) { }
  1931. }
  1932. if (rpcBaseURL == null) {
  1933. var rpcFallbackURL = this.url('admin/ubus');
  1934. rpcBaseURL = Request.get('/ubus/').then(function(res) {
  1935. return (rpcBaseURL = (res.status == 400) ? '/ubus/' : rpcFallbackURL);
  1936. }, function() {
  1937. return (rpcBaseURL = rpcFallbackURL);
  1938. }).then(function(url) {
  1939. try {
  1940. window.sessionStorage.setItem('rpcBaseURL', url);
  1941. }
  1942. catch (e) { }
  1943. return url;
  1944. });
  1945. }
  1946. return Promise.resolve(rpcBaseURL);
  1947. },
  1948. probeSystemFeatures: function() {
  1949. var sessionid = classes.rpc.getSessionID();
  1950. if (sysFeatures == null) {
  1951. try {
  1952. var data = JSON.parse(window.sessionStorage.getItem('sysFeatures'));
  1953. if (this.isObject(data) &amp;&amp; this.isObject(data[sessionid]))
  1954. sysFeatures = data[sessionid];
  1955. }
  1956. catch (e) {}
  1957. }
  1958. if (!this.isObject(sysFeatures)) {
  1959. sysFeatures = classes.rpc.declare({
  1960. object: 'luci',
  1961. method: 'getFeatures',
  1962. expect: { '': {} }
  1963. })().then(function(features) {
  1964. try {
  1965. var data = {};
  1966. data[sessionid] = features;
  1967. window.sessionStorage.setItem('sysFeatures', JSON.stringify(data));
  1968. }
  1969. catch (e) {}
  1970. sysFeatures = features;
  1971. return features;
  1972. });
  1973. }
  1974. return Promise.resolve(sysFeatures);
  1975. },
  1976. /**
  1977. * Test whether a particular system feature is available, such as
  1978. * hostapd SAE support or an installed firewall. The features are
  1979. * queried once at the beginning of the LuCI session and cached in
  1980. * `SessionStorage` throughout the lifetime of the associated tab or
  1981. * browser window.
  1982. *
  1983. * @instance
  1984. * @memberof LuCI
  1985. *
  1986. * @param {string} feature
  1987. * The feature to test. For detailed list of known feature flags,
  1988. * see `/modules/luci-base/root/usr/libexec/rpcd/luci`.
  1989. *
  1990. * @param {string} [subfeature]
  1991. * Some feature classes like `hostapd` provide sub-feature flags,
  1992. * such as `sae` or `11w` support. The `subfeature` argument can
  1993. * be used to query these.
  1994. *
  1995. * @return {boolean|null}
  1996. * Return `true` if the queried feature (and sub-feature) is available
  1997. * or `false` if the requested feature isn't present or known.
  1998. * Return `null` when a sub-feature was queried for a feature which
  1999. * has no sub-features.
  2000. */
  2001. hasSystemFeature: function() {
  2002. var ft = sysFeatures[arguments[0]];
  2003. if (arguments.length == 2)
  2004. return this.isObject(ft) ? ft[arguments[1]] : null;
  2005. return (ft != null &amp;&amp; ft != false);
  2006. },
  2007. /* private */
  2008. notifySessionExpiry: function() {
  2009. Poll.stop();
  2010. L.ui.showModal(_('Session expired'), [
  2011. E('div', { class: 'alert-message warning' },
  2012. _('A new login is required since the authentication session expired.')),
  2013. E('div', { class: 'right' },
  2014. E('div', {
  2015. class: 'btn primary',
  2016. click: function() {
  2017. var loc = window.location;
  2018. window.location = loc.protocol + '//' + loc.host + loc.pathname + loc.search;
  2019. }
  2020. }, _('To login…')))
  2021. ]);
  2022. L.raise('SessionError', 'Login session is expired');
  2023. },
  2024. /* private */
  2025. setupDOM: function(res) {
  2026. var domEv = res[0],
  2027. uiClass = res[1],
  2028. rpcClass = res[2],
  2029. formClass = res[3],
  2030. rpcBaseURL = res[4];
  2031. rpcClass.setBaseURL(rpcBaseURL);
  2032. rpcClass.addInterceptor(function(msg, req) {
  2033. if (!L.isObject(msg) || !L.isObject(msg.error) || msg.error.code != -32002)
  2034. return;
  2035. if (!L.isObject(req) || (req.object == 'session' &amp;&amp; req.method == 'access'))
  2036. return;
  2037. return rpcClass.declare({
  2038. 'object': 'session',
  2039. 'method': 'access',
  2040. 'params': [ 'scope', 'object', 'function' ],
  2041. 'expect': { access: true }
  2042. })('uci', 'luci', 'read').catch(L.notifySessionExpiry);
  2043. });
  2044. Request.addInterceptor(function(res) {
  2045. var isDenied = false;
  2046. if (res.status == 403 &amp;&amp; res.headers.get('X-LuCI-Login-Required') == 'yes')
  2047. isDenied = true;
  2048. if (!isDenied)
  2049. return;
  2050. L.notifySessionExpiry();
  2051. });
  2052. return this.probeSystemFeatures().finally(this.initDOM);
  2053. },
  2054. /* private */
  2055. initDOM: function() {
  2056. originalCBIInit();
  2057. Poll.start();
  2058. document.dispatchEvent(new CustomEvent('luci-loaded'));
  2059. },
  2060. /**
  2061. * The `env` object holds environment settings used by LuCI, such
  2062. * as request timeouts, base URLs etc.
  2063. *
  2064. * @instance
  2065. * @memberof LuCI
  2066. */
  2067. env: {},
  2068. /**
  2069. * Construct a relative URL path from the given prefix and parts.
  2070. * The resulting URL is guaranteed to only contain the characters
  2071. * `a-z`, `A-Z`, `0-9`, `_`, `.`, `%`, `,`, `;`, and `-` as well
  2072. * as `/` for the path separator.
  2073. *
  2074. * @instance
  2075. * @memberof LuCI
  2076. *
  2077. * @param {string} [prefix]
  2078. * The prefix to join the given parts with. If the `prefix` is
  2079. * omitted, it defaults to an empty string.
  2080. *
  2081. * @param {string[]} [parts]
  2082. * An array of parts to join into an URL path. Parts may contain
  2083. * slashes and any of the other characters mentioned above.
  2084. *
  2085. * @return {string}
  2086. * Return the joined URL path.
  2087. */
  2088. path: function(prefix, parts) {
  2089. var url = [ prefix || '' ];
  2090. for (var i = 0; i &lt; parts.length; i++)
  2091. if (/^(?:[a-zA-Z0-9_.%,;-]+\/)*[a-zA-Z0-9_.%,;-]+$/.test(parts[i]))
  2092. url.push('/', parts[i]);
  2093. if (url.length === 1)
  2094. url.push('/');
  2095. return url.join('');
  2096. },
  2097. /**
  2098. * Construct an URL pathrelative to the script path of the server
  2099. * side LuCI application (usually `/cgi-bin/luci`).
  2100. *
  2101. * The resulting URL is guaranteed to only contain the characters
  2102. * `a-z`, `A-Z`, `0-9`, `_`, `.`, `%`, `,`, `;`, and `-` as well
  2103. * as `/` for the path separator.
  2104. *
  2105. * @instance
  2106. * @memberof LuCI
  2107. *
  2108. * @param {string[]} [parts]
  2109. * An array of parts to join into an URL path. Parts may contain
  2110. * slashes and any of the other characters mentioned above.
  2111. *
  2112. * @return {string}
  2113. * Returns the resulting URL path.
  2114. */
  2115. url: function() {
  2116. return this.path(this.env.scriptname, arguments);
  2117. },
  2118. /**
  2119. * Construct an URL path relative to the global static resource path
  2120. * of the LuCI ui (usually `/luci-static/resources`).
  2121. *
  2122. * The resulting URL is guaranteed to only contain the characters
  2123. * `a-z`, `A-Z`, `0-9`, `_`, `.`, `%`, `,`, `;`, and `-` as well
  2124. * as `/` for the path separator.
  2125. *
  2126. * @instance
  2127. * @memberof LuCI
  2128. *
  2129. * @param {string[]} [parts]
  2130. * An array of parts to join into an URL path. Parts may contain
  2131. * slashes and any of the other characters mentioned above.
  2132. *
  2133. * @return {string}
  2134. * Returns the resulting URL path.
  2135. */
  2136. resource: function() {
  2137. return this.path(this.env.resource, arguments);
  2138. },
  2139. /**
  2140. * Return the complete URL path to the current view.
  2141. *
  2142. * @instance
  2143. * @memberof LuCI
  2144. *
  2145. * @return {string}
  2146. * Returns the URL path to the current view.
  2147. */
  2148. location: function() {
  2149. return this.path(this.env.scriptname, this.env.requestpath);
  2150. },
  2151. /**
  2152. * Tests whether the passed argument is a JavaScript object.
  2153. * This function is meant to be an object counterpart to the
  2154. * standard `Array.isArray()` function.
  2155. *
  2156. * @instance
  2157. * @memberof LuCI
  2158. *
  2159. * @param {*} [val]
  2160. * The value to test
  2161. *
  2162. * @return {boolean}
  2163. * Returns `true` if the given value is of type object and
  2164. * not `null`, else returns `false`.
  2165. */
  2166. isObject: function(val) {
  2167. return (val != null &amp;&amp; typeof(val) == 'object');
  2168. },
  2169. /**
  2170. * Return an array of sorted object keys, optionally sorted by
  2171. * a different key or a different sorting mode.
  2172. *
  2173. * @instance
  2174. * @memberof LuCI
  2175. *
  2176. * @param {object} obj
  2177. * The object to extract the keys from. If the given value is
  2178. * not an object, the function will return an empty array.
  2179. *
  2180. * @param {string} [key]
  2181. * Specifies the key to order by. This is mainly useful for
  2182. * nested objects of objects or objects of arrays when sorting
  2183. * shall not be performed by the primary object keys but by
  2184. * some other key pointing to a value within the nested values.
  2185. *
  2186. * @param {string} [sortmode]
  2187. * May be either `addr` or `num` to override the natural
  2188. * lexicographic sorting with a sorting suitable for IP/MAC style
  2189. * addresses or numeric values respectively.
  2190. *
  2191. * @return {string[]}
  2192. * Returns an array containing the sorted keys of the given object.
  2193. */
  2194. sortedKeys: function(obj, key, sortmode) {
  2195. if (obj == null || typeof(obj) != 'object')
  2196. return [];
  2197. return Object.keys(obj).map(function(e) {
  2198. var v = (key != null) ? obj[e][key] : e;
  2199. switch (sortmode) {
  2200. case 'addr':
  2201. v = (v != null) ? v.replace(/(?:^|[.:])([0-9a-fA-F]{1,4})/g,
  2202. function(m0, m1) { return ('000' + m1.toLowerCase()).substr(-4) }) : null;
  2203. break;
  2204. case 'num':
  2205. v = (v != null) ? +v : null;
  2206. break;
  2207. }
  2208. return [ e, v ];
  2209. }).filter(function(e) {
  2210. return (e[1] != null);
  2211. }).sort(function(a, b) {
  2212. return (a[1] > b[1]);
  2213. }).map(function(e) {
  2214. return e[0];
  2215. });
  2216. },
  2217. /**
  2218. * Converts the given value to an array. If the given value is of
  2219. * type array, it is returned as-is, values of type object are
  2220. * returned as one-element array containing the object, empty
  2221. * strings and `null` values are returned as empty array, all other
  2222. * values are converted using `String()`, trimmed, split on white
  2223. * space and returned as array.
  2224. *
  2225. * @instance
  2226. * @memberof LuCI
  2227. *
  2228. * @param {*} val
  2229. * The value to convert into an array.
  2230. *
  2231. * @return {Array&lt;*>}
  2232. * Returns the resulting array.
  2233. */
  2234. toArray: function(val) {
  2235. if (val == null)
  2236. return [];
  2237. else if (Array.isArray(val))
  2238. return val;
  2239. else if (typeof(val) == 'object')
  2240. return [ val ];
  2241. var s = String(val).trim();
  2242. if (s == '')
  2243. return [];
  2244. return s.split(/\s+/);
  2245. },
  2246. /**
  2247. * Returns a promise resolving with either the given value or or with
  2248. * the given default in case the input value is a rejecting promise.
  2249. *
  2250. * @instance
  2251. * @memberof LuCI
  2252. *
  2253. * @param {*} value
  2254. * The value to resolve the promise with.
  2255. *
  2256. * @param {*} defvalue
  2257. * The default value to resolve the promise with in case the given
  2258. * input value is a rejecting promise.
  2259. *
  2260. * @returns {Promise&lt;*>}
  2261. * Returns a new promise resolving either to the given input value or
  2262. * to the given default value on error.
  2263. */
  2264. resolveDefault: function(value, defvalue) {
  2265. return Promise.resolve(value).catch(function() { return defvalue });
  2266. },
  2267. /**
  2268. * The request callback function is invoked whenever an HTTP
  2269. * reply to a request made using the `L.get()`, `L.post()` or
  2270. * `L.poll()` function is timed out or received successfully.
  2271. *
  2272. * @instance
  2273. * @memberof LuCI
  2274. *
  2275. * @callback LuCI.requestCallbackFn
  2276. * @param {XMLHTTPRequest} xhr
  2277. * The XMLHTTPRequest instance used to make the request.
  2278. *
  2279. * @param {*} data
  2280. * The response JSON if the response could be parsed as such,
  2281. * else `null`.
  2282. *
  2283. * @param {number} duration
  2284. * The total duration of the request in milliseconds.
  2285. */
  2286. /**
  2287. * Issues a GET request to the given url and invokes the specified
  2288. * callback function. The function is a wrapper around
  2289. * {@link LuCI.Request#request Request.request()}.
  2290. *
  2291. * @deprecated
  2292. * @instance
  2293. * @memberof LuCI
  2294. *
  2295. * @param {string} url
  2296. * The URL to request.
  2297. *
  2298. * @param {Object&lt;string, string>} [args]
  2299. * Additional query string arguments to append to the URL.
  2300. *
  2301. * @param {LuCI.requestCallbackFn} cb
  2302. * The callback function to invoke when the request finishes.
  2303. *
  2304. * @return {Promise&lt;null>}
  2305. * Returns a promise resolving to `null` when concluded.
  2306. */
  2307. get: function(url, args, cb) {
  2308. return this.poll(null, url, args, cb, false);
  2309. },
  2310. /**
  2311. * Issues a POST request to the given url and invokes the specified
  2312. * callback function. The function is a wrapper around
  2313. * {@link LuCI.Request#request Request.request()}. The request is
  2314. * sent using `application/x-www-form-urlencoded` encoding and will
  2315. * contain a field `token` with the current value of `LuCI.env.token`
  2316. * by default.
  2317. *
  2318. * @deprecated
  2319. * @instance
  2320. * @memberof LuCI
  2321. *
  2322. * @param {string} url
  2323. * The URL to request.
  2324. *
  2325. * @param {Object&lt;string, string>} [args]
  2326. * Additional post arguments to append to the request body.
  2327. *
  2328. * @param {LuCI.requestCallbackFn} cb
  2329. * The callback function to invoke when the request finishes.
  2330. *
  2331. * @return {Promise&lt;null>}
  2332. * Returns a promise resolving to `null` when concluded.
  2333. */
  2334. post: function(url, args, cb) {
  2335. return this.poll(null, url, args, cb, true);
  2336. },
  2337. /**
  2338. * Register a polling HTTP request that invokes the specified
  2339. * callback function. The function is a wrapper around
  2340. * {@link LuCI.Request.poll#add Request.poll.add()}.
  2341. *
  2342. * @deprecated
  2343. * @instance
  2344. * @memberof LuCI
  2345. *
  2346. * @param {number} interval
  2347. * The poll interval to use. If set to a value less than or equal
  2348. * to `0`, it will default to the global poll interval configured
  2349. * in `LuCI.env.pollinterval`.
  2350. *
  2351. * @param {string} url
  2352. * The URL to request.
  2353. *
  2354. * @param {Object&lt;string, string>} [args]
  2355. * Specifies additional arguments for the request. For GET requests,
  2356. * the arguments are appended to the URL as query string, for POST
  2357. * requests, they'll be added to the request body.
  2358. *
  2359. * @param {LuCI.requestCallbackFn} cb
  2360. * The callback function to invoke whenever a request finishes.
  2361. *
  2362. * @param {boolean} [post=false]
  2363. * When set to `false` or not specified, poll requests will be made
  2364. * using the GET method. When set to `true`, POST requests will be
  2365. * issued. In case of POST requests, the request body will contain
  2366. * an argument `token` with the current value of `LuCI.env.token` by
  2367. * default, regardless of the parameters specified with `args`.
  2368. *
  2369. * @return {function}
  2370. * Returns the internally created function that has been passed to
  2371. * {@link LuCI.Request.poll#add Request.poll.add()}. This value can
  2372. * be passed to {@link LuCI.Poll.remove Poll.remove()} to remove the
  2373. * polling request.
  2374. */
  2375. poll: function(interval, url, args, cb, post) {
  2376. if (interval !== null &amp;&amp; interval &lt;= 0)
  2377. interval = this.env.pollinterval;
  2378. var data = post ? { token: this.env.token } : null,
  2379. method = post ? 'POST' : 'GET';
  2380. if (!/^(?:\/|\S+:\/\/)/.test(url))
  2381. url = this.url(url);
  2382. if (args != null)
  2383. data = Object.assign(data || {}, args);
  2384. if (interval !== null)
  2385. return Request.poll.add(interval, url, { method: method, query: data }, cb);
  2386. else
  2387. return Request.request(url, { method: method, query: data })
  2388. .then(function(res) {
  2389. var json = null;
  2390. if (/^application\/json\b/.test(res.headers.get('Content-Type')))
  2391. try { json = res.json() } catch(e) {}
  2392. cb(res.xhr, json, res.duration);
  2393. });
  2394. },
  2395. /**
  2396. * Deprecated wrapper around {@link LuCI.Poll.remove Poll.remove()}.
  2397. *
  2398. * @deprecated
  2399. * @instance
  2400. * @memberof LuCI
  2401. *
  2402. * @param {function} entry
  2403. * The polling function to remove.
  2404. *
  2405. * @return {boolean}
  2406. * Returns `true` when the function has been removed or `false` if
  2407. * it could not be found.
  2408. */
  2409. stop: function(entry) { return Poll.remove(entry) },
  2410. /**
  2411. * Deprecated wrapper around {@link LuCI.Poll.stop Poll.stop()}.
  2412. *
  2413. * @deprecated
  2414. * @instance
  2415. * @memberof LuCI
  2416. *
  2417. * @return {boolean}
  2418. * Returns `true` when the polling loop has been stopped or `false`
  2419. * when it didn't run to begin with.
  2420. */
  2421. halt: function() { return Poll.stop() },
  2422. /**
  2423. * Deprecated wrapper around {@link LuCI.Poll.start Poll.start()}.
  2424. *
  2425. * @deprecated
  2426. * @instance
  2427. * @memberof LuCI
  2428. *
  2429. * @return {boolean}
  2430. * Returns `true` when the polling loop has been started or `false`
  2431. * when it was already running.
  2432. */
  2433. run: function() { return Poll.start() },
  2434. /**
  2435. * @class
  2436. * @memberof LuCI
  2437. * @hideconstructor
  2438. * @classdesc
  2439. *
  2440. * The `dom` class provides convenience method for creating and
  2441. * manipulating DOM elements.
  2442. */
  2443. dom: Class.singleton(/* @lends LuCI.dom.prototype */ {
  2444. __name__: 'LuCI.DOM',
  2445. /**
  2446. * Tests whether the given argument is a valid DOM `Node`.
  2447. *
  2448. * @instance
  2449. * @memberof LuCI.dom
  2450. * @param {*} e
  2451. * The value to test.
  2452. *
  2453. * @returns {boolean}
  2454. * Returns `true` if the value is a DOM `Node`, else `false`.
  2455. */
  2456. elem: function(e) {
  2457. return (e != null &amp;&amp; typeof(e) == 'object' &amp;&amp; 'nodeType' in e);
  2458. },
  2459. /**
  2460. * Parses a given string as HTML and returns the first child node.
  2461. *
  2462. * @instance
  2463. * @memberof LuCI.dom
  2464. * @param {string} s
  2465. * A string containing an HTML fragment to parse. Note that only
  2466. * the first result of the resulting structure is returned, so an
  2467. * input value of `&lt;div>foo&lt;/div> &lt;div>bar&lt;/div>` will only return
  2468. * the first `div` element node.
  2469. *
  2470. * @returns {Node}
  2471. * Returns the first DOM `Node` extracted from the HTML fragment or
  2472. * `null` on parsing failures or if no element could be found.
  2473. */
  2474. parse: function(s) {
  2475. var elem;
  2476. try {
  2477. domParser = domParser || new DOMParser();
  2478. elem = domParser.parseFromString(s, 'text/html').body.firstChild;
  2479. }
  2480. catch(e) {}
  2481. if (!elem) {
  2482. try {
  2483. dummyElem = dummyElem || document.createElement('div');
  2484. dummyElem.innerHTML = s;
  2485. elem = dummyElem.firstChild;
  2486. }
  2487. catch (e) {}
  2488. }
  2489. return elem || null;
  2490. },
  2491. /**
  2492. * Tests whether a given `Node` matches the given query selector.
  2493. *
  2494. * This function is a convenience wrapper around the standard
  2495. * `Node.matches("selector")` function with the added benefit that
  2496. * the `node` argument may be a non-`Node` value, in which case
  2497. * this function simply returns `false`.
  2498. *
  2499. * @instance
  2500. * @memberof LuCI.dom
  2501. * @param {*} node
  2502. * The `Node` argument to test the selector against.
  2503. *
  2504. * @param {string} [selector]
  2505. * The query selector expression to test against the given node.
  2506. *
  2507. * @returns {boolean}
  2508. * Returns `true` if the given node matches the specified selector
  2509. * or `false` when the node argument is no valid DOM `Node` or the
  2510. * selector didn't match.
  2511. */
  2512. matches: function(node, selector) {
  2513. var m = this.elem(node) ? node.matches || node.msMatchesSelector : null;
  2514. return m ? m.call(node, selector) : false;
  2515. },
  2516. /**
  2517. * Returns the closest parent node that matches the given query
  2518. * selector expression.
  2519. *
  2520. * This function is a convenience wrapper around the standard
  2521. * `Node.closest("selector")` function with the added benefit that
  2522. * the `node` argument may be a non-`Node` value, in which case
  2523. * this function simply returns `null`.
  2524. *
  2525. * @instance
  2526. * @memberof LuCI.dom
  2527. * @param {*} node
  2528. * The `Node` argument to find the closest parent for.
  2529. *
  2530. * @param {string} [selector]
  2531. * The query selector expression to test against each parent.
  2532. *
  2533. * @returns {Node|null}
  2534. * Returns the closest parent node matching the selector or
  2535. * `null` when the node argument is no valid DOM `Node` or the
  2536. * selector didn't match any parent.
  2537. */
  2538. parent: function(node, selector) {
  2539. if (this.elem(node) &amp;&amp; node.closest)
  2540. return node.closest(selector);
  2541. while (this.elem(node))
  2542. if (this.matches(node, selector))
  2543. return node;
  2544. else
  2545. node = node.parentNode;
  2546. return null;
  2547. },
  2548. /**
  2549. * Appends the given children data to the given node.
  2550. *
  2551. * @instance
  2552. * @memberof LuCI.dom
  2553. * @param {*} node
  2554. * The `Node` argument to append the children to.
  2555. *
  2556. * @param {*} [children]
  2557. * The childrens to append to the given node.
  2558. *
  2559. * When `children` is an array, then each item of the array
  2560. * will be either appended as child element or text node,
  2561. * depending on whether the item is a DOM `Node` instance or
  2562. * some other non-`null` value. Non-`Node`, non-`null` values
  2563. * will be converted to strings first before being passed as
  2564. * argument to `createTextNode()`.
  2565. *
  2566. * When `children` is a function, it will be invoked with
  2567. * the passed `node` argument as sole parameter and the `append`
  2568. * function will be invoked again, with the given `node` argument
  2569. * as first and the return value of the `children` function as
  2570. * second parameter.
  2571. *
  2572. * When `children` is is a DOM `Node` instance, it will be
  2573. * appended to the given `node`.
  2574. *
  2575. * When `children` is any other non-`null` value, it will be
  2576. * converted to a string and appened to the `innerHTML` property
  2577. * of the given `node`.
  2578. *
  2579. * @returns {Node|null}
  2580. * Returns the last children `Node` appended to the node or `null`
  2581. * if either the `node` argument was no valid DOM `node` or if the
  2582. * `children` was `null` or didn't result in further DOM nodes.
  2583. */
  2584. append: function(node, children) {
  2585. if (!this.elem(node))
  2586. return null;
  2587. if (Array.isArray(children)) {
  2588. for (var i = 0; i &lt; children.length; i++)
  2589. if (this.elem(children[i]))
  2590. node.appendChild(children[i]);
  2591. else if (children !== null &amp;&amp; children !== undefined)
  2592. node.appendChild(document.createTextNode('' + children[i]));
  2593. return node.lastChild;
  2594. }
  2595. else if (typeof(children) === 'function') {
  2596. return this.append(node, children(node));
  2597. }
  2598. else if (this.elem(children)) {
  2599. return node.appendChild(children);
  2600. }
  2601. else if (children !== null &amp;&amp; children !== undefined) {
  2602. node.innerHTML = '' + children;
  2603. return node.lastChild;
  2604. }
  2605. return null;
  2606. },
  2607. /**
  2608. * Replaces the content of the given node with the given children.
  2609. *
  2610. * This function first removes any children of the given DOM
  2611. * `Node` and then adds the given given children following the
  2612. * rules outlined below.
  2613. *
  2614. * @instance
  2615. * @memberof LuCI.dom
  2616. * @param {*} node
  2617. * The `Node` argument to replace the children of.
  2618. *
  2619. * @param {*} [children]
  2620. * The childrens to replace into the given node.
  2621. *
  2622. * When `children` is an array, then each item of the array
  2623. * will be either appended as child element or text node,
  2624. * depending on whether the item is a DOM `Node` instance or
  2625. * some other non-`null` value. Non-`Node`, non-`null` values
  2626. * will be converted to strings first before being passed as
  2627. * argument to `createTextNode()`.
  2628. *
  2629. * When `children` is a function, it will be invoked with
  2630. * the passed `node` argument as sole parameter and the `append`
  2631. * function will be invoked again, with the given `node` argument
  2632. * as first and the return value of the `children` function as
  2633. * second parameter.
  2634. *
  2635. * When `children` is is a DOM `Node` instance, it will be
  2636. * appended to the given `node`.
  2637. *
  2638. * When `children` is any other non-`null` value, it will be
  2639. * converted to a string and appened to the `innerHTML` property
  2640. * of the given `node`.
  2641. *
  2642. * @returns {Node|null}
  2643. * Returns the last children `Node` appended to the node or `null`
  2644. * if either the `node` argument was no valid DOM `node` or if the
  2645. * `children` was `null` or didn't result in further DOM nodes.
  2646. */
  2647. content: function(node, children) {
  2648. if (!this.elem(node))
  2649. return null;
  2650. var dataNodes = node.querySelectorAll('[data-idref]');
  2651. for (var i = 0; i &lt; dataNodes.length; i++)
  2652. delete this.registry[dataNodes[i].getAttribute('data-idref')];
  2653. while (node.firstChild)
  2654. node.removeChild(node.firstChild);
  2655. return this.append(node, children);
  2656. },
  2657. /**
  2658. * Sets attributes or registers event listeners on element nodes.
  2659. *
  2660. * @instance
  2661. * @memberof LuCI.dom
  2662. * @param {*} node
  2663. * The `Node` argument to set the attributes or add the event
  2664. * listeners for. When the given `node` value is not a valid
  2665. * DOM `Node`, the function returns and does nothing.
  2666. *
  2667. * @param {string|Object&lt;string, *>} key
  2668. * Specifies either the attribute or event handler name to use,
  2669. * or an object containing multiple key, value pairs which are
  2670. * each added to the node as either attribute or event handler,
  2671. * depending on the respective value.
  2672. *
  2673. * @param {*} [val]
  2674. * Specifies the attribute value or event handler function to add.
  2675. * If the `key` parameter is an `Object`, this parameter will be
  2676. * ignored.
  2677. *
  2678. * When `val` is of type function, it will be registered as event
  2679. * handler on the given `node` with the `key` parameter being the
  2680. * event name.
  2681. *
  2682. * When `val` is of type object, it will be serialized as JSON and
  2683. * added as attribute to the given `node`, using the given `key`
  2684. * as attribute name.
  2685. *
  2686. * When `val` is of any other type, it will be added as attribute
  2687. * to the given `node` as-is, with the underlying `setAttribute()`
  2688. * call implicitely turning it into a string.
  2689. */
  2690. attr: function(node, key, val) {
  2691. if (!this.elem(node))
  2692. return null;
  2693. var attr = null;
  2694. if (typeof(key) === 'object' &amp;&amp; key !== null)
  2695. attr = key;
  2696. else if (typeof(key) === 'string')
  2697. attr = {}, attr[key] = val;
  2698. for (key in attr) {
  2699. if (!attr.hasOwnProperty(key) || attr[key] == null)
  2700. continue;
  2701. switch (typeof(attr[key])) {
  2702. case 'function':
  2703. node.addEventListener(key, attr[key]);
  2704. break;
  2705. case 'object':
  2706. node.setAttribute(key, JSON.stringify(attr[key]));
  2707. break;
  2708. default:
  2709. node.setAttribute(key, attr[key]);
  2710. }
  2711. }
  2712. },
  2713. /**
  2714. * Creates a new DOM `Node` from the given `html`, `attr` and
  2715. * `data` parameters.
  2716. *
  2717. * This function has multiple signatures, it can be either invoked
  2718. * in the form `create(html[, attr[, data]])` or in the form
  2719. * `create(html[, data])`. The used variant is determined from the
  2720. * type of the second argument.
  2721. *
  2722. * @instance
  2723. * @memberof LuCI.dom
  2724. * @param {*} html
  2725. * Describes the node to create.
  2726. *
  2727. * When the value of `html` is of type array, a `DocumentFragment`
  2728. * node is created and each item of the array is first converted
  2729. * to a DOM `Node` by passing it through `create()` and then added
  2730. * as child to the fragment.
  2731. *
  2732. * When the value of `html` is a DOM `Node` instance, no new
  2733. * element will be created but the node will be used as-is.
  2734. *
  2735. * When the value of `html` is a string starting with `&lt;`, it will
  2736. * be passed to `dom.parse()` and the resulting value is used.
  2737. *
  2738. * When the value of `html` is any other string, it will be passed
  2739. * to `document.createElement()` for creating a new DOM `Node` of
  2740. * the given name.
  2741. *
  2742. * @param {Object&lt;string, *>} [attr]
  2743. * Specifies an Object of key, value pairs to set as attributes
  2744. * or event handlers on the created node. Refer to
  2745. * {@link LuCI.dom#attr dom.attr()} for details.
  2746. *
  2747. * @param {*} [data]
  2748. * Specifies children to append to the newly created element.
  2749. * Refer to {@link LuCI.dom#append dom.append()} for details.
  2750. *
  2751. * @throws {InvalidCharacterError}
  2752. * Throws an `InvalidCharacterError` when the given `html`
  2753. * argument contained malformed markup (such as not escaped
  2754. * `&amp;` characters in XHTML mode) or when the given node name
  2755. * in `html` contains characters which are not legal in DOM
  2756. * element names, such as spaces.
  2757. *
  2758. * @returns {Node}
  2759. * Returns the newly created `Node`.
  2760. */
  2761. create: function() {
  2762. var html = arguments[0],
  2763. attr = arguments[1],
  2764. data = arguments[2],
  2765. elem;
  2766. if (!(attr instanceof Object) || Array.isArray(attr))
  2767. data = attr, attr = null;
  2768. if (Array.isArray(html)) {
  2769. elem = document.createDocumentFragment();
  2770. for (var i = 0; i &lt; html.length; i++)
  2771. elem.appendChild(this.create(html[i]));
  2772. }
  2773. else if (this.elem(html)) {
  2774. elem = html;
  2775. }
  2776. else if (html.charCodeAt(0) === 60) {
  2777. elem = this.parse(html);
  2778. }
  2779. else {
  2780. elem = document.createElement(html);
  2781. }
  2782. if (!elem)
  2783. return null;
  2784. this.attr(elem, attr);
  2785. this.append(elem, data);
  2786. return elem;
  2787. },
  2788. registry: {},
  2789. /**
  2790. * Attaches or detaches arbitrary data to and from a DOM `Node`.
  2791. *
  2792. * This function is useful to attach non-string values or runtime
  2793. * data that is not serializable to DOM nodes. To decouple data
  2794. * from the DOM, values are not added directly to nodes, but
  2795. * inserted into a registry instead which is then referenced by a
  2796. * string key stored as `data-idref` attribute in the node.
  2797. *
  2798. * This function has multiple signatures and is sensitive to the
  2799. * number of arguments passed to it.
  2800. *
  2801. * - `dom.data(node)` -
  2802. * Fetches all data associated with the given node.
  2803. * - `dom.data(node, key)` -
  2804. * Fetches a specific key associated with the given node.
  2805. * - `dom.data(node, key, val)` -
  2806. * Sets a specific key to the given value associated with the
  2807. * given node.
  2808. * - `dom.data(node, null)` -
  2809. * Clears any data associated with the node.
  2810. * - `dom.data(node, key, null)` -
  2811. * Clears the given key associated with the node.
  2812. *
  2813. * @instance
  2814. * @memberof LuCI.dom
  2815. * @param {Node} node
  2816. * The DOM `Node` instance to set or retrieve the data for.
  2817. *
  2818. * @param {string|null} [key]
  2819. * This is either a string specifying the key to retrieve, or
  2820. * `null` to unset the entire node data.
  2821. *
  2822. * @param {*|null} [val]
  2823. * This is either a non-`null` value to set for a given key or
  2824. * `null` to remove the given `key` from the specified node.
  2825. *
  2826. * @returns {*}
  2827. * Returns the get or set value, or `null` when no value could
  2828. * be found.
  2829. */
  2830. data: function(node, key, val) {
  2831. var id = node.getAttribute('data-idref');
  2832. /* clear all data */
  2833. if (arguments.length > 1 &amp;&amp; key == null) {
  2834. if (id != null) {
  2835. node.removeAttribute('data-idref');
  2836. val = this.registry[id]
  2837. delete this.registry[id];
  2838. return val;
  2839. }
  2840. return null;
  2841. }
  2842. /* clear a key */
  2843. else if (arguments.length > 2 &amp;&amp; key != null &amp;&amp; val == null) {
  2844. if (id != null) {
  2845. val = this.registry[id][key];
  2846. delete this.registry[id][key];
  2847. return val;
  2848. }
  2849. return null;
  2850. }
  2851. /* set a key */
  2852. else if (arguments.length > 2 &amp;&amp; key != null &amp;&amp; val != null) {
  2853. if (id == null) {
  2854. do { id = Math.floor(Math.random() * 0xffffffff).toString(16) }
  2855. while (this.registry.hasOwnProperty(id));
  2856. node.setAttribute('data-idref', id);
  2857. this.registry[id] = {};
  2858. }
  2859. return (this.registry[id][key] = val);
  2860. }
  2861. /* get all data */
  2862. else if (arguments.length == 1) {
  2863. if (id != null)
  2864. return this.registry[id];
  2865. return null;
  2866. }
  2867. /* get a key */
  2868. else if (arguments.length == 2) {
  2869. if (id != null)
  2870. return this.registry[id][key];
  2871. }
  2872. return null;
  2873. },
  2874. /**
  2875. * Binds the given class instance ot the specified DOM `Node`.
  2876. *
  2877. * This function uses the `dom.data()` facility to attach the
  2878. * passed instance of a Class to a node. This is needed for
  2879. * complex widget elements or similar where the corresponding
  2880. * class instance responsible for the element must be retrieved
  2881. * from DOM nodes obtained by `querySelector()` or similar means.
  2882. *
  2883. * @instance
  2884. * @memberof LuCI.dom
  2885. * @param {Node} node
  2886. * The DOM `Node` instance to bind the class to.
  2887. *
  2888. * @param {Class} inst
  2889. * The Class instance to bind to the node.
  2890. *
  2891. * @throws {TypeError}
  2892. * Throws a `TypeError` when the given instance argument isn't
  2893. * a valid Class instance.
  2894. *
  2895. * @returns {Class}
  2896. * Returns the bound class instance.
  2897. */
  2898. bindClassInstance: function(node, inst) {
  2899. if (!(inst instanceof Class))
  2900. L.error('TypeError', 'Argument must be a class instance');
  2901. return this.data(node, '_class', inst);
  2902. },
  2903. /**
  2904. * Finds a bound class instance on the given node itself or the
  2905. * first bound instance on its closest parent node.
  2906. *
  2907. * @instance
  2908. * @memberof LuCI.dom
  2909. * @param {Node} node
  2910. * The DOM `Node` instance to start from.
  2911. *
  2912. * @returns {Class|null}
  2913. * Returns the founds class instance if any or `null` if no bound
  2914. * class could be found on the node itself or any of its parents.
  2915. */
  2916. findClassInstance: function(node) {
  2917. var inst = null;
  2918. do {
  2919. inst = this.data(node, '_class');
  2920. node = node.parentNode;
  2921. }
  2922. while (!(inst instanceof Class) &amp;&amp; node != null);
  2923. return inst;
  2924. },
  2925. /**
  2926. * Finds a bound class instance on the given node itself or the
  2927. * first bound instance on its closest parent node and invokes
  2928. * the specified method name on the found class instance.
  2929. *
  2930. * @instance
  2931. * @memberof LuCI.dom
  2932. * @param {Node} node
  2933. * The DOM `Node` instance to start from.
  2934. *
  2935. * @param {string} method
  2936. * The name of the method to invoke on the found class instance.
  2937. *
  2938. * @param {...*} params
  2939. * Additional arguments to pass to the invoked method as-is.
  2940. *
  2941. * @returns {*|null}
  2942. * Returns the return value of the invoked method if a class
  2943. * instance and method has been found. Returns `null` if either
  2944. * no bound class instance could be found, or if the found
  2945. * instance didn't have the requested `method`.
  2946. */
  2947. callClassMethod: function(node, method /*, ... */) {
  2948. var inst = this.findClassInstance(node);
  2949. if (inst == null || typeof(inst[method]) != 'function')
  2950. return null;
  2951. return inst[method].apply(inst, inst.varargs(arguments, 2));
  2952. },
  2953. /**
  2954. * The ignore callback function is invoked by `isEmpty()` for each
  2955. * child node to decide whether to ignore a child node or not.
  2956. *
  2957. * When this function returns `false`, the node passed to it is
  2958. * ignored, else not.
  2959. *
  2960. * @callback LuCI.dom~ignoreCallbackFn
  2961. * @param {Node} node
  2962. * The child node to test.
  2963. *
  2964. * @returns {boolean}
  2965. * Boolean indicating whether to ignore the node or not.
  2966. */
  2967. /**
  2968. * Tests whether a given DOM `Node` instance is empty or appears
  2969. * empty.
  2970. *
  2971. * Any element child nodes which have the CSS class `hidden` set
  2972. * or for which the optionally passed `ignoreFn` callback function
  2973. * returns `false` are ignored.
  2974. *
  2975. * @instance
  2976. * @memberof LuCI.dom
  2977. * @param {Node} node
  2978. * The DOM `Node` instance to test.
  2979. *
  2980. * @param {LuCI.dom~ignoreCallbackFn} [ignoreFn]
  2981. * Specifies an optional function which is invoked for each child
  2982. * node to decide whether the child node should be ignored or not.
  2983. *
  2984. * @returns {boolean}
  2985. * Returns `true` if the node does not have any children or if
  2986. * any children node either has a `hidden` CSS class or a `false`
  2987. * result when testing it using the given `ignoreFn`.
  2988. */
  2989. isEmpty: function(node, ignoreFn) {
  2990. for (var child = node.firstElementChild; child != null; child = child.nextElementSibling)
  2991. if (!child.classList.contains('hidden') &amp;&amp; (!ignoreFn || !ignoreFn(child)))
  2992. return false;
  2993. return true;
  2994. }
  2995. }),
  2996. Poll: Poll,
  2997. Class: Class,
  2998. Request: Request,
  2999. /**
  3000. * @class
  3001. * @memberof LuCI
  3002. * @hideconstructor
  3003. * @classdesc
  3004. *
  3005. * The `view` class forms the basis of views and provides a standard
  3006. * set of methods to inherit from.
  3007. */
  3008. view: Class.extend(/* @lends LuCI.view.prototype */ {
  3009. __name__: 'LuCI.View',
  3010. __init__: function() {
  3011. var vp = document.getElementById('view');
  3012. L.dom.content(vp, E('div', { 'class': 'spinning' }, _('Loading view…')));
  3013. return Promise.resolve(this.load())
  3014. .then(L.bind(this.render, this))
  3015. .then(L.bind(function(nodes) {
  3016. var vp = document.getElementById('view');
  3017. L.dom.content(vp, nodes);
  3018. L.dom.append(vp, this.addFooter());
  3019. }, this)).catch(L.error);
  3020. },
  3021. /**
  3022. * The load function is invoked before the view is rendered.
  3023. *
  3024. * The invocation of this function is wrapped by
  3025. * `Promise.resolve()` so it may return Promises if needed.
  3026. *
  3027. * The return value of the function (or the resolved values
  3028. * of the promise returned by it) will be passed as first
  3029. * argument to `render()`.
  3030. *
  3031. * This function is supposed to be overwritten by subclasses,
  3032. * the default implementation does nothing.
  3033. *
  3034. * @instance
  3035. * @abstract
  3036. * @memberof LuCI.view
  3037. *
  3038. * @returns {*|Promise&lt;*>}
  3039. * May return any value or a Promise resolving to any value.
  3040. */
  3041. load: function() {},
  3042. /**
  3043. * The render function is invoked after the
  3044. * {@link LuCI.view#load load()} function and responsible
  3045. * for setting up the view contents. It must return a DOM
  3046. * `Node` or `DocumentFragment` holding the contents to
  3047. * insert into the view area.
  3048. *
  3049. * The invocation of this function is wrapped by
  3050. * `Promise.resolve()` so it may return Promises if needed.
  3051. *
  3052. * The return value of the function (or the resolved values
  3053. * of the promise returned by it) will be inserted into the
  3054. * main content area using
  3055. * {@link LuCI.dom#append dom.append()}.
  3056. *
  3057. * This function is supposed to be overwritten by subclasses,
  3058. * the default implementation does nothing.
  3059. *
  3060. * @instance
  3061. * @abstract
  3062. * @memberof LuCI.view
  3063. * @param {*|null} load_results
  3064. * This function will receive the return value of the
  3065. * {@link LuCI.view#load view.load()} function as first
  3066. * argument.
  3067. *
  3068. * @returns {Node|Promise&lt;Node>}
  3069. * Should return a DOM `Node` value or a `Promise` resolving
  3070. * to a `Node` value.
  3071. */
  3072. render: function() {},
  3073. /**
  3074. * The handleSave function is invoked when the user clicks
  3075. * the `Save` button in the page action footer.
  3076. *
  3077. * The default implementation should be sufficient for most
  3078. * views using {@link form#Map form.Map()} based forms - it
  3079. * will iterate all forms present in the view and invoke
  3080. * the {@link form#Map#save Map.save()} method on each form.
  3081. *
  3082. * Views not using `Map` instances or requiring other special
  3083. * logic should overwrite `handleSave()` with a custom
  3084. * implementation.
  3085. *
  3086. * To disable the `Save` page footer button, views extending
  3087. * this base class should overwrite the `handleSave` function
  3088. * with `null`.
  3089. *
  3090. * The invocation of this function is wrapped by
  3091. * `Promise.resolve()` so it may return Promises if needed.
  3092. *
  3093. * @instance
  3094. * @memberof LuCI.view
  3095. * @param {Event} ev
  3096. * The DOM event that triggered the function.
  3097. *
  3098. * @returns {*|Promise&lt;*>}
  3099. * Any return values of this function are discarded, but
  3100. * passed through `Promise.resolve()` to ensure that any
  3101. * returned promise runs to completion before the button
  3102. * is reenabled.
  3103. */
  3104. handleSave: function(ev) {
  3105. var tasks = [];
  3106. document.getElementById('maincontent')
  3107. .querySelectorAll('.cbi-map').forEach(function(map) {
  3108. tasks.push(L.dom.callClassMethod(map, 'save'));
  3109. });
  3110. return Promise.all(tasks);
  3111. },
  3112. /**
  3113. * The handleSaveApply function is invoked when the user clicks
  3114. * the `Save &amp; Apply` button in the page action footer.
  3115. *
  3116. * The default implementation should be sufficient for most
  3117. * views using {@link form#Map form.Map()} based forms - it
  3118. * will first invoke
  3119. * {@link LuCI.view.handleSave view.handleSave()} and then
  3120. * call {@link ui#changes#apply ui.changes.apply()} to start the
  3121. * modal config apply and page reload flow.
  3122. *
  3123. * Views not using `Map` instances or requiring other special
  3124. * logic should overwrite `handleSaveApply()` with a custom
  3125. * implementation.
  3126. *
  3127. * To disable the `Save &amp; Apply` page footer button, views
  3128. * extending this base class should overwrite the
  3129. * `handleSaveApply` function with `null`.
  3130. *
  3131. * The invocation of this function is wrapped by
  3132. * `Promise.resolve()` so it may return Promises if needed.
  3133. *
  3134. * @instance
  3135. * @memberof LuCI.view
  3136. * @param {Event} ev
  3137. * The DOM event that triggered the function.
  3138. *
  3139. * @returns {*|Promise&lt;*>}
  3140. * Any return values of this function are discarded, but
  3141. * passed through `Promise.resolve()` to ensure that any
  3142. * returned promise runs to completion before the button
  3143. * is reenabled.
  3144. */
  3145. handleSaveApply: function(ev) {
  3146. return this.handleSave(ev).then(function() {
  3147. L.ui.changes.apply(true);
  3148. });
  3149. },
  3150. /**
  3151. * The handleReset function is invoked when the user clicks
  3152. * the `Reset` button in the page action footer.
  3153. *
  3154. * The default implementation should be sufficient for most
  3155. * views using {@link form#Map form.Map()} based forms - it
  3156. * will iterate all forms present in the view and invoke
  3157. * the {@link form#Map#save Map.reset()} method on each form.
  3158. *
  3159. * Views not using `Map` instances or requiring other special
  3160. * logic should overwrite `handleReset()` with a custom
  3161. * implementation.
  3162. *
  3163. * To disable the `Reset` page footer button, views extending
  3164. * this base class should overwrite the `handleReset` function
  3165. * with `null`.
  3166. *
  3167. * The invocation of this function is wrapped by
  3168. * `Promise.resolve()` so it may return Promises if needed.
  3169. *
  3170. * @instance
  3171. * @memberof LuCI.view
  3172. * @param {Event} ev
  3173. * The DOM event that triggered the function.
  3174. *
  3175. * @returns {*|Promise&lt;*>}
  3176. * Any return values of this function are discarded, but
  3177. * passed through `Promise.resolve()` to ensure that any
  3178. * returned promise runs to completion before the button
  3179. * is reenabled.
  3180. */
  3181. handleReset: function(ev) {
  3182. var tasks = [];
  3183. document.getElementById('maincontent')
  3184. .querySelectorAll('.cbi-map').forEach(function(map) {
  3185. tasks.push(L.dom.callClassMethod(map, 'reset'));
  3186. });
  3187. return Promise.all(tasks);
  3188. },
  3189. /**
  3190. * Renders a standard page action footer if any of the
  3191. * `handleSave()`, `handleSaveApply()` or `handleReset()`
  3192. * functions are defined.
  3193. *
  3194. * The default implementation should be sufficient for most
  3195. * views - it will render a standard page footer with action
  3196. * buttons labeled `Save`, `Save &amp; Apply` and `Reset`
  3197. * triggering the `handleSave()`, `handleSaveApply()` and
  3198. * `handleReset()` functions respectively.
  3199. *
  3200. * When any of these `handle*()` functions is overwritten
  3201. * with `null` by a view extending this class, the
  3202. * corresponding button will not be rendered.
  3203. *
  3204. * @instance
  3205. * @memberof LuCI.view
  3206. * @returns {DocumentFragment}
  3207. * Returns a `DocumentFragment` containing the footer bar
  3208. * with buttons for each corresponding `handle*()` action
  3209. * or an empty `DocumentFragment` if all three `handle*()`
  3210. * methods are overwritten with `null`.
  3211. */
  3212. addFooter: function() {
  3213. var footer = E([]);
  3214. if (this.handleSaveApply || this.handleSave || this.handleReset) {
  3215. footer.appendChild(E('div', { 'class': 'cbi-page-actions' }, [
  3216. this.handleSaveApply ? E('button', {
  3217. 'class': 'cbi-button cbi-button-apply',
  3218. 'click': L.ui.createHandlerFn(this, 'handleSaveApply')
  3219. }, [ _('Save &amp; Apply') ]) : '', ' ',
  3220. this.handleSave ? E('button', {
  3221. 'class': 'cbi-button cbi-button-save',
  3222. 'click': L.ui.createHandlerFn(this, 'handleSave')
  3223. }, [ _('Save') ]) : '', ' ',
  3224. this.handleReset ? E('button', {
  3225. 'class': 'cbi-button cbi-button-reset',
  3226. 'click': L.ui.createHandlerFn(this, 'handleReset')
  3227. }, [ _('Reset') ]) : ''
  3228. ]));
  3229. }
  3230. return footer;
  3231. }
  3232. })
  3233. });
  3234. /**
  3235. * @class
  3236. * @memberof LuCI
  3237. * @deprecated
  3238. * @classdesc
  3239. *
  3240. * The `LuCI.XHR` class is a legacy compatibility shim for the
  3241. * functionality formerly provided by `xhr.js`. It is registered as global
  3242. * `window.XHR` symbol for compatibility with legacy code.
  3243. *
  3244. * New code should use {@link LuCI.Request} instead to implement HTTP
  3245. * request handling.
  3246. */
  3247. var XHR = Class.extend(/** @lends LuCI.XHR.prototype */ {
  3248. __name__: 'LuCI.XHR',
  3249. __init__: function() {
  3250. if (window.console &amp;&amp; console.debug)
  3251. console.debug('Direct use XHR() is deprecated, please use L.Request instead');
  3252. },
  3253. _response: function(cb, res, json, duration) {
  3254. if (this.active)
  3255. cb(res, json, duration);
  3256. delete this.active;
  3257. },
  3258. /**
  3259. * This function is a legacy wrapper around
  3260. * {@link LuCI#get LuCI.get()}.
  3261. *
  3262. * @instance
  3263. * @deprecated
  3264. * @memberof LuCI.XHR
  3265. *
  3266. * @param {string} url
  3267. * The URL to request
  3268. *
  3269. * @param {Object} [data]
  3270. * Additional query string data
  3271. *
  3272. * @param {LuCI.requestCallbackFn} [callback]
  3273. * Callback function to invoke on completion
  3274. *
  3275. * @param {number} [timeout]
  3276. * Request timeout to use
  3277. *
  3278. * @return {Promise&lt;null>}
  3279. */
  3280. get: function(url, data, callback, timeout) {
  3281. this.active = true;
  3282. L.get(url, data, this._response.bind(this, callback), timeout);
  3283. },
  3284. /**
  3285. * This function is a legacy wrapper around
  3286. * {@link LuCI#post LuCI.post()}.
  3287. *
  3288. * @instance
  3289. * @deprecated
  3290. * @memberof LuCI.XHR
  3291. *
  3292. * @param {string} url
  3293. * The URL to request
  3294. *
  3295. * @param {Object} [data]
  3296. * Additional data to append to the request body.
  3297. *
  3298. * @param {LuCI.requestCallbackFn} [callback]
  3299. * Callback function to invoke on completion
  3300. *
  3301. * @param {number} [timeout]
  3302. * Request timeout to use
  3303. *
  3304. * @return {Promise&lt;null>}
  3305. */
  3306. post: function(url, data, callback, timeout) {
  3307. this.active = true;
  3308. L.post(url, data, this._response.bind(this, callback), timeout);
  3309. },
  3310. /**
  3311. * Cancels a running request.
  3312. *
  3313. * This function does not actually cancel the underlying
  3314. * `XMLHTTPRequest` request but it sets a flag which prevents the
  3315. * invocation of the callback function when the request eventually
  3316. * finishes or timed out.
  3317. *
  3318. * @instance
  3319. * @deprecated
  3320. * @memberof LuCI.XHR
  3321. */
  3322. cancel: function() { delete this.active },
  3323. /**
  3324. * Checks the running state of the request.
  3325. *
  3326. * @instance
  3327. * @deprecated
  3328. * @memberof LuCI.XHR
  3329. *
  3330. * @returns {boolean}
  3331. * Returns `true` if the request is still running or `false` if it
  3332. * already completed.
  3333. */
  3334. busy: function() { return (this.active === true) },
  3335. /**
  3336. * Ignored for backwards compatibility.
  3337. *
  3338. * This function does nothing.
  3339. *
  3340. * @instance
  3341. * @deprecated
  3342. * @memberof LuCI.XHR
  3343. */
  3344. abort: function() {},
  3345. /**
  3346. * Existing for backwards compatibility.
  3347. *
  3348. * This function simply throws an `InternalError` when invoked.
  3349. *
  3350. * @instance
  3351. * @deprecated
  3352. * @memberof LuCI.XHR
  3353. *
  3354. * @throws {InternalError}
  3355. * Throws an `InternalError` with the message `Not implemented`
  3356. * when invoked.
  3357. */
  3358. send_form: function() { L.error('InternalError', 'Not implemented') },
  3359. });
  3360. XHR.get = function() { return window.L.get.apply(window.L, arguments) };
  3361. XHR.post = function() { return window.L.post.apply(window.L, arguments) };
  3362. XHR.poll = function() { return window.L.poll.apply(window.L, arguments) };
  3363. XHR.stop = Request.poll.remove.bind(Request.poll);
  3364. XHR.halt = Request.poll.stop.bind(Request.poll);
  3365. XHR.run = Request.poll.start.bind(Request.poll);
  3366. XHR.running = Request.poll.active.bind(Request.poll);
  3367. window.XHR = XHR;
  3368. window.LuCI = LuCI;
  3369. })(window, document);
  3370. </code></pre>
  3371. </article>
  3372. </section>
  3373. <footer>
  3374. Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.6.3</a> on Thu Nov 07 2019 12:36:05 GMT+0100 (Central European Standard Time)
  3375. </footer>
  3376. </div>
  3377. </div>
  3378. <script>prettyPrint();</script>
  3379. <script src="scripts/jaguar.js"></script>
  3380. </body>
  3381. </html>