all.js 288 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604
  1. /* ---- lib/Class.coffee ---- */
  2. (function() {
  3. var Class,
  4. slice = [].slice;
  5. Class = (function() {
  6. function Class() {}
  7. Class.prototype.trace = true;
  8. Class.prototype.log = function() {
  9. var args;
  10. args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
  11. if (!this.trace) {
  12. return;
  13. }
  14. if (typeof console === 'undefined') {
  15. return;
  16. }
  17. args.unshift("[" + this.constructor.name + "]");
  18. console.log.apply(console, args);
  19. return this;
  20. };
  21. Class.prototype.logStart = function() {
  22. var args, name;
  23. name = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
  24. if (!this.trace) {
  25. return;
  26. }
  27. this.logtimers || (this.logtimers = {});
  28. this.logtimers[name] = +(new Date);
  29. if (args.length > 0) {
  30. this.log.apply(this, ["" + name].concat(slice.call(args), ["(started)"]));
  31. }
  32. return this;
  33. };
  34. Class.prototype.logEnd = function() {
  35. var args, ms, name;
  36. name = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
  37. ms = +(new Date) - this.logtimers[name];
  38. this.log.apply(this, ["" + name].concat(slice.call(args), ["(Done in " + ms + "ms)"]));
  39. return this;
  40. };
  41. return Class;
  42. })();
  43. window.Class = Class;
  44. }).call(this);
  45. /* ---- lib/Promise.coffee ---- */
  46. (function() {
  47. var Promise,
  48. slice = [].slice;
  49. Promise = (function() {
  50. Promise.when = function() {
  51. var args, fn, i, len, num_uncompleted, promise, task, task_id, tasks;
  52. tasks = 1 <= arguments.length ? slice.call(arguments, 0) : [];
  53. num_uncompleted = tasks.length;
  54. args = new Array(num_uncompleted);
  55. promise = new Promise();
  56. fn = function(task_id) {
  57. return task.then(function() {
  58. args[task_id] = Array.prototype.slice.call(arguments);
  59. num_uncompleted--;
  60. if (num_uncompleted === 0) {
  61. return promise.complete.apply(promise, args);
  62. }
  63. });
  64. };
  65. for (task_id = i = 0, len = tasks.length; i < len; task_id = ++i) {
  66. task = tasks[task_id];
  67. fn(task_id);
  68. }
  69. return promise;
  70. };
  71. function Promise() {
  72. this.resolved = false;
  73. this.end_promise = null;
  74. this.result = null;
  75. this.callbacks = [];
  76. }
  77. Promise.prototype.resolve = function() {
  78. var back, callback, i, len, ref;
  79. if (this.resolved) {
  80. return false;
  81. }
  82. this.resolved = true;
  83. this.data = arguments;
  84. if (!arguments.length) {
  85. this.data = [true];
  86. }
  87. this.result = this.data[0];
  88. ref = this.callbacks;
  89. for (i = 0, len = ref.length; i < len; i++) {
  90. callback = ref[i];
  91. back = callback.apply(callback, this.data);
  92. }
  93. if (this.end_promise) {
  94. return this.end_promise.resolve(back);
  95. }
  96. };
  97. Promise.prototype.fail = function() {
  98. return this.resolve(false);
  99. };
  100. Promise.prototype.then = function(callback) {
  101. if (this.resolved === true) {
  102. callback.apply(callback, this.data);
  103. return;
  104. }
  105. this.callbacks.push(callback);
  106. return this.end_promise = new Promise();
  107. };
  108. return Promise;
  109. })();
  110. window.Promise = Promise;
  111. /*
  112. s = Date.now()
  113. log = (text) ->
  114. console.log Date.now()-s, Array.prototype.slice.call(arguments).join(", ")
  115. log "Started"
  116. cmd = (query) ->
  117. p = new Promise()
  118. setTimeout ( ->
  119. p.resolve query+" Result"
  120. ), 100
  121. return p
  122. back = cmd("SELECT * FROM message").then (res) ->
  123. log res
  124. return "Return from query"
  125. .then (res) ->
  126. log "Back then", res
  127. log "Query started", back
  128. */
  129. }).call(this);
  130. /* ---- lib/Property.coffee ---- */
  131. (function() {
  132. Function.prototype.property = function(prop, desc) {
  133. return Object.defineProperty(this.prototype, prop, desc);
  134. };
  135. }).call(this);
  136. /* ---- lib/Prototypes.coffee ---- */
  137. (function() {
  138. String.prototype.startsWith = function(s) {
  139. return this.slice(0, s.length) === s;
  140. };
  141. String.prototype.endsWith = function(s) {
  142. return s === '' || this.slice(-s.length) === s;
  143. };
  144. String.prototype.repeat = function(count) {
  145. return new Array(count + 1).join(this);
  146. };
  147. window.isEmpty = function(obj) {
  148. var key;
  149. for (key in obj) {
  150. return false;
  151. }
  152. return true;
  153. };
  154. }).call(this);
  155. /* ---- lib/maquette.js ---- */
  156. (function (root, factory) {
  157. if (typeof define === 'function' && define.amd) {
  158. // AMD. Register as an anonymous module.
  159. define(['exports'], factory);
  160. } else if (typeof exports === 'object' && typeof exports.nodeName !== 'string') {
  161. // CommonJS
  162. factory(exports);
  163. } else {
  164. // Browser globals
  165. factory(root.maquette = {});
  166. }
  167. }(this, function (exports) {
  168. 'use strict';
  169. ;
  170. ;
  171. ;
  172. ;
  173. var NAMESPACE_W3 = 'http://www.w3.org/';
  174. var NAMESPACE_SVG = NAMESPACE_W3 + '2000/svg';
  175. var NAMESPACE_XLINK = NAMESPACE_W3 + '1999/xlink';
  176. // Utilities
  177. var emptyArray = [];
  178. var extend = function (base, overrides) {
  179. var result = {};
  180. Object.keys(base).forEach(function (key) {
  181. result[key] = base[key];
  182. });
  183. if (overrides) {
  184. Object.keys(overrides).forEach(function (key) {
  185. result[key] = overrides[key];
  186. });
  187. }
  188. return result;
  189. };
  190. // Hyperscript helper functions
  191. var same = function (vnode1, vnode2) {
  192. if (vnode1.vnodeSelector !== vnode2.vnodeSelector) {
  193. return false;
  194. }
  195. if (vnode1.properties && vnode2.properties) {
  196. if (vnode1.properties.key !== vnode2.properties.key) {
  197. return false;
  198. }
  199. return vnode1.properties.bind === vnode2.properties.bind;
  200. }
  201. return !vnode1.properties && !vnode2.properties;
  202. };
  203. var toTextVNode = function (data) {
  204. return {
  205. vnodeSelector: '',
  206. properties: undefined,
  207. children: undefined,
  208. text: data.toString(),
  209. domNode: null
  210. };
  211. };
  212. var appendChildren = function (parentSelector, insertions, main) {
  213. for (var i = 0; i < insertions.length; i++) {
  214. var item = insertions[i];
  215. if (Array.isArray(item)) {
  216. appendChildren(parentSelector, item, main);
  217. } else {
  218. if (item !== null && item !== undefined) {
  219. if (!item.hasOwnProperty('vnodeSelector')) {
  220. item = toTextVNode(item);
  221. }
  222. main.push(item);
  223. }
  224. }
  225. }
  226. };
  227. // Render helper functions
  228. var missingTransition = function () {
  229. throw new Error('Provide a transitions object to the projectionOptions to do animations');
  230. };
  231. var DEFAULT_PROJECTION_OPTIONS = {
  232. namespace: undefined,
  233. eventHandlerInterceptor: undefined,
  234. styleApplyer: function (domNode, styleName, value) {
  235. // Provides a hook to add vendor prefixes for browsers that still need it.
  236. domNode.style[styleName] = value;
  237. },
  238. transitions: {
  239. enter: missingTransition,
  240. exit: missingTransition
  241. }
  242. };
  243. var applyDefaultProjectionOptions = function (projectorOptions) {
  244. return extend(DEFAULT_PROJECTION_OPTIONS, projectorOptions);
  245. };
  246. var checkStyleValue = function (styleValue) {
  247. if (typeof styleValue !== 'string') {
  248. throw new Error('Style values must be strings');
  249. }
  250. };
  251. var setProperties = function (domNode, properties, projectionOptions) {
  252. if (!properties) {
  253. return;
  254. }
  255. var eventHandlerInterceptor = projectionOptions.eventHandlerInterceptor;
  256. var propNames = Object.keys(properties);
  257. var propCount = propNames.length;
  258. for (var i = 0; i < propCount; i++) {
  259. var propName = propNames[i];
  260. /* tslint:disable:no-var-keyword: edge case */
  261. var propValue = properties[propName];
  262. /* tslint:enable:no-var-keyword */
  263. if (propName === 'className') {
  264. throw new Error('Property "className" is not supported, use "class".');
  265. } else if (propName === 'class') {
  266. if (domNode.className) {
  267. // May happen if classes is specified before class
  268. domNode.className += ' ' + propValue;
  269. } else {
  270. domNode.className = propValue;
  271. }
  272. } else if (propName === 'classes') {
  273. // object with string keys and boolean values
  274. var classNames = Object.keys(propValue);
  275. var classNameCount = classNames.length;
  276. for (var j = 0; j < classNameCount; j++) {
  277. var className = classNames[j];
  278. if (propValue[className]) {
  279. domNode.classList.add(className);
  280. }
  281. }
  282. } else if (propName === 'styles') {
  283. // object with string keys and string (!) values
  284. var styleNames = Object.keys(propValue);
  285. var styleCount = styleNames.length;
  286. for (var j = 0; j < styleCount; j++) {
  287. var styleName = styleNames[j];
  288. var styleValue = propValue[styleName];
  289. if (styleValue) {
  290. checkStyleValue(styleValue);
  291. projectionOptions.styleApplyer(domNode, styleName, styleValue);
  292. }
  293. }
  294. } else if (propName === 'key') {
  295. continue;
  296. } else if (propValue === null || propValue === undefined) {
  297. continue;
  298. } else {
  299. var type = typeof propValue;
  300. if (type === 'function') {
  301. if (propName.lastIndexOf('on', 0) === 0) {
  302. if (eventHandlerInterceptor) {
  303. propValue = eventHandlerInterceptor(propName, propValue, domNode, properties); // intercept eventhandlers
  304. }
  305. if (propName === 'oninput') {
  306. (function () {
  307. // record the evt.target.value, because IE and Edge sometimes do a requestAnimationFrame between changing value and running oninput
  308. var oldPropValue = propValue;
  309. propValue = function (evt) {
  310. evt.target['oninput-value'] = evt.target.value;
  311. // may be HTMLTextAreaElement as well
  312. oldPropValue.apply(this, [evt]);
  313. };
  314. }());
  315. }
  316. domNode[propName] = propValue;
  317. }
  318. } else if (type === 'string' && propName !== 'value' && propName !== 'innerHTML') {
  319. if (projectionOptions.namespace === NAMESPACE_SVG && propName === 'href') {
  320. domNode.setAttributeNS(NAMESPACE_XLINK, propName, propValue);
  321. } else {
  322. domNode.setAttribute(propName, propValue);
  323. }
  324. } else {
  325. domNode[propName] = propValue;
  326. }
  327. }
  328. }
  329. };
  330. var updateProperties = function (domNode, previousProperties, properties, projectionOptions) {
  331. if (!properties) {
  332. return;
  333. }
  334. var propertiesUpdated = false;
  335. var propNames = Object.keys(properties);
  336. var propCount = propNames.length;
  337. for (var i = 0; i < propCount; i++) {
  338. var propName = propNames[i];
  339. // assuming that properties will be nullified instead of missing is by design
  340. var propValue = properties[propName];
  341. var previousValue = previousProperties[propName];
  342. if (propName === 'class') {
  343. if (previousValue !== propValue) {
  344. throw new Error('"class" property may not be updated. Use the "classes" property for conditional css classes.');
  345. }
  346. } else if (propName === 'classes') {
  347. var classList = domNode.classList;
  348. var classNames = Object.keys(propValue);
  349. var classNameCount = classNames.length;
  350. for (var j = 0; j < classNameCount; j++) {
  351. var className = classNames[j];
  352. var on = !!propValue[className];
  353. var previousOn = !!previousValue[className];
  354. if (on === previousOn) {
  355. continue;
  356. }
  357. propertiesUpdated = true;
  358. if (on) {
  359. classList.add(className);
  360. } else {
  361. classList.remove(className);
  362. }
  363. }
  364. } else if (propName === 'styles') {
  365. var styleNames = Object.keys(propValue);
  366. var styleCount = styleNames.length;
  367. for (var j = 0; j < styleCount; j++) {
  368. var styleName = styleNames[j];
  369. var newStyleValue = propValue[styleName];
  370. var oldStyleValue = previousValue[styleName];
  371. if (newStyleValue === oldStyleValue) {
  372. continue;
  373. }
  374. propertiesUpdated = true;
  375. if (newStyleValue) {
  376. checkStyleValue(newStyleValue);
  377. projectionOptions.styleApplyer(domNode, styleName, newStyleValue);
  378. } else {
  379. projectionOptions.styleApplyer(domNode, styleName, '');
  380. }
  381. }
  382. } else {
  383. if (!propValue && typeof previousValue === 'string') {
  384. propValue = '';
  385. }
  386. if (propName === 'value') {
  387. if (domNode[propName] !== propValue && domNode['oninput-value'] !== propValue) {
  388. domNode[propName] = propValue;
  389. // Reset the value, even if the virtual DOM did not change
  390. domNode['oninput-value'] = undefined;
  391. }
  392. // else do not update the domNode, otherwise the cursor position would be changed
  393. if (propValue !== previousValue) {
  394. propertiesUpdated = true;
  395. }
  396. } else if (propValue !== previousValue) {
  397. var type = typeof propValue;
  398. if (type === 'function') {
  399. throw new Error('Functions may not be updated on subsequent renders (property: ' + propName + '). Hint: declare event handler functions outside the render() function.');
  400. }
  401. if (type === 'string' && propName !== 'innerHTML') {
  402. if (projectionOptions.namespace === NAMESPACE_SVG && propName === 'href') {
  403. domNode.setAttributeNS(NAMESPACE_XLINK, propName, propValue);
  404. } else {
  405. domNode.setAttribute(propName, propValue);
  406. }
  407. } else {
  408. if (domNode[propName] !== propValue) {
  409. domNode[propName] = propValue;
  410. }
  411. }
  412. propertiesUpdated = true;
  413. }
  414. }
  415. }
  416. return propertiesUpdated;
  417. };
  418. var findIndexOfChild = function (children, sameAs, start) {
  419. if (sameAs.vnodeSelector !== '') {
  420. // Never scan for text-nodes
  421. for (var i = start; i < children.length; i++) {
  422. if (same(children[i], sameAs)) {
  423. return i;
  424. }
  425. }
  426. }
  427. return -1;
  428. };
  429. var nodeAdded = function (vNode, transitions) {
  430. if (vNode.properties) {
  431. var enterAnimation = vNode.properties.enterAnimation;
  432. if (enterAnimation) {
  433. if (typeof enterAnimation === 'function') {
  434. enterAnimation(vNode.domNode, vNode.properties);
  435. } else {
  436. transitions.enter(vNode.domNode, vNode.properties, enterAnimation);
  437. }
  438. }
  439. }
  440. };
  441. var nodeToRemove = function (vNode, transitions) {
  442. var domNode = vNode.domNode;
  443. if (vNode.properties) {
  444. var exitAnimation = vNode.properties.exitAnimation;
  445. if (exitAnimation) {
  446. domNode.style.pointerEvents = 'none';
  447. var removeDomNode = function () {
  448. if (domNode.parentNode) {
  449. domNode.parentNode.removeChild(domNode);
  450. }
  451. };
  452. if (typeof exitAnimation === 'function') {
  453. exitAnimation(domNode, removeDomNode, vNode.properties);
  454. return;
  455. } else {
  456. transitions.exit(vNode.domNode, vNode.properties, exitAnimation, removeDomNode);
  457. return;
  458. }
  459. }
  460. }
  461. if (domNode.parentNode) {
  462. domNode.parentNode.removeChild(domNode);
  463. }
  464. };
  465. var checkDistinguishable = function (childNodes, indexToCheck, parentVNode, operation) {
  466. var childNode = childNodes[indexToCheck];
  467. if (childNode.vnodeSelector === '') {
  468. return; // Text nodes need not be distinguishable
  469. }
  470. var properties = childNode.properties;
  471. var key = properties ? properties.key === undefined ? properties.bind : properties.key : undefined;
  472. if (!key) {
  473. for (var i = 0; i < childNodes.length; i++) {
  474. if (i !== indexToCheck) {
  475. var node = childNodes[i];
  476. if (same(node, childNode)) {
  477. if (operation === 'added') {
  478. throw new Error(parentVNode.vnodeSelector + ' had a ' + childNode.vnodeSelector + ' child ' + 'added, but there is now more than one. You must add unique key properties to make them distinguishable.');
  479. } else {
  480. throw new Error(parentVNode.vnodeSelector + ' had a ' + childNode.vnodeSelector + ' child ' + 'removed, but there were more than one. You must add unique key properties to make them distinguishable.');
  481. }
  482. }
  483. }
  484. }
  485. }
  486. };
  487. var createDom;
  488. var updateDom;
  489. var updateChildren = function (vnode, domNode, oldChildren, newChildren, projectionOptions) {
  490. if (oldChildren === newChildren) {
  491. return false;
  492. }
  493. oldChildren = oldChildren || emptyArray;
  494. newChildren = newChildren || emptyArray;
  495. var oldChildrenLength = oldChildren.length;
  496. var newChildrenLength = newChildren.length;
  497. var transitions = projectionOptions.transitions;
  498. var oldIndex = 0;
  499. var newIndex = 0;
  500. var i;
  501. var textUpdated = false;
  502. while (newIndex < newChildrenLength) {
  503. var oldChild = oldIndex < oldChildrenLength ? oldChildren[oldIndex] : undefined;
  504. var newChild = newChildren[newIndex];
  505. if (oldChild !== undefined && same(oldChild, newChild)) {
  506. textUpdated = updateDom(oldChild, newChild, projectionOptions) || textUpdated;
  507. oldIndex++;
  508. } else {
  509. var findOldIndex = findIndexOfChild(oldChildren, newChild, oldIndex + 1);
  510. if (findOldIndex >= 0) {
  511. // Remove preceding missing children
  512. for (i = oldIndex; i < findOldIndex; i++) {
  513. nodeToRemove(oldChildren[i], transitions);
  514. checkDistinguishable(oldChildren, i, vnode, 'removed');
  515. }
  516. textUpdated = updateDom(oldChildren[findOldIndex], newChild, projectionOptions) || textUpdated;
  517. oldIndex = findOldIndex + 1;
  518. } else {
  519. // New child
  520. createDom(newChild, domNode, oldIndex < oldChildrenLength ? oldChildren[oldIndex].domNode : undefined, projectionOptions);
  521. nodeAdded(newChild, transitions);
  522. checkDistinguishable(newChildren, newIndex, vnode, 'added');
  523. }
  524. }
  525. newIndex++;
  526. }
  527. if (oldChildrenLength > oldIndex) {
  528. // Remove child fragments
  529. for (i = oldIndex; i < oldChildrenLength; i++) {
  530. nodeToRemove(oldChildren[i], transitions);
  531. checkDistinguishable(oldChildren, i, vnode, 'removed');
  532. }
  533. }
  534. return textUpdated;
  535. };
  536. var addChildren = function (domNode, children, projectionOptions) {
  537. if (!children) {
  538. return;
  539. }
  540. for (var i = 0; i < children.length; i++) {
  541. createDom(children[i], domNode, undefined, projectionOptions);
  542. }
  543. };
  544. var initPropertiesAndChildren = function (domNode, vnode, projectionOptions) {
  545. addChildren(domNode, vnode.children, projectionOptions);
  546. // children before properties, needed for value property of <select>.
  547. if (vnode.text) {
  548. domNode.textContent = vnode.text;
  549. }
  550. setProperties(domNode, vnode.properties, projectionOptions);
  551. if (vnode.properties && vnode.properties.afterCreate) {
  552. vnode.properties.afterCreate(domNode, projectionOptions, vnode.vnodeSelector, vnode.properties, vnode.children);
  553. }
  554. };
  555. createDom = function (vnode, parentNode, insertBefore, projectionOptions) {
  556. var domNode, i, c, start = 0, type, found;
  557. var vnodeSelector = vnode.vnodeSelector;
  558. if (vnodeSelector === '') {
  559. domNode = vnode.domNode = document.createTextNode(vnode.text);
  560. if (insertBefore !== undefined) {
  561. parentNode.insertBefore(domNode, insertBefore);
  562. } else {
  563. parentNode.appendChild(domNode);
  564. }
  565. } else {
  566. for (i = 0; i <= vnodeSelector.length; ++i) {
  567. c = vnodeSelector.charAt(i);
  568. if (i === vnodeSelector.length || c === '.' || c === '#') {
  569. type = vnodeSelector.charAt(start - 1);
  570. found = vnodeSelector.slice(start, i);
  571. if (type === '.') {
  572. domNode.classList.add(found);
  573. } else if (type === '#') {
  574. domNode.id = found;
  575. } else {
  576. if (found === 'svg') {
  577. projectionOptions = extend(projectionOptions, { namespace: NAMESPACE_SVG });
  578. }
  579. if (projectionOptions.namespace !== undefined) {
  580. domNode = vnode.domNode = document.createElementNS(projectionOptions.namespace, found);
  581. } else {
  582. domNode = vnode.domNode = document.createElement(found);
  583. }
  584. if (insertBefore !== undefined) {
  585. parentNode.insertBefore(domNode, insertBefore);
  586. } else {
  587. parentNode.appendChild(domNode);
  588. }
  589. }
  590. start = i + 1;
  591. }
  592. }
  593. initPropertiesAndChildren(domNode, vnode, projectionOptions);
  594. }
  595. };
  596. updateDom = function (previous, vnode, projectionOptions) {
  597. var domNode = previous.domNode;
  598. var textUpdated = false;
  599. if (previous === vnode) {
  600. return false; // By contract, VNode objects may not be modified anymore after passing them to maquette
  601. }
  602. var updated = false;
  603. if (vnode.vnodeSelector === '') {
  604. if (vnode.text !== previous.text) {
  605. var newVNode = document.createTextNode(vnode.text);
  606. domNode.parentNode.replaceChild(newVNode, domNode);
  607. vnode.domNode = newVNode;
  608. textUpdated = true;
  609. return textUpdated;
  610. }
  611. } else {
  612. if (vnode.vnodeSelector.lastIndexOf('svg', 0) === 0) {
  613. projectionOptions = extend(projectionOptions, { namespace: NAMESPACE_SVG });
  614. }
  615. if (previous.text !== vnode.text) {
  616. updated = true;
  617. if (vnode.text === undefined) {
  618. domNode.removeChild(domNode.firstChild); // the only textnode presumably
  619. } else {
  620. domNode.textContent = vnode.text;
  621. }
  622. }
  623. updated = updateChildren(vnode, domNode, previous.children, vnode.children, projectionOptions) || updated;
  624. updated = updateProperties(domNode, previous.properties, vnode.properties, projectionOptions) || updated;
  625. if (vnode.properties && vnode.properties.afterUpdate) {
  626. vnode.properties.afterUpdate(domNode, projectionOptions, vnode.vnodeSelector, vnode.properties, vnode.children);
  627. }
  628. }
  629. if (updated && vnode.properties && vnode.properties.updateAnimation) {
  630. vnode.properties.updateAnimation(domNode, vnode.properties, previous.properties);
  631. }
  632. vnode.domNode = previous.domNode;
  633. return textUpdated;
  634. };
  635. var createProjection = function (vnode, projectionOptions) {
  636. return {
  637. update: function (updatedVnode) {
  638. if (vnode.vnodeSelector !== updatedVnode.vnodeSelector) {
  639. throw new Error('The selector for the root VNode may not be changed. (consider using dom.merge and add one extra level to the virtual DOM)');
  640. }
  641. updateDom(vnode, updatedVnode, projectionOptions);
  642. vnode = updatedVnode;
  643. },
  644. domNode: vnode.domNode
  645. };
  646. };
  647. ;
  648. // The other two parameters are not added here, because the Typescript compiler creates surrogate code for desctructuring 'children'.
  649. exports.h = function (selector) {
  650. var properties = arguments[1];
  651. if (typeof selector !== 'string') {
  652. throw new Error();
  653. }
  654. var childIndex = 1;
  655. if (properties && !properties.hasOwnProperty('vnodeSelector') && !Array.isArray(properties) && typeof properties === 'object') {
  656. childIndex = 2;
  657. } else {
  658. // Optional properties argument was omitted
  659. properties = undefined;
  660. }
  661. var text = undefined;
  662. var children = undefined;
  663. var argsLength = arguments.length;
  664. // Recognize a common special case where there is only a single text node
  665. if (argsLength === childIndex + 1) {
  666. var onlyChild = arguments[childIndex];
  667. if (typeof onlyChild === 'string') {
  668. text = onlyChild;
  669. } else if (onlyChild !== undefined && onlyChild.length === 1 && typeof onlyChild[0] === 'string') {
  670. text = onlyChild[0];
  671. }
  672. }
  673. if (text === undefined) {
  674. children = [];
  675. for (; childIndex < arguments.length; childIndex++) {
  676. var child = arguments[childIndex];
  677. if (child === null || child === undefined) {
  678. continue;
  679. } else if (Array.isArray(child)) {
  680. appendChildren(selector, child, children);
  681. } else if (child.hasOwnProperty('vnodeSelector')) {
  682. children.push(child);
  683. } else {
  684. children.push(toTextVNode(child));
  685. }
  686. }
  687. }
  688. return {
  689. vnodeSelector: selector,
  690. properties: properties,
  691. children: children,
  692. text: text === '' ? undefined : text,
  693. domNode: null
  694. };
  695. };
  696. /**
  697. * Contains simple low-level utility functions to manipulate the real DOM.
  698. */
  699. exports.dom = {
  700. /**
  701. * Creates a real DOM tree from `vnode`. The [[Projection]] object returned will contain the resulting DOM Node in
  702. * its [[Projection.domNode|domNode]] property.
  703. * This is a low-level method. Users wil typically use a [[Projector]] instead.
  704. * @param vnode - The root of the virtual DOM tree that was created using the [[h]] function. NOTE: [[VNode]]
  705. * objects may only be rendered once.
  706. * @param projectionOptions - Options to be used to create and update the projection.
  707. * @returns The [[Projection]] which also contains the DOM Node that was created.
  708. */
  709. create: function (vnode, projectionOptions) {
  710. projectionOptions = applyDefaultProjectionOptions(projectionOptions);
  711. createDom(vnode, document.createElement('div'), undefined, projectionOptions);
  712. return createProjection(vnode, projectionOptions);
  713. },
  714. /**
  715. * Appends a new childnode to the DOM which is generated from a [[VNode]].
  716. * This is a low-level method. Users wil typically use a [[Projector]] instead.
  717. * @param parentNode - The parent node for the new childNode.
  718. * @param vnode - The root of the virtual DOM tree that was created using the [[h]] function. NOTE: [[VNode]]
  719. * objects may only be rendered once.
  720. * @param projectionOptions - Options to be used to create and update the [[Projection]].
  721. * @returns The [[Projection]] that was created.
  722. */
  723. append: function (parentNode, vnode, projectionOptions) {
  724. projectionOptions = applyDefaultProjectionOptions(projectionOptions);
  725. createDom(vnode, parentNode, undefined, projectionOptions);
  726. return createProjection(vnode, projectionOptions);
  727. },
  728. /**
  729. * Inserts a new DOM node which is generated from a [[VNode]].
  730. * This is a low-level method. Users wil typically use a [[Projector]] instead.
  731. * @param beforeNode - The node that the DOM Node is inserted before.
  732. * @param vnode - The root of the virtual DOM tree that was created using the [[h]] function.
  733. * NOTE: [[VNode]] objects may only be rendered once.
  734. * @param projectionOptions - Options to be used to create and update the projection, see [[createProjector]].
  735. * @returns The [[Projection]] that was created.
  736. */
  737. insertBefore: function (beforeNode, vnode, projectionOptions) {
  738. projectionOptions = applyDefaultProjectionOptions(projectionOptions);
  739. createDom(vnode, beforeNode.parentNode, beforeNode, projectionOptions);
  740. return createProjection(vnode, projectionOptions);
  741. },
  742. /**
  743. * Merges a new DOM node which is generated from a [[VNode]] with an existing DOM Node.
  744. * This means that the virtual DOM and the real DOM will have one overlapping element.
  745. * Therefore the selector for the root [[VNode]] will be ignored, but its properties and children will be applied to the Element provided.
  746. * This is a low-level method. Users wil typically use a [[Projector]] instead.
  747. * @param domNode - The existing element to adopt as the root of the new virtual DOM. Existing attributes and childnodes are preserved.
  748. * @param vnode - The root of the virtual DOM tree that was created using the [[h]] function. NOTE: [[VNode]] objects
  749. * may only be rendered once.
  750. * @param projectionOptions - Options to be used to create and update the projection, see [[createProjector]].
  751. * @returns The [[Projection]] that was created.
  752. */
  753. merge: function (element, vnode, projectionOptions) {
  754. projectionOptions = applyDefaultProjectionOptions(projectionOptions);
  755. vnode.domNode = element;
  756. initPropertiesAndChildren(element, vnode, projectionOptions);
  757. return createProjection(vnode, projectionOptions);
  758. }
  759. };
  760. /**
  761. * Creates a [[CalculationCache]] object, useful for caching [[VNode]] trees.
  762. * In practice, caching of [[VNode]] trees is not needed, because achieving 60 frames per second is almost never a problem.
  763. * For more information, see [[CalculationCache]].
  764. *
  765. * @param <Result> The type of the value that is cached.
  766. */
  767. exports.createCache = function () {
  768. var cachedInputs = undefined;
  769. var cachedOutcome = undefined;
  770. var result = {
  771. invalidate: function () {
  772. cachedOutcome = undefined;
  773. cachedInputs = undefined;
  774. },
  775. result: function (inputs, calculation) {
  776. if (cachedInputs) {
  777. for (var i = 0; i < inputs.length; i++) {
  778. if (cachedInputs[i] !== inputs[i]) {
  779. cachedOutcome = undefined;
  780. }
  781. }
  782. }
  783. if (!cachedOutcome) {
  784. cachedOutcome = calculation();
  785. cachedInputs = inputs;
  786. }
  787. return cachedOutcome;
  788. }
  789. };
  790. return result;
  791. };
  792. /**
  793. * Creates a {@link Mapping} instance that keeps an array of result objects synchronized with an array of source objects.
  794. * See {@link http://maquettejs.org/docs/arrays.html|Working with arrays}.
  795. *
  796. * @param <Source> The type of source items. A database-record for instance.
  797. * @param <Target> The type of target items. A [[Component]] for instance.
  798. * @param getSourceKey `function(source)` that must return a key to identify each source object. The result must either be a string or a number.
  799. * @param createResult `function(source, index)` that must create a new result object from a given source. This function is identical
  800. * to the `callback` argument in `Array.map(callback)`.
  801. * @param updateResult `function(source, target, index)` that updates a result to an updated source.
  802. */
  803. exports.createMapping = function (getSourceKey, createResult, updateResult) {
  804. var keys = [];
  805. var results = [];
  806. return {
  807. results: results,
  808. map: function (newSources) {
  809. var newKeys = newSources.map(getSourceKey);
  810. var oldTargets = results.slice();
  811. var oldIndex = 0;
  812. for (var i = 0; i < newSources.length; i++) {
  813. var source = newSources[i];
  814. var sourceKey = newKeys[i];
  815. if (sourceKey === keys[oldIndex]) {
  816. results[i] = oldTargets[oldIndex];
  817. updateResult(source, oldTargets[oldIndex], i);
  818. oldIndex++;
  819. } else {
  820. var found = false;
  821. for (var j = 1; j < keys.length; j++) {
  822. var searchIndex = (oldIndex + j) % keys.length;
  823. if (keys[searchIndex] === sourceKey) {
  824. results[i] = oldTargets[searchIndex];
  825. updateResult(newSources[i], oldTargets[searchIndex], i);
  826. oldIndex = searchIndex + 1;
  827. found = true;
  828. break;
  829. }
  830. }
  831. if (!found) {
  832. results[i] = createResult(source, i);
  833. }
  834. }
  835. }
  836. results.length = newSources.length;
  837. keys = newKeys;
  838. }
  839. };
  840. };
  841. /**
  842. * Creates a [[Projector]] instance using the provided projectionOptions.
  843. *
  844. * For more information, see [[Projector]].
  845. *
  846. * @param projectionOptions Options that influence how the DOM is rendered and updated.
  847. */
  848. exports.createProjector = function (projectorOptions) {
  849. var projector;
  850. var projectionOptions = applyDefaultProjectionOptions(projectorOptions);
  851. projectionOptions.eventHandlerInterceptor = function (propertyName, eventHandler, domNode, properties) {
  852. return function () {
  853. // intercept function calls (event handlers) to do a render afterwards.
  854. projector.scheduleRender();
  855. return eventHandler.apply(properties.bind || this, arguments);
  856. };
  857. };
  858. var renderCompleted = true;
  859. var scheduled;
  860. var stopped = false;
  861. var projections = [];
  862. var renderFunctions = [];
  863. // matches the projections array
  864. var doRender = function () {
  865. scheduled = undefined;
  866. if (!renderCompleted) {
  867. return; // The last render threw an error, it should be logged in the browser console.
  868. }
  869. renderCompleted = false;
  870. for (var i = 0; i < projections.length; i++) {
  871. var updatedVnode = renderFunctions[i]();
  872. projections[i].update(updatedVnode);
  873. }
  874. renderCompleted = true;
  875. };
  876. projector = {
  877. scheduleRender: function () {
  878. if (!scheduled && !stopped) {
  879. scheduled = requestAnimationFrame(doRender);
  880. }
  881. },
  882. stop: function () {
  883. if (scheduled) {
  884. cancelAnimationFrame(scheduled);
  885. scheduled = undefined;
  886. }
  887. stopped = true;
  888. },
  889. resume: function () {
  890. stopped = false;
  891. renderCompleted = true;
  892. projector.scheduleRender();
  893. },
  894. append: function (parentNode, renderMaquetteFunction) {
  895. projections.push(exports.dom.append(parentNode, renderMaquetteFunction(), projectionOptions));
  896. renderFunctions.push(renderMaquetteFunction);
  897. },
  898. insertBefore: function (beforeNode, renderMaquetteFunction) {
  899. projections.push(exports.dom.insertBefore(beforeNode, renderMaquetteFunction(), projectionOptions));
  900. renderFunctions.push(renderMaquetteFunction);
  901. },
  902. merge: function (domNode, renderMaquetteFunction) {
  903. projections.push(exports.dom.merge(domNode, renderMaquetteFunction(), projectionOptions));
  904. renderFunctions.push(renderMaquetteFunction);
  905. },
  906. replace: function (domNode, renderMaquetteFunction) {
  907. var vnode = renderMaquetteFunction();
  908. createDom(vnode, domNode.parentNode, domNode, projectionOptions);
  909. domNode.parentNode.removeChild(domNode);
  910. projections.push(createProjection(vnode, projectionOptions));
  911. renderFunctions.push(renderMaquetteFunction);
  912. },
  913. detach: function (renderMaquetteFunction) {
  914. for (var i = 0; i < renderFunctions.length; i++) {
  915. if (renderFunctions[i] === renderMaquetteFunction) {
  916. renderFunctions.splice(i, 1);
  917. return projections.splice(i, 1)[0];
  918. }
  919. }
  920. throw new Error('renderMaquetteFunction was not found');
  921. }
  922. };
  923. return projector;
  924. };
  925. }));
  926. /* ---- lib/marked.min.js ---- */
  927. /**
  928. * marked - a markdown parser
  929. * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed)
  930. * https://github.com/chjj/marked
  931. */
  932. (function(){var block={newline:/^\n+/,code:/^( {4}[^\n]+\n*)+/,fences:noop,hr:/^( *[-*_]){3,} *(?:\n+|$)/,heading:/^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,nptable:noop,lheading:/^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,blockquote:/^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/,list:/^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,html:/^ *(?:comment|closed|closing) *(?:\n{2,}|\s*$)/,def:/^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,table:noop,paragraph:/^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,text:/^[^\n]+/};block.bullet=/(?:[*+-]|\d+\.)/;block.item=/^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;block.item=replace(block.item,"gm")(/bull/g,block.bullet)();block.list=replace(block.list)(/bull/g,block.bullet)("hr","\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))")("def","\\n+(?="+block.def.source+")")();block.blockquote=replace(block.blockquote)("def",block.def)();block._tag="(?!(?:"+"a|em|strong|small|s|cite|q|dfn|abbr|data|time|code"+"|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo"+"|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b";block.html=replace(block.html)("comment",/<!--[\s\S]*?-->/)("closed",/<(tag)[\s\S]+?<\/\1>/)("closing",/<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/)(/tag/g,block._tag)();block.paragraph=replace(block.paragraph)("hr",block.hr)("heading",block.heading)("lheading",block.lheading)("blockquote",block.blockquote)("tag","<"+block._tag)("def",block.def)();block.normal=merge({},block);block.gfm=merge({},block.normal,{fences:/^ *(`{3,}|~{3,}) *(\S+)? *\n([\s\S]+?)\s*\1 *(?:\n+|$)/,paragraph:/^/});block.gfm.paragraph=replace(block.paragraph)("(?!","(?!"+block.gfm.fences.source.replace("\\1","\\2")+"|"+block.list.source.replace("\\1","\\3")+"|")();block.tables=merge({},block.gfm,{nptable:/^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,table:/^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/});function Lexer(options){this.tokens=[];this.tokens.links={};this.options=options||marked.defaults;this.rules=block.normal;if(this.options.gfm){if(this.options.tables){this.rules=block.tables}else{this.rules=block.gfm}}}Lexer.rules=block;Lexer.lex=function(src,options){var lexer=new Lexer(options);return lexer.lex(src)};Lexer.prototype.lex=function(src){src=src.replace(/\r\n|\r/g,"\n").replace(/\t/g," ").replace(/\u00a0/g," ").replace(/\u2424/g,"\n");return this.token(src,true)};Lexer.prototype.token=function(src,top,bq){var src=src.replace(/^ +$/gm,""),next,loose,cap,bull,b,item,space,i,l;while(src){if(cap=this.rules.newline.exec(src)){src=src.substring(cap[0].length);if(cap[0].length>1){this.tokens.push({type:"space"})}}if(cap=this.rules.code.exec(src)){src=src.substring(cap[0].length);cap=cap[0].replace(/^ {4}/gm,"");this.tokens.push({type:"code",text:!this.options.pedantic?cap.replace(/\n+$/,""):cap});continue}if(cap=this.rules.fences.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"code",lang:cap[2],text:cap[3]});continue}if(cap=this.rules.heading.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"heading",depth:cap[1].length,text:cap[2]});continue}if(top&&(cap=this.rules.nptable.exec(src))){src=src.substring(cap[0].length);item={type:"table",header:cap[1].replace(/^ *| *\| *$/g,"").split(/ *\| */),align:cap[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:cap[3].replace(/\n$/,"").split("\n")};for(i=0;i<item.align.length;i++){if(/^ *-+: *$/.test(item.align[i])){item.align[i]="right"}else if(/^ *:-+: *$/.test(item.align[i])){item.align[i]="center"}else if(/^ *:-+ *$/.test(item.align[i])){item.align[i]="left"}else{item.align[i]=null}}for(i=0;i<item.cells.length;i++){item.cells[i]=item.cells[i].split(/ *\| */)}this.tokens.push(item);continue}if(cap=this.rules.lheading.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"heading",depth:cap[2]==="="?1:2,text:cap[1]});continue}if(cap=this.rules.hr.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"hr"});continue}if(cap=this.rules.blockquote.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"blockquote_start"});cap=cap[0].replace(/^ *> ?/gm,"");this.token(cap,top,true);this.tokens.push({type:"blockquote_end"});continue}if(cap=this.rules.list.exec(src)){src=src.substring(cap[0].length);bull=cap[2];this.tokens.push({type:"list_start",ordered:bull.length>1});cap=cap[0].match(this.rules.item);next=false;l=cap.length;i=0;for(;i<l;i++){item=cap[i];space=item.length;item=item.replace(/^ *([*+-]|\d+\.) +/,"");if(~item.indexOf("\n ")){space-=item.length;item=!this.options.pedantic?item.replace(new RegExp("^ {1,"+space+"}","gm"),""):item.replace(/^ {1,4}/gm,"")}if(this.options.smartLists&&i!==l-1){b=block.bullet.exec(cap[i+1])[0];if(bull!==b&&!(bull.length>1&&b.length>1)){src=cap.slice(i+1).join("\n")+src;i=l-1}}loose=next||/\n\n(?!\s*$)/.test(item);if(i!==l-1){next=item.charAt(item.length-1)==="\n";if(!loose)loose=next}this.tokens.push({type:loose?"loose_item_start":"list_item_start"});this.token(item,false,bq);this.tokens.push({type:"list_item_end"})}this.tokens.push({type:"list_end"});continue}if(cap=this.rules.html.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:this.options.sanitize?"paragraph":"html",pre:cap[1]==="pre"||cap[1]==="script"||cap[1]==="style",text:cap[0]});continue}if(!bq&&top&&(cap=this.rules.def.exec(src))){src=src.substring(cap[0].length);this.tokens.links[cap[1].toLowerCase()]={href:cap[2],title:cap[3]};continue}if(top&&(cap=this.rules.table.exec(src))){src=src.substring(cap[0].length);item={type:"table",header:cap[1].replace(/^ *| *\| *$/g,"").split(/ *\| */),align:cap[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:cap[3].replace(/(?: *\| *)?\n$/,"").split("\n")};for(i=0;i<item.align.length;i++){if(/^ *-+: *$/.test(item.align[i])){item.align[i]="right"}else if(/^ *:-+: *$/.test(item.align[i])){item.align[i]="center"}else if(/^ *:-+ *$/.test(item.align[i])){item.align[i]="left"}else{item.align[i]=null}}for(i=0;i<item.cells.length;i++){item.cells[i]=item.cells[i].replace(/^ *\| *| *\| *$/g,"").split(/ *\| */)}this.tokens.push(item);continue}if(top&&(cap=this.rules.paragraph.exec(src))){src=src.substring(cap[0].length);this.tokens.push({type:"paragraph",text:cap[1].charAt(cap[1].length-1)==="\n"?cap[1].slice(0,-1):cap[1]});continue}if(cap=this.rules.text.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"text",text:cap[0]});continue}if(src){throw new Error("Infinite loop on byte: "+src.charCodeAt(0))}}return this.tokens};var inline={escape:/^\\([\\`*{}\[\]()#+\-.!_>])/,autolink:/^<([^ >]+(@|:\/)[^ >]+)>/,url:noop,tag:/^<!--[\s\S]*?-->|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,link:/^!?\[(inside)\]\(href\)/,reflink:/^!?\[(inside)\]\s*\[([^\]]*)\]/,nolink:/^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,strong:/^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,em:/^\b_((?:__|[\s\S])+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,code:/^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,br:/^ {2,}\n(?!\s*$)/,del:noop,text:/^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/};inline._inside=/(?:\[[^\]]*\]|[^\[\]]|\](?=[^\[]*\]))*/;inline._href=/\s*<?([\s\S]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/;inline.link=replace(inline.link)("inside",inline._inside)("href",inline._href)();inline.reflink=replace(inline.reflink)("inside",inline._inside)();inline.normal=merge({},inline);inline.pedantic=merge({},inline.normal,{strong:/^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,em:/^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/});inline.gfm=merge({},inline.normal,{escape:replace(inline.escape)("])","~|])")(),url:/^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,del:/^~~(?=\S)([\s\S]*?\S)~~/,text:replace(inline.text)("]|","~]|")("|","|https?://|")()});inline.breaks=merge({},inline.gfm,{br:replace(inline.br)("{2,}","*")(),text:replace(inline.gfm.text)("{2,}","*")()});function InlineLexer(links,options){this.options=options||marked.defaults;this.links=links;this.rules=inline.normal;this.renderer=this.options.renderer||new Renderer;this.renderer.options=this.options;if(!this.links){throw new Error("Tokens array requires a `links` property.")}if(this.options.gfm){if(this.options.breaks){this.rules=inline.breaks}else{this.rules=inline.gfm}}else if(this.options.pedantic){this.rules=inline.pedantic}}InlineLexer.rules=inline;InlineLexer.output=function(src,links,options){var inline=new InlineLexer(links,options);return inline.output(src)};InlineLexer.prototype.output=function(src){var out="",link,text,href,cap;while(src){if(cap=this.rules.escape.exec(src)){src=src.substring(cap[0].length);out+=cap[1];continue}if(cap=this.rules.autolink.exec(src)){src=src.substring(cap[0].length);if(cap[2]==="@"){text=cap[1].charAt(6)===":"?this.mangle(cap[1].substring(7)):this.mangle(cap[1]);href=this.mangle("mailto:")+text}else{text=escape(cap[1]);href=text}out+=this.renderer.link(href,null,text);continue}if(!this.inLink&&(cap=this.rules.url.exec(src))){src=src.substring(cap[0].length);text=escape(cap[1]);href=text;out+=this.renderer.link(href,null,text);continue}if(cap=this.rules.tag.exec(src)){if(!this.inLink&&/^<a /i.test(cap[0])){this.inLink=true}else if(this.inLink&&/^<\/a>/i.test(cap[0])){this.inLink=false}src=src.substring(cap[0].length);out+=this.options.sanitize?escape(cap[0]):cap[0];continue}if(cap=this.rules.link.exec(src)){src=src.substring(cap[0].length);this.inLink=true;out+=this.outputLink(cap,{href:cap[2],title:cap[3]});this.inLink=false;continue}if((cap=this.rules.reflink.exec(src))||(cap=this.rules.nolink.exec(src))){src=src.substring(cap[0].length);link=(cap[2]||cap[1]).replace(/\s+/g," ");link=this.links[link.toLowerCase()];if(!link||!link.href){out+=cap[0].charAt(0);src=cap[0].substring(1)+src;continue}this.inLink=true;out+=this.outputLink(cap,link);this.inLink=false;continue}if(cap=this.rules.strong.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.strong(this.output(cap[2]||cap[1]));continue}if(cap=this.rules.em.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.em(this.output(cap[2]||cap[1]));continue}if(cap=this.rules.code.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.codespan(escape(cap[2],true));continue}if(cap=this.rules.br.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.br();continue}if(cap=this.rules.del.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.del(this.output(cap[1]));continue}if(cap=this.rules.text.exec(src)){src=src.substring(cap[0].length);out+=escape(this.smartypants(cap[0]));continue}if(src){throw new Error("Infinite loop on byte: "+src.charCodeAt(0))}}return out};InlineLexer.prototype.outputLink=function(cap,link){var href=escape(link.href),title=link.title?escape(link.title):null;return cap[0].charAt(0)!=="!"?this.renderer.link(href,title,this.output(cap[1])):this.renderer.image(href,title,escape(cap[1]))};InlineLexer.prototype.smartypants=function(text){if(!this.options.smartypants)return text;return text.replace(/--/g,"—").replace(/(^|[-\u2014/(\[{"\s])'/g,"$1‘").replace(/'/g,"’").replace(/(^|[-\u2014/(\[{\u2018\s])"/g,"$1“").replace(/"/g,"”").replace(/\.{3}/g,"…")};InlineLexer.prototype.mangle=function(text){var out="",l=text.length,i=0,ch;for(;i<l;i++){ch=text.charCodeAt(i);if(Math.random()>.5){ch="x"+ch.toString(16)}out+="&#"+ch+";"}return out};function Renderer(options){this.options=options||{}}Renderer.prototype.code=function(code,lang,escaped){if(this.options.highlight){var out=this.options.highlight(code,lang);if(out!=null&&out!==code){escaped=true;code=out}}if(!lang){return"<pre><code>"+(escaped?code:escape(code,true))+"\n</code></pre>"}return'<pre><code class="'+this.options.langPrefix+escape(lang,true)+'">'+(escaped?code:escape(code,true))+"\n</code></pre>\n"};Renderer.prototype.blockquote=function(quote){return"<blockquote>\n"+quote+"</blockquote>\n"};Renderer.prototype.html=function(html){return html};Renderer.prototype.heading=function(text,level,raw){return"<h"+level+' id="'+this.options.headerPrefix+raw.toLowerCase().replace(/[^\w]+/g,"-")+'">'+text+"</h"+level+">\n"};Renderer.prototype.hr=function(){return this.options.xhtml?"<hr/>\n":"<hr>\n"};Renderer.prototype.list=function(body,ordered){var type=ordered?"ol":"ul";return"<"+type+">\n"+body+"</"+type+">\n"};Renderer.prototype.listitem=function(text){return"<li>"+text+"</li>\n"};Renderer.prototype.paragraph=function(text){return"<p>"+text+"</p>\n"};Renderer.prototype.table=function(header,body){return"<table>\n"+"<thead>\n"+header+"</thead>\n"+"<tbody>\n"+body+"</tbody>\n"+"</table>\n"};Renderer.prototype.tablerow=function(content){return"<tr>\n"+content+"</tr>\n"};Renderer.prototype.tablecell=function(content,flags){var type=flags.header?"th":"td";var tag=flags.align?"<"+type+' style="text-align:'+flags.align+'">':"<"+type+">";return tag+content+"</"+type+">\n"};Renderer.prototype.strong=function(text){return"<strong>"+text+"</strong>"};Renderer.prototype.em=function(text){return"<em>"+text+"</em>"};Renderer.prototype.codespan=function(text){return"<code>"+text+"</code>"};Renderer.prototype.br=function(){return this.options.xhtml?"<br/>":"<br>"};Renderer.prototype.del=function(text){return"<del>"+text+"</del>"};Renderer.prototype.link=function(href,title,text){if(this.options.sanitize){try{var prot=decodeURIComponent(unescape(href)).replace(/[^\w:]/g,"").toLowerCase()}catch(e){return""}if(prot.indexOf("javascript:")===0){return""}}var out='<a href="'+href+'"';if(title){out+=' title="'+title+'"'}out+=">"+text+"</a>";return out};Renderer.prototype.image=function(href,title,text){var out='<img src="'+href+'" alt="'+text+'"';if(title){out+=' title="'+title+'"'}out+=this.options.xhtml?"/>":">";return out};function Parser(options){this.tokens=[];this.token=null;this.options=options||marked.defaults;this.options.renderer=this.options.renderer||new Renderer;this.renderer=this.options.renderer;this.renderer.options=this.options}Parser.parse=function(src,options,renderer){var parser=new Parser(options,renderer);return parser.parse(src)};Parser.prototype.parse=function(src){this.inline=new InlineLexer(src.links,this.options,this.renderer);this.tokens=src.reverse();var out="";while(this.next()){out+=this.tok()}return out};Parser.prototype.next=function(){return this.token=this.tokens.pop()};Parser.prototype.peek=function(){return this.tokens[this.tokens.length-1]||0};Parser.prototype.parseText=function(){var body=this.token.text;while(this.peek().type==="text"){body+="\n"+this.next().text}return this.inline.output(body)};Parser.prototype.tok=function(){switch(this.token.type){case"space":{return""}case"hr":{return this.renderer.hr()}case"heading":{return this.renderer.heading(this.inline.output(this.token.text),this.token.depth,this.token.text)}case"code":{return this.renderer.code(this.token.text,this.token.lang,this.token.escaped)}case"table":{var header="",body="",i,row,cell,flags,j;cell="";for(i=0;i<this.token.header.length;i++){flags={header:true,align:this.token.align[i]};cell+=this.renderer.tablecell(this.inline.output(this.token.header[i]),{header:true,align:this.token.align[i]})}header+=this.renderer.tablerow(cell);for(i=0;i<this.token.cells.length;i++){row=this.token.cells[i];cell="";for(j=0;j<row.length;j++){cell+=this.renderer.tablecell(this.inline.output(row[j]),{header:false,align:this.token.align[j]})}body+=this.renderer.tablerow(cell)}return this.renderer.table(header,body)}case"blockquote_start":{var body="";while(this.next().type!=="blockquote_end"){body+=this.tok()}return this.renderer.blockquote(body)}case"list_start":{var body="",ordered=this.token.ordered;while(this.next().type!=="list_end"){body+=this.tok()}return this.renderer.list(body,ordered)}case"list_item_start":{var body="";while(this.next().type!=="list_item_end"){body+=this.token.type==="text"?this.parseText():this.tok()}return this.renderer.listitem(body)}case"loose_item_start":{var body="";while(this.next().type!=="list_item_end"){body+=this.tok()}return this.renderer.listitem(body)}case"html":{var html=!this.token.pre&&!this.options.pedantic?this.inline.output(this.token.text):this.token.text;return this.renderer.html(html)}case"paragraph":{return this.renderer.paragraph(this.inline.output(this.token.text))}case"text":{return this.renderer.paragraph(this.parseText())}}};function escape(html,encode){return html.replace(!encode?/&(?!#?\w+;)/g:/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}function unescape(html){return html.replace(/&([#\w]+);/g,function(_,n){n=n.toLowerCase();if(n==="colon")return":";if(n.charAt(0)==="#"){return n.charAt(1)==="x"?String.fromCharCode(parseInt(n.substring(2),16)):String.fromCharCode(+n.substring(1))}return""})}function replace(regex,opt){regex=regex.source;opt=opt||"";return function self(name,val){if(!name)return new RegExp(regex,opt);val=val.source||val;val=val.replace(/(^|[^\[])\^/g,"$1");regex=regex.replace(name,val);return self}}function noop(){}noop.exec=noop;function merge(obj){var i=1,target,key;for(;i<arguments.length;i++){target=arguments[i];for(key in target){if(Object.prototype.hasOwnProperty.call(target,key)){obj[key]=target[key]}}}return obj}function marked(src,opt,callback){if(callback||typeof opt==="function"){if(!callback){callback=opt;opt=null}opt=merge({},marked.defaults,opt||{});var highlight=opt.highlight,tokens,pending,i=0;try{tokens=Lexer.lex(src,opt)}catch(e){return callback(e)}pending=tokens.length;var done=function(err){if(err){opt.highlight=highlight;return callback(err)}var out;try{out=Parser.parse(tokens,opt)}catch(e){err=e}opt.highlight=highlight;return err?callback(err):callback(null,out)};if(!highlight||highlight.length<3){return done()}delete opt.highlight;if(!pending)return done();for(;i<tokens.length;i++){(function(token){if(token.type!=="code"){return--pending||done()}return highlight(token.text,token.lang,function(err,code){if(err)return done(err);if(code==null||code===token.text){return--pending||done()}token.text=code;token.escaped=true;--pending||done()})})(tokens[i])}return}try{if(opt)opt=merge({},marked.defaults,opt);return Parser.parse(Lexer.lex(src,opt),opt)}catch(e){e.message+="\nPlease report this to https://github.com/chjj/marked.";if((opt||marked.defaults).silent){return"<p>An error occured:</p><pre>"+escape(e.message+"",true)+"</pre>"}throw e}}marked.options=marked.setOptions=function(opt){merge(marked.defaults,opt);return marked};marked.defaults={gfm:true,tables:true,breaks:false,pedantic:false,sanitize:false,smartLists:false,silent:false,highlight:null,langPrefix:"lang-",smartypants:false,headerPrefix:"",renderer:new Renderer,xhtml:false};marked.Parser=Parser;marked.parser=Parser.parse;marked.Renderer=Renderer;marked.Lexer=Lexer;marked.lexer=Lexer.lex;marked.InlineLexer=InlineLexer;marked.inlineLexer=InlineLexer.output;marked.parse=marked;if(typeof module!=="undefined"&&typeof exports==="object"){module.exports=marked}else if(typeof define==="function"&&define.amd){define(function(){return marked})}else{this.marked=marked}}).call(function(){return this||(typeof window!=="undefined"?window:global)}());
  933. /* ---- PageFiles/Bigfiles.coffee ---- */
  934. (function() {
  935. var Bigfiles,
  936. bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
  937. extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
  938. hasProp = {}.hasOwnProperty;
  939. Bigfiles = (function(superClass) {
  940. extend(Bigfiles, superClass);
  941. function Bigfiles() {
  942. this.render = bind(this.render, this);
  943. this.getHref = bind(this.getHref, this);
  944. this.updateFiles = bind(this.updateFiles, this);
  945. this.files = new SiteFiles(this);
  946. this.files.mode = "bigfiles";
  947. this.files.limit = 100;
  948. this.files.update = this.updateFiles;
  949. this.row = {
  950. "address": "bigfiles"
  951. };
  952. }
  953. Bigfiles.prototype.updateFiles = function(cb) {
  954. var orderby;
  955. if (Page.server_info.rev < 3090) {
  956. return typeof cb === "function" ? cb() : void 0;
  957. }
  958. orderby = this.files.orderby + (this.files.orderby_desc ? " DESC" : "");
  959. return Page.cmd("optionalFileList", {
  960. address: "all",
  961. filter: "downloaded,bigfile",
  962. limit: this.files.limit + 1,
  963. orderby: orderby
  964. }, (function(_this) {
  965. return function(res) {
  966. var i, len, row;
  967. for (i = 0, len = res.length; i < len; i++) {
  968. row = res[i];
  969. row.site = Page.site_list.sites_byaddress[row.address];
  970. }
  971. _this.files.items = res.slice(0, +(_this.files.limit - 1) + 1 || 9e9);
  972. _this.files.loaded = true;
  973. _this.files.has_more = res.length > _this.files.limit;
  974. Page.projector.scheduleRender();
  975. return typeof cb === "function" ? cb() : void 0;
  976. };
  977. })(this));
  978. };
  979. Bigfiles.prototype.getHref = function(row) {
  980. return row.inner_path;
  981. };
  982. Bigfiles.prototype.render = function() {
  983. if (!this.files.items.length) {
  984. return [];
  985. }
  986. return h("div.site", [h("div.title", [h("h3.name", "Bigfiles")]), this.files.render()]);
  987. };
  988. return Bigfiles;
  989. })(Class);
  990. window.Bigfiles = Bigfiles;
  991. }).call(this);
  992. /* ---- PageFiles/FilesResult.coffee ---- */
  993. (function() {
  994. var FilesResult,
  995. bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
  996. extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
  997. hasProp = {}.hasOwnProperty;
  998. FilesResult = (function(superClass) {
  999. extend(FilesResult, superClass);
  1000. function FilesResult() {
  1001. this.render = bind(this.render, this);
  1002. this.getHref = bind(this.getHref, this);
  1003. this.setFilter = bind(this.setFilter, this);
  1004. this.updateFiles = bind(this.updateFiles, this);
  1005. this.files = new SiteFiles(this);
  1006. this.files.mode = "result";
  1007. this.files.limit = 20;
  1008. this.files.update = this.updateFiles;
  1009. this.row = {
  1010. "address": "result"
  1011. };
  1012. this.filter_inner_path = "";
  1013. }
  1014. FilesResult.prototype.updateFiles = function(cb) {
  1015. var orderby;
  1016. this.log("Update FilesResult", this.filter_inner_path);
  1017. if (Page.server_info.rev < 4120) {
  1018. Page.projector.scheduleRender();
  1019. return typeof cb === "function" ? cb() : void 0;
  1020. }
  1021. orderby = this.files.orderby + (this.files.orderby_desc ? " DESC" : "");
  1022. return Page.cmd("optionalFileList", {
  1023. address: "all",
  1024. filter: "downloaded",
  1025. filter_inner_path: "%" + this.filter_inner_path + "%",
  1026. limit: this.files.limit + 1,
  1027. orderby: orderby
  1028. }, (function(_this) {
  1029. return function(res) {
  1030. var i, len, row;
  1031. for (i = 0, len = res.length; i < len; i++) {
  1032. row = res[i];
  1033. row.site = Page.site_list.sites_byaddress[row.address];
  1034. }
  1035. _this.files.items = res.slice(0, +(_this.files.limit - 1) + 1 || 9e9);
  1036. _this.files.loaded = true;
  1037. _this.files.has_more = res.length > _this.files.limit;
  1038. Page.projector.scheduleRender();
  1039. return typeof cb === "function" ? cb() : void 0;
  1040. };
  1041. })(this));
  1042. };
  1043. FilesResult.prototype.setFilter = function(filter, cb) {
  1044. this.filter_inner_path = filter;
  1045. return this.updateFiles(cb);
  1046. };
  1047. FilesResult.prototype.getHref = function(row) {
  1048. return row.inner_path;
  1049. };
  1050. FilesResult.prototype.render = function() {
  1051. if (Page.server_info.rev < 4120) {
  1052. return h("div.empty", [h("h4", "Feature not supported"), h("small", "You need to update to the latest version to use this feature")]);
  1053. }
  1054. if (!this.filter_inner_path) {
  1055. return [];
  1056. }
  1057. if (!this.files.items.length) {
  1058. return h("div.empty", [h("h4", "Filter result: " + this.filter_inner_path), h("small", "No files found")]);
  1059. }
  1060. return h("div.site", [h("div.title", [h("h3.name", "Filter result: " + this.filter_inner_path)]), this.files.render()]);
  1061. };
  1062. return FilesResult;
  1063. })(Class);
  1064. window.FilesResult = FilesResult;
  1065. }).call(this);
  1066. /* ---- PageFiles/PageFiles.coffee ---- */
  1067. (function() {
  1068. var PageFiles,
  1069. bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
  1070. extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
  1071. hasProp = {}.hasOwnProperty;
  1072. PageFiles = (function(superClass) {
  1073. extend(PageFiles, superClass);
  1074. function PageFiles() {
  1075. this.onSiteInfo = bind(this.onSiteInfo, this);
  1076. this.render = bind(this.render, this);
  1077. this.updateAllFiles = bind(this.updateAllFiles, this);
  1078. this.updateOptionalStats = bind(this.updateOptionalStats, this);
  1079. this.renderFilter = bind(this.renderFilter, this);
  1080. this.handleFilterKeyup = bind(this.handleFilterKeyup, this);
  1081. this.handleFilterInput = bind(this.handleFilterInput, this);
  1082. this.renderSelectbar = bind(this.renderSelectbar, this);
  1083. this.renderTotalbar = bind(this.renderTotalbar, this);
  1084. this.handleLimitInput = bind(this.handleLimitInput, this);
  1085. this.handleTotalbarMenu = bind(this.handleTotalbarMenu, this);
  1086. this.handleLimitSetClick = bind(this.handleLimitSetClick, this);
  1087. this.handleLimitCancelClick = bind(this.handleLimitCancelClick, this);
  1088. this.handleEditlimitClick = bind(this.handleEditlimitClick, this);
  1089. this.handleTotalbarOut = bind(this.handleTotalbarOut, this);
  1090. this.handleTotalbarOver = bind(this.handleTotalbarOver, this);
  1091. this.handleSelectbarDelete = bind(this.handleSelectbarDelete, this);
  1092. this.handleSelectbarUnpin = bind(this.handleSelectbarUnpin, this);
  1093. this.handleSelectbarPin = bind(this.handleSelectbarPin, this);
  1094. this.handleSelectbarCancel = bind(this.handleSelectbarCancel, this);
  1095. this.checkSelectedFiles = bind(this.checkSelectedFiles, this);
  1096. this.getSites = bind(this.getSites, this);
  1097. this.need_update = true;
  1098. this.updating_files = 0;
  1099. this.optional_stats = {
  1100. limit: "0",
  1101. free: "0",
  1102. used: "0"
  1103. };
  1104. this.updateOptionalStats();
  1105. this.hover_totalbar = false;
  1106. this.menu_totalbar = new Menu();
  1107. this.editing_limit = false;
  1108. this.limit = "";
  1109. this.selected_files_num = 0;
  1110. this.selected_files_size = 0;
  1111. this.selected_files_pinned = 0;
  1112. this.bigfiles = new Bigfiles();
  1113. this.result = new FilesResult();
  1114. this.display_limit = 0;
  1115. this.filtering = "";
  1116. this;
  1117. }
  1118. PageFiles.prototype.getSites = function() {
  1119. if (this.result.filter_inner_path) {
  1120. return this.result.files.getSites();
  1121. }
  1122. if (this.bigfiles.files.items.length > 0) {
  1123. return this.bigfiles.files.getSites().concat(Page.site_list.sites);
  1124. } else {
  1125. return Page.site_list.sites;
  1126. }
  1127. };
  1128. PageFiles.prototype.checkSelectedFiles = function() {
  1129. var i, len, ref, results, site, site_file;
  1130. this.selected_files_num = 0;
  1131. this.selected_files_size = 0;
  1132. this.selected_files_pinned = 0;
  1133. ref = this.getSites();
  1134. results = [];
  1135. for (i = 0, len = ref.length; i < len; i++) {
  1136. site = ref[i];
  1137. results.push((function() {
  1138. var j, len1, ref1, results1;
  1139. ref1 = site.files.items;
  1140. results1 = [];
  1141. for (j = 0, len1 = ref1.length; j < len1; j++) {
  1142. site_file = ref1[j];
  1143. if (!site.files.selected[site_file.inner_path]) {
  1144. continue;
  1145. }
  1146. this.selected_files_num += 1;
  1147. this.selected_files_size += site_file.size;
  1148. results1.push(this.selected_files_pinned += site_file.is_pinned);
  1149. }
  1150. return results1;
  1151. }).call(this));
  1152. }
  1153. return results;
  1154. };
  1155. PageFiles.prototype.handleSelectbarCancel = function() {
  1156. var i, j, key, len, len1, ref, ref1, ref2, site, site_file, val;
  1157. ref = this.getSites();
  1158. for (i = 0, len = ref.length; i < len; i++) {
  1159. site = ref[i];
  1160. ref1 = site.files.items;
  1161. for (j = 0, len1 = ref1.length; j < len1; j++) {
  1162. site_file = ref1[j];
  1163. ref2 = site.files.selected;
  1164. for (key in ref2) {
  1165. val = ref2[key];
  1166. delete site.files.selected[key];
  1167. }
  1168. }
  1169. }
  1170. this.checkSelectedFiles();
  1171. Page.projector.scheduleRender();
  1172. return false;
  1173. };
  1174. PageFiles.prototype.handleSelectbarPin = function() {
  1175. var i, inner_paths, len, ref, site, site_file;
  1176. ref = this.getSites();
  1177. for (i = 0, len = ref.length; i < len; i++) {
  1178. site = ref[i];
  1179. inner_paths = (function() {
  1180. var j, len1, ref1, results;
  1181. ref1 = site.files.items;
  1182. results = [];
  1183. for (j = 0, len1 = ref1.length; j < len1; j++) {
  1184. site_file = ref1[j];
  1185. if (site.files.selected[site_file.inner_path]) {
  1186. results.push(site_file.inner_path);
  1187. }
  1188. }
  1189. return results;
  1190. })();
  1191. if (inner_paths.length > 0) {
  1192. (function(site) {
  1193. return Page.cmd("optionalFilePin", [inner_paths, site.row.address], function() {
  1194. return site.files.update();
  1195. });
  1196. })(site);
  1197. }
  1198. }
  1199. return this.handleSelectbarCancel();
  1200. };
  1201. PageFiles.prototype.handleSelectbarUnpin = function() {
  1202. var i, inner_paths, len, ref, site, site_file;
  1203. ref = this.getSites();
  1204. for (i = 0, len = ref.length; i < len; i++) {
  1205. site = ref[i];
  1206. inner_paths = (function() {
  1207. var j, len1, ref1, results;
  1208. ref1 = site.files.items;
  1209. results = [];
  1210. for (j = 0, len1 = ref1.length; j < len1; j++) {
  1211. site_file = ref1[j];
  1212. if (site.files.selected[site_file.inner_path]) {
  1213. results.push(site_file.inner_path);
  1214. }
  1215. }
  1216. return results;
  1217. })();
  1218. if (inner_paths.length > 0) {
  1219. (function(site) {
  1220. return Page.cmd("optionalFileUnpin", [inner_paths, site.row.address], function() {
  1221. return site.files.update();
  1222. });
  1223. })(site);
  1224. }
  1225. }
  1226. return this.handleSelectbarCancel();
  1227. };
  1228. PageFiles.prototype.handleSelectbarDelete = function() {
  1229. var i, inner_path, inner_paths, j, len, len1, ref, site, site_file;
  1230. ref = this.getSites();
  1231. for (i = 0, len = ref.length; i < len; i++) {
  1232. site = ref[i];
  1233. inner_paths = (function() {
  1234. var j, len1, ref1, results;
  1235. ref1 = site.files.items;
  1236. results = [];
  1237. for (j = 0, len1 = ref1.length; j < len1; j++) {
  1238. site_file = ref1[j];
  1239. if (site.files.selected[site_file.inner_path]) {
  1240. results.push(site_file.inner_path);
  1241. }
  1242. }
  1243. return results;
  1244. })();
  1245. if (inner_paths.length > 0) {
  1246. for (j = 0, len1 = inner_paths.length; j < len1; j++) {
  1247. inner_path = inner_paths[j];
  1248. Page.cmd("optionalFileDelete", [inner_path, site.row.address]);
  1249. }
  1250. site.files.update();
  1251. }
  1252. }
  1253. Page.site_list.update();
  1254. return this.handleSelectbarCancel();
  1255. };
  1256. PageFiles.prototype.handleTotalbarOver = function() {
  1257. this.hover_totalbar = true;
  1258. return Page.projector.scheduleRender();
  1259. };
  1260. PageFiles.prototype.handleTotalbarOut = function() {
  1261. this.hover_totalbar = false;
  1262. return Page.projector.scheduleRender();
  1263. };
  1264. PageFiles.prototype.handleEditlimitClick = function() {
  1265. this.editing_limit = true;
  1266. return false;
  1267. };
  1268. PageFiles.prototype.handleLimitCancelClick = function() {
  1269. this.editing_limit = false;
  1270. return false;
  1271. };
  1272. PageFiles.prototype.handleLimitSetClick = function() {
  1273. var limit;
  1274. if (this.limit.indexOf("M") > 0 || this.limit.indexOf("m") > 0) {
  1275. limit = (parseFloat(this.limit) / 1024).toString();
  1276. } else if (this.limit.indexOf("%") > 0) {
  1277. limit = parseFloat(this.limit) + "%";
  1278. } else {
  1279. limit = parseFloat(this.limit).toString();
  1280. }
  1281. this.optional_stats.limit = limit;
  1282. Page.cmd("optionalLimitSet", limit);
  1283. this.editing_limit = false;
  1284. return false;
  1285. };
  1286. PageFiles.prototype.handleTotalbarMenu = function() {
  1287. this.menu_totalbar.items = [];
  1288. this.menu_totalbar.items.push(["Edit optional files limit", this.handleEditlimitClick]);
  1289. if (this.menu_totalbar.visible) {
  1290. this.menu_totalbar.hide();
  1291. } else {
  1292. this.menu_totalbar.show();
  1293. }
  1294. return false;
  1295. };
  1296. PageFiles.prototype.handleLimitInput = function(e) {
  1297. return this.limit = e.target.value;
  1298. };
  1299. PageFiles.prototype.renderTotalbar = function() {
  1300. /*
  1301. size_optional = 0
  1302. optional_downloaded = 0
  1303. for site in Page.site_list.sites
  1304. size_optional += site.row.settings.size_optional
  1305. optional_downloaded += site.row.settings.optional_downloaded
  1306. */
  1307. var limit, percent_limit, percent_optional_downloaded, percent_optional_used, total_space_limited;
  1308. if (this.editing_limit && parseFloat(this.limit) > 0) {
  1309. if (this.limit.indexOf("M") > 0 || this.limit.indexOf("m") > 0) {
  1310. limit = (parseFloat(this.limit) / 1024) + "GB";
  1311. } else {
  1312. limit = this.limit;
  1313. }
  1314. } else {
  1315. limit = this.optional_stats.limit;
  1316. }
  1317. if (limit.endsWith("%")) {
  1318. limit = this.optional_stats.free * (parseFloat(limit) / 100);
  1319. } else {
  1320. limit = parseFloat(limit) * 1024 * 1024 * 1024;
  1321. }
  1322. if (this.optional_stats.free > limit * 1.8 && !this.hover_totalbar) {
  1323. total_space_limited = limit * 1.8;
  1324. } else {
  1325. total_space_limited = this.optional_stats.free;
  1326. }
  1327. percent_optional_downloaded = (this.optional_stats.used / limit) * 100;
  1328. percent_optional_used = percent_optional_downloaded * (limit / total_space_limited);
  1329. percent_limit = (limit / total_space_limited) * 100;
  1330. return h("div#PageFilesDashboard", {
  1331. classes: {
  1332. editing: this.editing_limit
  1333. }
  1334. }, [
  1335. h("div.totalbar-edit", [
  1336. h("span.title", "Optional files limit:"), h("input", {
  1337. type: "text",
  1338. value: this.limit,
  1339. oninput: this.handleLimitInput
  1340. }), h("a.set", {
  1341. href: "#",
  1342. onclick: this.handleLimitSetClick
  1343. }, "Set"), h("a.cancel", {
  1344. href: "#",
  1345. onclick: this.handleLimitCancelClick
  1346. }, "Cancel")
  1347. ]), h("a.totalbar-title", {
  1348. href: "#",
  1349. title: "Space current used by optional files",
  1350. onclick: this.handleTotalbarMenu
  1351. }, "Used: " + (Text.formatSize(this.optional_stats.used)) + " / " + (Text.formatSize(limit)) + " (" + (Math.round(percent_optional_downloaded)) + "%)", h("div.icon-arrow-down")), this.menu_totalbar.render(), h("div.totalbar", {
  1352. onmouseover: this.handleTotalbarOver,
  1353. onmouseout: this.handleTotalbarOut
  1354. }, h("div.totalbar-used", {
  1355. style: "width: " + percent_optional_used + "%"
  1356. }), h("div.totalbar-limitbar", {
  1357. style: "width: " + percent_limit + "%"
  1358. }), h("div.totalbar-limit", {
  1359. style: "margin-left: " + percent_limit + "%"
  1360. }, h("span", {
  1361. title: "Space allowed to used by optional files"
  1362. }, Text.formatSize(limit))), h("div.totalbar-hddfree", h("span", {
  1363. title: "Total free space on your storage"
  1364. }, [
  1365. Text.formatSize(this.optional_stats.free), h("div.arrow", {
  1366. style: this.optional_stats.free > total_space_limited ? "width: 10px" : "width: 0px"
  1367. }, " \u25B6")
  1368. ])))
  1369. ]);
  1370. };
  1371. PageFiles.prototype.renderSelectbar = function() {
  1372. return h("div.selectbar", {
  1373. classes: {
  1374. visible: this.selected_files_num > 0
  1375. }
  1376. }, [
  1377. "Selected:", h("span.info", [h("span.num", this.selected_files_num + " files"), h("span.size", "(" + (Text.formatSize(this.selected_files_size)) + ")")]), h("div.actions", [
  1378. this.selected_files_pinned > this.selected_files_num / 2 ? h("a.action.pin.unpin", {
  1379. href: "#",
  1380. onclick: this.handleSelectbarUnpin
  1381. }, "UnPin") : h("a.action.pin", {
  1382. href: "#",
  1383. title: "Don't delete these files automatically",
  1384. onclick: this.handleSelectbarPin
  1385. }, "Pin"), h("a.action.delete", {
  1386. href: "#",
  1387. onclick: this.handleSelectbarDelete
  1388. }, "Delete")
  1389. ]), h("a.cancel.link", {
  1390. href: "#",
  1391. onclick: this.handleSelectbarCancel
  1392. }, "Cancel")
  1393. ]);
  1394. };
  1395. PageFiles.prototype.handleFilterInput = function(e) {
  1396. if (this.input_timer) {
  1397. clearInterval(this.input_timer);
  1398. }
  1399. this.filtering = e.target.value;
  1400. return this.input_timer = setTimeout(((function(_this) {
  1401. return function() {
  1402. return RateLimitCb(600, function(cb_done) {
  1403. return _this.result.setFilter(_this.filtering, function() {
  1404. _this.checkSelectedFiles();
  1405. return cb_done();
  1406. });
  1407. });
  1408. };
  1409. })(this)), 300);
  1410. };
  1411. PageFiles.prototype.handleFilterKeyup = function(e) {
  1412. if (e.keyCode === 27) {
  1413. e.target.value = "";
  1414. this.handleFilterInput(e);
  1415. }
  1416. return false;
  1417. };
  1418. PageFiles.prototype.renderFilter = function() {
  1419. return h("div.filter", [
  1420. h("input.text", {
  1421. placeholder: "Filter: File name",
  1422. spellcheck: false,
  1423. oninput: this.handleFilterInput,
  1424. onkeyup: this.handleFilterKeyup,
  1425. value: this.filtering
  1426. })
  1427. ]);
  1428. };
  1429. PageFiles.prototype.updateOptionalStats = function() {
  1430. return Page.cmd("optionalLimitStats", [], (function(_this) {
  1431. return function(res) {
  1432. _this.limit = res.limit;
  1433. if (!_this.limit.endsWith("%")) {
  1434. _this.limit += " GB";
  1435. }
  1436. return _this.optional_stats = res;
  1437. };
  1438. })(this));
  1439. };
  1440. PageFiles.prototype.updateAllFiles = function() {
  1441. var used;
  1442. this.updating_files = 0;
  1443. used = 0;
  1444. Page.site_list.sites.map((function(_this) {
  1445. return function(site) {
  1446. if (!site.row.settings.size_optional) {
  1447. return;
  1448. }
  1449. _this.updating_files += 1;
  1450. used += site.row.settings.optional_downloaded;
  1451. return site.files.update(function() {
  1452. return _this.updating_files -= 1;
  1453. });
  1454. };
  1455. })(this));
  1456. this.updating_files += 1;
  1457. return this.bigfiles.files.update((function(_this) {
  1458. return function() {
  1459. return _this.updating_files -= 1;
  1460. };
  1461. })(this));
  1462. };
  1463. PageFiles.prototype.render = function() {
  1464. var site, sites, sites_connected, sites_favorited;
  1465. if (Page.site_list.sites && !this.need_update && this.updating_files === 0 && document.body.className !== "loaded") {
  1466. document.body.classList.add("loaded");
  1467. }
  1468. if (this.need_update && Page.site_list.sites.length) {
  1469. this.updateAllFiles();
  1470. this.need_update = false;
  1471. }
  1472. sites = (function() {
  1473. var i, len, ref, results;
  1474. ref = Page.site_list.sites;
  1475. results = [];
  1476. for (i = 0, len = ref.length; i < len; i++) {
  1477. site = ref[i];
  1478. if (site.row.settings.size_optional) {
  1479. results.push(site);
  1480. }
  1481. }
  1482. return results;
  1483. })();
  1484. sites_favorited = (function() {
  1485. var i, len, results;
  1486. results = [];
  1487. for (i = 0, len = sites.length; i < len; i++) {
  1488. site = sites[i];
  1489. if (site.favorite) {
  1490. results.push(site);
  1491. }
  1492. }
  1493. return results;
  1494. })();
  1495. sites_connected = (function() {
  1496. var i, len, results;
  1497. results = [];
  1498. for (i = 0, len = sites.length; i < len; i++) {
  1499. site = sites[i];
  1500. if (!site.favorite) {
  1501. results.push(site);
  1502. }
  1503. }
  1504. return results;
  1505. })();
  1506. if (sites.length > 0 && sites[0].files.loaded === false) {
  1507. if (sites_favorited.length) {
  1508. sites_favorited = [sites_favorited[0]];
  1509. sites_connected = [];
  1510. } else {
  1511. sites_favorited = [];
  1512. sites_connected = [sites_connected[0]];
  1513. }
  1514. }
  1515. if (sites.length === 0) {
  1516. document.body.classList.add("loaded");
  1517. return h("div#PageFiles", this.renderSelectbar(), this.renderTotalbar(), h("div.empty", [h("h4", "Hello newcomer!"), h("small", "You have not downloaded any optional files yet")]));
  1518. }
  1519. if (this.display_limit < sites.length) {
  1520. setTimeout(((function(_this) {
  1521. return function() {
  1522. _this.display_limit += 1;
  1523. return Page.projector.scheduleRender();
  1524. };
  1525. })(this)), 1000);
  1526. }
  1527. return h("div#PageFiles", [
  1528. this.renderSelectbar(), this.renderTotalbar(), this.renderFilter(), this.result.filter_inner_path ? this.result.render() : (this.bigfiles.render(), sites_favorited.slice(0, +this.display_limit + 1 || 9e9).map((function(_this) {
  1529. return function(site) {
  1530. return site.renderOptionalStats();
  1531. };
  1532. })(this)), sites_connected.slice(0, +this.display_limit + 1 || 9e9).map((function(_this) {
  1533. return function(site) {
  1534. return site.renderOptionalStats();
  1535. };
  1536. })(this)))
  1537. ]);
  1538. };
  1539. PageFiles.prototype.onSiteInfo = function(site_info) {
  1540. var rate_limit, ref, ref1;
  1541. if (((ref = site_info.event) != null ? ref[0] : void 0) === "peers_added") {
  1542. return false;
  1543. }
  1544. if (site_info.tasks === 0 && ((ref1 = site_info.event) != null ? ref1[0] : void 0) === "file_done") {
  1545. rate_limit = 1000;
  1546. } else {
  1547. rate_limit = 10000;
  1548. }
  1549. return RateLimit(rate_limit, (function(_this) {
  1550. return function() {
  1551. return _this.need_update = true;
  1552. };
  1553. })(this));
  1554. };
  1555. return PageFiles;
  1556. })(Class);
  1557. window.PageFiles = PageFiles;
  1558. }).call(this);
  1559. /* ---- PageFiles/SiteFiles.coffee ---- */
  1560. (function() {
  1561. var SiteFiles,
  1562. bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
  1563. extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
  1564. hasProp = {}.hasOwnProperty;
  1565. SiteFiles = (function(superClass) {
  1566. extend(SiteFiles, superClass);
  1567. function SiteFiles(site1) {
  1568. this.site = site1;
  1569. this.update = bind(this.update, this);
  1570. this.render = bind(this.render, this);
  1571. this.renderOrderRight = bind(this.renderOrderRight, this);
  1572. this.renderOrder = bind(this.renderOrder, this);
  1573. this.handleMoreClick = bind(this.handleMoreClick, this);
  1574. this.handleOrderbyClick = bind(this.handleOrderbyClick, this);
  1575. this.handleRowMouseenter = bind(this.handleRowMouseenter, this);
  1576. this.handleSelectMousedown = bind(this.handleSelectMousedown, this);
  1577. this.handleSelectEnd = bind(this.handleSelectEnd, this);
  1578. this.handleSelectClick = bind(this.handleSelectClick, this);
  1579. this.getSites = bind(this.getSites, this);
  1580. this.limit = 10;
  1581. this.selected = {};
  1582. this.items = [];
  1583. this.loaded = false;
  1584. this.orderby = "time_downloaded";
  1585. this.mode = "site";
  1586. this.mode = "single_site";
  1587. this.orderby_desc = true;
  1588. this.has_more = false;
  1589. }
  1590. SiteFiles.prototype.getSites = function() {
  1591. var address, back, file, i, len, name, ref, site, sites;
  1592. back = [];
  1593. sites = {};
  1594. ref = this.items;
  1595. for (i = 0, len = ref.length; i < len; i++) {
  1596. file = ref[i];
  1597. if (sites[name = file.site.row.address] == null) {
  1598. sites[name] = {
  1599. row: file.site.row,
  1600. files: {
  1601. items: [],
  1602. selected: this.selected,
  1603. update: this.update
  1604. }
  1605. };
  1606. }
  1607. sites[file.site.row.address].files.items.push(file);
  1608. }
  1609. for (address in sites) {
  1610. site = sites[address];
  1611. back.push(site);
  1612. }
  1613. return back;
  1614. };
  1615. SiteFiles.prototype.handleSelectClick = function(e) {
  1616. return false;
  1617. };
  1618. SiteFiles.prototype.handleSelectEnd = function(e) {
  1619. document.body.removeEventListener('mouseup', this.handleSelectEnd);
  1620. return this.select_action = null;
  1621. };
  1622. SiteFiles.prototype.handleSelectMousedown = function(e) {
  1623. var inner_path;
  1624. inner_path = e.currentTarget.attributes.inner_path.value;
  1625. if (this.selected[inner_path]) {
  1626. delete this.selected[inner_path];
  1627. this.select_action = "deselect";
  1628. } else {
  1629. this.selected[inner_path] = true;
  1630. this.select_action = "select";
  1631. }
  1632. Page.page_files.checkSelectedFiles();
  1633. document.body.addEventListener('mouseup', this.handleSelectEnd);
  1634. e.stopPropagation();
  1635. Page.projector.scheduleRender();
  1636. return false;
  1637. };
  1638. SiteFiles.prototype.handleRowMouseenter = function(e) {
  1639. var inner_path;
  1640. if (e.buttons && this.select_action) {
  1641. inner_path = e.target.attributes.inner_path.value;
  1642. if (this.select_action === "select") {
  1643. this.selected[inner_path] = true;
  1644. } else {
  1645. delete this.selected[inner_path];
  1646. }
  1647. Page.page_files.checkSelectedFiles();
  1648. Page.projector.scheduleRender();
  1649. }
  1650. return false;
  1651. };
  1652. SiteFiles.prototype.handleOrderbyClick = function(e) {
  1653. var orderby;
  1654. orderby = e.currentTarget.attributes.orderby.value;
  1655. if (this.orderby === orderby) {
  1656. this.orderby_desc = !this.orderby_desc;
  1657. }
  1658. this.orderby = orderby;
  1659. this.update();
  1660. Page.projector.scheduleRender();
  1661. return false;
  1662. };
  1663. SiteFiles.prototype.handleMoreClick = function() {
  1664. this.limit += 15;
  1665. this.update();
  1666. return false;
  1667. };
  1668. SiteFiles.prototype.renderOrder = function(title, orderby) {
  1669. return h("a.title.orderby", {
  1670. href: "#" + orderby,
  1671. orderby: orderby,
  1672. onclick: this.handleOrderbyClick,
  1673. classes: {
  1674. selected: this.orderby === orderby,
  1675. desc: this.orderby_desc
  1676. }
  1677. }, [title, h("div.icon.icon-arrow-down")]);
  1678. };
  1679. SiteFiles.prototype.renderOrderRight = function(title, orderby) {
  1680. return h("a.title.orderby", {
  1681. href: "#" + orderby,
  1682. orderby: orderby,
  1683. onclick: this.handleOrderbyClick,
  1684. classes: {
  1685. selected: this.orderby === orderby,
  1686. desc: this.orderby_desc
  1687. }
  1688. }, [h("div.icon.icon-arrow-down"), title]);
  1689. };
  1690. SiteFiles.prototype.render = function() {
  1691. var ref;
  1692. if (!((ref = this.items) != null ? ref.length : void 0)) {
  1693. return [];
  1694. }
  1695. return [
  1696. h("div.files.files-" + this.mode, {
  1697. exitAnimation: Animation.slideUpInout
  1698. }, [
  1699. h("div.tr.thead", [h("div.td.pre", "."), this.mode === "bigfiles" || this.mode === "result" ? h("div.td.site", this.renderOrder("Site", "address")) : void 0, h("div.td.inner_path", this.renderOrder("Optional file", "is_pinned DESC, inner_path")), this.mode === "bigfiles" ? h("div.td.status", "Status") : void 0, h("div.td.size", this.renderOrderRight("Size", "size")), h("div.td.peer", this.renderOrder("Peers", "peer")), h("div.td.uploaded", this.renderOrder("Uploaded", "uploaded")), h("div.td.added", this.renderOrder("Finished", "time_downloaded"))]), h("div.tbody", this.items.map((function(_this) {
  1700. return function(file) {
  1701. var classes, percent, percent_bg, percent_title, profile_color, site, status;
  1702. site = file.site || _this.site;
  1703. if (file.peer >= 10) {
  1704. profile_color = "#47d094";
  1705. } else if (file.peer > 0) {
  1706. profile_color = "#f5b800";
  1707. } else {
  1708. profile_color = "#d1d1d1";
  1709. }
  1710. if (_this.mode === "bigfiles") {
  1711. if (file.pieces == null) {
  1712. file.pieces = 0;
  1713. }
  1714. if (file.pieces_downloaded == null) {
  1715. file.pieces_downloaded = 0;
  1716. }
  1717. if (file.pieces === 0 || file.pieces_downloaded === 0) {
  1718. percent = 0;
  1719. } else {
  1720. percent = parseInt((file.pieces_downloaded / file.pieces) * 100);
  1721. }
  1722. if (file.is_downloading || percent === 100) {
  1723. status = "";
  1724. percent_bg = "#9ef5cf";
  1725. } else {
  1726. status = "paused";
  1727. percent_bg = "#f5f49e";
  1728. }
  1729. percent_title = percent + "% " + status;
  1730. }
  1731. classes = {
  1732. selected: _this.selected[file.inner_path],
  1733. pinned: file.is_pinned
  1734. };
  1735. return h("div.tr", {
  1736. key: file.inner_path,
  1737. inner_path: file.inner_path,
  1738. exitAnimation: Animation.slideUpInout,
  1739. enterAnimation: Animation.slideDown,
  1740. classes: classes,
  1741. onmouseenter: _this.handleRowMouseenter
  1742. }, [
  1743. h("div.td.pre", h("a.checkbox-outer", {
  1744. href: "#Select",
  1745. onmousedown: _this.handleSelectMousedown,
  1746. onclick: _this.handleSelectClick,
  1747. inner_path: file.inner_path
  1748. }, h("span.checkbox"))), _this.mode === "bigfiles" || _this.mode === "result" ? h("div.td.site", h("a.link", {
  1749. href: site.getHref()
  1750. }, site.row.content.title)) : void 0, h("div.td.inner_path", h("a.title.link", {
  1751. href: site.getHref(file),
  1752. target: "_blank",
  1753. title: file.inner_path.replace(/.*\//, "")
  1754. }, file.inner_path.replace(/.*\//, "")), file.is_pinned ? h("span.pinned", {
  1755. exitAnimation: Animation.slideUpInout,
  1756. enterAnimation: Animation.slideDown
  1757. }, "Pinned") : void 0), _this.mode === "bigfiles" ? h("div.td.status", {
  1758. classes: {
  1759. "downloading": file.is_downloading
  1760. }
  1761. }, h("span.percent", {
  1762. title: file.pieces_downloaded + " of " + file.pieces + " pieces downloaded",
  1763. style: "box-shadow: inset " + (percent * 0.8) + "px 0px 0px " + percent_bg + ";"
  1764. }, percent_title)) : void 0, h("div.td.size", Text.formatSize(file.size)), h("div.td.peer", [
  1765. h("div.icon.icon-profile", {
  1766. style: "color: " + profile_color
  1767. }), h("span.num", file.peer)
  1768. ]), h("div.td.uploaded", h("div.uploaded-text", Text.formatSize(file.uploaded)), h("div.dots-container", [
  1769. h("span.dots.dots-bg", {
  1770. title: "Ratio: " + ((file.uploaded / file.size).toFixed(1))
  1771. }, "\u2022\u2022\u2022\u2022\u2022"), h("span.dots.dots-fg", {
  1772. title: "Ratio: " + ((file.uploaded / file.size).toFixed(1)),
  1773. style: "width: " + (Math.min(5, file.uploaded / file.size) * 9) + "px"
  1774. }, "\u2022\u2022\u2022\u2022\u2022")
  1775. ])), h("div.td.added", file.time_downloaded ? Time.since(file.time_downloaded) : "n/a")
  1776. ]);
  1777. };
  1778. })(this)))
  1779. ]), this.has_more ? h("div.more-container", h("a.more", {
  1780. href: "#More",
  1781. onclick: this.handleMoreClick
  1782. }, "More files...")) : void 0
  1783. ];
  1784. };
  1785. SiteFiles.prototype.update = function(cb) {
  1786. var orderby;
  1787. orderby = this.orderby + (this.orderby_desc ? " DESC" : "");
  1788. return Page.cmd("optionalFileList", {
  1789. address: this.site.row.address,
  1790. limit: this.limit + 1,
  1791. orderby: orderby
  1792. }, (function(_this) {
  1793. return function(res) {
  1794. _this.items = res.slice(0, +(_this.limit - 1) + 1 || 9e9);
  1795. _this.loaded = true;
  1796. _this.has_more = res.length > _this.limit;
  1797. Page.projector.scheduleRender();
  1798. return typeof cb === "function" ? cb() : void 0;
  1799. };
  1800. })(this));
  1801. };
  1802. return SiteFiles;
  1803. })(Class);
  1804. window.SiteFiles = SiteFiles;
  1805. }).call(this);
  1806. /* ---- PageSites/Dashboard.coffee ---- */
  1807. (function() {
  1808. var Dashboard,
  1809. bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
  1810. extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
  1811. hasProp = {}.hasOwnProperty,
  1812. indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
  1813. Dashboard = (function(superClass) {
  1814. extend(Dashboard, superClass);
  1815. function Dashboard() {
  1816. this.render = bind(this.render, this);
  1817. this.getWarnings = bind(this.getWarnings, this);
  1818. this.handleWarningsClick = bind(this.handleWarningsClick, this);
  1819. this.handleTrackersClick = bind(this.handleTrackersClick, this);
  1820. this.handleNewversionClick = bind(this.handleNewversionClick, this);
  1821. this.handleLogoutClick = bind(this.handleLogoutClick, this);
  1822. this.handleDonateClick = bind(this.handleDonateClick, this);
  1823. this.handleMultiuserClick = bind(this.handleMultiuserClick, this);
  1824. this.handlePortRecheckClick = bind(this.handlePortRecheckClick, this);
  1825. this.handlePortClick = bind(this.handlePortClick, this);
  1826. this.handleDisableAlwaysTorClick = bind(this.handleDisableAlwaysTorClick, this);
  1827. this.handleEnableAlwaysTorClick = bind(this.handleEnableAlwaysTorClick, this);
  1828. this.handleTorClick = bind(this.handleTorClick, this);
  1829. this.menu_newversion = new Menu();
  1830. this.menu_port = new Menu();
  1831. this.menu_tor = new Menu();
  1832. this.menu_trackers = new Menu();
  1833. this.menu_multiuser = new Menu();
  1834. this.menu_donate = new Menu();
  1835. this.menu_warnings = new Menu();
  1836. this.port_checking = false;
  1837. this.has_web_gl = null;
  1838. Page.cmd('wrapperPermissionAdd', 'ADMIN')
  1839. }
  1840. Dashboard.prototype.isTorAlways = function() {
  1841. return Page.server_info.fileserver_ip === "127.0.0.1";
  1842. };
  1843. Dashboard.prototype.hasWebGl = function() {
  1844. var canvas, ctx;
  1845. if (this.has_web_gl === null) {
  1846. canvas = document.createElement('canvas');
  1847. ctx = canvas.getContext("webgl");
  1848. this.has_web_gl = ctx ? true : false;
  1849. this.log("Webgl:", this.has_web_gl);
  1850. }
  1851. return this.has_web_gl;
  1852. };
  1853. Dashboard.prototype.getTorTitle = function() {
  1854. var tor_title;
  1855. tor_title = Page.server_info.tor_status.replace(/\((.*)\)/, "").trim();
  1856. if (tor_title === "Disabled") {
  1857. tor_title = _("Disabled");
  1858. } else if (tor_title === "Error") {
  1859. tor_title = _("Error");
  1860. }
  1861. return tor_title;
  1862. };
  1863. Dashboard.prototype.tagTrackersTitle = function() {
  1864. var key, num_ok, num_total, stats, status_db, title, val;
  1865. if (Page.server_info.offline) {
  1866. return h("span.status.status-warning", "n/a");
  1867. }
  1868. num_ok = 0;
  1869. num_total = 0;
  1870. status_db = {
  1871. announcing: [],
  1872. error: [],
  1873. announced: []
  1874. };
  1875. if (Page.announcer_stats) {
  1876. stats = Page.announcer_stats;
  1877. } else {
  1878. stats = Page.announcer_info;
  1879. }
  1880. for (key in stats) {
  1881. val = stats[key];
  1882. if (val.status === "announced") {
  1883. num_ok += 1;
  1884. }
  1885. num_total += 1;
  1886. }
  1887. title = num_ok + "/" + num_total;
  1888. if (num_total === 0) {
  1889. return h("span.status", "Waiting...");
  1890. } else if (num_ok > num_total / 2) {
  1891. return h("span.status.status-ok", title);
  1892. } else if (num_ok > 0) {
  1893. return h("span.status.status-warning", title);
  1894. } else {
  1895. return h("span.status.status-error", title);
  1896. }
  1897. };
  1898. Dashboard.prototype.handleTorClick = function() {
  1899. var ref;
  1900. this.menu_tor.items = [];
  1901. this.menu_tor.items.push(["Status: " + ((ref = Page.server_info) != null ? ref.tor_status : void 0), Text.getSiteUrl("1DocsYf2tZVVMEMJFHiDsppmFicZCWkVv1") + "faq/#how-to-make-zeronet-work-with-tor-under-linux"]);
  1902. if (this.getTorTitle() !== "OK") {
  1903. this.menu_tor.items.push(["How to make Tor connection work?", Text.getSiteUrl("1DocsYf2tZVVMEMJFHiDsppmFicZCWkVv1") + "faq/#how-to-make-zeronet-work-with-tor-under-linux"]);
  1904. }
  1905. this.menu_tor.items.push(["How to use ZeroNet in Tor Browser?", Text.getSiteUrl("1DocsYf2tZVVMEMJFHiDsppmFicZCWkVv1") + "faq/#how-to-use-zeronet-in-tor-browser"]);
  1906. this.menu_tor.items.push(["---"]);
  1907. if (this.isTorAlways()) {
  1908. this.menu_tor.items.push(["Disable always Tor mode", this.handleDisableAlwaysTorClick]);
  1909. } else {
  1910. this.menu_tor.items.push(["Enable Tor for every connection (slower)", this.handleEnableAlwaysTorClick]);
  1911. }
  1912. this.menu_tor.toggle();
  1913. return false;
  1914. };
  1915. Dashboard.prototype.handleEnableAlwaysTorClick = function() {
  1916. return Page.cmd("configSet", ["tor", "always"], (function(_this) {
  1917. return function(res) {
  1918. Page.cmd("wrapperNotification", ["done", "Tor always mode enabled, please restart your ZeroNet to make it work.<br>For your privacy switch to Tor browser and start a new profile by renaming the data directory."]);
  1919. return Page.cmd("wrapperConfirm", ["Restart ZeroNet client?", "Restart now"], function(res) {
  1920. if (res) {
  1921. return Page.cmd("serverShutdown", {
  1922. restart: true
  1923. });
  1924. }
  1925. });
  1926. };
  1927. })(this));
  1928. };
  1929. Dashboard.prototype.handleDisableAlwaysTorClick = function() {
  1930. return Page.cmd("configSet", ["tor", null], (function(_this) {
  1931. return function(res) {
  1932. return Page.cmd("wrapperNotification", ["done", "Tor always mode disabled, please restart your ZeroNet."]);
  1933. };
  1934. })(this));
  1935. };
  1936. Dashboard.prototype.handlePortClick = function() {
  1937. var format, port_opened;
  1938. this.menu_port.items = [];
  1939. if (Page.server_info.offline) {
  1940. this.menu_port.items.push(["Offline mode, network communication disabled.", "/Config"]);
  1941. } else if (Page.server_info.ip_external) {
  1942. this.menu_port.items.push(["Nice! Your port " + Page.server_info.fileserver_port + " is opened.", Text.getSiteUrl("1DocsYf2tZVVMEMJFHiDsppmFicZCWkVv1") + "faq/#do-i-need-to-have-a-port-opened"]);
  1943. } else if (this.isTorAlways()) {
  1944. this.menu_port.items.push(["Good, your port is always closed when using ZeroNet in Tor always mode.", Text.getSiteUrl("1DocsYf2tZVVMEMJFHiDsppmFicZCWkVv1") + "faq/#do-i-need-to-have-a-port-opened"]);
  1945. } else if (this.getTorTitle() === "OK") {
  1946. this.menu_port.items.push(["Your port " + Page.server_info.fileserver_port + " is closed, but your Tor gateway is running well.", Text.getSiteUrl("1DocsYf2tZVVMEMJFHiDsppmFicZCWkVv1") + "faq/#do-i-need-to-have-a-port-opened"]);
  1947. } else {
  1948. this.menu_port.items.push(["Your port " + Page.server_info.fileserver_port + " is closed. You are still fine, but for faster experience try open it.", Text.getSiteUrl("1DocsYf2tZVVMEMJFHiDsppmFicZCWkVv1") + "faq/#do-i-need-to-have-a-port-opened"]);
  1949. }
  1950. if (Page.server_info.port_opened) {
  1951. this.menu_port.items.push(["---"]);
  1952. port_opened = Page.server_info.port_opened;
  1953. format = {
  1954. "true": h("span.status.status-ok", "Opened"),
  1955. "false": h("span.status.status-warning", "Closed"),
  1956. "null": h("span.status.status-disabled", "Unsupported"),
  1957. undefined: h("span.status.status-disabled", "Checking...")
  1958. };
  1959. this.menu_port.items.push([["IPv4: ", format[port_opened.ipv4], ", IPv6: ", format[port_opened.ipv6]], null]);
  1960. }
  1961. this.menu_port.items.push(["---"]);
  1962. this.menu_port.items.push(["Re-check opened port", this.handlePortRecheckClick]);
  1963. this.menu_port.toggle();
  1964. return false;
  1965. };
  1966. Dashboard.prototype.handlePortRecheckClick = function() {
  1967. this.port_checking = true;
  1968. return Page.cmd("serverPortcheck", [], (function(_this) {
  1969. return function(res) {
  1970. _this.port_checking = false;
  1971. return Page.reloadServerInfo();
  1972. };
  1973. })(this));
  1974. };
  1975. Dashboard.prototype.handleMultiuserClick = function() {
  1976. this.menu_multiuser.items = [];
  1977. this.menu_multiuser.items.push([
  1978. "Show your masterseed", (function() {
  1979. return Page.cmd("userShowMasterSeed");
  1980. })
  1981. ]);
  1982. if (Page.server_info.multiuser_admin) {
  1983. this.menu_multiuser.items.push([
  1984. "Select user", (function() {
  1985. return Page.cmd("userSelectForm");
  1986. })
  1987. ]);
  1988. }
  1989. this.menu_multiuser.items.push([
  1990. "Logout", (function() {
  1991. return Page.cmd("userLogout");
  1992. })
  1993. ]);
  1994. this.menu_multiuser.toggle();
  1995. return false;
  1996. };
  1997. Dashboard.prototype.handleDonateClick = function() {
  1998. this.menu_donate.items = [];
  1999. this.menu_donate.items.push(["Join, participate and support development", "https://riza-committee.github.io/community/"]);
  2000. this.menu_donate.toggle();
  2001. return false;
  2002. };
  2003. Dashboard.prototype.handleLogoutClick = function() {
  2004. return Page.cmd("uiLogout");
  2005. };
  2006. Dashboard.prototype.handleNewversionClick = function() {
  2007. this.menu_newversion.items = [];
  2008. this.menu_newversion.items.push([
  2009. "Update ZeroNet", (function() {
  2010. return Page.updateZeronet();
  2011. })
  2012. ]);
  2013. this.menu_newversion.items.push(["Details of the update", Text.getSiteUrl("Blog.ZeroNetwork.bit")]);
  2014. this.menu_newversion.toggle();
  2015. return false;
  2016. };
  2017. Dashboard.prototype.handleTrackersClick = function() {
  2018. var request_taken, stat, stats, status, success_percent, title, title_text, tracker_name, tracker_url;
  2019. if (Page.announcer_stats) {
  2020. stats = Page.announcer_stats;
  2021. Page.reloadAnnouncerStats();
  2022. } else {
  2023. stats = Page.announcer_info;
  2024. }
  2025. this.menu_trackers.items = [];
  2026. for (tracker_url in stats) {
  2027. stat = stats[tracker_url];
  2028. tracker_name = tracker_url.replace(/(.*:\/\/.*?)[\/#].*/, "$1").replace(/:[0-9]+$/, "");
  2029. success_percent = parseInt((stat.num_success / stat.num_request) * 100);
  2030. if (isNaN(success_percent)) {
  2031. success_percent = "?";
  2032. }
  2033. status = stat.status.capitalize();
  2034. if (status === "Announced" && stat.time_request && stat.time_status) {
  2035. request_taken = stat.time_status - stat.time_request;
  2036. status += " in " + (request_taken.toFixed(2)) + "s";
  2037. }
  2038. title_text = "Requests: " + stat.num_request;
  2039. if (stat.last_error) {
  2040. title_text += ", Last error: " + stat.last_error + " (" + (Time.since(stat.time_last_error)) + ")";
  2041. }
  2042. title = [
  2043. tracker_name, h("span.tracker-status", {
  2044. title: title_text
  2045. }, status + " (" + success_percent + "% success)")
  2046. ];
  2047. this.menu_trackers.items.push([title, null]);
  2048. }
  2049. this.menu_trackers.toggle();
  2050. return false;
  2051. };
  2052. Dashboard.prototype.handleWarningsClick = function() {
  2053. var i, len, warning, warnings;
  2054. warnings = this.getWarnings();
  2055. this.menu_warnings.items = [];
  2056. for (i = 0, len = warnings.length; i < len; i++) {
  2057. warning = warnings[i];
  2058. this.menu_warnings.items.push([h("b.status-error", warning.title), warning.href]);
  2059. if (warning.descr) {
  2060. this.menu_warnings.items.push([warning.descr, warning.href]);
  2061. }
  2062. this.menu_warnings.items.push(["---"]);
  2063. }
  2064. this.menu_warnings.items.push([
  2065. "Restart ZeroNet client", (function(_this) {
  2066. return function() {
  2067. return Page.cmd("serverShutdown", {
  2068. restart: true
  2069. });
  2070. };
  2071. })(this)
  2072. ]);
  2073. this.menu_warnings.toggle();
  2074. return false;
  2075. };
  2076. Dashboard.prototype.getWarnings = function() {
  2077. var warnings;
  2078. warnings = [];
  2079. if (navigator.userAgent.match(/(\b(MS)?IE\s+|Trident\/7.0)/)) {
  2080. warnings.push({
  2081. title: "Unsupported browser",
  2082. href: "http://browsehappy.com/",
  2083. descr: "Internet Explorer is not fully supported browser by ZeroNet, please consider switching to Firefox, Chromium or other compatible browser"
  2084. });
  2085. }
  2086. if (this.isTorAlways() && (!navigator.userAgent.match(/(Firefox)/) || (navigator.maxTouchPoints != null) || (navigator.serviceWorker != null))) {
  2087. warnings.push({
  2088. title: "Your browser is not safe",
  2089. href: Text.getSiteUrl("1DocsYf2tZVVMEMJFHiDsppmFicZCWkVv1") + "faq/#how-to-use-zeronet-in-tor-browser",
  2090. descr: "To protect your anonymity you should use ZeroNet in the Tor browser."
  2091. });
  2092. }
  2093. if (Page.server_info.lib_verify_best === "btctools") {
  2094. warnings.push({
  2095. title: "Slow verification library",
  2096. href: "#",
  2097. descr: "To significantly reduce CPU usage install libsecp256k1 or OpenSSL"
  2098. });
  2099. }
  2100. if (Math.abs(Page.server_info.timecorrection) > 30) {
  2101. warnings.push({
  2102. title: ["Time out of sync: ", 0 - Page.server_info.timecorrection.toFixed(2), "s"],
  2103. href: "https://time.is",
  2104. descr: "Looks like your system time is out of sync. Other users may not see your posted content and other problems could happen."
  2105. });
  2106. }
  2107. if (Page.server_errors.length > 2) {
  2108. warnings = warnings.concat(Page.server_errors.slice(-2).reverse());
  2109. warnings.push({
  2110. title: (Page.server_errors.length - 2) + " more errors...",
  2111. href: "#ZeroNet:Console"
  2112. });
  2113. } else {
  2114. warnings = warnings.concat(Page.server_errors);
  2115. }
  2116. return warnings;
  2117. };
  2118. Dashboard.prototype.render = function() {
  2119. var tor_title, warnings;
  2120. if (Page.server_info) {
  2121. tor_title = this.getTorTitle();
  2122. warnings = this.getWarnings();
  2123. return h("div#Dashboard", warnings.length ? h("a.warnings.dashboard-item", {
  2124. href: "#Warnings",
  2125. onmousedown: this.handleWarningsClick,
  2126. onclick: Page.returnFalse
  2127. }, "Warnings: " + warnings.length) : void 0, this.menu_warnings.render(".menu-warnings"), parseFloat(Page.server_info.version.replace(/\./g, "0")) < parseFloat(Page.latest_version.replace(/\./g, "0")) ? h("a.newversion.dashboard-item", {
  2128. href: "#Update",
  2129. onmousedown: this.handleNewversionClick,
  2130. onclick: Page.returnFalse
  2131. }, "New ZeroNet version: " + Page.latest_version) : Page.server_info.rev < Page.latest_rev ? h("a.newversion.dashboard-item", {
  2132. href: "#Update",
  2133. onmousedown: this.handleNewversionClick,
  2134. onclick: Page.returnFalse
  2135. }, "New important update: rev" + Page.latest_rev) : void 0, this.menu_newversion.render(".menu-newversion"), h("a.port.dashboard-item.donate", {
  2136. "href": "#Donate",
  2137. onmousedown: this.handleDonateClick,
  2138. onclick: Page.returnFalse
  2139. }, [h("div.icon-heart")]), this.menu_donate.render(".menu-donate"), Page.server_info.multiuser ? h("a.port.dashboard-item.multiuser", {
  2140. href: "#Multiuser",
  2141. onmousedown: this.handleMultiuserClick,
  2142. onclick: Page.returnFalse
  2143. }, [
  2144. h("span", "User: "), h("span.status", {
  2145. style: "color: " + (Text.toColor(Page.server_info.master_address))
  2146. }, Page.server_info.master_address.slice(0, 5) + ".." + Page.server_info.master_address.slice(-4))
  2147. ]) : void 0, Page.server_info.multiuser ? this.menu_multiuser.render(".menu-multiuser") : void 0, indexOf.call(Page.server_info.plugins, "UiPassword") >= 0 ? h("a.port.dashboard-item.logout", {
  2148. href: "#Logout",
  2149. onmousedown: this.handleLogoutClick,
  2150. onclick: Page.returnFalse
  2151. }, [h("span", "Logout")]) : void 0, this.menu_port.render(".menu-port.menu-left"), h("a.dashboard-item.port", {
  2152. href: "#Port",
  2153. classes: {
  2154. bounce: this.port_checking
  2155. },
  2156. onmousedown: this.handlePortClick,
  2157. onclick: Page.returnFalse
  2158. }, [h("span", "Port: "), Page.server_info.offline ? h("span.status.status-warning", "Offline mode") : this.port_checking ? h("span.status", "Checking") : Page.server_info.ip_external === null ? h("span.status", "Checking") : Page.server_info.ip_external === true ? h("span.status.status-ok", "Opened") : this.isTorAlways ? h("span.status.status-ok", "Closed") : tor_title === "OK" ? h("span.status.status-warning", "Closed") : h("span.status.status-bad", "Closed")]), h("a.dashboard-item.tor", {
  2159. href: "#Tor",
  2160. onmousedown: this.handleTorClick,
  2161. onclick: Page.returnFalse
  2162. }, [h("span", "Tor: "), tor_title === "OK" ? this.isTorAlways() ? h("span.status.status-ok", "Always") : h("span.status.status-ok", "Available") : h("span.status.status-warning", tor_title)]), this.menu_tor.render(".menu-tor"), Page.announcer_info || Page.announcer_stats ? h("a.dashboard-item.trackers", {
  2163. href: "#Trackers",
  2164. onmousedown: this.handleTrackersClick,
  2165. onclick: Page.returnFalse
  2166. }, [h("span", "Trackers: "), this.tagTrackersTitle()]) : void 0, this.menu_trackers.render(".menu-trackers"));
  2167. } else {
  2168. return h("div#Dashboard");
  2169. }
  2170. };
  2171. return Dashboard;
  2172. })(Class);
  2173. window.Dashboard = Dashboard;
  2174. }).call(this);
  2175. /* ---- PageSites/FeedList.coffee ---- */
  2176. (function() {
  2177. var FeedList,
  2178. bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
  2179. extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
  2180. hasProp = {}.hasOwnProperty;
  2181. FeedList = (function(superClass) {
  2182. extend(FeedList, superClass);
  2183. function FeedList() {
  2184. this.onSiteInfo = bind(this.onSiteInfo, this);
  2185. this.render = bind(this.render, this);
  2186. this.renderSearchHelp = bind(this.renderSearchHelp, this);
  2187. this.saveFeedVisit = bind(this.saveFeedVisit, this);
  2188. this.getClass = bind(this.getClass, this);
  2189. this.renderNotifications = bind(this.renderNotifications, this);
  2190. this.handleNotificationHideClick = bind(this.handleNotificationHideClick, this);
  2191. this.renderSearchStat = bind(this.renderSearchStat, this);
  2192. this.renderWelcome = bind(this.renderWelcome, this);
  2193. this.renderFeed = bind(this.renderFeed, this);
  2194. this.exitAnimation = bind(this.exitAnimation, this);
  2195. this.enterAnimation = bind(this.enterAnimation, this);
  2196. this.handleSearchClear = bind(this.handleSearchClear, this);
  2197. this.handleSearchInfoClick = bind(this.handleSearchInfoClick, this);
  2198. this.handleFilterClick = bind(this.handleFilterClick, this);
  2199. this.handleSearchKeyup = bind(this.handleSearchKeyup, this);
  2200. this.handleSearchInput = bind(this.handleSearchInput, this);
  2201. this.storeNodeSearch = bind(this.storeNodeSearch, this);
  2202. this.search = bind(this.search, this);
  2203. this.update = bind(this.update, this);
  2204. this.displayRows = bind(this.displayRows, this);
  2205. this.checkScroll = bind(this.checkScroll, this);
  2206. this.feeds = null;
  2207. this.searching = null;
  2208. this.searching_text = null;
  2209. this.searched = null;
  2210. this.res = null;
  2211. this.loading = false;
  2212. this.filter = null;
  2213. this.feed_types = {};
  2214. this.need_update = false;
  2215. this.updating = false;
  2216. this.limit = 30;
  2217. this.query_limit = 20;
  2218. this.query_day_limit = 3;
  2219. this.show_stats = false;
  2220. this.feed_keys = {};
  2221. this.date_feed_visit = null;
  2222. this.date_save_feed_visit = 0;
  2223. Page.on_settings.then((function(_this) {
  2224. return function() {
  2225. _this.need_update = true;
  2226. return document.body.onscroll = function() {
  2227. return RateLimit(300, function() {
  2228. return _this.checkScroll();
  2229. });
  2230. };
  2231. };
  2232. })(this));
  2233. this;
  2234. }
  2235. FeedList.prototype.checkScroll = function() {
  2236. var ref, scroll_top;
  2237. scroll_top = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0;
  2238. if (scroll_top + window.innerHeight > document.getElementById("FeedList").clientHeight - 400 && !this.updating && ((ref = this.feeds) != null ? ref.length : void 0) > 5 && Page.mode === "Sites" && this.limit < 300) {
  2239. this.limit += 30;
  2240. this.query_limit += 30;
  2241. if (this.query_day_limit !== null) {
  2242. this.query_day_limit += 5;
  2243. if (this.query_day_limit > 30) {
  2244. this.query_day_limit = null;
  2245. }
  2246. }
  2247. this.log("checkScroll update");
  2248. if (this.searching && Page.server_info.rev >= 3817) {
  2249. this.search(this.searching);
  2250. } else {
  2251. this.update();
  2252. }
  2253. return true;
  2254. } else {
  2255. return false;
  2256. }
  2257. };
  2258. FeedList.prototype.displayRows = function(rows, search) {
  2259. var i, last_row, len, row, row_group;
  2260. this.feeds = [];
  2261. this.feed_keys = {};
  2262. if (!rows) {
  2263. return false;
  2264. }
  2265. rows.sort(function(a, b) {
  2266. return a.date_added + (a.type === "mention" ? 1 : 0) - b.date_added - (b.type === "mention" ? 1 : 0);
  2267. });
  2268. row_group = {};
  2269. last_row = {};
  2270. this.feed_types = {};
  2271. rows.reverse();
  2272. for (i = 0, len = rows.length; i < len; i++) {
  2273. row = rows[i];
  2274. if (last_row.body === row.body && last_row.date_added === row.date_added) {
  2275. continue;
  2276. }
  2277. if (row_group.type === row.type && row.url === row_group.url && row.site === row_group.site) {
  2278. if (row_group.body_more == null) {
  2279. row_group.body_more = [];
  2280. row_group.body_more.push(row.body);
  2281. } else if (row_group.body_more.length < 3) {
  2282. row_group.body_more.push(row.body);
  2283. } else {
  2284. if (row_group.more == null) {
  2285. row_group.more = 0;
  2286. }
  2287. row_group.more += 1;
  2288. }
  2289. row_group.feed_id = row.date_added;
  2290. } else {
  2291. if (row.feed_id == null) {
  2292. row.feed_id = row.date_added;
  2293. }
  2294. row.key = row.site + row.type + row.title + row.feed_id;
  2295. if (this.feed_keys[row.key]) {
  2296. this.log("Duplicate feed key: " + row.key);
  2297. } else {
  2298. this.feeds.push(row);
  2299. }
  2300. this.feed_keys[row.key] = true;
  2301. row_group = row;
  2302. }
  2303. this.feed_types[row.type] = true;
  2304. last_row = row;
  2305. }
  2306. return Page.projector.scheduleRender();
  2307. };
  2308. FeedList.prototype.update = function(cb) {
  2309. var params;
  2310. if (this.searching || this.updating) {
  2311. return false;
  2312. }
  2313. if (!Page.server_info || Page.server_info.rev < 1850) {
  2314. params = [];
  2315. } else {
  2316. params = {
  2317. limit: this.query_limit,
  2318. day_limit: this.query_day_limit
  2319. };
  2320. }
  2321. this.logStart("Updating feed", params);
  2322. this.updating = true;
  2323. return Page.cmd("feedQuery", params, (function(_this) {
  2324. return function(res) {
  2325. var rows;
  2326. if (res.rows) {
  2327. rows = res.rows;
  2328. } else {
  2329. rows = res;
  2330. }
  2331. _this.res = res;
  2332. if (rows.length < 10 && _this.query_day_limit !== null) {
  2333. _this.log("Only " + res.rows.length + " results, query without day limit");
  2334. _this.query_limit = 20;
  2335. _this.query_day_limit = null;
  2336. _this.updating = false;
  2337. _this.update();
  2338. return false;
  2339. }
  2340. _this.displayRows(rows);
  2341. setTimeout(_this.checkScroll, 100);
  2342. _this.logEnd("Updating feed");
  2343. if (cb) {
  2344. cb();
  2345. }
  2346. return _this.updating = false;
  2347. };
  2348. })(this));
  2349. };
  2350. FeedList.prototype.search = function(search, cb) {
  2351. var params;
  2352. if (Page.server_info.rev < 1230) {
  2353. this.displayRows([]);
  2354. if (cb) {
  2355. cb();
  2356. }
  2357. return;
  2358. }
  2359. if (!Page.server_info || Page.server_info.rev < 3817) {
  2360. params = search;
  2361. } else {
  2362. params = {
  2363. search: search,
  2364. limit: this.query_limit * 3,
  2365. day_limit: this.query_day_limit * 10 || null
  2366. };
  2367. }
  2368. this.log("Searching for", params);
  2369. this.loading = true;
  2370. Page.projector.scheduleRender();
  2371. return Page.cmd("feedSearch", params, (function(_this) {
  2372. return function(res) {
  2373. _this.loading = false;
  2374. if (res.rows.length < 10 && _this.query_day_limit !== null) {
  2375. _this.log("Only " + res.rows.length + " results, search without day limit");
  2376. _this.query_limit = 30;
  2377. _this.query_day_limit = null;
  2378. _this.search(search, cb);
  2379. return false;
  2380. }
  2381. _this.displayRows(res["rows"], search);
  2382. delete res["rows"];
  2383. _this.res = res;
  2384. _this.searched = search;
  2385. if (cb) {
  2386. return cb();
  2387. }
  2388. };
  2389. })(this));
  2390. };
  2391. FeedList.prototype.storeNodeSearch = function(node) {
  2392. return document.body.onkeypress = (function(_this) {
  2393. return function(e) {
  2394. var ref, ref1;
  2395. if ((ref = e.charCode) === 0 || ref === 32) {
  2396. return;
  2397. }
  2398. if (((ref1 = document.activeElement) != null ? ref1.tagName : void 0) !== "INPUT") {
  2399. return node.focus();
  2400. }
  2401. };
  2402. })(this);
  2403. };
  2404. FeedList.prototype.handleSearchInput = function(e) {
  2405. var delay, ref;
  2406. if (((ref = this.searching) != null ? ref.length : void 0) > 3) {
  2407. delay = 400;
  2408. } else {
  2409. delay = 800;
  2410. }
  2411. if (Page.site_list.sites.length > 300) {
  2412. delay = delay * 3;
  2413. } else if (Page.site_list.sites.length > 100) {
  2414. delay = delay * 2;
  2415. }
  2416. this.searching = e.target.value;
  2417. this.searching_text = this.searching.replace(/[^ ]+:.*$/, "").trim();
  2418. if (Page.server_info.rev < 1230) {
  2419. this.feeds = [];
  2420. this.feed_keys = {};
  2421. }
  2422. if (e.target.value === "") {
  2423. delay = 1;
  2424. }
  2425. if (e.keyCode === 13) {
  2426. delay = 1;
  2427. }
  2428. clearInterval(this.input_timer);
  2429. setTimeout((function(_this) {
  2430. return function() {
  2431. return _this.waiting = true;
  2432. };
  2433. })(this));
  2434. this.input_timer = setTimeout(((function(_this) {
  2435. return function() {
  2436. return RateLimitCb(delay, function(cb_done) {
  2437. _this.limit = 30;
  2438. _this.query_limit = 20;
  2439. _this.query_day_limit = 3;
  2440. _this.waiting = false;
  2441. if (_this.searching) {
  2442. return _this.search(_this.searching, function() {
  2443. return cb_done();
  2444. });
  2445. } else {
  2446. return _this.update(function() {
  2447. cb_done();
  2448. if (!_this.searching) {
  2449. _this.searching = null;
  2450. }
  2451. return _this.searched = null;
  2452. });
  2453. }
  2454. });
  2455. };
  2456. })(this)), delay);
  2457. return false;
  2458. };
  2459. FeedList.prototype.handleSearchKeyup = function(e) {
  2460. if (e.keyCode === 27) {
  2461. e.target.value = "";
  2462. this.handleSearchInput(e);
  2463. }
  2464. if (e.keyCode === 13) {
  2465. this.handleSearchInput(e);
  2466. }
  2467. return false;
  2468. };
  2469. FeedList.prototype.handleFilterClick = function(e) {
  2470. this.filter = e.target.getAttribute("href").replace("#", "");
  2471. if (this.filter === "all") {
  2472. this.filter = null;
  2473. }
  2474. return false;
  2475. };
  2476. FeedList.prototype.handleSearchInfoClick = function(e) {
  2477. this.show_stats = !this.show_stats;
  2478. return false;
  2479. };
  2480. FeedList.prototype.handleSearchClear = function(e) {
  2481. e.target.value = "";
  2482. this.handleSearchInput(e);
  2483. return false;
  2484. };
  2485. FeedList.prototype.formatTitle = function(title) {
  2486. if (this.searching_text && this.searching_text.length > 1) {
  2487. return Text.highlight(title, this.searching_text);
  2488. } else {
  2489. if (title) {
  2490. return title;
  2491. } else {
  2492. return "";
  2493. }
  2494. }
  2495. };
  2496. FeedList.prototype.formatBody = function(body, type) {
  2497. var username_formatted, username_match;
  2498. body = body.replace(/[\n\r]+/, "\n");
  2499. if (type === "comment" || type === "mention") {
  2500. username_match = body.match(/^(([a-zA-Z0-9\.]+)@[a-zA-Z0-9\.]+|@(.*?)):/);
  2501. if (username_match) {
  2502. if (username_match[2]) {
  2503. username_formatted = username_match[2] + " › ";
  2504. } else {
  2505. username_formatted = username_match[3] + " › ";
  2506. }
  2507. body = body.replace(/> \[(.*?)\].*/g, "$1: ");
  2508. body = body.replace(/^[ ]*>.*/gm, "");
  2509. body = body.replace(username_match[0], "");
  2510. } else {
  2511. username_formatted = "";
  2512. }
  2513. body = body.replace(/\n/g, " ");
  2514. body = body.trim();
  2515. if (this.searching_text && this.searching_text.length > 1) {
  2516. body = Text.highlight(body, this.searching_text);
  2517. if (body[0].length > 60 && body.length > 1) {
  2518. body[0] = "..." + body[0].slice(body[0].length - 50, +(body[0].length - 1) + 1 || 9e9);
  2519. }
  2520. return [h("b", Text.highlight(username_formatted, this.searching_text)), body];
  2521. } else {
  2522. body = body.slice(0, 201);
  2523. return [h("b", [username_formatted]), body];
  2524. }
  2525. } else {
  2526. body = body.replace(/\n/g, " ");
  2527. if (this.searching_text && this.searching_text.length > 1) {
  2528. body = Text.highlight(body, this.searching_text);
  2529. if (body[0].length > 60) {
  2530. body[0] = "..." + body[0].slice(body[0].length - 50, +(body[0].length - 1) + 1 || 9e9);
  2531. }
  2532. } else {
  2533. body = body.slice(0, 201);
  2534. }
  2535. return body;
  2536. }
  2537. };
  2538. FeedList.prototype.formatType = function(type, title) {
  2539. if (type === "comment") {
  2540. return "Comment on";
  2541. } else if (type === "mention") {
  2542. if (title) {
  2543. return "You got mentioned in";
  2544. } else {
  2545. return "You got mentioned";
  2546. }
  2547. } else {
  2548. return "";
  2549. }
  2550. };
  2551. FeedList.prototype.enterAnimation = function(elem, props) {
  2552. if (this.searching === null) {
  2553. return Animation.slideDown.apply(this, arguments);
  2554. } else {
  2555. return null;
  2556. }
  2557. };
  2558. FeedList.prototype.exitAnimation = function(elem, remove_func, props) {
  2559. if (this.searching === null) {
  2560. return Animation.slideUp.apply(this, arguments);
  2561. } else {
  2562. return remove_func();
  2563. }
  2564. };
  2565. FeedList.prototype.renderFeed = function(feed) {
  2566. var classes, err, site, type_formatted;
  2567. if (this.filter && feed.type !== this.filter) {
  2568. return null;
  2569. }
  2570. try {
  2571. site = Page.site_list.item_list.items_bykey[feed.site];
  2572. type_formatted = this.formatType(feed.type, feed.title);
  2573. classes = {};
  2574. if (this.date_feed_visit && feed.date_added > this.date_feed_visit) {
  2575. classes["new"] = true;
  2576. }
  2577. return h("div.feed." + feed.type, {
  2578. key: feed.key,
  2579. enterAnimation: this.enterAnimation,
  2580. exitAnimation: this.exitAnimation,
  2581. classes: classes
  2582. }, [
  2583. h("div.details", [
  2584. h("span.dot", {
  2585. title: "new"
  2586. }, "\u2022"), h("a.site", {
  2587. href: site.getHref()
  2588. }, [site.row.content.title]), h("div.added", [Time.since(feed.date_added)])
  2589. ]), h("div.circle", {
  2590. style: "border-color: " + (Text.toColor(feed.type + site.row.address, 60, 60))
  2591. }), h("div.title-container", [
  2592. type_formatted ? h("span.type", type_formatted) : void 0, h("a.title", {
  2593. href: site.getHref() + feed.url
  2594. }, this.formatTitle(feed.title))
  2595. ]), h("div.body", {
  2596. key: feed.body,
  2597. enterAnimation: this.enterAnimation,
  2598. exitAnimation: this.exitAnimation
  2599. }, this.formatBody(feed.body, feed.type)), feed.body_more ? feed.body_more.map((function(_this) {
  2600. return function(body_more) {
  2601. return h("div.body", {
  2602. key: body_more,
  2603. enterAnimation: _this.enterAnimation,
  2604. exitAnimation: _this.exitAnimation
  2605. }, _this.formatBody(body_more, feed.type));
  2606. };
  2607. })(this)) : void 0, feed.more > 0 ? h("a.more", {
  2608. href: site.getHref() + feed.url
  2609. }, ["+" + feed.more + " more"]) : void 0
  2610. ]);
  2611. } catch (error) {
  2612. err = error;
  2613. this.log(err);
  2614. return h("div", {
  2615. key: Time.timestamp()
  2616. });
  2617. }
  2618. };
  2619. FeedList.prototype.renderWelcome = function() {
  2620. return h("div.welcome", [
  2621. h("h1", "Welcome to 0net"), h("h2", "we use zeronet-conservancy client"), h("h2", "Let's build & preserve a decentralized Internet together!"), h("div.served", ["This site currently served by ", h("b.peers", Page.site_info["peers"] || "n/a"), " peers, without any central server."]), h("div.sites", [
  2622. h("h3", "Some sites we created:"),
  2623. h("a.site.site-zerome", {
  2624. href: Text.getSiteUrl("1MeFqFfFFGQfa1J3gJyYYUvb5Lksczq7nH")
  2625. }, [h("div.title", ["ZeroMe"]), h("div.description", ["P2P microblogging social network"]), h("div.visit", ["Activate \u2501"])]),
  2626. h("a.site.site-zerotalk", {
  2627. href: Text.getSiteUrl("1TaLkFrMwvbNsooF4ioKAY9EuxTBTjipT")
  2628. }, [h("div.title", ["ZeroTalk"]), h("div.description", ["An old general discussion forum"]), h("div.visit", ["Activate \u2501"])]),
  2629. h("a.site.site-searchindex", {
  2630. href: Text.getSiteUrl("1xiwbXaTbo9XU32hEpW4NyjZHrugSFdo6")
  2631. }, [h("div.title", ["Search and index sites"]), h("div.description", ["Another site discovery and search service"]), h("div.visit", ["Activate \u2501"])])
  2632. ])
  2633. ]);
  2634. };
  2635. FeedList.prototype.renderSearchStat = function(stat) {
  2636. var back, site, total_taken;
  2637. if (stat.taken === 0) {
  2638. return null;
  2639. }
  2640. total_taken = this.res.taken;
  2641. site = Page.site_list.item_list.items_bykey[stat.site];
  2642. if (!site) {
  2643. return [];
  2644. }
  2645. back = [];
  2646. back.push(h("tr", {
  2647. key: stat.site + "_" + stat.feed_name,
  2648. classes: {
  2649. "slow": stat.taken > total_taken * 0.1,
  2650. "extra-slow": stat.taken > total_taken * 0.3
  2651. }
  2652. }, [
  2653. h("td.site", h("a.site", {
  2654. href: site.getHref()
  2655. }, [site.row.content.title])), h("td.feed_name", stat.feed_name), h("td.taken", (stat.taken != null ? stat.taken + "s" : "n/a "))
  2656. ]));
  2657. if (stat.error) {
  2658. back.push(h("tr.error", h("td", "Error:"), h("td", {
  2659. colSpan: 2
  2660. }, stat.error)));
  2661. }
  2662. return back;
  2663. };
  2664. FeedList.prototype.handleNotificationHideClick = function(e) {
  2665. var address;
  2666. address = e.target.getAttribute("address");
  2667. Page.settings.siteblocks_ignore[address] = true;
  2668. Page.mute_list.update();
  2669. Page.saveSettings();
  2670. return false;
  2671. };
  2672. FeedList.prototype.renderNotifications = function() {
  2673. return h("div.notifications", {
  2674. classes: {
  2675. empty: Page.mute_list.siteblocks_serving.length === 0
  2676. }
  2677. }, [
  2678. Page.mute_list.siteblocks_serving.map((function(_this) {
  2679. return function(siteblock) {
  2680. return h("div.notification", {
  2681. key: siteblock.address,
  2682. enterAnimation: Animation.show,
  2683. exitAnimation: Animation.slideUpInout
  2684. }, [
  2685. "You are serving a blocked site: ", h("a.site", {
  2686. href: siteblock.site.getHref()
  2687. }, siteblock.site.row.content.title), h("span.reason", [h("b", "Reason: "), siteblock.reason]), h("a.hide", {
  2688. href: "#Hide",
  2689. onclick: _this.handleNotificationHideClick,
  2690. address: siteblock.address
  2691. }, "\u00D7")
  2692. ]);
  2693. };
  2694. })(this))
  2695. ]);
  2696. };
  2697. FeedList.prototype.getClass = function() {
  2698. if (this.searching !== null) {
  2699. return "search";
  2700. } else {
  2701. return "newsfeed.limit-" + this.limit;
  2702. }
  2703. };
  2704. FeedList.prototype.saveFeedVisit = function(date_feed_visit) {
  2705. this.log("Saving feed visit...", Page.settings.date_feed_visit, "->", date_feed_visit);
  2706. Page.settings.date_feed_visit = date_feed_visit;
  2707. return Page.saveSettings();
  2708. };
  2709. FeedList.prototype.renderSearchHelp = function() {
  2710. return h("div.search-help", ["Tip: Search in specific site using ", h("code", "anything site:SiteName")]);
  2711. };
  2712. FeedList.prototype.render = function() {
  2713. var feed_type, ref, ref1;
  2714. if (this.need_update) {
  2715. RateLimitCb(5000, this.update);
  2716. this.need_update = false;
  2717. }
  2718. if (this.feeds && Page.settings.date_feed_visit < ((ref = this.feeds[0]) != null ? ref.date_added : void 0)) {
  2719. this.saveFeedVisit(this.feeds[0].date_added);
  2720. }
  2721. if (this.feeds && Page.site_list.loaded && document.body.className !== "loaded" && !this.updating) {
  2722. if (document.body.scrollTop > 500) {
  2723. setTimeout((function() {
  2724. return document.body.classList.add("loaded");
  2725. }), 2000);
  2726. } else {
  2727. document.body.classList.add("loaded");
  2728. }
  2729. }
  2730. return h("div#FeedList.FeedContainer", {
  2731. classes: {
  2732. faded: Page.mute_list.visible
  2733. }
  2734. }, Page.mute_list.updated ? this.renderNotifications() : void 0, this.feeds === null || !Page.site_list.loaded ? h("div.loading") : this.feeds.length > 0 || this.searching !== null ? [
  2735. h("div.feeds-filters", [
  2736. h("a.feeds-filter", {
  2737. href: "#all",
  2738. classes: {
  2739. active: this.filter === null
  2740. },
  2741. onclick: this.handleFilterClick
  2742. }, "All"), (function() {
  2743. var results;
  2744. results = [];
  2745. for (feed_type in this.feed_types) {
  2746. results.push(h("a.feeds-filter", {
  2747. key: feed_type,
  2748. href: "#" + feed_type,
  2749. classes: {
  2750. active: this.filter === feed_type
  2751. },
  2752. onclick: this.handleFilterClick
  2753. }, feed_type));
  2754. }
  2755. return results;
  2756. }).call(this)
  2757. ]), h("div.feeds-line"), h("div.feeds-search", {
  2758. classes: {
  2759. "searching": this.searching,
  2760. "searched": this.searched,
  2761. "loading": this.loading || this.waiting
  2762. }
  2763. }, h("div.icon-magnifier"), this.loading ? h("div.loader", {
  2764. enterAnimation: Animation.show,
  2765. exitAnimation: Animation.hide
  2766. }, h("div.arc")) : void 0, this.searched && !this.loading ? h("a.search-clear.nolink", {
  2767. href: "#clear",
  2768. onclick: this.handleSearchClear,
  2769. enterAnimation: Animation.show,
  2770. exitAnimation: Animation.hide
  2771. }, "\u00D7") : void 0, ((ref1 = this.res) != null ? ref1.stats : void 0) ? h("a.search-info.nolink", {
  2772. href: "#ShowStats",
  2773. enterAnimation: Animation.show,
  2774. exitAnimation: Animation.hide,
  2775. onclick: this.handleSearchInfoClick
  2776. }, (this.searching ? this.res.num + " results " : "") + ("from " + this.res.sites + " sites in " + (this.res.taken.toFixed(2)) + "s")) : void 0, h("input", {
  2777. type: "text",
  2778. placeholder: "Search in connected sites",
  2779. value: this.searching,
  2780. onkeyup: this.handleSearchKeyup,
  2781. oninput: this.handleSearchInput,
  2782. afterCreate: this.storeNodeSearch
  2783. }), this.show_stats ? h("div.search-info-stats", {
  2784. enterAnimation: Animation.slideDown,
  2785. exitAnimation: Animation.slideUp
  2786. }, [h("table", [h("tr", h("th", "Site"), h("th", "Feed"), h("th.taken", "Taken")), this.res.stats.map(this.renderSearchStat)])]) : void 0, this.renderSearchHelp(), Page.server_info.rev < 1230 && this.searching ? h("div.search-noresult", {
  2787. enterAnimation: Animation.show
  2788. }, [
  2789. "You need to ", h("a", {
  2790. href: "#Update",
  2791. onclick: Page.head.handleUpdateZeronetClick
  2792. }, "update"), " your ZeroNet client to use the search feature!"
  2793. ]) : this.feeds.length === 0 && this.searched ? h("div.search-noresult", {
  2794. enterAnimation: Animation.show
  2795. }, "No results for " + this.searched) : void 0), h("div.FeedList." + this.getClass(), {
  2796. classes: {
  2797. loading: this.loading || this.waiting
  2798. }
  2799. }, this.feeds.slice(0, +this.limit + 1 || 9e9).map(this.renderFeed))
  2800. ] : this.renderWelcome());
  2801. };
  2802. FeedList.prototype.onSiteInfo = function(site_info) {
  2803. var ref, ref1, ref2;
  2804. if (((ref = site_info.event) != null ? ref[0] : void 0) === "file_done" && ((ref1 = site_info.event) != null ? ref1[1].endsWith(".json") : void 0) && !((ref2 = site_info.event) != null ? ref2[1].endsWith("content.json") : void 0)) {
  2805. if (!this.searching) {
  2806. return this.need_update = true;
  2807. }
  2808. }
  2809. };
  2810. return FeedList;
  2811. })(Class);
  2812. window.FeedList = FeedList;
  2813. }).call(this);
  2814. /* ---- PageSites/MuteList.coffee ---- */
  2815. (function() {
  2816. var MuteList,
  2817. bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
  2818. extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
  2819. hasProp = {}.hasOwnProperty;
  2820. MuteList = (function(superClass) {
  2821. extend(MuteList, superClass);
  2822. function MuteList() {
  2823. this.show = bind(this.show, this);
  2824. this.render = bind(this.render, this);
  2825. this.renderIncludes = bind(this.renderIncludes, this);
  2826. this.renderSiteblocks = bind(this.renderSiteblocks, this);
  2827. this.renderMutes = bind(this.renderMutes, this);
  2828. this.storeNode = bind(this.storeNode, this);
  2829. this.afterUpdate = bind(this.afterUpdate, this);
  2830. this.handleIncludeRemoveClick = bind(this.handleIncludeRemoveClick, this);
  2831. this.handleMuteRemoveClick = bind(this.handleMuteRemoveClick, this);
  2832. this.handleHideClick = bind(this.handleHideClick, this);
  2833. this.updateFilterIncludes = bind(this.updateFilterIncludes, this);
  2834. this.update = bind(this.update, this);
  2835. this.mutes = null;
  2836. this.includes = null;
  2837. this.visible = false;
  2838. this.max_height = 0;
  2839. this.updated = false;
  2840. this.siteblocks_serving = [];
  2841. Page.site_list.on_loaded.then((function(_this) {
  2842. return function() {
  2843. return _this.updateFilterIncludes();
  2844. };
  2845. })(this));
  2846. this;
  2847. }
  2848. MuteList.prototype.update = function() {
  2849. this.need_update = false;
  2850. Page.cmd("MuteList", [], (function(_this) {
  2851. return function(res) {
  2852. var auth_address, mute;
  2853. _this.mutes = [];
  2854. for (auth_address in res) {
  2855. mute = res[auth_address];
  2856. mute.auth_address = auth_address;
  2857. mute.site = Page.site_list.sites_byaddress[mute.source];
  2858. _this.mutes.push(mute);
  2859. }
  2860. _this.mutes.sort(function(a, b) {
  2861. return b.date_added - a.date_added;
  2862. });
  2863. if (!_this.max_height) {
  2864. _this.max_height = 100;
  2865. }
  2866. _this.updated = true;
  2867. return Page.projector.scheduleRender();
  2868. };
  2869. })(this));
  2870. return this.updateFilterIncludes();
  2871. };
  2872. MuteList.prototype.updateFilterIncludes = function() {
  2873. return Page.cmd("FilterIncludeList", {
  2874. all_sites: true,
  2875. filters: true
  2876. }, (function(_this) {
  2877. return function(res) {
  2878. var address, auth_address, i, include, len, mute, mutes, ref, ref1, siteblock, siteblocks;
  2879. _this.siteblocks_serving = [];
  2880. _this.includes = [];
  2881. for (i = 0, len = res.length; i < len; i++) {
  2882. include = res[i];
  2883. include.site = Page.site_list.sites_byaddress[include.address];
  2884. mutes = [];
  2885. if (include.mutes != null) {
  2886. ref = include.mutes;
  2887. for (auth_address in ref) {
  2888. mute = ref[auth_address];
  2889. mute.auth_address = auth_address;
  2890. mutes.push(mute);
  2891. }
  2892. }
  2893. include.mutes = mutes;
  2894. siteblocks = [];
  2895. if (include.siteblocks != null) {
  2896. ref1 = include.siteblocks;
  2897. for (address in ref1) {
  2898. siteblock = ref1[address];
  2899. siteblock.address = address;
  2900. siteblocks.push(siteblock);
  2901. if (Page.site_list.sites_byaddress[address] && !Page.settings.siteblocks_ignore[address]) {
  2902. siteblock.site = Page.site_list.sites_byaddress[address];
  2903. _this.siteblocks_serving.push(siteblock);
  2904. }
  2905. }
  2906. }
  2907. include.siteblocks = siteblocks;
  2908. _this.includes.push(include);
  2909. }
  2910. _this.includes.sort(function(a, b) {
  2911. return b.date_added - a.date_added;
  2912. });
  2913. _this.updated = true;
  2914. return Page.projector.scheduleRender();
  2915. };
  2916. })(this));
  2917. };
  2918. MuteList.prototype.handleHideClick = function() {
  2919. this.visible = false;
  2920. setTimeout(((function(_this) {
  2921. return function() {
  2922. return _this.updateFilterIncludes();
  2923. };
  2924. })(this)), 1000);
  2925. return this.max_height = 0;
  2926. };
  2927. MuteList.prototype.handleMuteRemoveClick = function(e) {
  2928. var mute;
  2929. mute = e.target.mute;
  2930. if (mute.removed) {
  2931. Page.cmd("muteAdd", [mute.auth_address, mute.cert_user_id, mute.reason]);
  2932. } else {
  2933. Page.cmd("muteRemove", mute.auth_address);
  2934. }
  2935. mute.removed = !mute.removed;
  2936. return false;
  2937. };
  2938. MuteList.prototype.handleIncludeRemoveClick = function(e) {
  2939. var include;
  2940. include = e.target.include;
  2941. if (include.removed) {
  2942. Page.cmd("filterIncludeAdd", [include.inner_path, include.description, include.address]);
  2943. } else {
  2944. Page.cmd("filterIncludeRemove", {
  2945. inner_path: include.inner_path,
  2946. address: include.address
  2947. });
  2948. }
  2949. include.removed = !include.removed;
  2950. return false;
  2951. };
  2952. MuteList.prototype.afterUpdate = function() {
  2953. this.updated = false;
  2954. if (this.node && this.visible) {
  2955. this.max_height = this.node.offsetHeight + 100;
  2956. return Page.projector.scheduleRender();
  2957. }
  2958. };
  2959. MuteList.prototype.storeNode = function(node) {
  2960. return this.node = node;
  2961. };
  2962. MuteList.prototype.renderMutes = function(mutes, mode) {
  2963. if (mode == null) {
  2964. mode = "mutes";
  2965. }
  2966. return h("div.mutes", [
  2967. h("div.mute.mute-head", [
  2968. h("div.mute-col", "Muted user"), h("div.mute-col", {
  2969. style: "width: 66%"
  2970. }, "Why?")
  2971. ]), mutes.map((function(_this) {
  2972. return function(mute) {
  2973. return h("div.mute", {
  2974. key: mute.auth_address,
  2975. classes: {
  2976. removed: mute.removed
  2977. }
  2978. }, [
  2979. h("div.mute-col", [h("div.cert_user_id", mute.cert_user_id), h("div.auth_address", mute.auth_address)]), h("div.mute-col", {
  2980. style: "width: 66%"
  2981. }, [
  2982. h("div.source", mute.site != null ? mute.site.row.content.title : mute.source), h("div.reason", {
  2983. innerHTML: Text.renderMarked(mute.reason)
  2984. }), h("div.date_added", " \u2500 " + Time.since(mute.date_added))
  2985. ]), mode === "mutes" ? h("a.action", {
  2986. href: "#Unmute",
  2987. onclick: _this.handleMuteRemoveClick,
  2988. mute: mute
  2989. }, "×") : void 0
  2990. ]);
  2991. };
  2992. })(this))
  2993. ]);
  2994. };
  2995. MuteList.prototype.renderSiteblocks = function(siteblocks) {
  2996. return h("div.siteblocks", [
  2997. h("div.mute.mute-head", [
  2998. h("div.mute-col", "Blocked site"), h("div.mute-col", {
  2999. style: "width: 66%"
  3000. }, "Why?")
  3001. ]), siteblocks.map((function(_this) {
  3002. return function(siteblock) {
  3003. return h("div.mute", {
  3004. key: siteblock.address,
  3005. classes: {
  3006. removed: siteblock.removed
  3007. }
  3008. }, [
  3009. h("div.mute-col", [h("div.cert_user_id", siteblock.name), h("div.auth_address", siteblock.address)]), h("div.mute-col", {
  3010. style: "width: 66%"
  3011. }, [
  3012. h("div.reason", {
  3013. innerHTML: Text.renderMarked(siteblock.reason)
  3014. }), h("div.date_added", " \u2500 " + Time.since(siteblock.date_added))
  3015. ])
  3016. ]);
  3017. };
  3018. })(this))
  3019. ]);
  3020. };
  3021. MuteList.prototype.renderIncludes = function() {
  3022. return h("div.includes", [
  3023. this.includes.map((function(_this) {
  3024. return function(include) {
  3025. return h("div.include", {
  3026. key: include.address + include.inner_path,
  3027. classes: {
  3028. removed: include.removed
  3029. }
  3030. }, [
  3031. h("h2", h("a.site", {
  3032. href: include.site.getHref()
  3033. }, include.site.row.content.title), " \u203A ", h("a.inner_path", {
  3034. href: "#"
  3035. }, include.inner_path)), h("a.action", {
  3036. href: "#Remove+include",
  3037. onclick: _this.handleIncludeRemoveClick,
  3038. include: include
  3039. }, "×"), include.mutes.length ? _this.renderMutes(include.mutes, "includes") : void 0, include.siteblocks.length ? _this.renderSiteblocks(include.siteblocks) : void 0
  3040. ]);
  3041. };
  3042. })(this))
  3043. ]);
  3044. };
  3045. MuteList.prototype.render = function() {
  3046. var ref, ref1;
  3047. if (this.need_update) {
  3048. this.update();
  3049. }
  3050. if (!this.mutes) {
  3051. return h("div#MuteList", {
  3052. classes: {
  3053. visible: false
  3054. }
  3055. }, "Muted");
  3056. }
  3057. if (this.updated) {
  3058. this.updated = false;
  3059. setTimeout(this.afterUpdate);
  3060. }
  3061. return h("div#MuteList", {
  3062. classes: {
  3063. visible: this.visible
  3064. },
  3065. style: "max-height: " + this.max_height + "px"
  3066. }, [
  3067. h("a.mute-hide", {
  3068. href: "#Hide",
  3069. onclick: this.handleHideClick
  3070. }, "\u2039 Back to feed"), ((ref = this.mutes) != null ? ref.length : void 0) === 0 && ((ref1 = this.includes) != null ? ref1.length : void 0) === 0 ? h("div.mute-empty", "Your mute list is empty! :)") : h("div", {
  3071. afterCreate: this.storeNode
  3072. }, [this.mutes.length > 0 ? this.renderMutes(this.mutes) : void 0, this.includes ? this.renderIncludes() : void 0])
  3073. ]);
  3074. };
  3075. MuteList.prototype.show = function() {
  3076. this.visible = true;
  3077. Page.site_list.on_loaded.then((function(_this) {
  3078. return function() {
  3079. return _this.need_update = true;
  3080. };
  3081. })(this));
  3082. return Page.projector.scheduleRender();
  3083. };
  3084. return MuteList;
  3085. })(Class);
  3086. window.MuteList = MuteList;
  3087. }).call(this);
  3088. /* ---- PageSites/Site.coffee ---- */
  3089. (function() {
  3090. var Site,
  3091. bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
  3092. extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
  3093. hasProp = {}.hasOwnProperty,
  3094. indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
  3095. Site = (function(superClass) {
  3096. extend(Site, superClass);
  3097. function Site(row, item_list) {
  3098. this.item_list = item_list;
  3099. this.renderOptionalStats = bind(this.renderOptionalStats, this);
  3100. this.render = bind(this.render, this);
  3101. this.handleLimitIncreaseClick = bind(this.handleLimitIncreaseClick, this);
  3102. this.handleHelpsClick = bind(this.handleHelpsClick, this);
  3103. this.handleHelpAllClick = bind(this.handleHelpAllClick, this);
  3104. this.handleHelpClick = bind(this.handleHelpClick, this);
  3105. this.handleSettingsClick = bind(this.handleSettingsClick, this);
  3106. this.handleDeleteClick = bind(this.handleDeleteClick, this);
  3107. this.handleCloneUpgradeClick = bind(this.handleCloneUpgradeClick, this);
  3108. this.handleCloneClick = bind(this.handleCloneClick, this);
  3109. this.handlePauseClick = bind(this.handlePauseClick, this);
  3110. this.handleResumeClick = bind(this.handleResumeClick, this);
  3111. this.handleCheckfilesClick = bind(this.handleCheckfilesClick, this);
  3112. this.handleUpdateClick = bind(this.handleUpdateClick, this);
  3113. this.handleUnfavoriteClick = bind(this.handleUnfavoriteClick, this);
  3114. this.handleFavoriteClick = bind(this.handleFavoriteClick, this);
  3115. this.deleted = false;
  3116. this.show_errors = false;
  3117. this.message_visible = false;
  3118. this.message = null;
  3119. this.message_class = "";
  3120. this.message_collapsed = false;
  3121. this.message_timer = null;
  3122. this.favorite = Page.settings.favorite_sites[row.address];
  3123. this.key = row.address;
  3124. this.optional_helps = [];
  3125. this.optional_helps_disabled = {};
  3126. this.setRow(row);
  3127. this.files = new SiteFiles(this);
  3128. this.menu = new Menu();
  3129. this.menu_helps = null;
  3130. }
  3131. Site.prototype.setRow = function(row) {
  3132. var base, base1, base2, base3, key, ref, ref1, ref2, val;
  3133. if ((base = row.settings).modified == null) {
  3134. base.modified = 0;
  3135. }
  3136. if ((base1 = row.settings).size == null) {
  3137. base1.size = 0;
  3138. }
  3139. if ((base2 = row.settings).added == null) {
  3140. base2.added = 0;
  3141. }
  3142. if ((base3 = row.settings).peers == null) {
  3143. base3.peers = 0;
  3144. }
  3145. if (((ref = row.event) != null ? ref[0] : void 0) === "updated" && row.content_updated !== false) {
  3146. this.setMessage("Updated!", "done");
  3147. } else if (((ref1 = row.event) != null ? ref1[0] : void 0) === "updating") {
  3148. this.setMessage("Updating...");
  3149. } else if (row.tasks > 0) {
  3150. this.setMessage("Updating: " + (Math.max(row.tasks, row.bad_files)) + " left");
  3151. } else if (row.bad_files > 0) {
  3152. if (row.peers <= 1) {
  3153. this.setMessage("No peers", "error");
  3154. } else {
  3155. this.setMessage(row.bad_files + " file update failed", "error");
  3156. }
  3157. } else if (row.content_updated === false) {
  3158. if (row.peers <= 1) {
  3159. this.setMessage("No peers", "error");
  3160. } else {
  3161. this.setMessage("Update failed", "error");
  3162. }
  3163. } else if (row.tasks === 0 && ((ref2 = this.row) != null ? ref2.tasks : void 0) > 0) {
  3164. this.setMessage("Updated!", "done");
  3165. }
  3166. if (row.body == null) {
  3167. row.body = "";
  3168. }
  3169. this.optional_helps = (function() {
  3170. var ref3, results;
  3171. ref3 = row.settings.optional_help;
  3172. results = [];
  3173. for (key in ref3) {
  3174. val = ref3[key];
  3175. results.push([key, val]);
  3176. }
  3177. return results;
  3178. })();
  3179. return this.row = row;
  3180. };
  3181. Site.prototype.setMessage = function(message, message_class) {
  3182. this.message_class = message_class != null ? message_class : "";
  3183. if (message) {
  3184. this.message = message;
  3185. this.message_visible = true;
  3186. if (this.message_class === "error" && !this.show_errors) {
  3187. this.message_collapsed = true;
  3188. } else {
  3189. this.message_collapsed = false;
  3190. }
  3191. } else {
  3192. this.message_visible = false;
  3193. }
  3194. clearInterval(this.message_timer);
  3195. if (this.message_class === "done") {
  3196. this.message_timer = setTimeout(((function(_this) {
  3197. return function() {
  3198. return _this.setMessage("");
  3199. };
  3200. })(this)), 5000);
  3201. }
  3202. return Page.projector.scheduleRender();
  3203. };
  3204. Site.prototype.isWorking = function() {
  3205. var ref;
  3206. return this.row.tasks > 0 || ((ref = this.row.event) != null ? ref[0] : void 0) === "updating";
  3207. };
  3208. Site.prototype.handleFavoriteClick = function() {
  3209. this.favorite = true;
  3210. this.menu = new Menu();
  3211. Page.settings.favorite_sites[this.row.address] = true;
  3212. Page.saveSettings();
  3213. Page.site_list.reorder();
  3214. return false;
  3215. };
  3216. Site.prototype.handleUnfavoriteClick = function() {
  3217. this.favorite = false;
  3218. this.menu = new Menu();
  3219. delete Page.settings.favorite_sites[this.row.address];
  3220. Page.saveSettings();
  3221. Page.site_list.reorder();
  3222. return false;
  3223. };
  3224. Site.prototype.handleUpdateClick = function() {
  3225. Page.cmd("siteUpdate", {
  3226. "address": this.row.address
  3227. });
  3228. this.show_errors = true;
  3229. return false;
  3230. };
  3231. Site.prototype.handleCheckfilesClick = function() {
  3232. Page.cmd("siteUpdate", {
  3233. "address": this.row.address,
  3234. "check_files": true,
  3235. since: 0
  3236. });
  3237. this.show_errors = true;
  3238. return false;
  3239. };
  3240. Site.prototype.handleResumeClick = function() {
  3241. Page.cmd("siteResume", {
  3242. "address": this.row.address
  3243. });
  3244. return false;
  3245. };
  3246. Site.prototype.handlePauseClick = function() {
  3247. Page.cmd("sitePause", {
  3248. "address": this.row.address
  3249. });
  3250. return false;
  3251. };
  3252. Site.prototype.handleCloneClick = function() {
  3253. Page.cmd("siteClone", {
  3254. "address": this.row.address
  3255. });
  3256. return false;
  3257. };
  3258. Site.prototype.handleCloneUpgradeClick = function() {
  3259. Page.cmd("wrapperConfirm", ["Are you sure?" + (" Any modifications you made on<br><b>" + this.row.content.title + "</b> site's js/css files will be lost."), "Upgrade"], (function(_this) {
  3260. return function(confirmed) {
  3261. return Page.cmd("siteClone", {
  3262. "address": _this.row.content.cloned_from,
  3263. "root_inner_path": _this.row.content.clone_root,
  3264. "target_address": _this.row.address
  3265. });
  3266. };
  3267. })(this));
  3268. return false;
  3269. };
  3270. Site.prototype.handleDeleteClick = function() {
  3271. if (this.row.settings.own) {
  3272. Page.cmd("wrapperConfirm", ["You can delete your site using the site's sidebar.", ["Open site"]], (function(_this) {
  3273. return function(confirmed) {
  3274. if (confirmed) {
  3275. return window.top.location = _this.getHref() + "#ZeroNet:OpenSidebar";
  3276. }
  3277. };
  3278. })(this));
  3279. } else {
  3280. if (!this.row.content.title) {
  3281. Page.cmd("siteDelete", {
  3282. "address": this.row.address
  3283. });
  3284. this.item_list.deleteItem(this);
  3285. Page.projector.scheduleRender();
  3286. } else if (Page.server_info.rev > 2060) {
  3287. Page.cmd("wrapperConfirm", ["Are you sure?" + (" <b>" + this.row.content.title + "</b>"), ["Delete", "Blacklist"]], (function(_this) {
  3288. return function(confirmed) {
  3289. if (confirmed === 1) {
  3290. Page.cmd("siteDelete", {
  3291. "address": _this.row.address
  3292. });
  3293. _this.item_list.deleteItem(_this);
  3294. return Page.projector.scheduleRender();
  3295. } else if (confirmed === 2) {
  3296. return Page.cmd("wrapperPrompt", ["Blacklist <b>" + _this.row.content.title + "</b>", "text", "Delete and Blacklist", "Reason"], function(reason) {
  3297. Page.cmd("siteDelete", {
  3298. "address": _this.row.address
  3299. });
  3300. Page.cmd("siteblockAdd", [_this.row.address, reason]);
  3301. _this.item_list.deleteItem(_this);
  3302. return Page.projector.scheduleRender();
  3303. });
  3304. }
  3305. };
  3306. })(this));
  3307. } else {
  3308. Page.cmd("wrapperConfirm", ["Are you sure?" + (" <b>" + this.row.content.title + "</b>"), "Delete"], (function(_this) {
  3309. return function(confirmed) {
  3310. if (confirmed) {
  3311. Page.cmd("siteDelete", {
  3312. "address": _this.row.address
  3313. });
  3314. _this.item_list.deleteItem(_this);
  3315. return Page.projector.scheduleRender();
  3316. }
  3317. };
  3318. })(this));
  3319. }
  3320. }
  3321. return false;
  3322. };
  3323. Site.prototype.handleSettingsClick = function(e) {
  3324. this.menu.items = [];
  3325. if (this.favorite) {
  3326. this.menu.items.push(["Unfavorite", this.handleUnfavoriteClick]);
  3327. } else {
  3328. this.menu.items.push(["Favorite", this.handleFavoriteClick]);
  3329. }
  3330. this.menu.items.push(["Update", this.handleUpdateClick]);
  3331. this.menu.items.push(["Check files", this.handleCheckfilesClick]);
  3332. if (this.row.settings.serving) {
  3333. this.menu.items.push(["Pause", this.handlePauseClick]);
  3334. } else {
  3335. this.menu.items.push(["Resume", this.handleResumeClick]);
  3336. }
  3337. this.menu.items.push(["Save as .zip", "/ZeroNet-Internal/Zip?address=" + this.row.address]);
  3338. if (this.row.content.cloneable === true) {
  3339. this.menu.items.push(["Clone", this.handleCloneClick]);
  3340. }
  3341. if (this.row.settings.own && this.row.content.cloned_from && Page.server_info.rev >= 2080) {
  3342. this.menu.items.push(["---"]);
  3343. this.menu.items.push(["Upgrade code", this.handleCloneUpgradeClick]);
  3344. }
  3345. this.menu.items.push(["---"]);
  3346. this.menu.items.push(["Delete", this.handleDeleteClick]);
  3347. if (this.menu.visible) {
  3348. this.menu.hide();
  3349. } else {
  3350. this.menu.show();
  3351. }
  3352. return false;
  3353. };
  3354. Site.prototype.handleHelpClick = function(directory, title) {
  3355. if (this.optional_helps_disabled[directory]) {
  3356. Page.cmd("OptionalHelp", [directory, title, this.row.address]);
  3357. delete this.optional_helps_disabled[directory];
  3358. } else {
  3359. Page.cmd("OptionalHelpRemove", [directory, this.row.address]);
  3360. this.optional_helps_disabled[directory] = true;
  3361. }
  3362. return true;
  3363. };
  3364. Site.prototype.handleHelpAllClick = function() {
  3365. if (this.row.settings.autodownloadoptional === true) {
  3366. return Page.cmd("OptionalHelpAll", [false, this.row.address], (function(_this) {
  3367. return function() {
  3368. _this.row.settings.autodownloadoptional = false;
  3369. return Page.projector.scheduleRender();
  3370. };
  3371. })(this));
  3372. } else {
  3373. return Page.cmd("OptionalHelpAll", [true, this.row.address], (function(_this) {
  3374. return function() {
  3375. _this.row.settings.autodownloadoptional = true;
  3376. return Page.projector.scheduleRender();
  3377. };
  3378. })(this));
  3379. }
  3380. };
  3381. Site.prototype.handleHelpsClick = function(e) {
  3382. var directory, i, len, ref, ref1, title;
  3383. if (e.target.classList.contains("menu-item")) {
  3384. return;
  3385. }
  3386. if (!this.menu_helps) {
  3387. this.menu_helps = new Menu();
  3388. }
  3389. this.menu_helps.items = [];
  3390. this.menu_helps.items.push([
  3391. "Help distribute all new files", this.handleHelpAllClick, ((function(_this) {
  3392. return function() {
  3393. return _this.row.settings.autodownloadoptional;
  3394. };
  3395. })(this))
  3396. ]);
  3397. if (this.optional_helps.length > 0) {
  3398. this.menu_helps.items.push(["---"]);
  3399. }
  3400. ref = this.optional_helps;
  3401. for (i = 0, len = ref.length; i < len; i++) {
  3402. ref1 = ref[i], directory = ref1[0], title = ref1[1];
  3403. this.menu_helps.items.push([
  3404. title, ((function(_this) {
  3405. return function() {
  3406. return _this.handleHelpClick(directory, title);
  3407. };
  3408. })(this)), ((function(_this) {
  3409. return function() {
  3410. return !_this.optional_helps_disabled[directory];
  3411. };
  3412. })(this))
  3413. ]);
  3414. }
  3415. this.menu_helps.toggle();
  3416. return true;
  3417. };
  3418. Site.prototype.getHref = function(row) {
  3419. var href;
  3420. href = Text.getSiteUrl(this.row.address);
  3421. if (row != null ? row.inner_path : void 0) {
  3422. return href + row.inner_path;
  3423. } else {
  3424. return href;
  3425. }
  3426. };
  3427. Site.prototype.handleLimitIncreaseClick = function() {
  3428. if (Page.server_info.rev < 3170) {
  3429. return Page.cmd("wrapperNotification", ["info", "You need ZeroNet Rev3170 to use this command"]);
  3430. }
  3431. Page.cmd("as", [this.row.address, "siteSetLimit", this.row.need_limit], (function(_this) {
  3432. return function(res) {
  3433. if (res === "ok") {
  3434. Page.cmd("wrapperNotification", ["done", "Site <b>" + _this.row.content.title + "</b> storage limit modified to <b>" + _this.row.need_limit + "MB</b>", 5000]);
  3435. } else {
  3436. Page.cmd("wrapperNotification", ["error", res.error]);
  3437. }
  3438. return Page.projector.scheduleRender();
  3439. };
  3440. })(this));
  3441. return false;
  3442. };
  3443. Site.prototype.render = function() {
  3444. var now, ref;
  3445. now = Date.now() / 1000;
  3446. return h("div.site", {
  3447. key: this.key,
  3448. "data-key": this.key,
  3449. classes: {
  3450. "modified-lastday": now - this.row.settings.modified < 60 * 60 * 24,
  3451. "disabled": !this.row.settings.serving && !this.row.demo,
  3452. "working": this.isWorking()
  3453. }
  3454. }, h("div.circle", {
  3455. style: "color: " + (Text.toColor(this.row.address, 40, 50))
  3456. }, ["\u2022"]), h("a.inner", {
  3457. href: this.getHref(),
  3458. title: ((ref = this.row.content.title) != null ? ref.length : void 0) > 20 ? this.row.content.title : void 0
  3459. }, [
  3460. h("span.title", [this.row.content.title || this.row.address]), h("div.details", [h("span.modified", [h("div.icon-clock"), Page.settings.sites_orderby === "size" ? h("span.value", [(this.row.settings.size / 1024 / 1024 + (this.row.settings.size_optional != null) / 1024 / 1024).toFixed(1), "MB"]) : h("span.value", [Time.since(this.row.settings.modified)])]), h("span.peers", [h("div.icon-profile"), h("span.value", [Math.max((this.row.settings.peers ? this.row.settings.peers : 0), this.row.peers)])])]), this.row.demo ? h("div.details.demo", "Activate \u00BB") : void 0, this.row.need_limit ? h("a.details.needaction", {
  3461. href: "#Set+limit",
  3462. onclick: this.handleLimitIncreaseClick
  3463. }, "Set limit to " + this.row.need_limit + "MB") : void 0, h("div.message", {
  3464. classes: {
  3465. visible: this.message_visible,
  3466. done: this.message_class === 'done',
  3467. error: this.message_class === 'error',
  3468. collapsed: this.message_collapsed
  3469. }
  3470. }, [this.message])
  3471. ]), h("a.settings", {
  3472. href: "#Settings",
  3473. tabIndex: -1,
  3474. onmousedown: this.handleSettingsClick,
  3475. onclick: Page.returnFalse
  3476. }, ["\u22EE"]), this.menu.render());
  3477. };
  3478. Site.prototype.renderCircle = function(value, max) {
  3479. var dashoffset, stroke;
  3480. if (value < 1) {
  3481. dashoffset = 75 + (1 - value) * 75;
  3482. } else {
  3483. dashoffset = Math.max(0, 75 - ((value - 1) / 9) * 75);
  3484. }
  3485. stroke = "hsl(" + (Math.min(555, value * 50)) + ", 100%, 61%)";
  3486. return h("div.circle", {
  3487. title: "Upload/Download ratio",
  3488. innerHTML: "<svg class=\"circle-svg\" width=\"30\" height=\"30\" viewPort=\"0 0 30 30\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle r=\"12\" cx=\"15\" cy=\"15\" fill=\"transparent\" class='circle-bg'></circle>\n <circle r=\"12\" cx=\"15\" cy=\"15\" fill=\"transparent\" class='circle-fg' style='stroke-dashoffset: " + dashoffset + "; stroke: " + stroke + "'></circle>\n</svg>"
  3489. });
  3490. };
  3491. Site.prototype.renderOptionalStats = function() {
  3492. var ratio, ratio_hue, row;
  3493. row = this.row;
  3494. ratio = (row.settings.bytes_sent / row.settings.bytes_recv).toFixed(1);
  3495. if (ratio >= 100) {
  3496. ratio = "\u221E";
  3497. } else if (ratio >= 10) {
  3498. ratio = (row.settings.bytes_sent / row.settings.bytes_recv).toFixed(0);
  3499. }
  3500. ratio_hue = Math.min(555, (row.settings.bytes_sent / row.settings.bytes_recv) * 50);
  3501. return h("div.site", {
  3502. key: this.key
  3503. }, [
  3504. h("div.title", [
  3505. h("h3.name", h("a", {
  3506. href: this.getHref()
  3507. }, row.content.title)), h("div.size", {
  3508. title: "Site size limit: " + (Text.formatSize(row.size_limit * 1024 * 1024))
  3509. }, [
  3510. "" + (Text.formatSize(row.settings.size)), h("div.bar", h("div.bar-active", {
  3511. style: "width: " + (100 * (row.settings.size / (row.size_limit * 1024 * 1024))) + "%"
  3512. }))
  3513. ]), h("div.plus", "+"), h("div.size.size-optional", {
  3514. title: "Optional files on site: " + (Text.formatSize(row.settings.size_optional))
  3515. }, [
  3516. "" + (Text.formatSize(row.settings.optional_downloaded)), h("span.size-title", "Optional"), h("div.bar", h("div.bar-active", {
  3517. style: "width: " + (100 * (row.settings.optional_downloaded / row.settings.size_optional)) + "%"
  3518. }))
  3519. ]), h("a.helps", {
  3520. href: "#",
  3521. onmousedown: this.handleHelpsClick,
  3522. onclick: Page.returnFalse
  3523. }, h("div.icon-share"), this.row.settings.autodownloadoptional ? "\u2661" : this.optional_helps.length, h("div.icon-arrow-down"), this.menu_helps ? this.menu_helps.render() : void 0), this.renderCircle(parseFloat((row.settings.bytes_sent / row.settings.bytes_recv).toFixed(1)), 10), h("div.circle-value", {
  3524. classes: {
  3525. negative: ratio < 1
  3526. },
  3527. style: "color: hsl(" + ratio_hue + ", 70%, 60%)"
  3528. }, ratio), h("div.transfers", [
  3529. h("div.up", {
  3530. "title": "Uploaded"
  3531. }, "\u22F0 \u00A0" + (Text.formatSize(row.settings.bytes_sent))), h("div.down", {
  3532. "title": "Downloaded"
  3533. }, "\u22F1 \u00A0" + (Text.formatSize(row.settings.bytes_recv)))
  3534. ])
  3535. ]), this.files.render()
  3536. ]);
  3537. };
  3538. return Site;
  3539. })(Class);
  3540. window.Site = Site;
  3541. }).call(this);
  3542. /* ---- PageSites/SiteList.coffee ---- */
  3543. (function() {
  3544. var SiteList,
  3545. bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
  3546. extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
  3547. hasProp = {}.hasOwnProperty;
  3548. SiteList = (function(superClass) {
  3549. extend(SiteList, superClass);
  3550. function SiteList() {
  3551. this.onSiteInfo = bind(this.onSiteInfo, this);
  3552. this.render = bind(this.render, this);
  3553. this.handleSiteListMoreClick = bind(this.handleSiteListMoreClick, this);
  3554. this.handleFilterClear = bind(this.handleFilterClear, this);
  3555. this.handleFilterKeyup = bind(this.handleFilterKeyup, this);
  3556. this.handleFilterInput = bind(this.handleFilterInput, this);
  3557. this.renderMergedSites = bind(this.renderMergedSites, this);
  3558. this.reorder = bind(this.reorder, this);
  3559. this.sortRows = bind(this.sortRows, this);
  3560. this.reorderTimer = bind(this.reorderTimer, this);
  3561. this.item_list = new ItemList(Site, "address");
  3562. this.sites = this.item_list.items;
  3563. this.sites_byaddress = this.item_list.items_bykey;
  3564. this.inactive_demo_sites = null;
  3565. this.loaded = false;
  3566. this.on_loaded = new Promise();
  3567. this.schedule_reorder = false;
  3568. this.merged_db = {};
  3569. this.filtering = "";
  3570. setInterval(this.reorderTimer, 10000);
  3571. this.limit = 100;
  3572. Page.on_settings.then((function(_this) {
  3573. return function() {
  3574. return Page.on_server_info.then(function() {
  3575. _this.update();
  3576. return Page.cmd("channelJoinAllsite", {
  3577. "channel": "siteChanged"
  3578. });
  3579. });
  3580. };
  3581. })(this));
  3582. }
  3583. SiteList.prototype.reorderTimer = function() {
  3584. if (!this.schedule_reorder) {
  3585. return;
  3586. }
  3587. if (!document.querySelector('.left:hover') && !document.querySelector(".working") && !Page.mode === "Files") {
  3588. this.reorder();
  3589. return this.schedule_reorder = false;
  3590. }
  3591. };
  3592. SiteList.prototype.sortRows = function(rows) {
  3593. if (Page.settings.sites_orderby === "modified") {
  3594. rows.sort(function(a, b) {
  3595. return b.row.settings.modified - a.row.settings.modified;
  3596. });
  3597. } else if (Page.settings.sites_orderby === "addtime") {
  3598. rows.sort(function(a, b) {
  3599. return b.row.settings.added - a.row.settings.added;
  3600. });
  3601. } else if (Page.settings.sites_orderby === "size") {
  3602. rows.sort(function(a, b) {
  3603. return b.row.settings.size - a.row.settings.size;
  3604. });
  3605. } else {
  3606. rows.sort(function(a, b) {
  3607. return Math.max(b.row.peers, b.row.settings.peers) - Math.max(a.row.peers, a.row.settings.peers);
  3608. });
  3609. }
  3610. return rows;
  3611. };
  3612. SiteList.prototype.reorder = function() {
  3613. this.sortRows(this.item_list.items);
  3614. return Page.projector.scheduleRender();
  3615. };
  3616. SiteList.prototype.update = function() {
  3617. var args;
  3618. if (Page.server_info.rev >= 3660) {
  3619. args = {
  3620. connecting_sites: true
  3621. };
  3622. } else {
  3623. args = {};
  3624. }
  3625. Page.cmd("siteList", args, (function(_this) {
  3626. return function(site_rows) {
  3627. var favorite_sites;
  3628. favorite_sites = Page.settings.favorite_sites;
  3629. _this.item_list.sync(site_rows);
  3630. _this.sortRows(_this.item_list.items);
  3631. if (_this.inactive_demo_sites === null) {
  3632. _this.updateInactiveDemoSites();
  3633. }
  3634. Page.projector.scheduleRender();
  3635. _this.loaded = true;
  3636. _this.log("loaded");
  3637. return _this.on_loaded.resolve();
  3638. };
  3639. })(this));
  3640. return this;
  3641. };
  3642. SiteList.prototype.updateInactiveDemoSites = function() {
  3643. var demo_site_rows, i, len, results, site_row;
  3644. demo_site_rows = [
  3645. {
  3646. address: "1MeFqFfFFGQfa1J3gJyYYUvb5Lksczq7nH",
  3647. demo: true,
  3648. content: {
  3649. title: "ZeroMe",
  3650. },
  3651. settings: {}
  3652. }, {
  3653. address: "1TaLkFrMwvbNsooF4ioKAY9EuxTBTjipT",
  3654. demo: true,
  3655. content: {
  3656. title: "ZeroTalk",
  3657. },
  3658. settings: {}
  3659. }, {
  3660. address: "1EfLnw7GDXbZfJmGNoXGQ4XkuHGWkRZTMq",
  3661. demo: true,
  3662. content: {
  3663. title: "ZeroTalk Tech",
  3664. },
  3665. settings: {}
  3666. }, {
  3667. address: "13gLfTixjjktySEGHBMnmrQu4qMJpoRuXw",
  3668. demo: true,
  3669. content: {
  3670. title: "The All-Night Bookstore and Cafe",
  3671. },
  3672. settings: {}
  3673. }, {
  3674. address: "1MaiL5gfBM1cyb4a8e3iiL8L5gXmoAJu27",
  3675. demo: true,
  3676. content: {
  3677. title: "ZeroMail",
  3678. },
  3679. settings: {}
  3680. }, {
  3681. address: "1SiTEs2D3rCBxeMoLHXei2UYqFcxctdwB",
  3682. demo: true,
  3683. content: {
  3684. title: "ZeroSites",
  3685. },
  3686. settings: {}
  3687. }, {
  3688. address: "186THqMWuptrZxq1rxzpguAivK3Bs6z84o",
  3689. demo: true,
  3690. content: {
  3691. title: "0list"
  3692. },
  3693. settings: {}
  3694. }, {
  3695. address: "1xiwbXaTbo9XU32hEpW4NyjZHrugSFdo6",
  3696. demo: true,
  3697. content: {
  3698. title: "Search and Index sites"
  3699. },
  3700. settings: {}
  3701. }, {
  3702. address: "15CEFKBRHFfAP9rmL6hhLmHoXrrgmw4B5o",
  3703. demo: true,
  3704. content: {
  3705. title: "Syncronite"
  3706. },
  3707. settings: {}
  3708. }
  3709. ];
  3710. this.inactive_demo_sites = [];
  3711. results = [];
  3712. for (i = 0, len = demo_site_rows.length; i < len; i++) {
  3713. site_row = demo_site_rows[i];
  3714. if (this.filtering && site.row.content.title.toLowerCase().indexOf(this.filtering.toLowerCase()) === -1) {
  3715. continue;
  3716. }
  3717. if (!this.sites_byaddress[site_row.address]) {
  3718. results.push(this.inactive_demo_sites.push(new Site(site_row)));
  3719. } else {
  3720. results.push(void 0);
  3721. }
  3722. }
  3723. return results;
  3724. };
  3725. SiteList.prototype.renderMergedSites = function() {
  3726. var back, i, len, merged_db, merged_sites, merged_type, name, ref, site;
  3727. merged_db = {};
  3728. ref = this.sites_merged;
  3729. for (i = 0, len = ref.length; i < len; i++) {
  3730. site = ref[i];
  3731. if (!site.row.content.merged_type) {
  3732. continue;
  3733. }
  3734. if (merged_db[name = site.row.content.merged_type] == null) {
  3735. merged_db[name] = [];
  3736. }
  3737. merged_db[site.row.content.merged_type].push(site);
  3738. }
  3739. back = [];
  3740. for (merged_type in merged_db) {
  3741. merged_sites = merged_db[merged_type];
  3742. back.push([
  3743. h("h2.more", {
  3744. key: "Merged: " + merged_type
  3745. }, "Merged: " + merged_type), h("div.SiteList.merged.merged-" + merged_type, merged_sites.map(function(item) {
  3746. return item.render();
  3747. }))
  3748. ]);
  3749. }
  3750. return back;
  3751. };
  3752. SiteList.prototype.handleFilterInput = function(e) {
  3753. return this.filtering = e.target.value;
  3754. };
  3755. SiteList.prototype.handleFilterKeyup = function(e) {
  3756. if (e.keyCode === 27) {
  3757. e.target.value = "";
  3758. this.handleFilterInput(e);
  3759. }
  3760. return false;
  3761. };
  3762. SiteList.prototype.handleFilterClear = function(e) {
  3763. e.target.value = "";
  3764. this.handleFilterInput(e);
  3765. return false;
  3766. };
  3767. SiteList.prototype.handleSiteListMoreClick = function(e) {
  3768. this.limit += 1000;
  3769. Page.projector.scheduleRender();
  3770. return false;
  3771. };
  3772. SiteList.prototype.render = function() {
  3773. var filter_base, i, len, num_found, ref, ref1, ref2, site;
  3774. if (!this.loaded) {
  3775. return h("div#SiteList");
  3776. }
  3777. this.sites_needaction = [];
  3778. this.sites_favorited = [];
  3779. this.sites_owned = [];
  3780. this.sites_recent = [];
  3781. this.sites_connected = [];
  3782. this.sites_connecting = [];
  3783. this.sites_merged = [];
  3784. num_found = 0;
  3785. ref = this.sites;
  3786. for (i = 0, len = ref.length; i < len; i++) {
  3787. site = ref[i];
  3788. if (this.filtering) {
  3789. filter_base = site.row.content.title + site.row.content.merged_type + site.row.address;
  3790. if (filter_base.toLowerCase().indexOf(this.filtering.toLowerCase()) === -1) {
  3791. continue;
  3792. }
  3793. }
  3794. if (site.row.settings.size * 1.2 > site.row.size_limit * 1024 * 1024) {
  3795. site.row.need_limit = site.row.size_limit * 2;
  3796. this.sites_needaction.push(site);
  3797. } else if (site.favorite) {
  3798. this.sites_favorited.push(site);
  3799. } else if (site.row.content.merged_type) {
  3800. this.sites_merged.push(site);
  3801. } else if ((ref1 = site.row.settings) != null ? ref1.own : void 0) {
  3802. this.sites_owned.push(site);
  3803. } else if (((ref2 = site.row.settings) != null ? ref2.downloaded : void 0) > Time.timestamp() - 60 * 60 * 24) {
  3804. this.sites_recent.push(site);
  3805. } else if (site.row.content.title) {
  3806. this.sites_connected.push(site);
  3807. } else {
  3808. this.sites_connecting.push(site);
  3809. }
  3810. num_found += 1;
  3811. }
  3812. return h("div#SiteList", [
  3813. this.sites.length > 10 ? h("input.site-filter", {
  3814. placeholder: "Filter: Site name",
  3815. spellcheck: false,
  3816. oninput: this.handleFilterInput,
  3817. onkeyup: this.handleFilterKeyup,
  3818. value: this.filtering
  3819. }) : void 0, this.filtering ? [
  3820. h("span.filter-num", {
  3821. updateAnimation: Animation.show,
  3822. enterAnimation: Animation.show,
  3823. exitAnimation: Animation.hide
  3824. }, "(found " + num_found + " of " + this.sites.length + " sites)"), h("a.filter-clear", {
  3825. href: "#clear",
  3826. onclick: this.handleFilterClear
  3827. }, "\u00D7")
  3828. ] : void 0, this.sites_recent.length > 0 ? h("h2.recent", "Recently downloaded:") : void 0, h("div.SiteList.recent", this.sites_recent.map(function(item) {
  3829. return item.render();
  3830. })), this.sites_needaction.length > 0 ? h("h2.needaction", "Running out of size limit:") : void 0, h("div.SiteList.needaction", this.sites_needaction.map(function(item) {
  3831. return item.render();
  3832. })), this.sites_favorited.length > 0 ? h("h2.favorited", "Favorited sites:") : void 0, h("div.SiteList.favorited", this.sites_favorited.map(function(item) {
  3833. return item.render();
  3834. })), this.sites_owned.length > 0 ? h("h2.owned", "Owned sites:") : void 0, h("div.SiteList.owned", this.sites_owned.map(function(item) {
  3835. return item.render();
  3836. })), this.sites_connecting.length > 0 ? h("h2.connecting", "Connecting sites:") : void 0, h("div.SiteList.connecting", this.sites_connecting.map(function(item) {
  3837. return item.render();
  3838. })), this.sites_connected.length > 0 ? h("h2.connected", "Connected sites:") : void 0, h("div.SiteList.connected", [
  3839. this.sites_connected.slice(0, +(this.limit - 1) + 1 || 9e9).map(function(item) {
  3840. return item.render();
  3841. }), this.sites_connected.length > this.limit ? h("a.site-list-more", {
  3842. href: "#Show+more+connected+sites",
  3843. onclick: this.handleSiteListMoreClick
  3844. }, "Show more") : void 0
  3845. ]), this.renderMergedSites(), this.inactive_demo_sites !== null && this.inactive_demo_sites.length > 0 ? [
  3846. h("h2.more", {
  3847. key: "More"
  3848. }, "More sites:"), h("div.SiteList.more", this.inactive_demo_sites.map(function(item) {
  3849. return item.render();
  3850. }))
  3851. ] : void 0
  3852. ]);
  3853. };
  3854. SiteList.prototype.onSiteInfo = function(site_info) {
  3855. var ref;
  3856. if ((ref = this.item_list.items_bykey[site_info.address]) != null) {
  3857. ref.setRow(site_info);
  3858. }
  3859. this.schedule_reorder = true;
  3860. return Page.projector.scheduleRender();
  3861. };
  3862. return SiteList;
  3863. })(Class);
  3864. window.SiteList = SiteList;
  3865. }).call(this);
  3866. /* ---- PageSites/Trigger.coffee ---- */
  3867. (function() {
  3868. var Trigger,
  3869. bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
  3870. extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
  3871. hasProp = {}.hasOwnProperty;
  3872. Trigger = (function(superClass) {
  3873. extend(Trigger, superClass);
  3874. function Trigger() {
  3875. this.render = bind(this.render, this);
  3876. this.handleTitleClick = bind(this.handleTitleClick, this);
  3877. this.active = false;
  3878. }
  3879. Trigger.prototype.handleTitleClick = function() {
  3880. this.active = !this.active;
  3881. if (this.active) {
  3882. document.getElementById("left").classList.add("trigger-on");
  3883. } else {
  3884. document.getElementById("left").classList.remove("trigger-on");
  3885. }
  3886. return false;
  3887. };
  3888. Trigger.prototype.render = function() {
  3889. return h("div.Trigger", {
  3890. classes: {
  3891. "active": this.active
  3892. }
  3893. }, [
  3894. h("a.icon", {
  3895. "href": "#Trigger",
  3896. onclick: this.handleTitleClick,
  3897. ontouchend: ""
  3898. }, h("div.arrow-right"))
  3899. ]);
  3900. };
  3901. return Trigger;
  3902. })(Class);
  3903. window.Trigger = Trigger;
  3904. }).call(this);
  3905. /* ---- PageStats/Chart.coffee ---- */
  3906. (function() {
  3907. var Chart,
  3908. bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
  3909. extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
  3910. hasProp = {}.hasOwnProperty;
  3911. Chart = (function(superClass) {
  3912. extend(Chart, superClass);
  3913. function Chart() {
  3914. this.render = bind(this.render, this);
  3915. this.updateChart = bind(this.updateChart, this);
  3916. this.update = bind(this.update, this);
  3917. this.getTitle = bind(this.getTitle, this);
  3918. this.initChart = bind(this.initChart, this);
  3919. this.query = "";
  3920. this.title = "";
  3921. this.value = "";
  3922. this.line_data = [];
  3923. this.details = [];
  3924. this.colorize = "cc00ff0a";
  3925. this.chart_ctx = null;
  3926. this.chart_type_name = null;
  3927. this.need_update = false;
  3928. }
  3929. Chart.prototype.initChart = function(node) {
  3930. this.chart_canvas = node;
  3931. return this.chart_ctx = node.getContext("2d");
  3932. };
  3933. Chart.prototype.getTitle = function() {
  3934. return this.title;
  3935. };
  3936. Chart.prototype.update = function() {
  3937. var query_type_data, type_name;
  3938. Page.cmd("chartDbQuery", this.getChartQuery(), (function(_this) {
  3939. return function(res) {
  3940. var j, len, row;
  3941. _this.line_data = [];
  3942. for (j = 0, len = res.length; j < len; j++) {
  3943. row = res[j];
  3944. _this.line_data.push(row.value);
  3945. }
  3946. _this.line_data.reverse();
  3947. return _this.updateChart();
  3948. };
  3949. })(this));
  3950. query_type_data = "SELECT * FROM data\nWHERE\n type_id IN :type_ids AND\n date_added = (SELECT date_added FROM data ORDER BY data_id DESC LIMIT 1)";
  3951. return Page.cmd("chartDbQuery", [
  3952. query_type_data, {
  3953. type_ids: (function() {
  3954. var j, len, ref, results;
  3955. ref = this.type_names;
  3956. results = [];
  3957. for (j = 0, len = ref.length; j < len; j++) {
  3958. type_name = ref[j];
  3959. results.push(Page.page_stats.type_id_db[type_name]);
  3960. }
  3961. return results;
  3962. }).call(this)
  3963. }
  3964. ], (function(_this) {
  3965. return function(res) {
  3966. var j, len, row, type_data;
  3967. type_data = {};
  3968. for (j = 0, len = res.length; j < len; j++) {
  3969. row = res[j];
  3970. type_data[Page.page_stats.type_name_db[row.type_id]] = row.value;
  3971. }
  3972. _this.details = typeof _this.formatDetails === "function" ? _this.formatDetails(type_data) : void 0;
  3973. _this.value = typeof _this.formatValue === "function" ? _this.formatValue(type_data) : void 0;
  3974. return Page.projector.scheduleRender();
  3975. };
  3976. })(this));
  3977. };
  3978. Chart.prototype.updateChart = function() {
  3979. var data, data_max, data_min, gradient, i, j, len, line_y, ref, step, stroke;
  3980. this.chart_ctx.clearRect(0, 0, this.chart_canvas.width, this.chart_canvas.height);
  3981. stroke = this.chart_ctx.createLinearGradient(0, 0, 900, 0);
  3982. stroke.addColorStop(0, this.chart_stroke[0]);
  3983. stroke.addColorStop(1, this.chart_stroke[1]);
  3984. this.chart_ctx.lineWidth = 4;
  3985. this.chart_ctx.strokeStyle = stroke;
  3986. this.chart_ctx.fillStyle = '#66666611';
  3987. gradient = this.chart_ctx.createLinearGradient(0, 200, 0, 400);
  3988. gradient.addColorStop(0, "#42324599");
  3989. gradient.addColorStop(1, "#2C2E3700");
  3990. this.chart_ctx.fillStyle = gradient;
  3991. this.chart_ctx.beginPath();
  3992. this.chart_ctx.moveTo(-10, 0);
  3993. step = 900 / (this.line_data.length - 2);
  3994. data_max = Math.max.apply(null, this.line_data);
  3995. data_min = Math.min.apply(null, this.line_data);
  3996. ref = this.line_data;
  3997. for (i = j = 0, len = ref.length; j < len; i = ++j) {
  3998. data = ref[i];
  3999. line_y = 250 - ((data - data_min) / (data_max - data_min)) * 120;
  4000. this.chart_ctx.lineTo((i - 1) * step, line_y);
  4001. }
  4002. this.chart_ctx.lineTo((i + 1) * step, line_y);
  4003. this.chart_ctx.lineTo(i * step, 450);
  4004. this.chart_ctx.lineTo(0, 450);
  4005. this.chart_ctx.fill();
  4006. this.chart_ctx.stroke();
  4007. return this.chart_ctx.shadowBlur = 0;
  4008. };
  4009. Chart.prototype.render = function() {
  4010. if (this.need_update) {
  4011. this.update();
  4012. this.need_update = false;
  4013. }
  4014. return h("div.Chart", {
  4015. style: "background-image: radial-gradient(at 29% top, #eaaeda05, " + this.colorize + ")"
  4016. }, [
  4017. h("div.titles", [
  4018. h("div.title", this.getTitle()), h("div.value", this.value), h("div.details", this.details.map((function(_this) {
  4019. return function(detail) {
  4020. return [
  4021. detail, h("br", {
  4022. key: detail
  4023. })
  4024. ];
  4025. };
  4026. })(this)))
  4027. ]), h("canvas.canvas", {
  4028. afterCreate: this.initChart,
  4029. width: 900,
  4030. height: 400
  4031. })
  4032. ]);
  4033. };
  4034. return Chart;
  4035. })(Class);
  4036. window.Chart = Chart;
  4037. }).call(this);
  4038. /* ---- PageStats/ChartBig.coffee ---- */
  4039. (function() {
  4040. var ChartBig,
  4041. bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
  4042. extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
  4043. hasProp = {}.hasOwnProperty;
  4044. ChartBig = (function(superClass) {
  4045. extend(ChartBig, superClass);
  4046. function ChartBig() {
  4047. this.render = bind(this.render, this);
  4048. this.initChart = bind(this.initChart, this);
  4049. this.storeCanvasNode = bind(this.storeCanvasNode, this);
  4050. this.update = bind(this.update, this);
  4051. var types;
  4052. this.need_update = false;
  4053. this.data = {};
  4054. this.data_max = {};
  4055. this.data_total = {};
  4056. types = {};
  4057. }
  4058. ChartBig.prototype.update = function(cb) {
  4059. var date_added_from, date_added_to, interval, query, query_group, query_select, step, type, type_ids;
  4060. if (Page.params.interval === "1w") {
  4061. interval = 60 * 60 * 24 * 7;
  4062. step = 60 * 60;
  4063. query_select = "MAX(date_added) AS date_added, type_id, SUM(value) AS value";
  4064. query_group = "GROUP BY type_id, strftime('%Y-%m-%d %H', date_added, 'unixepoch', 'localtime')";
  4065. } else {
  4066. interval = 60 * 60 * 24;
  4067. step = 60 * 5;
  4068. query_select = "*";
  4069. query_group = "";
  4070. }
  4071. if (Page.params.date_added_to) {
  4072. date_added_to = (new Date(Page.params.date_added_to + " 23:59")).getTime() / 1000;
  4073. date_added_from = date_added_to - interval;
  4074. } else {
  4075. date_added_to = Time.timestamp();
  4076. date_added_from = Time.timestamp() - interval;
  4077. }
  4078. query = "SELECT " + query_select + " FROM data\nWHERE type_id IN :type_ids AND date_added >= :date_added_from AND date_added <= :date_added_to\n" + query_group + "\nORDER BY date_added";
  4079. type_ids = (function() {
  4080. var j, len, ref, results;
  4081. ref = this.types;
  4082. results = [];
  4083. for (j = 0, len = ref.length; j < len; j++) {
  4084. type = ref[j];
  4085. results.push(Page.page_stats.type_id_db[type.name]);
  4086. }
  4087. return results;
  4088. }).call(this);
  4089. return Page.cmd("chartDbQuery", [
  4090. query, {
  4091. type_ids: type_ids,
  4092. date_added_from: date_added_from,
  4093. date_added_to: date_added_to
  4094. }
  4095. ], (function(_this) {
  4096. return function(res) {
  4097. var data_date_added, data_found, data_value, dataset, i, j, k, l, len, len1, len2, len3, len4, m, n, row, type_id, type_name;
  4098. _this.logStart("Parse result");
  4099. _this.data = {
  4100. labels: []
  4101. };
  4102. _this.data_max = {};
  4103. _this.data_total = {};
  4104. for (j = 0, len = type_ids.length; j < len; j++) {
  4105. type_id = type_ids[j];
  4106. _this.data[type_id] = {};
  4107. _this.data_max[Page.page_stats.type_name_db[type_id]] = 0;
  4108. _this.data_total[Page.page_stats.type_name_db[type_id]] = 0;
  4109. }
  4110. for (k = 0, len1 = res.length; k < len1; k++) {
  4111. row = res[k];
  4112. type_name = Page.page_stats.type_name_db[row.type_id];
  4113. _this.data[row.type_id][Math.ceil(row.date_added / step) * step] = row.value;
  4114. _this.data_max[type_name] = Math.max(row.value, _this.data_max[type_name]);
  4115. _this.data_total[type_name] += row.value;
  4116. }
  4117. _this.configuration.options.scales.yAxes[0].ticks.suggestedMax = Math.max(_this.data_max["file_bytes_sent"], _this.data_max["file_bytes_recv"]);
  4118. _this.configuration.options.scales.yAxes[0].ticks.suggestedMin = 0 - _this.configuration.options.scales.yAxes[0].ticks.suggestedMax;
  4119. _this.configuration.options.scales.yAxes[1].ticks.suggestedMax = Math.max(_this.data_max["request_num_sent"], _this.data_max["request_num_recv"]);
  4120. _this.configuration.options.scales.yAxes[1].ticks.suggestedMin = 0 - _this.configuration.options.scales.yAxes[1].ticks.suggestedMax;
  4121. for (i = l = 0, len2 = type_ids.length; l < len2; i = ++l) {
  4122. type_id = type_ids[i];
  4123. dataset = _this.configuration.data.datasets[_this.types[i].dataset_id];
  4124. dataset.data.length = 0;
  4125. dataset.data_i = 0;
  4126. }
  4127. _this.configuration.data.labels.length = 0;
  4128. _this.configuration.data.labels_i = 0;
  4129. data_date_added = Math.ceil(date_added_from / step) * step;
  4130. while (data_date_added <= date_added_to) {
  4131. if (!data_found) {
  4132. for (i = m = 0, len3 = type_ids.length; m < len3; i = ++m) {
  4133. type_id = type_ids[i];
  4134. if (_this.data[type_id][data_date_added]) {
  4135. data_found = true;
  4136. break;
  4137. }
  4138. }
  4139. if (!data_found) {
  4140. data_date_added += step;
  4141. continue;
  4142. }
  4143. }
  4144. for (i = n = 0, len4 = type_ids.length; n < len4; i = ++n) {
  4145. type_id = type_ids[i];
  4146. data_value = _this.data[type_id][data_date_added];
  4147. dataset = _this.configuration.data.datasets[_this.types[i].dataset_id];
  4148. type = _this.types[i];
  4149. if (type.negative) {
  4150. data_value = 0 - data_value;
  4151. }
  4152. dataset.data[dataset.data_i] = data_value;
  4153. dataset.data_i += 1;
  4154. }
  4155. _this.configuration.data.labels.push(data_date_added * 1000);
  4156. _this.configuration.data.labels_i += 1;
  4157. data_date_added += step;
  4158. }
  4159. _this.logEnd("Parse result", "labels: " + _this.configuration.data.labels.length);
  4160. if (_this.chart) {
  4161. _this.chart.update();
  4162. } else {
  4163. _this.initChart();
  4164. }
  4165. if (typeof cb === "function") {
  4166. cb();
  4167. }
  4168. return Page.projector.scheduleRender();
  4169. };
  4170. })(this));
  4171. };
  4172. ChartBig.prototype.storeCanvasNode = function(node) {
  4173. if (this.chart) {
  4174. this.chart.clear();
  4175. this.chart.destroy();
  4176. this.chart = null;
  4177. }
  4178. node.parentNode.style.height = node.getBoundingClientRect().height + "px";
  4179. this.ctx = node.getContext("2d");
  4180. this.chart_node = node;
  4181. return this.configuration != null ? this.configuration : this.configuration = this.getChartConfiguration();
  4182. };
  4183. ChartBig.prototype.initChart = function() {
  4184. var timer_resize;
  4185. this.log("initChart");
  4186. this.chart = new Chart(this.ctx, this.configuration);
  4187. setTimeout(((function(_this) {
  4188. return function() {
  4189. return _this.chart_node.parentNode.style.height = "";
  4190. };
  4191. })(this)), 100);
  4192. timer_resize = null;
  4193. return window.addEventListener("resize", (function(_this) {
  4194. return function() {
  4195. clearInterval(timer_resize);
  4196. return setTimeout((function() {
  4197. return _this.chart.resize();
  4198. }), 300);
  4199. };
  4200. })(this));
  4201. };
  4202. ChartBig.prototype.testDataAddition = function() {
  4203. var timer_i;
  4204. timer_i = 0;
  4205. return setInterval(((function(_this) {
  4206. return function() {
  4207. var data, dataset, i, j, k, len, len1, new_data, new_labels, type_id;
  4208. new_labels = _this.configuration.data.labels.slice();
  4209. new_data = _this.configuration.data.datasets[_this.types[0].dataset_id].data.slice();
  4210. _this.configuration.data.labels = [];
  4211. timer_i += 1;
  4212. for (i = j = 0, len = type_ids.length; j < len; i = ++j) {
  4213. type_id = type_ids[i];
  4214. dataset = _this.configuration.data.datasets[_this.types[i].dataset_id];
  4215. dataset.data.push(Math.round(Math.random() * 10));
  4216. dataset.data.shift();
  4217. }
  4218. for (k = 0, len1 = new_data.length; k < len1; k++) {
  4219. data = new_data[k];
  4220. _this.configuration.data.datasets[_this.types[0].dataset_id].data.push(data);
  4221. }
  4222. _this.configuration.data.labels = new_labels;
  4223. _this.configuration.data.labels.push(1000 * (Time.timestamp() + (timer_i * 60 * 5)));
  4224. _this.configuration.data.labels.shift();
  4225. return _this.chart.update();
  4226. };
  4227. })(this)), 5000);
  4228. };
  4229. ChartBig.prototype.createGradientStroke = function(stops) {
  4230. var color, gradient, i, j, len;
  4231. gradient = this.ctx.createLinearGradient(0, 0, 900, 0);
  4232. for (i = j = 0, len = stops.length; j < len; i = ++j) {
  4233. color = stops[i];
  4234. gradient.addColorStop(i * (1 / (stops.length - 1)), color);
  4235. }
  4236. return gradient;
  4237. };
  4238. ChartBig.prototype.createGradientFill = function(stops, mode) {
  4239. var color, gradient, i, j, len;
  4240. if (mode == null) {
  4241. mode = "normal";
  4242. }
  4243. if (mode === "lower") {
  4244. gradient = this.ctx.createLinearGradient(0, 0, 0, 300);
  4245. } else {
  4246. gradient = this.ctx.createLinearGradient(0, 50, 0, 200);
  4247. }
  4248. for (i = j = 0, len = stops.length; j < len; i = ++j) {
  4249. color = stops[i];
  4250. gradient.addColorStop(i * (1 / (stops.length - 1)), color);
  4251. }
  4252. return gradient;
  4253. };
  4254. ChartBig.prototype.getChartConfiguration = function() {
  4255. var configuration, gradient_fill, gradient_fill_down, gradient_fill_up, gradient_stroke, gradient_stroke_bgline_down, gradient_stroke_bgline_up, gradient_stroke_down, gradient_stroke_up;
  4256. gradient_stroke = this.createGradientStroke(["#5A46DF", "#8F49AA", "#D64C57"]);
  4257. gradient_stroke_bgline_up = this.createGradientStroke(["#EEAAFF11", "#EEAAFF33", "#2da3b366"]);
  4258. gradient_stroke_bgline_down = this.createGradientStroke(["#EEAAFF11", "#EEAAFF33", "#80623f88"]);
  4259. gradient_stroke_up = this.createGradientStroke(["#2b68d9", "#2f99be", "#1dfc59"]);
  4260. gradient_stroke_down = this.createGradientStroke(["#bac735", "#c2a548", "#f1294b"]);
  4261. gradient_fill = this.createGradientFill(["#50455DEE", "#26262C33"]);
  4262. gradient_fill_up = this.createGradientFill(["#1dfc5922", "#2f373333"]);
  4263. gradient_fill_down = this.createGradientFill(["#45353533", "#f1294b22"], "lower");
  4264. configuration = {
  4265. type: 'line',
  4266. data: {
  4267. labels: [],
  4268. datasets: [
  4269. {
  4270. type: 'line',
  4271. label: "Upload",
  4272. borderColor: gradient_stroke_up,
  4273. pointBorderColor: gradient_stroke_up,
  4274. pointBackgroundColor: gradient_stroke_up,
  4275. pointHoverBackgroundColor: gradient_stroke_up,
  4276. pointHoverBorderColor: gradient_stroke_up,
  4277. pointHoverRadius: 2,
  4278. pointRadius: 0,
  4279. steppedLine: true,
  4280. fill: true,
  4281. backgroundColor: gradient_fill_up,
  4282. borderWidth: 1,
  4283. lineTension: 0,
  4284. data: []
  4285. }, {
  4286. type: 'line',
  4287. label: "Download",
  4288. borderColor: gradient_stroke_down,
  4289. pointBorderColor: gradient_stroke_down,
  4290. pointBackgroundColor: gradient_stroke_down,
  4291. pointHoverBackgroundColor: gradient_stroke_down,
  4292. pointHoverBorderColor: gradient_stroke_down,
  4293. pointHoverRadius: 2,
  4294. pointRadius: 0,
  4295. steppedLine: true,
  4296. fill: true,
  4297. backgroundColor: gradient_fill_down,
  4298. borderWidth: 1,
  4299. lineTension: 0,
  4300. data: []
  4301. }, {
  4302. type: 'line',
  4303. label: 'Sent',
  4304. borderColor: gradient_stroke_bgline_up,
  4305. backgroundColor: "rgba(255,255,255,0.0)",
  4306. pointRadius: 0,
  4307. borderWidth: 1,
  4308. pointHoverRadius: 2,
  4309. pointHoverBackgroundColor: gradient_stroke_bgline_up,
  4310. pointHoverBorderColor: gradient_stroke_bgline_up,
  4311. fill: true,
  4312. yAxisID: 'Request',
  4313. steppedLine: true,
  4314. lineTension: 0,
  4315. data: []
  4316. }, {
  4317. type: 'line',
  4318. label: 'Received',
  4319. borderColor: gradient_stroke_bgline_down,
  4320. backgroundColor: "rgba(255,255,255,0.0)",
  4321. pointRadius: 0,
  4322. borderWidth: 1,
  4323. pointHoverRadius: 2,
  4324. pointHoverBackgroundColor: gradient_stroke_bgline_down,
  4325. pointHoverBorderColor: gradient_stroke_bgline_down,
  4326. fill: true,
  4327. yAxisID: 'Request',
  4328. steppedLine: true,
  4329. lineTension: 0,
  4330. data: []
  4331. }
  4332. ]
  4333. },
  4334. options: {
  4335. animation: {
  4336. easing: "easeOutExpo",
  4337. duration: 2000
  4338. },
  4339. legend: {
  4340. display: false,
  4341. position: "top",
  4342. labels: {
  4343. fontColor: 'white'
  4344. }
  4345. },
  4346. title: {
  4347. display: false
  4348. },
  4349. tooltips: {
  4350. mode: "index",
  4351. intersect: false,
  4352. displayColors: false,
  4353. xPadding: 10,
  4354. yPadding: 10,
  4355. cornerRadius: 0,
  4356. caretPadding: 10,
  4357. bodyFontColor: "rgba(255,255,255,0.6)",
  4358. callbacks: {
  4359. title: function(tootlip_items, data) {
  4360. return Time.date(tootlip_items[0].xLabel, "long").replace(/:00$/, "");
  4361. },
  4362. label: function(tootlip_items, data) {
  4363. if (data.datasets[tootlip_items.datasetIndex].yAxisID === "Request") {
  4364. return data.datasets[tootlip_items.datasetIndex].label + ": " + Math.abs(tootlip_items.yLabel) + " requests";
  4365. } else {
  4366. return data.datasets[tootlip_items.datasetIndex].label + ": " + Text.formatSize(Math.abs(tootlip_items.yLabel));
  4367. }
  4368. }
  4369. }
  4370. },
  4371. hover: {
  4372. mode: "index",
  4373. intersect: false
  4374. },
  4375. scales: {
  4376. yAxes: [
  4377. {
  4378. id: 'Transfer',
  4379. ticks: {
  4380. fontColor: "rgba(100,110,132,1)",
  4381. fontStyle: "bold",
  4382. beginAtZero: true,
  4383. suggestedMax: 30000000,
  4384. suggestedMin: -30000000,
  4385. display: true,
  4386. padding: 30,
  4387. callback: function(value) {
  4388. return Text.formatSize(Math.abs(value));
  4389. }
  4390. },
  4391. gridLines: {
  4392. drawTicks: true,
  4393. drawBorder: false,
  4394. display: true,
  4395. zeroLineColor: "rgba(255,255,255,0.1)",
  4396. tickMarkLength: 20,
  4397. zeroLineBorderDashOffset: 100,
  4398. color: "rgba(255,255,255,0.05)"
  4399. }
  4400. }, {
  4401. id: 'Request',
  4402. position: "right",
  4403. ticks: {
  4404. beginAtZero: true,
  4405. maxTicksLimit: 5,
  4406. suggestedMax: 180,
  4407. suggestedMin: -180,
  4408. display: false
  4409. },
  4410. gridLines: {
  4411. display: false,
  4412. zeroLineColor: "rgba(255,255,255,0)",
  4413. drawBorder: false
  4414. }
  4415. }
  4416. ],
  4417. xAxes: [
  4418. {
  4419. type: "time",
  4420. gridLines: {
  4421. color: "rgba(255,255,255,0.1)",
  4422. display: false,
  4423. offsetGridLines: true,
  4424. drawBorder: false
  4425. },
  4426. ticks: {
  4427. padding: 15,
  4428. fontColor: "rgba(100,110,132,1)",
  4429. fontStyle: "bold",
  4430. callback: (function(_this) {
  4431. return function(data_label, index) {
  4432. var back, parts;
  4433. if (_this.last_data_label == null) {
  4434. _this.last_data_label = "None 00 00:00";
  4435. }
  4436. if (_this.last_data_label.match(/.* /)[0] === data_label.match(/.* /)[0]) {
  4437. back = ["", data_label.replace(/.* /, "")];
  4438. } else {
  4439. parts = data_label.split(" ");
  4440. if (parts.length !== 3) {
  4441. return data_label;
  4442. }
  4443. back = [parts[0] + " " + parts[1], parts[2]];
  4444. }
  4445. _this.last_data_label = data_label;
  4446. return back;
  4447. };
  4448. })(this)
  4449. },
  4450. time: {
  4451. displayFormats: {
  4452. 'second': 'MMM DD HH:mm',
  4453. 'minute': 'MMM DD HH:mm',
  4454. 'hour': 'MMM DD HH:mm',
  4455. 'day': 'MMM DD HH:mm',
  4456. 'week': 'MMM DD HH:mm',
  4457. 'month': 'MMM DD HH:mm',
  4458. 'quarter': 'MMM DD HH:mm',
  4459. 'year': 'MMM DD HH:mm'
  4460. }
  4461. }
  4462. }
  4463. ]
  4464. }
  4465. }
  4466. };
  4467. return configuration;
  4468. };
  4469. ChartBig.prototype.render = function() {
  4470. if (this.need_update) {
  4471. this.update();
  4472. this.need_update = false;
  4473. }
  4474. return h("div.ChartBig", [
  4475. h("canvas." + Page.params.interval, {
  4476. width: 1350,
  4477. height: 450,
  4478. afterCreate: this.storeCanvasNode,
  4479. updateAnimation: Animation.show,
  4480. mode: Page.params.interval
  4481. })
  4482. ]);
  4483. };
  4484. return ChartBig;
  4485. })(Class);
  4486. window.ChartBig = ChartBig;
  4487. }).call(this);
  4488. /* ---- PageStats/ChartLegend.coffee ---- */
  4489. (function() {
  4490. var ChartLegend,
  4491. bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
  4492. extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
  4493. hasProp = {}.hasOwnProperty;
  4494. ChartLegend = (function(superClass) {
  4495. extend(ChartLegend, superClass);
  4496. function ChartLegend() {
  4497. this.renderItem = bind(this.renderItem, this);
  4498. this.items_left = [];
  4499. this.items_right = [];
  4500. }
  4501. ChartLegend.prototype.renderItem = function(item) {
  4502. var hidden, value;
  4503. this.i += 1;
  4504. if (item.dot == null) {
  4505. item.dot = "\u25CF";
  4506. }
  4507. value = item.getValue();
  4508. hidden = !value;
  4509. if (item.post) {
  4510. value += " " + item.post;
  4511. }
  4512. if (item.type === "ratio") {
  4513. return h("div.legend-item", {
  4514. classes: {
  4515. hidden: hidden
  4516. }
  4517. }, [
  4518. h("div.title", item.title), h("div.value", [
  4519. h("span", {
  4520. updateAnimation: Animation.show,
  4521. delay: this.i * 0.1
  4522. }, Math.round(value * 10) / 10), h("div.dots-container", [
  4523. h("span.dots.dots-fg", {
  4524. style: "width: " + (Math.min(value, 5) * 11.5) + "px; color: " + item.color
  4525. }, item.dot.repeat(5)), h("span.dots.dots-bg", item.dot.repeat(5))
  4526. ])
  4527. ])
  4528. ]);
  4529. } else {
  4530. return h("div.legend-item", {
  4531. classes: {
  4532. hidden: hidden
  4533. }
  4534. }, [
  4535. h("div.title", [
  4536. h("span.dot", {
  4537. style: "color: " + item.color
  4538. }, item.dot + " "), item.title
  4539. ]), h("div.value", {
  4540. updateAnimation: Animation.show,
  4541. delay: this.i * 0.1
  4542. }, value)
  4543. ]);
  4544. }
  4545. };
  4546. ChartLegend.prototype.render = function() {
  4547. this.i = 0;
  4548. return h("div.ChartLegend", h("div.legend-items.align-left", this.items_left.map(this.renderItem)), h("div.legend-items.align-right", this.items_right.map(this.renderItem)));
  4549. };
  4550. return ChartLegend;
  4551. })(Class);
  4552. window.ChartLegend = ChartLegend;
  4553. }).call(this);
  4554. /* ---- PageStats/ChartRadar.coffee ---- */
  4555. (function() {
  4556. var ChartRadar,
  4557. bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
  4558. extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
  4559. hasProp = {}.hasOwnProperty;
  4560. ChartRadar = (function(superClass) {
  4561. extend(ChartRadar, superClass);
  4562. function ChartRadar(id) {
  4563. this.id = id;
  4564. this.render = bind(this.render, this);
  4565. this.renderLabel = bind(this.renderLabel, this);
  4566. this.handleLegendClick = bind(this.handleLegendClick, this);
  4567. this.initChart = bind(this.initChart, this);
  4568. this.formatLabel = bind(this.formatLabel, this);
  4569. this.getChartConfiguration = bind(this.getChartConfiguration, this);
  4570. this.initCanvas = bind(this.initCanvas, this);
  4571. this.update = bind(this.update, this);
  4572. this.configuration = {};
  4573. this.site_stats = [];
  4574. this.need_update = false;
  4575. this.order_by = "site_bw";
  4576. this.legends = [
  4577. {
  4578. id: "site_bw",
  4579. title: "Transferred data (last 7 days)",
  4580. color: "#608DECDD"
  4581. }, {
  4582. id: "site_size",
  4583. title: "Site size",
  4584. color: "#9C27B0DD"
  4585. }
  4586. ];
  4587. }
  4588. ChartRadar.prototype.update = function() {
  4589. var query, type_ids, type_name;
  4590. query = "SELECT type_id, site_id, SUM(value) AS sum, value\nFROM data\nWHERE type_id IN :type_ids AND date_added > " + (Time.timestamp() - 60 * 60 * 24 * 7) + "\nGROUP BY type_id, site_id";
  4591. type_ids = (function() {
  4592. var j, len, ref, results;
  4593. ref = ["site_bytes_sent", "site_bytes_recv", "site_size"];
  4594. results = [];
  4595. for (j = 0, len = ref.length; j < len; j++) {
  4596. type_name = ref[j];
  4597. results.push(Page.page_stats.type_id_db[type_name]);
  4598. }
  4599. return results;
  4600. })();
  4601. return Page.cmd("chartDbQuery", [
  4602. query, {
  4603. type_ids: type_ids
  4604. }
  4605. ], (function(_this) {
  4606. return function(res) {
  4607. var address, data, i, j, k, len, len1, max_site_bw, max_site_size, ref, row, site, stat;
  4608. _this.logStart("Parse result");
  4609. data = {};
  4610. for (j = 0, len = res.length; j < len; j++) {
  4611. row = res[j];
  4612. address = Page.page_stats.site_address_db[row.site_id];
  4613. type_name = Page.page_stats.type_name_db[row.type_id];
  4614. site = Page.site_list.sites_byaddress[address];
  4615. if (!site) {
  4616. continue;
  4617. }
  4618. if (data[address] == null) {
  4619. data[address] = {
  4620. address: address,
  4621. site: site
  4622. };
  4623. }
  4624. if (type_name === "site_size") {
  4625. data[address][type_name] = row.value;
  4626. } else {
  4627. data[address][type_name] = row.sum || 0;
  4628. }
  4629. }
  4630. _this.site_stats = [];
  4631. for (address in data) {
  4632. stat = data[address];
  4633. stat.site_bw = stat.site_bytes_sent + stat.site_bytes_recv;
  4634. _this.site_stats.push(stat);
  4635. }
  4636. _this.site_stats.sort(function(a, b) {
  4637. return b[_this.order_by] - a[_this.order_by];
  4638. });
  4639. if (_this.site_stats.length > 8) {
  4640. _this.site_stats.length = 8;
  4641. }
  4642. max_site_bw = Math.max.apply(null, (function() {
  4643. var k, len1, ref, results;
  4644. ref = this.site_stats;
  4645. results = [];
  4646. for (k = 0, len1 = ref.length; k < len1; k++) {
  4647. stat = ref[k];
  4648. results.push(stat.site_bw);
  4649. }
  4650. return results;
  4651. }).call(_this));
  4652. max_site_size = Math.max.apply(null, (function() {
  4653. var k, len1, ref, results;
  4654. ref = this.site_stats;
  4655. results = [];
  4656. for (k = 0, len1 = ref.length; k < len1; k++) {
  4657. stat = ref[k];
  4658. results.push(stat.site_size);
  4659. }
  4660. return results;
  4661. }).call(_this));
  4662. ref = _this.site_stats;
  4663. for (i = k = 0, len1 = ref.length; k < len1; i = ++k) {
  4664. stat = ref[i];
  4665. _this.configuration.data.labels[i] = stat.site.row.content.title;
  4666. _this.configuration.data.datasets[0].data[i] = Math.log(1 + (stat.site_bw / max_site_bw) * 100);
  4667. _this.configuration.data.datasets[1].data[i] = Math.log(1 + (stat.site_size / max_site_size) * 100);
  4668. }
  4669. _this.logEnd("Parse result", "sites: " + _this.site_stats.length);
  4670. Page.projector.scheduleRender();
  4671. if (_this.chart) {
  4672. return _this.chart.update();
  4673. } else {
  4674. return _this.initChart();
  4675. }
  4676. };
  4677. })(this));
  4678. };
  4679. ChartRadar.prototype.initCanvas = function(node) {
  4680. if (this.chart) {
  4681. this.chart.clear();
  4682. this.chart.destroy();
  4683. this.chart = null;
  4684. }
  4685. this.ctx = node.getContext("2d");
  4686. return this.configuration = this.getChartConfiguration();
  4687. };
  4688. ChartRadar.prototype.getChartConfiguration = function() {
  4689. var fill, fill2, shadowed;
  4690. fill = this.ctx.createLinearGradient(0, 0, 900, 0);
  4691. fill.addColorStop(0, "#608DECCC");
  4692. fill.addColorStop(1, "#9C27B0CC");
  4693. fill2 = this.ctx.createLinearGradient(0, 0, 900, 0);
  4694. fill2.addColorStop(0, "#9C27B0DD");
  4695. fill2.addColorStop(1, "#608DECDD");
  4696. shadowed = {
  4697. beforeDatasetsDraw: function(chart, options) {
  4698. chart.ctx.shadowColor = 'rgba(0, 0, 0, 0.5)';
  4699. return chart.ctx.shadowBlur = 40;
  4700. },
  4701. afterDatasetsDraw: function(chart, options) {
  4702. chart.ctx.shadowColor = 'rgba(0, 0, 0, 0)';
  4703. return chart.ctx.shadowBlur = 0;
  4704. }
  4705. };
  4706. return {
  4707. type: 'radar',
  4708. data: {
  4709. labels: [],
  4710. datasets: [
  4711. {
  4712. label: "Transferred data",
  4713. backgroundColor: fill,
  4714. borderColor: "transparent",
  4715. borderWidth: 0,
  4716. pointBorderWidth: 0,
  4717. pointRadius: 0,
  4718. data: []
  4719. }, {
  4720. label: "Site size",
  4721. backgroundColor: fill2,
  4722. borderColor: "transparent",
  4723. borderWidth: 0,
  4724. pointBorderWidth: 0,
  4725. pointRadius: 0,
  4726. data: []
  4727. }
  4728. ]
  4729. },
  4730. options: {
  4731. legend: {
  4732. display: false,
  4733. position: "bottom",
  4734. labels: {
  4735. padding: 5
  4736. }
  4737. },
  4738. scale: {
  4739. ticks: {
  4740. display: false,
  4741. maxTicksLimit: 5,
  4742. beginAtZero: true
  4743. },
  4744. angleLines: {
  4745. color: "#99999911"
  4746. },
  4747. gridLines: {
  4748. color: "#99999911",
  4749. tickMarkLength: 1
  4750. },
  4751. tooltips: {
  4752. enabled: true
  4753. },
  4754. pointLabels: {
  4755. fontColor: "rgba(200,210,232,1)",
  4756. fontSize: 14,
  4757. fontFamily: "Roboto",
  4758. fontStyle: "lighter",
  4759. padding: 10,
  4760. callback: this.formatLabel
  4761. }
  4762. }
  4763. },
  4764. plugins: [shadowed]
  4765. };
  4766. };
  4767. ChartRadar.prototype.formatLabel = function() {
  4768. return [""];
  4769. };
  4770. ChartRadar.prototype.initChart = function() {
  4771. var timer_resize;
  4772. this.chart = new Chart(this.ctx, this.configuration);
  4773. timer_resize = null;
  4774. return window.addEventListener("resize", (function(_this) {
  4775. return function() {
  4776. _this.log("resize");
  4777. clearInterval(timer_resize);
  4778. return setTimeout((function() {
  4779. return _this.chart.resize();
  4780. }), 300);
  4781. };
  4782. })(this));
  4783. };
  4784. ChartRadar.prototype.handleLegendClick = function(e) {
  4785. this.order_by = e.currentTarget.getAttribute("href").replace("#", "");
  4786. this.update();
  4787. return false;
  4788. };
  4789. ChartRadar.prototype.renderLabel = function(stat, i) {
  4790. var left, r, top;
  4791. if (i % (this.site_stats.length / 2) === 0) {
  4792. r = 37;
  4793. } else {
  4794. r = 40;
  4795. }
  4796. left = 50 + r * Math.sin(2 * Math.PI * i / this.site_stats.length);
  4797. top = 50 - r * Math.cos(2 * Math.PI * i / this.site_stats.length);
  4798. return h("div.radar-label", {
  4799. key: stat.address + i,
  4800. style: "left: " + left + "%; top: " + top + "%",
  4801. enterAnimation: Animation.show,
  4802. exitAnimation: Animation.hide,
  4803. delay: i * 0.05
  4804. }, h("a.title", {
  4805. href: stat.site.getHref()
  4806. }, stat.site.row.content.title), " ", h("span.value", " (" + (Text.formatSize(stat[this.order_by]) || 'No data yet') + ")"));
  4807. };
  4808. ChartRadar.prototype.render = function() {
  4809. var label_i;
  4810. if (this.need_update) {
  4811. this.update();
  4812. this.need_update = false;
  4813. }
  4814. label_i = 0;
  4815. return h("div.ChartRadar", [
  4816. h("div.radar-container", [
  4817. h("div.radar-labels", this.site_stats.map((function(_this) {
  4818. return function(stat) {
  4819. var label;
  4820. label = _this.renderLabel(stat, label_i);
  4821. label_i += 1;
  4822. return label;
  4823. };
  4824. })(this))), h("div.canvas-container", h("canvas", {
  4825. width: 600,
  4826. height: 600,
  4827. afterCreate: this.initCanvas
  4828. }))
  4829. ]), h("div.radar-legends", this.legends.map((function(_this) {
  4830. return function(legend) {
  4831. return h("a.radar-legend", {
  4832. id: legend.id,
  4833. classes: {
  4834. active: _this.order_by === legend.id
  4835. },
  4836. onclick: _this.handleLegendClick,
  4837. href: "#" + legend.id
  4838. }, [
  4839. h("div.legend-box", {
  4840. style: "background-color: " + legend.color
  4841. }), h("span.title", legend.title)
  4842. ]);
  4843. };
  4844. })(this)))
  4845. ]);
  4846. };
  4847. return ChartRadar;
  4848. })(Class);
  4849. window.ChartRadar = ChartRadar;
  4850. }).call(this);
  4851. /* ---- PageStats/ChartTimeline.coffee ---- */
  4852. (function() {
  4853. var ChartTimeline,
  4854. bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
  4855. extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
  4856. hasProp = {}.hasOwnProperty;
  4857. ChartTimeline = (function(superClass) {
  4858. extend(ChartTimeline, superClass);
  4859. function ChartTimeline() {
  4860. this.render = bind(this.render, this);
  4861. this.update = bind(this.update, this);
  4862. this.updateChart = bind(this.updateChart, this);
  4863. this.initChart = bind(this.initChart, this);
  4864. var i, j;
  4865. this.items = [];
  4866. for (i = j = 6; j >= 0; i = --j) {
  4867. this.items.push({
  4868. id: i,
  4869. title: "\u200B",
  4870. data: "\u200B",
  4871. value: i,
  4872. active: false
  4873. });
  4874. }
  4875. this.active_id = 0;
  4876. this.chart_ctx = null;
  4877. this.need_update = false;
  4878. this.line_data = null;
  4879. }
  4880. ChartTimeline.prototype.initChart = function(node) {
  4881. this.chart_canvas = node;
  4882. this.chart_ctx = node.getContext("2d");
  4883. if (this.line_data) {
  4884. return this.updateChart();
  4885. }
  4886. };
  4887. ChartTimeline.prototype.updateChart = function() {
  4888. var data, data_last_i, data_max, i, j, len, line_width, line_x, line_y, ref, val;
  4889. this.chart_ctx.clearRect(0, 0, this.chart_canvas.width, this.chart_canvas.height);
  4890. this.chart_ctx.lineWidth = 0;
  4891. this.chart_ctx.fillStyle = '#EDC54B';
  4892. this.chart_ctx.beginPath();
  4893. this.chart_ctx.moveTo(-10, 0);
  4894. data_max = Math.max.apply(null, this.line_data);
  4895. data_last_i = ((function() {
  4896. var j, len, ref, results;
  4897. ref = this.line_data;
  4898. results = [];
  4899. for (i = j = 0, len = ref.length; j < len; i = ++j) {
  4900. val = ref[i];
  4901. if (val > 0) {
  4902. results.push(i);
  4903. }
  4904. }
  4905. return results;
  4906. }).call(this)).pop();
  4907. line_width = 1400 / this.line_data.length;
  4908. ref = this.line_data;
  4909. for (i = j = 0, len = ref.length; j < len; i = ++j) {
  4910. data = ref[i];
  4911. line_x = i * line_width;
  4912. line_y = parseInt(101 - (data / data_max) * 100);
  4913. this.chart_ctx.lineTo(line_x, line_y);
  4914. if (i === data_last_i) {
  4915. break;
  4916. }
  4917. }
  4918. this.chart_ctx.lineTo(line_x, 120);
  4919. this.chart_ctx.lineTo(0, 120);
  4920. this.chart_ctx.fill();
  4921. if (data_last_i > 36) {
  4922. this.chart_ctx.beginPath();
  4923. this.chart_ctx.lineWidth = 0;
  4924. this.chart_ctx.strokeStyle = '#EDC54B';
  4925. this.chart_ctx.setLineDash([0, 1, 1]);
  4926. this.chart_ctx.moveTo(line_x, line_y);
  4927. this.chart_ctx.lineTo(1500, line_y);
  4928. return this.chart_ctx.stroke();
  4929. }
  4930. };
  4931. ChartTimeline.prototype.update = function() {
  4932. var c, data, date_added_from, date_added_to, day_total, group_steps, interval_step, query, step, type_id;
  4933. query = "SELECT\nMAX(date_added) AS date_added, AVG(value) AS avg, SUM(value) AS sum\nFROM data\nWHERE type_id = :type_id AND date_added >= :date_added_from AND date_added <= :date_added_to\nGROUP BY strftime('%Y-%m-%d %H', date_added, 'unixepoch', 'localtime')\nORDER BY date_added DESC";
  4934. if (Page.params.interval === "1w") {
  4935. c = new Date();
  4936. c.setDate(c.getDate() - (c.getDay() || 7) + 7);
  4937. date_added_to = c.setHours(23, 59, 59, 0) / 1000;
  4938. interval_step = 60 * 60 * 24 * 7;
  4939. date_added_from = date_added_to - interval_step * 7;
  4940. group_steps = 6;
  4941. } else if (Page.params.interval === "1m") {
  4942. c = new Date();
  4943. c.setDate(30);
  4944. date_added_to = c.setHours(23, 59, 59, 0) / 1000;
  4945. interval_step = 60 * 60 * 24 * 30;
  4946. date_added_from = date_added_to - interval_step * 30;
  4947. group_steps = 24 * 3;
  4948. } else {
  4949. date_added_to = (new Date()).setHours(23, 59, 59, 0) / 1000;
  4950. interval_step = 60 * 60 * 24;
  4951. date_added_from = date_added_to - interval_step * 7;
  4952. group_steps = 2;
  4953. }
  4954. step = 60 * 60;
  4955. type_id = Page.page_stats.type_id_db["file_bytes_sent"];
  4956. data = {};
  4957. day_total = {};
  4958. return Page.cmd("chartDbQuery", [
  4959. query, {
  4960. type_id: type_id,
  4961. date_added_from: date_added_from,
  4962. date_added_to: date_added_to
  4963. }
  4964. ], (function(_this) {
  4965. return function(res) {
  4966. var data_date_added, data_from, data_to, day_data, day_from, day_name, day_string, day_to, group_step_data, i, j, k, l, len, m, n, ref, row, x;
  4967. _this.logStart("Parse result");
  4968. _this.line_data = [];
  4969. for (j = 0, len = res.length; j < len; j++) {
  4970. row = res[j];
  4971. data[Math.ceil(row.date_added / step) * step] = row.sum;
  4972. day_string = Time.dateIso(row.date_added * 1000);
  4973. if (day_total[day_string] == null) {
  4974. day_total[day_string] = 0;
  4975. }
  4976. day_total[day_string] += row.sum;
  4977. }
  4978. data_date_added = Math.ceil(date_added_from / step) * step;
  4979. while (data_date_added <= date_added_to) {
  4980. group_step_data = 0;
  4981. for (i = k = 0, ref = group_steps; 0 <= ref ? k <= ref : k >= ref; i = 0 <= ref ? ++k : --k) {
  4982. group_step_data += data[data_date_added] || 0;
  4983. data_date_added += step;
  4984. }
  4985. _this.line_data.push(group_step_data);
  4986. }
  4987. _this.items = [];
  4988. for (i = l = 7; l >= 1; i = --l) {
  4989. data_from = date_added_to - i * interval_step + 1;
  4990. data_to = data_from + interval_step - 1;
  4991. if (Page.params.interval === "1w") {
  4992. day_data = 0;
  4993. for (x = m = 0; m <= 6; x = ++m) {
  4994. day_data += day_total[Time.dateIso(data_from + (60 * 60 * 24 * x))] || 0;
  4995. }
  4996. day_from = Time.date(data_from, "day");
  4997. day_to = Time.date(data_from + interval_step - 1, "day");
  4998. day_to = day_to.replace(day_from.split(" ")[0], "");
  4999. day_name = day_from + " - " + day_to;
  5000. } else if (Page.params.interval === "1m") {
  5001. day_data = 0;
  5002. for (x = n = 0; n <= 30; x = ++n) {
  5003. day_data += day_total[Time.dateIso(data_from + (60 * 60 * 24 * x))] || 0;
  5004. }
  5005. day_name = Time.date(data_from, "month");
  5006. } else {
  5007. day_data = day_total[Time.dateIso(data_from)];
  5008. day_name = Time.weekDay(data_from);
  5009. }
  5010. _this.items.push({
  5011. id: i,
  5012. title: day_name,
  5013. data: day_data,
  5014. value: data_to
  5015. });
  5016. }
  5017. _this.logEnd("Parse result", "data: " + _this.line_data.length);
  5018. Page.projector.scheduleRender();
  5019. return _this.updateChart();
  5020. };
  5021. })(this));
  5022. };
  5023. ChartTimeline.prototype.renderItem = function(item) {
  5024. var classes, date_added_to;
  5025. date_added_to = Time.dateIso(item.value);
  5026. if (item.value >= Time.timestamp()) {
  5027. date_added_to = "";
  5028. }
  5029. classes = {
  5030. active: (Page.params.date_added_to || "") === date_added_to
  5031. };
  5032. return h("a.timeline-item", {
  5033. key: item.title,
  5034. enterAnimation: Animation.show,
  5035. delay: item.id * 0.05,
  5036. href: Page.createUrl("date_added_to", date_added_to),
  5037. onclick: Page.handleLinkClick,
  5038. classes: classes
  5039. }, h("span.title", item.title), h("span.data", Text.formatSize(item.data) || "0 MB"));
  5040. };
  5041. ChartTimeline.prototype.render = function() {
  5042. var ref;
  5043. if (this.need_update) {
  5044. this.update();
  5045. this.need_update = false;
  5046. }
  5047. return h("div.ChartTimeline", [
  5048. h("div.timeline-borders", this.items.map((function(_this) {
  5049. return function(item) {
  5050. var date_added_to;
  5051. date_added_to = Time.dateIso(item.value);
  5052. if (item.value >= Time.timestamp()) {
  5053. date_added_to = "";
  5054. }
  5055. return h("div.timeline-border", {
  5056. key: item.id,
  5057. classes: {
  5058. active: (Page.params.date_added_to || "") === date_added_to
  5059. }
  5060. });
  5061. };
  5062. })(this))), h("canvas.chart", {
  5063. afterCreate: this.initChart,
  5064. width: 1400,
  5065. height: 100,
  5066. data: (ref = this.line_data) != null ? ref.length : void 0,
  5067. delay: 0.3,
  5068. updateAnimation: Animation.show
  5069. }), h("div.timeline-items", this.items.map((function(_this) {
  5070. return function(item) {
  5071. return _this.renderItem(item);
  5072. };
  5073. })(this)))
  5074. ]);
  5075. };
  5076. return ChartTimeline;
  5077. })(Class);
  5078. window.ChartTimeline = ChartTimeline;
  5079. }).call(this);
  5080. /* ---- PageStats/ChartWorld.coffee ---- */
  5081. (function() {
  5082. var ChartWorld,
  5083. bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
  5084. extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
  5085. hasProp = {}.hasOwnProperty;
  5086. ChartWorld = (function(superClass) {
  5087. extend(ChartWorld, superClass);
  5088. function ChartWorld() {
  5089. this.render = bind(this.render, this);
  5090. this.initCanvas = bind(this.initCanvas, this);
  5091. this.drawPoints = bind(this.drawPoints, this);
  5092. this.update = bind(this.update, this);
  5093. this.points = [];
  5094. this.need_update = false;
  5095. }
  5096. ChartWorld.prototype.update = function() {
  5097. /*
  5098. @points = [
  5099. {lat: 0, lon: 0},
  5100. {lat: 30, lon: 30},
  5101. {lat: 33.137551, lon: 129.902344},
  5102. {lat: 0.351560, lon: 115.136719},
  5103. {lat: 40.178873, lon: -8.261719},
  5104. {lat: 52.482780, lon: -0.878906},
  5105. {lat: 47.040182, lon: 19.511719},
  5106. {lat: 38.548165, lon: -76.113281},
  5107. {lat: 40.446947, lon: -122.871094}
  5108. {lat: -16.972741, lon: 46.582031}
  5109. {lat: -35.173808, lon: 19.511719}
  5110. {lat: -33.431441, lon: 116.542969}
  5111. {lat: -45.336702, lon: 168.222656}
  5112. {lat: -54.977614, lon: -67.412109}
  5113. {lat: 8.928487, lon: -62.314453}
  5114. {lat: 65.20515, lon: -14.670696}
  5115. {lat: 64.90863, lon: -21.70194625}
  5116. ]
  5117. return false
  5118. */
  5119. return Page.cmd("chartGetPeerLocations", [], (function(_this) {
  5120. return function(res) {
  5121. var country, country_db, i, item, items, j, len, len1, name, num, num_others, point, ref, ref1;
  5122. _this.points = res;
  5123. country_db = {};
  5124. items = Page.page_stats.country_list.items;
  5125. items.length = 0;
  5126. ref = _this.points;
  5127. for (i = 0, len = ref.length; i < len; i++) {
  5128. point = ref[i];
  5129. if (country_db[name = point.country] == null) {
  5130. country_db[name] = 0;
  5131. }
  5132. country_db[point.country] += 1;
  5133. }
  5134. for (country in country_db) {
  5135. num = country_db[country];
  5136. items.push({
  5137. title: country,
  5138. value: num
  5139. });
  5140. }
  5141. items.sort(function(a, b) {
  5142. return b.value - a.value;
  5143. });
  5144. if (items.length > 15) {
  5145. num_others = 0;
  5146. ref1 = items.slice(14);
  5147. for (j = 0, len1 = ref1.length; j < len1; j++) {
  5148. item = ref1[j];
  5149. num_others += item.value;
  5150. }
  5151. items.length = 14;
  5152. items.push({
  5153. title: "Other",
  5154. value: num_others,
  5155. type: "other"
  5156. });
  5157. }
  5158. _this.drawPoints();
  5159. return Page.projector.scheduleRender();
  5160. };
  5161. })(this));
  5162. };
  5163. ChartWorld.prototype.drawPoints = function() {
  5164. var i, left, len, point, ref, results, top;
  5165. this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
  5166. ref = this.points;
  5167. results = [];
  5168. for (i = 0, len = ref.length; i < len; i++) {
  5169. point = ref[i];
  5170. left = (47 + (point.lon / 3.65)) * this.canvas.width / 100;
  5171. top = (59 - (point.lat / 1.52)) * this.canvas.height / 100;
  5172. results.push(this.ctx.fillRect(left, top, 2, 2));
  5173. }
  5174. return results;
  5175. };
  5176. ChartWorld.prototype.initCanvas = function(node) {
  5177. this.canvas = node;
  5178. this.ctx = node.getContext("2d");
  5179. this.ctx.globalCompositeOperation = 'screen';
  5180. this.ctx.fillStyle = '#30758e';
  5181. return this.drawPoints();
  5182. };
  5183. ChartWorld.prototype.render = function() {
  5184. if (this.need_update) {
  5185. this.update();
  5186. this.need_update = false;
  5187. }
  5188. return h("div.ChartWorld", [
  5189. h("canvas.map-points", {
  5190. width: 878,
  5191. height: 371,
  5192. afterCreate: this.initCanvas
  5193. }), h("img.map", {
  5194. src: "img/world.png"
  5195. })
  5196. ]);
  5197. };
  5198. return ChartWorld;
  5199. })(Class);
  5200. window.ChartWorld = ChartWorld;
  5201. }).call(this);
  5202. /* ---- PageStats/PageStats.coffee ---- */
  5203. (function() {
  5204. var PageStats,
  5205. bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
  5206. extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
  5207. hasProp = {}.hasOwnProperty;
  5208. PageStats = (function(superClass) {
  5209. extend(PageStats, superClass);
  5210. function PageStats() {
  5211. this.render = bind(this.render, this);
  5212. this.loadChartjs = bind(this.loadChartjs, this);
  5213. this.update = bind(this.update, this);
  5214. this.handleChartjsLoad = bind(this.handleChartjsLoad, this);
  5215. this.need_update = false;
  5216. this.need_load_chartjs = true;
  5217. this.chartjs_loaded = false;
  5218. this.chart_timeline = new ChartTimeline();
  5219. this.chart_big = new ChartBig();
  5220. this.chart_big.types = [
  5221. {
  5222. name: "file_bytes_sent",
  5223. dataset_id: 0
  5224. }, {
  5225. name: "file_bytes_recv",
  5226. dataset_id: 1,
  5227. negative: true
  5228. }, {
  5229. name: "request_num_sent",
  5230. dataset_id: 2,
  5231. negative: true
  5232. }, {
  5233. name: "request_num_recv",
  5234. dataset_id: 3
  5235. }
  5236. ];
  5237. this.chart_legend = new ChartLegend();
  5238. this.chart_legend.items_left = [
  5239. {
  5240. title: "Upload",
  5241. getValue: ((function(_this) {
  5242. return function() {
  5243. return Text.formatSize(_this.chart_big.data_total.file_bytes_sent);
  5244. };
  5245. })(this)),
  5246. color: "#1dfc59"
  5247. }, {
  5248. title: "Download",
  5249. getValue: ((function(_this) {
  5250. return function() {
  5251. return Text.formatSize(_this.chart_big.data_total.file_bytes_recv);
  5252. };
  5253. })(this)),
  5254. color: "#c94d47"
  5255. }, {
  5256. title: "Ratio",
  5257. getValue: ((function(_this) {
  5258. return function() {
  5259. return _this.chart_big.data_total.file_bytes_sent / _this.chart_big.data_total.file_bytes_recv;
  5260. };
  5261. })(this)),
  5262. type: "ratio",
  5263. color: "#16ffe9"
  5264. }
  5265. ];
  5266. this.chart_legend.items_right = [
  5267. {
  5268. title: "Sent",
  5269. getValue: ((function(_this) {
  5270. return function() {
  5271. return _this.chart_big.data_total.request_num_sent;
  5272. };
  5273. })(this)),
  5274. post: "requests",
  5275. dot: "\u2500",
  5276. color: "#2da3b3"
  5277. }, {
  5278. title: "Received",
  5279. getValue: ((function(_this) {
  5280. return function() {
  5281. return _this.chart_big.data_total.request_num_recv;
  5282. };
  5283. })(this)),
  5284. post: "requests",
  5285. dot: "\u2500",
  5286. color: "#80623f"
  5287. }
  5288. ];
  5289. this.chart_radar = new ChartRadar();
  5290. this.chart_connections = new Chart();
  5291. this.chart_connections.title = "Connections";
  5292. this.chart_connections.type_names = ["peer", "peer_onion", "connection", "connection_onion", "connection_in", "connection_ping_avg", "connection_ping_min"];
  5293. this.chart_connections.formatValue = function(type_data) {
  5294. return "" + type_data.connection + " of " + type_data.peer + " peers";
  5295. };
  5296. this.chart_connections.formatDetails = function(type_data) {
  5297. var back;
  5298. back = [];
  5299. back.push("Onion: " + type_data.peer_onion + " peers (" + (type_data.connection_onion || 0) + " connections)");
  5300. back.push("Incoming: " + (Math.round(type_data.connection_in / type_data.connection * 100)) + "%");
  5301. back.push("Ping avg: " + type_data.connection_ping_avg + "ms (min: " + type_data.connection_ping_min + "ms)");
  5302. return back;
  5303. };
  5304. this.chart_connections.chart_stroke = ["#608DECAA", "#D74C58FF"];
  5305. this.chart_connections.getChartQuery = function() {
  5306. return "SELECT * FROM data WHERE type_id = " + Page.page_stats.type_id_db['connection'] + " ORDER BY date_added DESC LIMIT 50";
  5307. };
  5308. this.chart_size = new Chart();
  5309. this.chart_size.getTitle = function() {
  5310. return h("a", {
  5311. href: Page.createUrl("bigchart", "size"),
  5312. onclick: Page.handleLinkClick
  5313. }, "Total size");
  5314. };
  5315. this.chart_size.chart_stroke = ["#F99739AA", "#51B8F2"];
  5316. this.chart_size.type_names = ["size", "size_optional", "optional_limit", "optional_used", "content"];
  5317. this.chart_size.formatValue = function(type_data) {
  5318. return Text.formatSize(type_data.size) + (" in " + Page.site_list.sites.length + " sites");
  5319. };
  5320. this.chart_size.formatDetails = function(type_data) {
  5321. var back;
  5322. back = [];
  5323. back.push("Content sources: " + type_data.content + " files");
  5324. back.push("Optional downloaded: " + (Text.formatSize(type_data.optional_used) || '0 MB') + " of " + (Text.formatSize(type_data.size_optional) || '0 MB') + " (limit: " + (Text.formatSize(type_data.optional_limit)) + ")");
  5325. return back;
  5326. };
  5327. this.chart_size.getChartQuery = function() {
  5328. return "SELECT CAST(value AS FLOAT) / 1024 / 1024 AS value FROM data WHERE type_id = " + Page.page_stats.type_id_db['size'] + " GROUP BY ROUND(date_added / 10000) ORDER BY date_added DESC LIMIT 50";
  5329. };
  5330. this.chart_world = new ChartWorld();
  5331. this.country_list = new StatList();
  5332. this.type_name_db = {};
  5333. this.type_id_db = {};
  5334. this.site_address_db = {};
  5335. this.site_id_db = {};
  5336. setInterval(((function(_this) {
  5337. return function() {
  5338. _this.need_update = true;
  5339. return Page.projector.scheduleRender();
  5340. };
  5341. })(this)), 5 * 60 * 1000);
  5342. }
  5343. PageStats.prototype.handleChartjsLoad = function() {
  5344. this.chartjs_loaded = true;
  5345. return Page.projector.scheduleRender();
  5346. };
  5347. PageStats.prototype.update = function() {
  5348. Page.cmd("chartDbQuery", "SELECT * FROM type", (function(_this) {
  5349. return function(res) {
  5350. var i, len, results, row;
  5351. _this.type_id_db = {};
  5352. _this.type_name_db = {};
  5353. results = [];
  5354. for (i = 0, len = res.length; i < len; i++) {
  5355. row = res[i];
  5356. _this.type_id_db[row.name] = row.type_id;
  5357. results.push(_this.type_name_db[row.type_id] = row.name);
  5358. }
  5359. return results;
  5360. };
  5361. })(this));
  5362. return Page.cmd("chartDbQuery", "SELECT * FROM site", (function(_this) {
  5363. return function(res) {
  5364. var i, len, row, sites;
  5365. sites = {};
  5366. _this.sites_by_id = {};
  5367. for (i = 0, len = res.length; i < len; i++) {
  5368. row = res[i];
  5369. _this.site_id_db[row.address] = row.site_id;
  5370. _this.site_address_db[row.site_id] = row.address;
  5371. }
  5372. _this.chart_big.need_update = true;
  5373. _this.chart_timeline.need_update = true;
  5374. _this.chart_connections.need_update = true;
  5375. _this.chart_size.need_update = true;
  5376. _this.chart_radar.need_update = true;
  5377. _this.chart_world.need_update = true;
  5378. return Page.projector.scheduleRender();
  5379. };
  5380. })(this));
  5381. };
  5382. PageStats.prototype.loadChartjs = function() {
  5383. var e;
  5384. e = document.createElement("script");
  5385. e.type = "text/javascript";
  5386. e.src = "chartjs/chart.bundle.min.js";
  5387. e.onload = this.handleChartjsLoad;
  5388. return document.body.appendChild(e);
  5389. };
  5390. PageStats.prototype.render = function() {
  5391. var intervals, ref;
  5392. if (((ref = Page.server_info) != null ? ref.rev : void 0) < 3220) {
  5393. return h("div#PageStats", h("div.empty", [h("h4", "Need update"), h("small", "You have to update to ZeroNet version 0.6.1 to use this feature.")]));
  5394. }
  5395. if (this.need_update) {
  5396. this.update();
  5397. this.need_update = false;
  5398. }
  5399. if (!this.need_update && document.body.className !== "loaded") {
  5400. setTimeout((function() {
  5401. return document.body.classList.add("loaded");
  5402. }), 1000);
  5403. }
  5404. if (this.need_load_chartjs) {
  5405. setTimeout(this.loadChartjs, 500);
  5406. this.need_load_chartjs = false;
  5407. }
  5408. intervals = ["1w", "1d"];
  5409. return h("div#PageStats", [
  5410. h("div.intervals", intervals.map((function(_this) {
  5411. return function(interval) {
  5412. var interval_param;
  5413. if (interval === "1d") {
  5414. interval_param = void 0;
  5415. } else {
  5416. interval_param = interval;
  5417. }
  5418. return h("a.interval", {
  5419. href: Page.createUrl("interval", interval_param),
  5420. onclick: Page.handleLinkClick,
  5421. classes: {
  5422. active: interval_param === Page.params.interval
  5423. }
  5424. }, interval);
  5425. };
  5426. })(this))), this.chart_timeline.render(), this.chartjs_loaded ? [this.chart_big.render(), this.chart_legend.render(), this.chart_radar.render(), h("div.Charts", [this.chart_connections.render(), this.chart_size.render()]), this.chart_world.render(), this.country_list.render()] : void 0
  5427. ]);
  5428. };
  5429. return PageStats;
  5430. })(Class);
  5431. window.PageStats = PageStats;
  5432. }).call(this);
  5433. /* ---- PageStats/StatList.coffee ---- */
  5434. (function() {
  5435. var StatList,
  5436. bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
  5437. extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
  5438. hasProp = {}.hasOwnProperty;
  5439. StatList = (function(superClass) {
  5440. extend(StatList, superClass);
  5441. function StatList() {
  5442. this.render = bind(this.render, this);
  5443. this.renderItem = bind(this.renderItem, this);
  5444. this.items = [];
  5445. }
  5446. StatList.prototype.renderItem = function(item) {
  5447. return h("div.stat-list-item", {
  5448. key: item.title,
  5449. classes: {
  5450. other: item.type === "other"
  5451. }
  5452. }, h("div.title", item.title), h("div.value", item.value + " peers"));
  5453. };
  5454. StatList.prototype.render = function() {
  5455. return h("div.StatList", [h("h4", "Top country"), h("div.stat-list-items", this.items.map(this.renderItem))]);
  5456. };
  5457. return StatList;
  5458. })(Class);
  5459. window.StatList = StatList;
  5460. }).call(this);
  5461. /* ---- utils/Animation.coffee ---- */
  5462. (function() {
  5463. var Animation;
  5464. Animation = (function() {
  5465. function Animation() {}
  5466. Animation.prototype.slideDown = function(elem, props) {
  5467. var cstyle, h, margin_bottom, margin_top, padding_bottom, padding_top, transition;
  5468. if (elem.offsetTop > 1000) {
  5469. return;
  5470. }
  5471. h = elem.offsetHeight;
  5472. cstyle = window.getComputedStyle(elem);
  5473. margin_top = cstyle.marginTop;
  5474. margin_bottom = cstyle.marginBottom;
  5475. padding_top = cstyle.paddingTop;
  5476. padding_bottom = cstyle.paddingBottom;
  5477. transition = cstyle.transition;
  5478. elem.style.boxSizing = "border-box";
  5479. elem.style.overflow = "hidden";
  5480. elem.style.transform = "scale(0.6)";
  5481. elem.style.opacity = "0";
  5482. elem.style.height = "0px";
  5483. elem.style.marginTop = "0px";
  5484. elem.style.marginBottom = "0px";
  5485. elem.style.paddingTop = "0px";
  5486. elem.style.paddingBottom = "0px";
  5487. elem.style.transition = "none";
  5488. setTimeout((function() {
  5489. elem.className += " animate-inout";
  5490. elem.style.height = h + "px";
  5491. elem.style.transform = "scale(1)";
  5492. elem.style.opacity = "1";
  5493. elem.style.marginTop = margin_top;
  5494. elem.style.marginBottom = margin_bottom;
  5495. elem.style.paddingTop = padding_top;
  5496. return elem.style.paddingBottom = padding_bottom;
  5497. }), 1);
  5498. return elem.addEventListener("transitionend", function() {
  5499. elem.classList.remove("animate-inout");
  5500. elem.style.transition = elem.style.transform = elem.style.opacity = elem.style.height = null;
  5501. elem.style.boxSizing = elem.style.marginTop = elem.style.marginBottom = null;
  5502. elem.style.paddingTop = elem.style.paddingBottom = elem.style.overflow = null;
  5503. return elem.removeEventListener("transitionend", arguments.callee, false);
  5504. });
  5505. };
  5506. Animation.prototype.slideUp = function(elem, remove_func, props) {
  5507. if (elem.offsetTop > 1000) {
  5508. return remove_func();
  5509. }
  5510. elem.className += " animate-back";
  5511. elem.style.boxSizing = "border-box";
  5512. elem.style.height = elem.offsetHeight + "px";
  5513. elem.style.overflow = "hidden";
  5514. elem.style.transform = "scale(1)";
  5515. elem.style.opacity = "1";
  5516. elem.style.pointerEvents = "none";
  5517. setTimeout((function() {
  5518. elem.style.height = "0px";
  5519. elem.style.marginTop = "0px";
  5520. elem.style.marginBottom = "0px";
  5521. elem.style.paddingTop = "0px";
  5522. elem.style.paddingBottom = "0px";
  5523. elem.style.transform = "scale(0.8)";
  5524. elem.style.borderTopWidth = "0px";
  5525. elem.style.borderBottomWidth = "0px";
  5526. return elem.style.opacity = "0";
  5527. }), 1);
  5528. return elem.addEventListener("transitionend", function(e) {
  5529. if (e.propertyName === "opacity" || e.elapsedTime >= 0.6) {
  5530. elem.removeEventListener("transitionend", arguments.callee, false);
  5531. return remove_func();
  5532. }
  5533. });
  5534. };
  5535. Animation.prototype.slideUpInout = function(elem, remove_func, props) {
  5536. elem.className += " animate-inout";
  5537. elem.style.boxSizing = "border-box";
  5538. elem.style.height = elem.offsetHeight + "px";
  5539. elem.style.overflow = "hidden";
  5540. elem.style.transform = "scale(1)";
  5541. elem.style.opacity = "1";
  5542. elem.style.pointerEvents = "none";
  5543. setTimeout((function() {
  5544. elem.style.height = "0px";
  5545. elem.style.marginTop = "0px";
  5546. elem.style.marginBottom = "0px";
  5547. elem.style.paddingTop = "0px";
  5548. elem.style.paddingBottom = "0px";
  5549. elem.style.transform = "scale(0.8)";
  5550. elem.style.borderTopWidth = "0px";
  5551. elem.style.borderBottomWidth = "0px";
  5552. return elem.style.opacity = "0";
  5553. }), 1);
  5554. return elem.addEventListener("transitionend", function(e) {
  5555. if (e.propertyName === "opacity" || e.elapsedTime >= 0.6) {
  5556. elem.removeEventListener("transitionend", arguments.callee, false);
  5557. return remove_func();
  5558. }
  5559. });
  5560. };
  5561. Animation.prototype.showRight = function(elem, props) {
  5562. elem.className += " animate";
  5563. elem.style.opacity = 0;
  5564. elem.style.transform = "TranslateX(-20px) Scale(1.01)";
  5565. setTimeout((function() {
  5566. elem.style.opacity = 1;
  5567. return elem.style.transform = "TranslateX(0px) Scale(1)";
  5568. }), 1);
  5569. return elem.addEventListener("transitionend", function() {
  5570. elem.classList.remove("animate");
  5571. return elem.style.transform = elem.style.opacity = null;
  5572. });
  5573. };
  5574. Animation.prototype.show = function(elem, props) {
  5575. var delay, ref;
  5576. delay = ((ref = arguments[arguments.length - 2]) != null ? ref.delay : void 0) * 1000 || 1;
  5577. elem.style.opacity = 0;
  5578. setTimeout((function() {
  5579. return elem.className += " animate";
  5580. }), 1);
  5581. setTimeout((function() {
  5582. return elem.style.opacity = 1;
  5583. }), delay);
  5584. return elem.addEventListener("transitionend", function() {
  5585. elem.classList.remove("animate");
  5586. elem.style.opacity = null;
  5587. return elem.removeEventListener("transitionend", arguments.callee, false);
  5588. });
  5589. };
  5590. Animation.prototype.hide = function(elem, remove_func, props) {
  5591. var delay, ref;
  5592. delay = ((ref = arguments[arguments.length - 2]) != null ? ref.delay : void 0) * 1000 || 1;
  5593. elem.className += " animate";
  5594. setTimeout((function() {
  5595. return elem.style.opacity = 0;
  5596. }), delay);
  5597. return elem.addEventListener("transitionend", function(e) {
  5598. if (e.propertyName === "opacity") {
  5599. return remove_func();
  5600. }
  5601. });
  5602. };
  5603. Animation.prototype.addVisibleClass = function(elem, props) {
  5604. return setTimeout(function() {
  5605. return elem.classList.add("visible");
  5606. });
  5607. };
  5608. return Animation;
  5609. })();
  5610. window.Animation = new Animation();
  5611. }).call(this);
  5612. /* ---- utils/Dollar.coffee ---- */
  5613. (function() {
  5614. window.$ = function(selector) {
  5615. if (selector.startsWith("#")) {
  5616. return document.getElementById(selector.replace("#", ""));
  5617. }
  5618. };
  5619. }).call(this);
  5620. /* ---- utils/ItemList.coffee ---- */
  5621. (function() {
  5622. var ItemList;
  5623. ItemList = (function() {
  5624. function ItemList(item_class1, key1) {
  5625. this.item_class = item_class1;
  5626. this.key = key1;
  5627. this.items = [];
  5628. this.items_bykey = {};
  5629. }
  5630. ItemList.prototype.sync = function(rows, item_class, key) {
  5631. var current_obj, i, item, len, results, row;
  5632. this.items.splice(0, this.items.length);
  5633. results = [];
  5634. for (i = 0, len = rows.length; i < len; i++) {
  5635. row = rows[i];
  5636. current_obj = this.items_bykey[row[this.key]];
  5637. if (current_obj) {
  5638. current_obj.row = row;
  5639. results.push(this.items.push(current_obj));
  5640. } else {
  5641. item = new this.item_class(row, this);
  5642. this.items_bykey[row[this.key]] = item;
  5643. results.push(this.items.push(item));
  5644. }
  5645. }
  5646. return results;
  5647. };
  5648. ItemList.prototype.deleteItem = function(item) {
  5649. var index;
  5650. index = this.items.indexOf(item);
  5651. if (index > -1) {
  5652. this.items.splice(index, 1);
  5653. } else {
  5654. console.log("Can't delete item", item);
  5655. }
  5656. return delete this.items_bykey[item.row[this.key]];
  5657. };
  5658. return ItemList;
  5659. })();
  5660. window.ItemList = ItemList;
  5661. }).call(this);
  5662. /* ---- utils/Menu.coffee ---- */
  5663. (function() {
  5664. var Menu,
  5665. bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
  5666. indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
  5667. Menu = (function() {
  5668. function Menu() {
  5669. this.render = bind(this.render, this);
  5670. this.getStyle = bind(this.getStyle, this);
  5671. this.renderItem = bind(this.renderItem, this);
  5672. this.handleClick = bind(this.handleClick, this);
  5673. this.getDirection = bind(this.getDirection, this);
  5674. this.storeNode = bind(this.storeNode, this);
  5675. this.toggle = bind(this.toggle, this);
  5676. this.hide = bind(this.hide, this);
  5677. this.show = bind(this.show, this);
  5678. this.visible = false;
  5679. this.items = [];
  5680. this.node = null;
  5681. this.height = 0;
  5682. this.direction = "bottom";
  5683. }
  5684. Menu.prototype.show = function() {
  5685. var ref;
  5686. if ((ref = window.visible_menu) != null) {
  5687. ref.hide();
  5688. }
  5689. this.visible = true;
  5690. window.visible_menu = this;
  5691. return this.direction = this.getDirection();
  5692. };
  5693. Menu.prototype.hide = function() {
  5694. return this.visible = false;
  5695. };
  5696. Menu.prototype.toggle = function() {
  5697. if (this.visible) {
  5698. this.hide();
  5699. } else {
  5700. this.show();
  5701. }
  5702. return Page.projector.scheduleRender();
  5703. };
  5704. Menu.prototype.addItem = function(title, cb, selected) {
  5705. if (selected == null) {
  5706. selected = false;
  5707. }
  5708. return this.items.push([title, cb, selected]);
  5709. };
  5710. Menu.prototype.storeNode = function(node) {
  5711. this.node = node;
  5712. if (this.visible) {
  5713. node.className = node.className.replace("visible", "");
  5714. setTimeout(((function(_this) {
  5715. return function() {
  5716. node.className += " visible";
  5717. return node.attributes.style.value = _this.getStyle();
  5718. };
  5719. })(this)), 20);
  5720. node.style.maxHeight = "none";
  5721. this.height = node.offsetHeight;
  5722. node.style.maxHeight = "0px";
  5723. return this.direction = this.getDirection();
  5724. }
  5725. };
  5726. Menu.prototype.getDirection = function() {
  5727. if (this.node && this.node.parentNode.getBoundingClientRect().top + this.height + 60 > document.body.clientHeight && this.node.parentNode.getBoundingClientRect().top - this.height > 0) {
  5728. return "top";
  5729. } else {
  5730. return "bottom";
  5731. }
  5732. };
  5733. Menu.prototype.handleClick = function(e) {
  5734. var cb, i, item, keep_menu, len, ref, selected, title;
  5735. keep_menu = false;
  5736. ref = this.items;
  5737. for (i = 0, len = ref.length; i < len; i++) {
  5738. item = ref[i];
  5739. title = item[0], cb = item[1], selected = item[2];
  5740. if (title === e.currentTarget.textContent || e.currentTarget["data-title"] === title) {
  5741. keep_menu = typeof cb === "function" ? cb(item) : void 0;
  5742. break;
  5743. }
  5744. }
  5745. if (keep_menu !== true && cb !== null) {
  5746. this.hide();
  5747. }
  5748. return false;
  5749. };
  5750. Menu.prototype.renderItem = function(item) {
  5751. var cb, classes, href, onclick, selected, title;
  5752. title = item[0], cb = item[1], selected = item[2];
  5753. if (typeof selected === "function") {
  5754. selected = selected();
  5755. }
  5756. if (title === "---") {
  5757. return h("div.menu-item-separator", {
  5758. key: Time.timestamp()
  5759. });
  5760. } else {
  5761. if (cb === null) {
  5762. href = void 0;
  5763. onclick = this.handleClick;
  5764. } else if (typeof cb === "string") {
  5765. href = cb;
  5766. onclick = true;
  5767. } else {
  5768. href = "#" + title;
  5769. onclick = this.handleClick;
  5770. }
  5771. classes = {
  5772. "selected": selected,
  5773. "noaction": cb === null
  5774. };
  5775. return h("a.menu-item", {
  5776. href: href,
  5777. onclick: onclick,
  5778. "data-title": title,
  5779. key: title,
  5780. classes: classes
  5781. }, title);
  5782. }
  5783. };
  5784. Menu.prototype.getStyle = function() {
  5785. var max_height, style;
  5786. if (this.visible) {
  5787. max_height = this.height;
  5788. } else {
  5789. max_height = 0;
  5790. }
  5791. style = "max-height: " + max_height + "px";
  5792. if (this.direction === "top") {
  5793. style += ";margin-top: " + (0 - this.height - 50) + "px";
  5794. } else {
  5795. style += ";margin-top: 0px";
  5796. }
  5797. return style;
  5798. };
  5799. Menu.prototype.render = function(class_name) {
  5800. if (class_name == null) {
  5801. class_name = "";
  5802. }
  5803. if (this.visible || this.node) {
  5804. return h("div.menu" + class_name, {
  5805. classes: {
  5806. "visible": this.visible
  5807. },
  5808. style: this.getStyle(),
  5809. afterCreate: this.storeNode
  5810. }, this.items.map(this.renderItem));
  5811. }
  5812. };
  5813. return Menu;
  5814. })();
  5815. window.Menu = Menu;
  5816. document.body.addEventListener("mouseup", function(e) {
  5817. var menu_node, menu_parents, ref, ref1;
  5818. if (!window.visible_menu || !window.visible_menu.node) {
  5819. return false;
  5820. }
  5821. menu_node = window.visible_menu.node;
  5822. menu_parents = [menu_node, menu_node.parentNode];
  5823. if ((ref = e.target.parentNode, indexOf.call(menu_parents, ref) < 0) && (ref1 = e.target.parentNode.parentNode, indexOf.call(menu_parents, ref1) < 0)) {
  5824. window.visible_menu.hide();
  5825. return Page.projector.scheduleRender();
  5826. }
  5827. });
  5828. }).call(this);
  5829. /* ---- utils/Prototypes.coffee ---- */
  5830. (function() {
  5831. String.prototype.startsWith = function(s) {
  5832. return this.slice(0, s.length) === s;
  5833. };
  5834. String.prototype.endsWith = function(s) {
  5835. return s === '' || this.slice(-s.length) === s;
  5836. };
  5837. String.prototype.capitalize = function() {
  5838. if (this.length) {
  5839. return this[0].toUpperCase() + this.slice(1);
  5840. } else {
  5841. return "";
  5842. }
  5843. };
  5844. String.prototype.repeat = function(count) {
  5845. return new Array(count + 1).join(this);
  5846. };
  5847. window.isEmpty = function(obj) {
  5848. var key;
  5849. for (key in obj) {
  5850. return false;
  5851. }
  5852. return true;
  5853. };
  5854. }).call(this);
  5855. /* ---- utils/RateLimit.coffee ---- */
  5856. (function() {
  5857. var call_after_interval, limits;
  5858. limits = {};
  5859. call_after_interval = {};
  5860. window.RateLimit = function(interval, fn) {
  5861. if (!limits[fn]) {
  5862. call_after_interval[fn] = false;
  5863. fn();
  5864. return limits[fn] = setTimeout((function() {
  5865. if (call_after_interval[fn]) {
  5866. fn();
  5867. }
  5868. delete limits[fn];
  5869. return delete call_after_interval[fn];
  5870. }), interval);
  5871. } else {
  5872. return call_after_interval[fn] = true;
  5873. }
  5874. };
  5875. }).call(this);
  5876. /* ---- utils/RateLimitCb.coffee ---- */
  5877. (function() {
  5878. var call_after_interval, calling, calling_iterval, last_time,
  5879. slice = [].slice;
  5880. last_time = {};
  5881. calling = {};
  5882. calling_iterval = {};
  5883. call_after_interval = {};
  5884. window.RateLimitCb = function(interval, fn, args) {
  5885. var cb;
  5886. if (args == null) {
  5887. args = [];
  5888. }
  5889. cb = function() {
  5890. var left;
  5891. left = interval - (Date.now() - last_time[fn]);
  5892. if (left <= 0) {
  5893. delete last_time[fn];
  5894. if (calling[fn]) {
  5895. RateLimitCb(interval, fn, calling[fn]);
  5896. }
  5897. return delete calling[fn];
  5898. } else {
  5899. return setTimeout((function() {
  5900. delete last_time[fn];
  5901. if (calling[fn]) {
  5902. RateLimitCb(interval, fn, calling[fn]);
  5903. }
  5904. return delete calling[fn];
  5905. }), left);
  5906. }
  5907. };
  5908. if (last_time[fn]) {
  5909. return calling[fn] = args;
  5910. } else {
  5911. last_time[fn] = Date.now();
  5912. return fn.apply(this, [cb].concat(slice.call(args)));
  5913. }
  5914. };
  5915. window.RateLimit = function(interval, fn) {
  5916. if (calling_iterval[fn] > interval) {
  5917. clearInterval(calling[fn]);
  5918. delete calling[fn];
  5919. }
  5920. if (!calling[fn]) {
  5921. call_after_interval[fn] = false;
  5922. fn();
  5923. calling_iterval[fn] = interval;
  5924. return calling[fn] = setTimeout((function() {
  5925. if (call_after_interval[fn]) {
  5926. fn();
  5927. }
  5928. delete calling[fn];
  5929. return delete call_after_interval[fn];
  5930. }), interval);
  5931. } else {
  5932. return call_after_interval[fn] = true;
  5933. }
  5934. };
  5935. /*
  5936. window.s = Date.now()
  5937. window.load = (done, num) ->
  5938. console.log "Loading #{num}...", Date.now()-window.s
  5939. setTimeout (-> done()), 1000
  5940. RateLimit 500, window.load, [0] # Called instantly
  5941. RateLimit 500, window.load, [1]
  5942. setTimeout (-> RateLimit 500, window.load, [300]), 300
  5943. setTimeout (-> RateLimit 500, window.load, [600]), 600 # Called after 1000ms
  5944. setTimeout (-> RateLimit 500, window.load, [1000]), 1000
  5945. setTimeout (-> RateLimit 500, window.load, [1200]), 1200 # Called after 2000ms
  5946. setTimeout (-> RateLimit 500, window.load, [3000]), 3000 # Called after 3000ms
  5947. */
  5948. }).call(this);
  5949. /* ---- utils/Text.coffee ---- */
  5950. (function() {
  5951. var MarkedRenderer, Text,
  5952. extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
  5953. hasProp = {}.hasOwnProperty,
  5954. indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
  5955. MarkedRenderer = (function(superClass) {
  5956. extend(MarkedRenderer, superClass);
  5957. function MarkedRenderer() {
  5958. return MarkedRenderer.__super__.constructor.apply(this, arguments);
  5959. }
  5960. MarkedRenderer.prototype.image = function(href, title, text) {
  5961. return "<code>![" + text + "](" + href + ")</code>";
  5962. };
  5963. return MarkedRenderer;
  5964. })(marked.Renderer);
  5965. Text = (function() {
  5966. function Text() {}
  5967. Text.prototype.toColor = function(text, saturation, lightness) {
  5968. var hash, i, j, ref;
  5969. if (saturation == null) {
  5970. saturation = 30;
  5971. }
  5972. if (lightness == null) {
  5973. lightness = 50;
  5974. }
  5975. hash = 0;
  5976. for (i = j = 0, ref = text.length - 1; 0 <= ref ? j <= ref : j >= ref; i = 0 <= ref ? ++j : --j) {
  5977. hash += text.charCodeAt(i) * i;
  5978. hash = hash % 1777;
  5979. }
  5980. return "hsl(" + (hash % 360) + ("," + saturation + "%," + lightness + "%)");
  5981. };
  5982. Text.prototype.renderMarked = function(text, options) {
  5983. if (options == null) {
  5984. options = {};
  5985. }
  5986. options["gfm"] = true;
  5987. options["breaks"] = true;
  5988. options["sanitize"] = true;
  5989. options["renderer"] = marked_renderer;
  5990. text = marked(text, options);
  5991. return this.fixHtmlLinks(text);
  5992. };
  5993. Text.prototype.emailLinks = function(text) {
  5994. return text.replace(/([a-zA-Z0-9]+)@zeroid.bit/g, "<a href='?to=$1' onclick='return Page.message_create.show(\"$1\")'>$1@zeroid.bit</a>");
  5995. };
  5996. Text.prototype.fixHtmlLinks = function(text) {
  5997. if (window.is_proxy) {
  5998. return text.replace(/href="http:\/\/(127.0.0.1|localhost):43110/g, 'href="http://zero');
  5999. } else {
  6000. return text.replace(/href="http:\/\/(127.0.0.1|localhost):43110/g, 'href="');
  6001. }
  6002. };
  6003. Text.prototype.fixLink = function(link) {
  6004. var back;
  6005. if (window.is_proxy) {
  6006. back = link.replace(/http:\/\/(127.0.0.1|localhost):43110/, 'http://zero');
  6007. return back.replace(/http:\/\/zero\/([^\/]+\.bit)/, "http://$1");
  6008. } else {
  6009. return link.replace(/http:\/\/(127.0.0.1|localhost):43110/, '');
  6010. }
  6011. };
  6012. Text.prototype.toUrl = function(text) {
  6013. return text.replace(/[^A-Za-z0-9]/g, "+").replace(/[+]+/g, "+").replace(/[+]+$/, "");
  6014. };
  6015. Text.prototype.getSiteUrl = function(address) {
  6016. if (window.is_proxy) {
  6017. if (indexOf.call(address, ".") >= 0) {
  6018. return "http://" + address + "/";
  6019. } else {
  6020. return "http://zero/" + address + "/";
  6021. }
  6022. } else {
  6023. return "/" + address + "/";
  6024. }
  6025. };
  6026. Text.prototype.fixReply = function(text) {
  6027. return text.replace(/(>.*\n)([^\n>])/gm, "$1\n$2");
  6028. };
  6029. Text.prototype.toBitcoinAddress = function(text) {
  6030. return text.replace(/[^A-Za-z0-9]/g, "");
  6031. };
  6032. Text.prototype.jsonEncode = function(obj) {
  6033. return unescape(encodeURIComponent(JSON.stringify(obj)));
  6034. };
  6035. Text.prototype.jsonDecode = function(obj) {
  6036. return JSON.parse(decodeURIComponent(escape(obj)));
  6037. };
  6038. Text.prototype.fileEncode = function(obj) {
  6039. if (typeof obj === "string") {
  6040. return btoa(unescape(encodeURIComponent(obj)));
  6041. } else {
  6042. return btoa(unescape(encodeURIComponent(JSON.stringify(obj, void 0, '\t'))));
  6043. }
  6044. };
  6045. Text.prototype.utf8Encode = function(s) {
  6046. return unescape(encodeURIComponent(s));
  6047. };
  6048. Text.prototype.utf8Decode = function(s) {
  6049. return decodeURIComponent(escape(s));
  6050. };
  6051. Text.prototype.distance = function(s1, s2) {
  6052. var char, extra_parts, j, key, len, match, next_find, next_find_i, val;
  6053. s1 = s1.toLocaleLowerCase();
  6054. s2 = s2.toLocaleLowerCase();
  6055. next_find_i = 0;
  6056. next_find = s2[0];
  6057. match = true;
  6058. extra_parts = {};
  6059. for (j = 0, len = s1.length; j < len; j++) {
  6060. char = s1[j];
  6061. if (char !== next_find) {
  6062. if (extra_parts[next_find_i]) {
  6063. extra_parts[next_find_i] += char;
  6064. } else {
  6065. extra_parts[next_find_i] = char;
  6066. }
  6067. } else {
  6068. next_find_i++;
  6069. next_find = s2[next_find_i];
  6070. }
  6071. }
  6072. if (extra_parts[next_find_i]) {
  6073. extra_parts[next_find_i] = "";
  6074. }
  6075. extra_parts = (function() {
  6076. var results;
  6077. results = [];
  6078. for (key in extra_parts) {
  6079. val = extra_parts[key];
  6080. results.push(val);
  6081. }
  6082. return results;
  6083. })();
  6084. if (next_find_i >= s2.length) {
  6085. return extra_parts.length + extra_parts.join("").length;
  6086. } else {
  6087. return false;
  6088. }
  6089. };
  6090. Text.prototype.parseQuery = function(query) {
  6091. var j, key, len, params, part, parts, ref, val;
  6092. params = {};
  6093. parts = query.split('&');
  6094. for (j = 0, len = parts.length; j < len; j++) {
  6095. part = parts[j];
  6096. ref = part.split("="), key = ref[0], val = ref[1];
  6097. if (val) {
  6098. params[decodeURIComponent(key)] = decodeURIComponent(val);
  6099. } else {
  6100. params["url"] = decodeURIComponent(key);
  6101. }
  6102. }
  6103. return params;
  6104. };
  6105. Text.prototype.encodeQuery = function(params) {
  6106. var back, key, val;
  6107. back = [];
  6108. if (params.url) {
  6109. back.push(params.url);
  6110. }
  6111. for (key in params) {
  6112. val = params[key];
  6113. if (!val || key === "url") {
  6114. continue;
  6115. }
  6116. back.push((encodeURIComponent(key)) + "=" + (encodeURIComponent(val)));
  6117. }
  6118. return back.join("&");
  6119. };
  6120. Text.prototype.highlight = function(text, search) {
  6121. var back, i, j, len, part, parts;
  6122. if (!text) {
  6123. return [""];
  6124. }
  6125. parts = text.split(RegExp(search, "i"));
  6126. back = [];
  6127. for (i = j = 0, len = parts.length; j < len; i = ++j) {
  6128. part = parts[i];
  6129. back.push(part);
  6130. if (i < parts.length - 1) {
  6131. back.push(h("span.highlight", {
  6132. key: i
  6133. }, search));
  6134. }
  6135. }
  6136. return back;
  6137. };
  6138. Text.prototype.formatSize = function(size) {
  6139. var size_mb;
  6140. if (!parseInt(size)) {
  6141. return "";
  6142. }
  6143. size_mb = size / 1024 / 1024;
  6144. if (size_mb >= 1000) {
  6145. return (size_mb / 1024).toFixed(1) + " GB";
  6146. } else if (size_mb >= 100) {
  6147. return size_mb.toFixed(0) + " MB";
  6148. } else if (size / 1024 >= 1000) {
  6149. return size_mb.toFixed(2) + " MB";
  6150. } else {
  6151. return (size / 1024).toFixed(2) + " KB";
  6152. }
  6153. };
  6154. return Text;
  6155. })();
  6156. window.marked_renderer = new MarkedRenderer();
  6157. window.is_proxy = document.location.host === "zero" || window.location.pathname === "/";
  6158. window.Text = new Text();
  6159. }).call(this);
  6160. /* ---- utils/Time.coffee ---- */
  6161. (function() {
  6162. var Time;
  6163. Time = (function() {
  6164. function Time() {}
  6165. Time.prototype.since = function(timestamp) {
  6166. var back, minutes, now, secs;
  6167. now = +(new Date) / 1000;
  6168. if (timestamp > 1000000000000) {
  6169. timestamp = timestamp / 1000;
  6170. }
  6171. secs = now - timestamp;
  6172. if (secs < 60) {
  6173. back = "Just now";
  6174. } else if (secs < 60 * 60) {
  6175. minutes = Math.round(secs / 60);
  6176. back = "" + minutes + " minutes ago";
  6177. } else if (secs < 60 * 60 * 24) {
  6178. back = (Math.round(secs / 60 / 60)) + " hours ago";
  6179. } else if (secs < 60 * 60 * 24 * 3) {
  6180. back = (Math.round(secs / 60 / 60 / 24)) + " days ago";
  6181. } else {
  6182. back = "on " + this.date(timestamp);
  6183. }
  6184. back = back.replace(/^1 ([a-z]+)s/, "1 $1");
  6185. return back;
  6186. };
  6187. Time.prototype.dateIso = function(timestamp) {
  6188. var tzoffset;
  6189. if (timestamp == null) {
  6190. timestamp = null;
  6191. }
  6192. if (!timestamp) {
  6193. timestamp = window.Time.timestamp();
  6194. }
  6195. if (timestamp > 1000000000000) {
  6196. timestamp = timestamp / 1000;
  6197. }
  6198. tzoffset = (new Date()).getTimezoneOffset() * 60;
  6199. return (new Date((timestamp - tzoffset) * 1000)).toISOString().split("T")[0];
  6200. };
  6201. Time.prototype.date = function(timestamp, format) {
  6202. var display, parts;
  6203. if (timestamp == null) {
  6204. timestamp = null;
  6205. }
  6206. if (format == null) {
  6207. format = "short";
  6208. }
  6209. if (!timestamp) {
  6210. timestamp = window.Time.timestamp();
  6211. }
  6212. if (timestamp > 1000000000000) {
  6213. timestamp = timestamp / 1000;
  6214. }
  6215. parts = (new Date(timestamp * 1000)).toString().split(" ");
  6216. if (format === "short") {
  6217. display = parts.slice(1, 4);
  6218. } else if (format === "day") {
  6219. display = parts.slice(1, 3);
  6220. } else if (format === "month") {
  6221. display = [parts[1], parts[3]];
  6222. } else if (format === "long") {
  6223. display = parts.slice(1, 5);
  6224. }
  6225. return display.join(" ").replace(/( [0-9]{4})/, ",$1");
  6226. };
  6227. Time.prototype.weekDay = function(timestamp) {
  6228. if (timestamp > 1000000000000) {
  6229. timestamp = timestamp / 1000;
  6230. }
  6231. return ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"][(new Date(timestamp * 1000)).getDay()];
  6232. };
  6233. Time.prototype.timestamp = function(date) {
  6234. if (date == null) {
  6235. date = "";
  6236. }
  6237. if (date === "now" || date === "") {
  6238. return parseInt(+(new Date) / 1000);
  6239. } else {
  6240. return parseInt(Date.parse(date) / 1000);
  6241. }
  6242. };
  6243. return Time;
  6244. })();
  6245. window.Time = new Time;
  6246. }).call(this);
  6247. /* ---- utils/Translate.coffee ---- */
  6248. (function() {
  6249. window._ = function(s) {
  6250. return s;
  6251. };
  6252. }).call(this);
  6253. /* ---- utils/ZeroFrame.coffee ---- */
  6254. (function() {
  6255. var ZeroFrame,
  6256. bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
  6257. extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
  6258. hasProp = {}.hasOwnProperty;
  6259. ZeroFrame = (function(superClass) {
  6260. extend(ZeroFrame, superClass);
  6261. function ZeroFrame(url) {
  6262. this.onCloseWebsocket = bind(this.onCloseWebsocket, this);
  6263. this.onOpenWebsocket = bind(this.onOpenWebsocket, this);
  6264. this.onRequest = bind(this.onRequest, this);
  6265. this.onMessage = bind(this.onMessage, this);
  6266. this.url = url;
  6267. this.waiting_cb = {};
  6268. this.wrapper_nonce = document.location.href.replace(/.*wrapper_nonce=([A-Za-z0-9]+).*/, "$1");
  6269. this.connect();
  6270. this.next_message_id = 1;
  6271. this.history_state = {};
  6272. this.init();
  6273. }
  6274. ZeroFrame.prototype.init = function() {
  6275. return this;
  6276. };
  6277. ZeroFrame.prototype.connect = function() {
  6278. this.target = window.parent;
  6279. window.addEventListener("message", this.onMessage, false);
  6280. this.cmd("innerReady");
  6281. window.addEventListener("beforeunload", (function(_this) {
  6282. return function(e) {
  6283. _this.log("save scrollTop", window.pageYOffset);
  6284. _this.history_state["scrollTop"] = window.pageYOffset;
  6285. return _this.cmd("wrapperReplaceState", [_this.history_state, null]);
  6286. };
  6287. })(this));
  6288. return this.cmd("wrapperGetState", [], (function(_this) {
  6289. return function(state) {
  6290. if (state != null) {
  6291. _this.history_state = state;
  6292. }
  6293. _this.log("restore scrollTop", state, window.pageYOffset);
  6294. if (window.pageYOffset === 0 && state) {
  6295. return window.scroll(window.pageXOffset, state.scrollTop);
  6296. }
  6297. };
  6298. })(this));
  6299. };
  6300. ZeroFrame.prototype.onMessage = function(e) {
  6301. var cmd, message;
  6302. message = e.data;
  6303. cmd = message.cmd;
  6304. if (cmd === "response") {
  6305. if (this.waiting_cb[message.to] != null) {
  6306. this.waiting_cb[message.to](message.result);
  6307. return delete this.waiting_cb[message.to];
  6308. } else {
  6309. return this.log("Websocket callback not found:", message);
  6310. }
  6311. } else if (cmd === "wrapperReady") {
  6312. return this.cmd("innerReady");
  6313. } else if (cmd === "ping") {
  6314. return this.response(message.id, "pong");
  6315. } else if (cmd === "wrapperOpenedWebsocket") {
  6316. return this.onOpenWebsocket();
  6317. } else if (cmd === "wrapperClosedWebsocket") {
  6318. return this.onCloseWebsocket();
  6319. } else {
  6320. return this.onRequest(cmd, message.params);
  6321. }
  6322. };
  6323. ZeroFrame.prototype.onRequest = function(cmd, message) {
  6324. return this.log("Unknown request", message);
  6325. };
  6326. ZeroFrame.prototype.response = function(to, result) {
  6327. return this.send({
  6328. "cmd": "response",
  6329. "to": to,
  6330. "result": result
  6331. });
  6332. };
  6333. ZeroFrame.prototype.cmd = function(cmd, params, cb) {
  6334. if (params == null) {
  6335. params = {};
  6336. }
  6337. if (cb == null) {
  6338. cb = null;
  6339. }
  6340. return this.send({
  6341. "cmd": cmd,
  6342. "params": params
  6343. }, cb);
  6344. };
  6345. ZeroFrame.prototype.send = function(message, cb) {
  6346. if (cb == null) {
  6347. cb = null;
  6348. }
  6349. message.wrapper_nonce = this.wrapper_nonce;
  6350. message.id = this.next_message_id;
  6351. this.next_message_id += 1;
  6352. this.target.postMessage(message, "*");
  6353. if (cb) {
  6354. return this.waiting_cb[message.id] = cb;
  6355. }
  6356. };
  6357. ZeroFrame.prototype.onOpenWebsocket = function() {
  6358. return this.log("Websocket open");
  6359. };
  6360. ZeroFrame.prototype.onCloseWebsocket = function() {
  6361. return this.log("Websocket close");
  6362. };
  6363. return ZeroFrame;
  6364. })(Class);
  6365. window.ZeroFrame = ZeroFrame;
  6366. }).call(this);
  6367. /* ---- Head.coffee ---- */
  6368. (function() {
  6369. var Head,
  6370. bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
  6371. extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
  6372. hasProp = {}.hasOwnProperty,
  6373. indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
  6374. Head = (function(superClass) {
  6375. extend(Head, superClass);
  6376. function Head() {
  6377. this.render = bind(this.render, this);
  6378. this.handleModeClick = bind(this.handleModeClick, this);
  6379. this.handleShutdownZeronetClick = bind(this.handleShutdownZeronetClick, this);
  6380. this.handleUpdateZeronetClick = bind(this.handleUpdateZeronetClick, this);
  6381. this.handleManageBlocksClick = bind(this.handleManageBlocksClick, this);
  6382. this.handleTorClick = bind(this.handleTorClick, this);
  6383. this.handleOrderbyClick = bind(this.handleOrderbyClick, this);
  6384. this.handleUpdateAllClick = bind(this.handleUpdateAllClick, this);
  6385. this.handleSettingsClick = bind(this.handleSettingsClick, this);
  6386. this.handleBackupClick = bind(this.handleBackupClick, this);
  6387. this.handleCreateSiteClick = bind(this.handleCreateSiteClick, this);
  6388. this.renderMenuTheme = bind(this.renderMenuTheme, this);
  6389. this.handleThemeClick = bind(this.handleThemeClick, this);
  6390. this.renderMenuLanguage = bind(this.renderMenuLanguage, this);
  6391. this.handleLanguageClick = bind(this.handleLanguageClick, this);
  6392. this.menu_settings = new Menu();
  6393. }
  6394. Head.prototype.formatUpdateInfo = function() {
  6395. if (parseFloat(Page.server_info.version.replace(".", "0")) < parseFloat(Page.latest_version.replace(".", "0"))) {
  6396. return "New version available!";
  6397. } else {
  6398. return "Up to date!";
  6399. }
  6400. };
  6401. Head.prototype.handleLanguageClick = function(e) {
  6402. var lang;
  6403. if (Page.server_info.rev < 1750) {
  6404. return Page.cmd("wrapperNotification", ["info", "You need ZeroNet 0.5.1 to change the interface's language"]);
  6405. }
  6406. lang = e.target.hash.replace("#", "");
  6407. Page.cmd("configSet", ["language", lang], function() {
  6408. Page.server_info.language = lang;
  6409. return top.location = "?Home";
  6410. });
  6411. return false;
  6412. };
  6413. Head.prototype.renderMenuLanguage = function() {
  6414. var lang, langs, ref;
  6415. langs = ["da", "de", "en", "es", "fr", "hu", "it", "nl", "pl", "pt", "pt-br", "ru", "sk", "tr", "uk", "zh", "zh-tw"];
  6416. if (Page.server_info.language && (ref = Page.server_info.language, indexOf.call(langs, ref) < 0)) {
  6417. langs.push(Page.server_info.language);
  6418. }
  6419. return h("div.menu-radio", h("div", "Language: "), (function() {
  6420. var i, len, results;
  6421. results = [];
  6422. for (i = 0, len = langs.length; i < len; i++) {
  6423. lang = langs[i];
  6424. results.push([
  6425. h("a", {
  6426. href: "#" + lang,
  6427. onclick: this.handleLanguageClick,
  6428. classes: {
  6429. selected: Page.server_info.language === lang,
  6430. long: lang.length > 2
  6431. }
  6432. }, lang), " "
  6433. ]);
  6434. }
  6435. return results;
  6436. }).call(this));
  6437. };
  6438. Head.prototype.handleThemeClick = function(e) {
  6439. var DARK, mqDark, theme;
  6440. if (Page.server_info.rev < 3670) {
  6441. return Page.cmd("wrapperNotification", ["info", "You need ZeroNet 0.6.4 to change the interface's theme"]);
  6442. }
  6443. theme = e.target.hash.replace("#", "");
  6444. if (theme === "system") {
  6445. if (Page.server_info.rev < 4085) {
  6446. return Page.cmd("wrapperNotification", ["info", "You need ZeroNet 0.7.0 to use system's theme"]);
  6447. }
  6448. DARK = "(prefers-color-scheme: dark)";
  6449. mqDark = window.matchMedia(DARK);
  6450. }
  6451. Page.cmd("userGetGlobalSettings", [], function(user_settings) {
  6452. if (theme === "system") {
  6453. theme = mqDark.matches ? "dark" : "light";
  6454. user_settings.use_system_theme = true;
  6455. } else {
  6456. user_settings.use_system_theme = false;
  6457. }
  6458. user_settings.theme = theme;
  6459. Page.server_info.user_settings = user_settings;
  6460. document.getElementById("style-live").innerHTML = "* { transition: all 0.5s ease-in-out }";
  6461. Page.cmd("userSetGlobalSettings", [user_settings]);
  6462. return setTimeout((function() {
  6463. document.body.className = document.body.className.replace(/theme-[a-z]+/, "");
  6464. document.body.className += " theme-" + theme;
  6465. return setTimeout((function() {
  6466. return document.getElementById("style-live").innerHTML = "";
  6467. }), 1000);
  6468. }), 300);
  6469. });
  6470. return false;
  6471. };
  6472. Head.prototype.renderMenuTheme = function() {
  6473. var ref, theme, theme_selected, themes;
  6474. themes = ["system", "light", "dark"];
  6475. if (Page.server_info.user_settings.use_system_theme) {
  6476. theme_selected = "system";
  6477. } else {
  6478. theme_selected = (ref = Page.server_info.user_settings) != null ? ref.theme : void 0;
  6479. if (!theme_selected) {
  6480. theme_selected = "system";
  6481. }
  6482. }
  6483. return h("div.menu-radio.menu-themes", h("div", "Theme: "), (function() {
  6484. var i, len, results;
  6485. results = [];
  6486. for (i = 0, len = themes.length; i < len; i++) {
  6487. theme = themes[i];
  6488. results.push([
  6489. h("a", {
  6490. href: "#" + theme,
  6491. onclick: this.handleThemeClick,
  6492. classes: {
  6493. selected: theme_selected === theme,
  6494. long: true
  6495. }
  6496. }, theme), " "
  6497. ]);
  6498. }
  6499. return results;
  6500. }).call(this));
  6501. };
  6502. Head.prototype.handleCreateSiteClick = function() {
  6503. if (Page.server_info.rev < 1770) {
  6504. return Page.cmd("wrapperNotification", ["info", "You need to update your ZeroNet client to use this feature"]);
  6505. }
  6506. return Page.cmd("siteClone", [Page.site_info.address, "template-new"]);
  6507. };
  6508. Head.prototype.handleBackupClick = function() {
  6509. if (Page.server_info.rev < 2165) {
  6510. return Page.cmd("wrapperNotification", ["info", "You need to update your ZeroNet client to use this feature"]);
  6511. }
  6512. Page.cmd("serverShowdirectory", "backup");
  6513. return Page.cmd("wrapperNotification", ["info", "Backup <b>users.json</b> file to keep your identity safe."]);
  6514. };
  6515. Head.prototype.handleSettingsClick = function() {
  6516. var base, orderby;
  6517. if ((base = Page.settings).sites_orderby == null) {
  6518. base.sites_orderby = "peers";
  6519. }
  6520. orderby = Page.settings.sites_orderby;
  6521. this.menu_settings.items = [];
  6522. this.menu_settings.items.push(["Update all sites", this.handleUpdateAllClick]);
  6523. this.menu_settings.items.push(["---"]);
  6524. this.menu_settings.items.push([
  6525. "Order sites by peers", ((function(_this) {
  6526. return function() {
  6527. return _this.handleOrderbyClick("peers");
  6528. };
  6529. })(this)), orderby === "peers"
  6530. ]);
  6531. this.menu_settings.items.push([
  6532. "Order sites by update time", ((function(_this) {
  6533. return function() {
  6534. return _this.handleOrderbyClick("modified");
  6535. };
  6536. })(this)), orderby === "modified"
  6537. ]);
  6538. this.menu_settings.items.push([
  6539. "Order sites by add time", ((function(_this) {
  6540. return function() {
  6541. return _this.handleOrderbyClick("addtime");
  6542. };
  6543. })(this)), orderby === "addtime"
  6544. ]);
  6545. this.menu_settings.items.push([
  6546. "Order sites by size", ((function(_this) {
  6547. return function() {
  6548. return _this.handleOrderbyClick("size");
  6549. };
  6550. })(this)), orderby === "size"
  6551. ]);
  6552. this.menu_settings.items.push(["---"]);
  6553. this.menu_settings.items.push([this.renderMenuTheme(), null]);
  6554. this.menu_settings.items.push(["---"]);
  6555. this.menu_settings.items.push([this.renderMenuLanguage(), null]);
  6556. this.menu_settings.items.push(["---"]);
  6557. this.menu_settings.items.push(["Create new, empty site", this.handleCreateSiteClick]);
  6558. this.menu_settings.items.push(["---"]);
  6559. this.menu_settings.items.push([[h("div.icon-mute", ""), "Manage blocked users and sites"], this.handleManageBlocksClick]);
  6560. if (Page.server_info.plugins.indexOf("UiConfig") >= 0) {
  6561. this.menu_settings.items.push([[h("div.icon-gear.emoji", "\u2699\uFE0E"), "Configuration"], "/Config"]);
  6562. }
  6563. if (Page.server_info.plugins.indexOf("UiPluginManager") >= 0) {
  6564. this.menu_settings.items.push([[h("div.icon-gear.emoji", "\u2B21"), "Plugins"], "/Plugins"]);
  6565. }
  6566. this.menu_settings.items.push(["---"]);
  6567. if (!Page.server_info.multiuser || Page.server_info.multiuser_admin) {
  6568. this.menu_settings.items.push(["Show data directory", this.handleBackupClick]);
  6569. }
  6570. // this.menu_settings.items.push(["Version " + Page.server_info.version + " (rev" + Page.server_info.rev + "): " + (this.formatUpdateInfo()), this.handleUpdateZeronetClick]);
  6571. this.menu_settings.items.push(["Version " + Page.server_info.version + " (rev" + Page.server_info.rev + ")"]);
  6572. if (!Page.server_info.multiuser || Page.server_info.multiuser_admin) {
  6573. this.menu_settings.items.push(["Shut down ZeroNet", this.handleShutdownZeronetClick]);
  6574. }
  6575. if (this.menu_settings.visible) {
  6576. this.menu_settings.hide();
  6577. } else {
  6578. this.menu_settings.show();
  6579. }
  6580. return false;
  6581. };
  6582. Head.prototype.handleUpdateAllClick = function() {
  6583. var i, len, ref, results, site;
  6584. ref = Page.site_list.sites;
  6585. results = [];
  6586. for (i = 0, len = ref.length; i < len; i++) {
  6587. site = ref[i];
  6588. if (site.row.settings.serving) {
  6589. results.push(Page.cmd("siteUpdate", {
  6590. "address": site.row.address
  6591. }));
  6592. } else {
  6593. results.push(void 0);
  6594. }
  6595. }
  6596. return results;
  6597. };
  6598. Head.prototype.handleOrderbyClick = function(orderby) {
  6599. Page.settings.sites_orderby = orderby;
  6600. Page.site_list.reorder();
  6601. return Page.saveSettings();
  6602. };
  6603. Head.prototype.handleTorClick = function() {
  6604. return true;
  6605. };
  6606. Head.prototype.handleManageBlocksClick = function() {
  6607. if (Page.server_info.rev < 1880) {
  6608. return Page.cmd("wrapperNotification", ["info", "You need ZeroNet 0.5.2 to use this feature."]);
  6609. }
  6610. Page.projector.replace($("#MuteList"), Page.mute_list.render);
  6611. return Page.mute_list.show();
  6612. };
  6613. Head.prototype.handleUpdateZeronetClick = function() {
  6614. return false;
  6615. };
  6616. Head.prototype.handleShutdownZeronetClick = function() {
  6617. return Page.cmd("wrapperConfirm", ["Are you sure?", "Shut down ZeroNet"], (function(_this) {
  6618. return function() {
  6619. return Page.cmd("serverShutdown");
  6620. };
  6621. })(this));
  6622. };
  6623. Head.prototype.handleModeClick = function(e) {
  6624. Page.handleLinkClick(e);
  6625. return false;
  6626. };
  6627. Head.prototype.render = function() {
  6628. return h("div#Head", h("a.settings", {
  6629. href: "#Settings",
  6630. onmousedown: this.handleSettingsClick,
  6631. onclick: Page.returnFalse
  6632. }, ["\u22EE"]), this.menu_settings.render(), h("a.logo", {
  6633. href: "?Home"
  6634. }, [
  6635. h("span", ["0net-conservancy dashboard"])
  6636. ]), h("div.modes", [
  6637. h("a.mode.sites", {
  6638. href: "?",
  6639. classes: {
  6640. active: Page.mode === "Sites"
  6641. },
  6642. onclick: Page.handleLinkClick
  6643. }, _("Sites")), h("a.mode.files", {
  6644. href: "?Files",
  6645. classes: {
  6646. active: Page.mode === "Files"
  6647. },
  6648. onclick: Page.handleLinkClick
  6649. }, _("Files")), h("a.mode.stats", {
  6650. href: "?Stats",
  6651. classes: {
  6652. active: Page.mode === "Stats"
  6653. },
  6654. onclick: Page.handleLinkClick
  6655. }, _("Stats"))
  6656. ]));
  6657. };
  6658. return Head;
  6659. })(Class);
  6660. window.Head = Head;
  6661. }).call(this);
  6662. /* ---- ZeroHello.coffee ---- */
  6663. (function() {
  6664. var ZeroHello,
  6665. bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
  6666. extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
  6667. hasProp = {}.hasOwnProperty;
  6668. window.h = maquette.h;
  6669. ZeroHello = (function(superClass) {
  6670. extend(ZeroHello, superClass);
  6671. function ZeroHello() {
  6672. this.reloadAnnouncerStats = bind(this.reloadAnnouncerStats, this);
  6673. this.reloadAnnouncerInfo = bind(this.reloadAnnouncerInfo, this);
  6674. this.reloadServerErrors = bind(this.reloadServerErrors, this);
  6675. this.reloadServerInfo = bind(this.reloadServerInfo, this);
  6676. this.reloadSiteInfo = bind(this.reloadSiteInfo, this);
  6677. this.onOpenWebsocket = bind(this.onOpenWebsocket, this);
  6678. this.handleLinkClick = bind(this.handleLinkClick, this);
  6679. return ZeroHello.__super__.constructor.apply(this, arguments);
  6680. }
  6681. ZeroHello.prototype.init = function() {
  6682. this.params = {};
  6683. this.site_info = null;
  6684. this.server_info = null;
  6685. this.announcer_info = null;
  6686. this.announcer_stats = null;
  6687. this.address = null;
  6688. this.on_site_info = new Promise();
  6689. this.on_server_info = new Promise();
  6690. this.on_settings = new Promise();
  6691. this.on_loaded = new Promise();
  6692. this.settings = null;
  6693. this.server_errors = [];
  6694. this.latest_version = "0.7.1";
  6695. this.latest_rev = 3616;
  6696. this.mode = "Sites";
  6697. this.change_timer = null;
  6698. return document.body.id = "Body" + this.mode;
  6699. };
  6700. ZeroHello.prototype.addRenderer = function(node, renderer) {
  6701. this.projector.replace(node, renderer);
  6702. return this.renderers.push(renderer);
  6703. };
  6704. ZeroHello.prototype.detachRenderers = function() {
  6705. var i, len, ref, renderer;
  6706. ref = this.renderers;
  6707. for (i = 0, len = ref.length; i < len; i++) {
  6708. renderer = ref[i];
  6709. this.projector.detach(renderer);
  6710. }
  6711. return this.renderers = [];
  6712. };
  6713. ZeroHello.prototype.setProjectorMode = function(mode) {
  6714. this.log("setProjectorMode", mode);
  6715. if (this.mode === mode) {
  6716. return;
  6717. }
  6718. this.detachRenderers();
  6719. if (mode === "Files") {
  6720. this.addRenderer($("#PageFiles"), this.page_files.render);
  6721. this.page_files.need_update = true;
  6722. } else if (mode === "Stats") {
  6723. this.addRenderer($("#PageStats"), this.page_stats.render);
  6724. this.page_stats.need_update = true;
  6725. } else {
  6726. mode = "Sites";
  6727. this.addRenderer($("#FeedList"), this.feed_list.render);
  6728. this.addRenderer($("#SiteList"), this.site_list.render);
  6729. }
  6730. this.mode = mode;
  6731. return setTimeout((function() {
  6732. document.body.id = "Body" + mode;
  6733. if (this.change_timer) {
  6734. clearInterval(this.change_timer);
  6735. }
  6736. document.body.classList.add("changing");
  6737. return this.change_timer = setTimeout((function() {
  6738. return document.body.classList.remove("changing");
  6739. }), 800);
  6740. }), 60);
  6741. };
  6742. ZeroHello.prototype.createProjector = function() {
  6743. var url;
  6744. this.projector = maquette.createProjector();
  6745. this.projectors = {};
  6746. this.renderers = [];
  6747. this.site_list = new SiteList();
  6748. this.feed_list = new FeedList();
  6749. this.page_files = new PageFiles();
  6750. this.page_stats = new PageStats();
  6751. this.head = new Head();
  6752. this.dashboard = new Dashboard();
  6753. this.mute_list = new MuteList();
  6754. this.trigger = new Trigger();
  6755. if (base.href.indexOf("?") === -1) {
  6756. this.route("");
  6757. } else {
  6758. url = base.href.replace(/.*?\?/, "");
  6759. this.route(url);
  6760. this.history_state["url"] = url;
  6761. }
  6762. this.loadSettings();
  6763. this.on_site_info.then((function(_this) {
  6764. return function() {
  6765. _this.projector.replace($("#Head"), _this.head.render);
  6766. _this.projector.replace($("#Dashboard"), _this.dashboard.render);
  6767. _this.projector.merge($("#Trigger"), _this.trigger.render);
  6768. return _this.setProjectorMode(_this.mode);
  6769. };
  6770. })(this));
  6771. return setInterval((function() {
  6772. return Page.projector.scheduleRender();
  6773. }), 60 * 1000);
  6774. };
  6775. ZeroHello.prototype.route = function(query) {
  6776. this.params = Text.parseQuery(query);
  6777. this.log("Route", this.params);
  6778. this.setProjectorMode(this.params.url);
  6779. if (this.mode === "Stats") {
  6780. this.page_stats.need_update = true;
  6781. } else if (this.mode === "Files") {
  6782. this.page_files.need_update = true;
  6783. }
  6784. return this.projector.scheduleRender();
  6785. };
  6786. ZeroHello.prototype.createUrl = function(key, val) {
  6787. var params, vals;
  6788. params = JSON.parse(JSON.stringify(this.params));
  6789. if (typeof key === "Object") {
  6790. vals = key;
  6791. for (key in keys) {
  6792. val = keys[key];
  6793. params[key] = val;
  6794. }
  6795. } else {
  6796. params[key] = val;
  6797. }
  6798. return "?" + Text.encodeQuery(params);
  6799. };
  6800. ZeroHello.prototype.setUrl = function(url, mode) {
  6801. if (mode == null) {
  6802. mode = "replace";
  6803. }
  6804. url = url.replace(/.*?\?/, "");
  6805. this.log("setUrl", this.history_state["url"], "->", url);
  6806. if (this.history_state["url"] === url) {
  6807. return false;
  6808. }
  6809. this.history_state["url"] = url;
  6810. if (mode === "replace") {
  6811. this.cmd("wrapperReplaceState", [this.history_state, "", url]);
  6812. } else {
  6813. this.cmd("wrapperPushState", [this.history_state, "", url]);
  6814. }
  6815. this.route(url);
  6816. return false;
  6817. };
  6818. ZeroHello.prototype.handleLinkClick = function(e) {
  6819. if (e.which === 2) {
  6820. return true;
  6821. } else {
  6822. this.log("save scrollTop", window.pageYOffset);
  6823. this.history_state["scrollTop"] = window.pageYOffset;
  6824. this.cmd("wrapperReplaceState", [this.history_state, null]);
  6825. window.scroll(window.pageXOffset, 0);
  6826. this.history_state["scrollTop"] = 0;
  6827. this.setUrl(e.currentTarget.search);
  6828. return false;
  6829. }
  6830. };
  6831. ZeroHello.prototype.loadSettings = function() {
  6832. return this.on_site_info.then((function(_this) {
  6833. return function() {
  6834. return _this.cmd("userGetSettings", [], function(res) {
  6835. var base1, base2, base3, base4;
  6836. if (!res || res.error) {
  6837. return _this.loadLocalStorage();
  6838. } else {
  6839. _this.settings = res;
  6840. if ((base1 = _this.settings).sites_orderby == null) {
  6841. base1.sites_orderby = "peers";
  6842. }
  6843. if ((base2 = _this.settings).favorite_sites == null) {
  6844. base2.favorite_sites = {};
  6845. }
  6846. if ((base3 = _this.settings).siteblocks_ignore == null) {
  6847. base3.siteblocks_ignore = {};
  6848. }
  6849. if ((base4 = _this.settings).date_feed_visit == null) {
  6850. base4.date_feed_visit = 1;
  6851. }
  6852. _this.feed_list.date_feed_visit = _this.settings.date_feed_visit;
  6853. return _this.on_settings.resolve(_this.settings);
  6854. }
  6855. });
  6856. };
  6857. })(this));
  6858. };
  6859. ZeroHello.prototype.loadLocalStorage = function() {
  6860. return this.cmd("wrapperGetLocalStorage", [], (function(_this) {
  6861. return function(settings) {
  6862. var base1, base2;
  6863. _this.settings = settings;
  6864. _this.log("Loaded localstorage");
  6865. if (_this.settings == null) {
  6866. _this.settings = {};
  6867. }
  6868. if ((base1 = _this.settings).sites_orderby == null) {
  6869. base1.sites_orderby = "peers";
  6870. }
  6871. if ((base2 = _this.settings).favorite_sites == null) {
  6872. base2.favorite_sites = {};
  6873. }
  6874. return _this.on_settings.resolve(_this.settings);
  6875. };
  6876. })(this));
  6877. };
  6878. ZeroHello.prototype.saveSettings = function(cb) {
  6879. if (this.settings) {
  6880. if (Page.server_info.rev > 2140) {
  6881. return this.cmd("userSetSettings", [this.settings], (function(_this) {
  6882. return function(res) {
  6883. if (cb) {
  6884. return cb(res);
  6885. }
  6886. };
  6887. })(this));
  6888. } else {
  6889. return this.cmd("wrapperSetLocalStorage", this.settings, (function(_this) {
  6890. return function(res) {
  6891. if (cb) {
  6892. return cb(res);
  6893. }
  6894. };
  6895. })(this));
  6896. }
  6897. }
  6898. };
  6899. ZeroHello.prototype.onOpenWebsocket = function(e) {
  6900. this.reloadServerInfo();
  6901. this.reloadServerErrors();
  6902. return this.reloadSiteInfo();
  6903. };
  6904. ZeroHello.prototype.reloadSiteInfo = function() {
  6905. return this.cmd("siteInfo", {}, (function(_this) {
  6906. return function(site_info) {
  6907. _this.address = site_info.address;
  6908. return _this.setSiteInfo(site_info);
  6909. };
  6910. })(this));
  6911. };
  6912. ZeroHello.prototype.reloadServerInfo = function(cb) {
  6913. return this.cmd("serverInfo", {}, (function(_this) {
  6914. return function(server_info) {
  6915. _this.setServerInfo(server_info);
  6916. return typeof cb === "function" ? cb(server_info) : void 0;
  6917. };
  6918. })(this));
  6919. };
  6920. ZeroHello.prototype.reloadServerErrors = function(cb) {
  6921. return this.cmd("serverErrors", {}, (function(_this) {
  6922. return function(server_errors) {
  6923. _this.setServerErrors(server_errors);
  6924. return typeof cb === "function" ? cb(server_errors) : void 0;
  6925. };
  6926. })(this));
  6927. };
  6928. ZeroHello.prototype.reloadAnnouncerInfo = function(cb) {
  6929. return this.cmd("announcerInfo", {}, (function(_this) {
  6930. return function(announcer_info) {
  6931. _this.setAnnouncerInfo(announcer_info);
  6932. return typeof cb === "function" ? cb() : void 0;
  6933. };
  6934. })(this));
  6935. };
  6936. ZeroHello.prototype.reloadAnnouncerStats = function(cb) {
  6937. return this.cmd("announcerStats", {}, (function(_this) {
  6938. return function(announcer_stats) {
  6939. _this.announcer_stats = announcer_stats;
  6940. Page.projector.scheduleRender();
  6941. return typeof cb === "function" ? cb() : void 0;
  6942. };
  6943. })(this));
  6944. };
  6945. ZeroHello.prototype.onRequest = function(cmd, params) {
  6946. if (cmd === "setSiteInfo") {
  6947. return this.setSiteInfo(params);
  6948. } else if (cmd === "setServerInfo") {
  6949. return this.setServerInfo(params);
  6950. } else if (cmd === "setAnnouncerInfo") {
  6951. return this.setAnnouncerInfo(params);
  6952. } else {
  6953. return this.log("Unknown command", params);
  6954. }
  6955. };
  6956. ZeroHello.prototype.setSiteInfo = function(site_info) {
  6957. var ref, ref1;
  6958. if (site_info.address === this.address) {
  6959. this.site_info = site_info;
  6960. if (((ref = this.server_info) != null ? ref.rev : void 0) > 3530) {
  6961. this.reloadAnnouncerStats();
  6962. } else if (((ref1 = this.server_info) != null ? ref1.rev : void 0) > 3460) {
  6963. this.reloadAnnouncerInfo();
  6964. }
  6965. }
  6966. this.site_list.onSiteInfo(site_info);
  6967. this.feed_list.onSiteInfo(site_info);
  6968. this.page_files.onSiteInfo(site_info);
  6969. return this.on_site_info.resolve();
  6970. };
  6971. ZeroHello.prototype.setServerInfo = function(server_info) {
  6972. var ref;
  6973. this.server_info = server_info;
  6974. if (parseFloat(Page.server_info.version.replace(/\./g, "0")) < 700) {
  6975. this.latest_version = "0.6.5";
  6976. }
  6977. this.projector.scheduleRender();
  6978. if (((ref = server_info.event) != null ? ref[0] : void 0) === "log_event") {
  6979. RateLimit(1000, (function(_this) {
  6980. return function() {
  6981. return _this.reloadServerErrors();
  6982. };
  6983. })(this));
  6984. }
  6985. return this.on_server_info.resolve();
  6986. };
  6987. ZeroHello.prototype.setServerErrors = function(server_errors) {
  6988. var date_added, i, len, level, message, ref;
  6989. this.server_errors = [];
  6990. for (i = 0, len = server_errors.length; i < len; i++) {
  6991. ref = server_errors[i], date_added = ref[0], level = ref[1], message = ref[2];
  6992. this.server_errors.push({
  6993. title: [Time.since(date_added), " - ", level],
  6994. descr: message,
  6995. href: null
  6996. });
  6997. }
  6998. return this.projector.scheduleRender();
  6999. };
  7000. ZeroHello.prototype.setAnnouncerInfo = function(announcer_info) {
  7001. this.announcer_info = announcer_info.stats;
  7002. return this.projector.scheduleRender();
  7003. };
  7004. ZeroHello.prototype.returnFalse = function() {
  7005. return false;
  7006. };
  7007. ZeroHello.prototype.updateZeronet = function() {
  7008. Page.cmd("wrapperNotification", ["info", "please update zeronet-conservancy via git", 8000]);
  7009. };
  7010. return ZeroHello;
  7011. })(ZeroFrame);
  7012. window.Page = new ZeroHello();
  7013. window.Page.createProjector();
  7014. }).call(this);