all.js 176 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477
  1. /* ---- /1MaiL5gfBM1cyb4a8e3iiL8L5gXmoAJu27/js/lib/Base64Number.js ---- */
  2. window.Base64Number = {
  3. _Rixits : "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/",
  4. fromNumber : function(number) {
  5. if (isNaN(Number(number)) || number === null ||
  6. number === Number.POSITIVE_INFINITY)
  7. throw "The input is not valid";
  8. if (number < 0)
  9. throw "Can't represent negative numbers now";
  10. var rixit; // like 'digit', only in some non-decimal radix
  11. var residual = Math.floor(number);
  12. var result = '';
  13. while (true) {
  14. rixit = residual % 64
  15. result = this._Rixits.charAt(rixit) + result;
  16. residual = Math.floor(residual / 64);
  17. if (residual == 0)
  18. break;
  19. }
  20. return result;
  21. },
  22. toNumber : function(rixits) {
  23. var result = 0;
  24. rixits = rixits.split('');
  25. for (var e = 0; e < rixits.length; e++) {
  26. result = (result * 64) + this._Rixits.indexOf(rixits[e]);
  27. }
  28. return result;
  29. }
  30. };
  31. /* ---- /1MaiL5gfBM1cyb4a8e3iiL8L5gXmoAJu27/js/lib/Promise.coffee ---- */
  32. (function() {
  33. var Promise,
  34. __slice = [].slice;
  35. Promise = (function() {
  36. Promise.when = function() {
  37. var args, num_uncompleted, promise, task, task_id, tasks, _fn, _i, _len;
  38. tasks = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
  39. num_uncompleted = tasks.length;
  40. args = new Array(num_uncompleted);
  41. promise = new Promise();
  42. _fn = function(task_id) {
  43. return task.then(function() {
  44. args[task_id] = Array.prototype.slice.call(arguments);
  45. num_uncompleted--;
  46. if (num_uncompleted === 0) {
  47. return promise.complete.apply(promise, args);
  48. }
  49. });
  50. };
  51. for (task_id = _i = 0, _len = tasks.length; _i < _len; task_id = ++_i) {
  52. task = tasks[task_id];
  53. _fn(task_id);
  54. }
  55. return promise;
  56. };
  57. function Promise() {
  58. this.resolved = false;
  59. this.end_promise = null;
  60. this.result = null;
  61. this.callbacks = [];
  62. }
  63. Promise.prototype.resolve = function() {
  64. var back, callback, _i, _len, _ref;
  65. if (this.resolved) {
  66. return false;
  67. }
  68. this.resolved = true;
  69. this.data = arguments;
  70. if (!arguments.length) {
  71. this.data = [true];
  72. }
  73. this.result = this.data[0];
  74. _ref = this.callbacks;
  75. for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  76. callback = _ref[_i];
  77. back = callback.apply(callback, this.data);
  78. }
  79. if (this.end_promise) {
  80. return this.end_promise.resolve(back);
  81. }
  82. };
  83. Promise.prototype.fail = function() {
  84. return this.resolve(false);
  85. };
  86. Promise.prototype.then = function(callback) {
  87. if (this.resolved === true) {
  88. callback.apply(callback, this.data);
  89. return;
  90. }
  91. this.callbacks.push(callback);
  92. return this.end_promise = new Promise();
  93. };
  94. return Promise;
  95. })();
  96. window.Promise = Promise;
  97. /*
  98. s = Date.now()
  99. log = (text) ->
  100. console.log Date.now()-s, Array.prototype.slice.call(arguments).join(", ")
  101. log "Started"
  102. cmd = (query) ->
  103. p = new Promise()
  104. setTimeout ( ->
  105. p.resolve query+" Result"
  106. ), 100
  107. return p
  108. back = cmd("SELECT * FROM message").then (res) ->
  109. log res
  110. return "Return from query"
  111. .then (res) ->
  112. log "Back then", res
  113. log "Query started", back
  114. */
  115. }).call(this);
  116. /* ---- /1MaiL5gfBM1cyb4a8e3iiL8L5gXmoAJu27/js/lib/Property.coffee ---- */
  117. (function() {
  118. Function.prototype.property = function(prop, desc) {
  119. return Object.defineProperty(this.prototype, prop, desc);
  120. };
  121. }).call(this);
  122. /* ---- /1MaiL5gfBM1cyb4a8e3iiL8L5gXmoAJu27/js/lib/maquette.js ---- */
  123. (function (global) {
  124. "use strict";
  125. // Utilities
  126. var emptyArray = [];
  127. var extend = function (base, overrides) {
  128. var result = {};
  129. Object.keys(base).forEach(function (key) {
  130. result[key] = base[key];
  131. });
  132. if(overrides) {
  133. Object.keys(overrides).forEach(function (key) {
  134. result[key] = overrides[key];
  135. });
  136. }
  137. return result;
  138. };
  139. // Hyperscript helper functions
  140. var appendChildren = function (parentSelector, insertions, main) {
  141. for(var i = 0; i < insertions.length; i++) {
  142. var item = insertions[i];
  143. if(Array.isArray(item)) {
  144. appendChildren(parentSelector, item, main);
  145. } else {
  146. if(item !== null && item !== undefined) {
  147. if(!item.hasOwnProperty("vnodeSelector")) {
  148. item = toTextVNode(item);
  149. }
  150. main.push(item);
  151. }
  152. }
  153. }
  154. };
  155. var toTextVNode = function (data) {
  156. return {
  157. vnodeSelector: "",
  158. properties: undefined,
  159. children: undefined,
  160. text: (data === null || data === undefined) ? "" : data.toString(),
  161. domNode: null
  162. };
  163. };
  164. // Render helper functions
  165. var missingTransition = function() {
  166. throw new Error("Provide a transitions object to the projectionOptions to do animations");
  167. };
  168. var defaultProjectionOptions = {
  169. namespace: undefined,
  170. eventHandlerInterceptor: undefined,
  171. styleApplyer: function(domNode, styleName, value) {
  172. // Provides a hook to add vendor prefixes for browsers that still need it.
  173. domNode.style[styleName] = value;
  174. },
  175. transitions: {
  176. enter: missingTransition,
  177. exit: missingTransition
  178. }
  179. };
  180. var applyDefaultProjectionOptions = function (projectionOptions) {
  181. return extend(defaultProjectionOptions, projectionOptions);
  182. };
  183. var setProperties = function (domNode, properties, projectionOptions) {
  184. if(!properties) {
  185. return;
  186. }
  187. var eventHandlerInterceptor = projectionOptions.eventHandlerInterceptor;
  188. for(var propName in properties) {
  189. var propValue = properties[propName];
  190. if(propName === "class" || propName === "className" || propName === "classList") {
  191. throw new Error("Property " + propName + " is not supported, use 'classes' instead.");
  192. } else if(propName === "classes") {
  193. // object with string keys and boolean values
  194. for(var className in propValue) {
  195. if(propValue[className]) {
  196. domNode.classList.add(className);
  197. }
  198. }
  199. } else if(propName === "styles") {
  200. // object with string keys and string (!) values
  201. for(var styleName in propValue) {
  202. var styleValue = propValue[styleName];
  203. if(styleValue) {
  204. if(typeof styleValue !== "string") {
  205. throw new Error("Style values may only be strings");
  206. }
  207. projectionOptions.styleApplyer(domNode, styleName, styleValue);
  208. }
  209. }
  210. } else if(propName === "key") {
  211. continue;
  212. } else if(propValue === null || propValue === undefined) {
  213. continue;
  214. } else {
  215. var type = typeof propValue;
  216. if(type === "function") {
  217. if(eventHandlerInterceptor && (propName.lastIndexOf("on", 0) === 0)) { // lastIndexOf(,0)===0 -> startsWith
  218. propValue = eventHandlerInterceptor(propName, propValue, domNode, properties); // intercept eventhandlers
  219. if(propName === "oninput") {
  220. (function () {
  221. // record the evt.target.value, because IE sometimes does a requestAnimationFrame between changing value and running oninput
  222. var oldPropValue = propValue;
  223. propValue = function (evt) {
  224. evt.target["oninput-value"] = evt.target.value;
  225. oldPropValue.apply(this, [evt]);
  226. };
  227. }());
  228. }
  229. }
  230. domNode[propName] = propValue;
  231. } else if(type === "string" && propName !== "value") {
  232. domNode.setAttribute(propName, propValue);
  233. } else {
  234. domNode[propName] = propValue;
  235. }
  236. }
  237. }
  238. };
  239. var updateProperties = function (domNode, previousProperties, properties, projectionOptions) {
  240. if(!properties) {
  241. return;
  242. }
  243. var propertiesUpdated = false;
  244. for(var propName in properties) {
  245. // assuming that properties will be nullified instead of missing is by design
  246. var propValue = properties[propName];
  247. var previousValue = previousProperties[propName];
  248. if(propName === "classes") {
  249. var classList = domNode.classList;
  250. for(var className in propValue) {
  251. var on = !!propValue[className];
  252. var previousOn = !!previousValue[className];
  253. if(on === previousOn) {
  254. continue;
  255. }
  256. propertiesUpdated = true;
  257. if(on) {
  258. classList.add(className);
  259. } else {
  260. classList.remove(className);
  261. }
  262. }
  263. } else if(propName === "styles") {
  264. for(var styleName in propValue) {
  265. var newStyleValue = propValue[styleName];
  266. var oldStyleValue = previousValue[styleName];
  267. if(newStyleValue === oldStyleValue) {
  268. continue;
  269. }
  270. propertiesUpdated = true;
  271. if(newStyleValue) {
  272. if(typeof newStyleValue !== "string") {
  273. throw new Error("Style values may only be strings");
  274. }
  275. projectionOptions.styleApplyer(domNode, styleName, newStyleValue);
  276. } else {
  277. projectionOptions.styleApplyer(domNode, styleName, "");
  278. }
  279. }
  280. } else {
  281. if(!propValue && typeof previousValue === "string") {
  282. propValue = "";
  283. }
  284. if(propName === "value") { // value can be manipulated by the user directly and using event.preventDefault() is not an option
  285. if(domNode[propName] !== propValue && domNode["oninput-value"] !== propValue) {
  286. domNode[propName] = propValue; // Reset the value, even if the virtual DOM did not change
  287. domNode["oninput-value"] = undefined;
  288. } // else do not update the domNode, otherwise the cursor position would be changed
  289. if(propValue !== previousValue) {
  290. propertiesUpdated = true;
  291. }
  292. } else if(propValue !== previousValue) {
  293. var type = typeof propValue;
  294. if(type === "function") {
  295. throw new Error("Functions may not be updated on subsequent renders (property: " + propName +
  296. "). Hint: declare event handler functions outside the render() function.");
  297. }
  298. if(type === "string") {
  299. domNode.setAttribute(propName, propValue);
  300. } else {
  301. if(domNode[propName] !== propValue) { // Comparison is here for side-effects in Edge with scrollLeft and scrollTop
  302. domNode[propName] = propValue;
  303. }
  304. }
  305. propertiesUpdated = true;
  306. }
  307. }
  308. }
  309. return propertiesUpdated;
  310. };
  311. var addChildren = function (domNode, children, projectionOptions) {
  312. if(!children) {
  313. return;
  314. }
  315. for(var i = 0; i < children.length; i++) {
  316. createDom(children[i], domNode, undefined, projectionOptions);
  317. }
  318. };
  319. var same = function (vnode1, vnode2) {
  320. if(vnode1.vnodeSelector !== vnode2.vnodeSelector) {
  321. return false;
  322. }
  323. if(vnode1.properties && vnode2.properties) {
  324. return vnode1.properties.key === vnode2.properties.key;
  325. }
  326. return !vnode1.properties && !vnode2.properties;
  327. };
  328. var findIndexOfChild = function (children, sameAs, start) {
  329. if(sameAs.vnodeSelector !== "") {
  330. // Never scan for text-nodes
  331. for(var i = start; i < children.length; i++) {
  332. if(same(children[i], sameAs)) {
  333. return i;
  334. }
  335. }
  336. }
  337. return -1;
  338. };
  339. var nodeAdded = function (vNode, transitions) {
  340. if(vNode.properties) {
  341. var enterAnimation = vNode.properties.enterAnimation;
  342. if(enterAnimation) {
  343. if(typeof enterAnimation === "function") {
  344. enterAnimation(vNode.domNode, vNode.properties);
  345. } else {
  346. transitions.enter(vNode.domNode, vNode.properties, enterAnimation);
  347. }
  348. }
  349. }
  350. };
  351. var nodeToRemove = function (vNode, transitions) {
  352. var domNode = vNode.domNode;
  353. if(vNode.properties) {
  354. var exitAnimation = vNode.properties.exitAnimation;
  355. if(exitAnimation) {
  356. domNode.style.pointerEvents = "none";
  357. var removeDomNode = function () {
  358. if(domNode.parentNode) {
  359. domNode.parentNode.removeChild(domNode);
  360. }
  361. };
  362. if(typeof exitAnimation === "function") {
  363. exitAnimation(domNode, removeDomNode, vNode.properties);
  364. return;
  365. } else {
  366. transitions.exit(vNode.domNode, vNode.properties, exitAnimation, removeDomNode);
  367. return;
  368. }
  369. }
  370. }
  371. if(domNode.parentNode) {
  372. domNode.parentNode.removeChild(domNode);
  373. }
  374. };
  375. var checkDistinguishable = function(childNodes, indexToCheck, parentVNode, operation) {
  376. var childNode = childNodes[indexToCheck];
  377. if (childNode.vnodeSelector === "") {
  378. return; // Text nodes need not be distinguishable
  379. }
  380. var key = childNode.properties ? childNode.properties.key : undefined;
  381. if (!key) { // A key is just assumed to be unique
  382. for (var i = 0; i < childNodes.length; i++) {
  383. if (i !== indexToCheck) {
  384. var node = childNodes[i];
  385. if (same(node, childNode)) {
  386. if (operation === "added") {
  387. throw new Error(parentVNode.vnodeSelector + " had a " + childNode.vnodeSelector + " child " +
  388. "added, but there is now more than one. You must add unique key properties to make them distinguishable.");
  389. } else {
  390. throw new Error(parentVNode.vnodeSelector + " had a " + childNode.vnodeSelector + " child " +
  391. "removed, but there were more than one. You must add unique key properties to make them distinguishable.");
  392. }
  393. }
  394. }
  395. }
  396. }
  397. };
  398. var updateChildren = function (vnode, domNode, oldChildren, newChildren, projectionOptions) {
  399. if(oldChildren === newChildren) {
  400. return false;
  401. }
  402. oldChildren = oldChildren || emptyArray;
  403. newChildren = newChildren || emptyArray;
  404. var oldChildrenLength = oldChildren.length;
  405. var newChildrenLength = newChildren.length;
  406. var transitions = projectionOptions.transitions;
  407. var oldIndex = 0;
  408. var newIndex = 0;
  409. var i;
  410. var textUpdated = false;
  411. while(newIndex < newChildrenLength) {
  412. var oldChild = (oldIndex < oldChildrenLength) ? oldChildren[oldIndex] : undefined;
  413. var newChild = newChildren[newIndex];
  414. if(oldChild !== undefined && same(oldChild, newChild)) {
  415. textUpdated = updateDom(oldChild, newChild, projectionOptions) || textUpdated;
  416. oldIndex++;
  417. } else {
  418. var findOldIndex = findIndexOfChild(oldChildren, newChild, oldIndex + 1);
  419. if(findOldIndex >= 0) {
  420. // Remove preceding missing children
  421. for(i = oldIndex; i < findOldIndex; i++) {
  422. nodeToRemove(oldChildren[i], transitions);
  423. checkDistinguishable(oldChildren, i, vnode, "removed");
  424. }
  425. textUpdated = updateDom(oldChildren[findOldIndex], newChild, projectionOptions) || textUpdated;
  426. oldIndex = findOldIndex + 1;
  427. } else {
  428. // New child
  429. createDom(newChild, domNode, (oldIndex < oldChildrenLength) ? oldChildren[oldIndex].domNode : undefined, projectionOptions);
  430. nodeAdded(newChild, transitions);
  431. checkDistinguishable(newChildren, newIndex, vnode, "added");
  432. }
  433. }
  434. newIndex++;
  435. }
  436. if(oldChildrenLength > oldIndex) {
  437. // Remove child fragments
  438. for(i = oldIndex; i < oldChildrenLength; i++) {
  439. nodeToRemove(oldChildren[i], transitions);
  440. checkDistinguishable(oldChildren, i, vnode, "removed");
  441. }
  442. }
  443. return textUpdated;
  444. };
  445. var createDom = function (vnode, parentNode, insertBefore, projectionOptions) {
  446. var domNode, i, c, start = 0, type, found;
  447. var vnodeSelector = vnode.vnodeSelector;
  448. if(vnodeSelector === "") {
  449. domNode = vnode.domNode = document.createTextNode(vnode.text);
  450. if(insertBefore !== undefined) {
  451. parentNode.insertBefore(domNode, insertBefore);
  452. } else {
  453. parentNode.appendChild(domNode);
  454. }
  455. } else {
  456. for (i = 0; i <= vnodeSelector.length; ++i) {
  457. c = vnodeSelector.charAt(i);
  458. if (i === vnodeSelector.length || c === '.' || c === '#') {
  459. type = vnodeSelector.charAt(start - 1);
  460. found = vnodeSelector.slice(start, i);
  461. if (type === ".") {
  462. domNode.classList.add(found);
  463. } else if (type === "#") {
  464. domNode.id = found;
  465. } else {
  466. if (found === "svg") {
  467. projectionOptions = extend(projectionOptions, { namespace: "http://www.w3.org/2000/svg" });
  468. }
  469. if (projectionOptions.namespace !== undefined) {
  470. domNode = vnode.domNode = document.createElementNS(projectionOptions.namespace, found);
  471. } else {
  472. domNode = vnode.domNode = document.createElement(found);
  473. }
  474. if (insertBefore !== undefined) {
  475. parentNode.insertBefore(domNode, insertBefore);
  476. } else {
  477. parentNode.appendChild(domNode);
  478. }
  479. }
  480. start = i + 1;
  481. }
  482. }
  483. initPropertiesAndChildren(domNode, vnode, projectionOptions);
  484. }
  485. };
  486. var initPropertiesAndChildren = function (domNode, vnode, projectionOptions) {
  487. addChildren(domNode, vnode.children, projectionOptions); // children before properties, needed for value property of <select>.
  488. if(vnode.text) {
  489. domNode.textContent = vnode.text;
  490. }
  491. setProperties(domNode, vnode.properties, projectionOptions);
  492. if(vnode.properties && vnode.properties.afterCreate) {
  493. vnode.properties.afterCreate(domNode, projectionOptions, vnode.vnodeSelector, vnode.properties, vnode.children);
  494. }
  495. };
  496. var updateDom = function (previous, vnode, projectionOptions) {
  497. var domNode = previous.domNode;
  498. if(!domNode) {
  499. throw new Error("previous node was not rendered");
  500. }
  501. var textUpdated = false;
  502. if(previous === vnode) {
  503. return textUpdated; // we assume that nothing has changed
  504. }
  505. var updated = false;
  506. if(vnode.vnodeSelector === "") {
  507. if(vnode.text !== previous.text) {
  508. domNode.nodeValue = vnode.text;
  509. textUpdated = true;
  510. }
  511. } else {
  512. if(vnode.vnodeSelector.lastIndexOf("svg", 0) === 0) { // lastIndexOf(needle,0)===0 means StartsWith
  513. projectionOptions = extend(projectionOptions, { namespace: "http://www.w3.org/2000/svg" });
  514. }
  515. if(previous.text !== vnode.text) {
  516. updated = true;
  517. if(vnode.text === undefined) {
  518. domNode.removeChild(domNode.firstChild); // the only textnode presumably
  519. } else {
  520. domNode.textContent = vnode.text;
  521. }
  522. }
  523. updated = updateChildren(vnode, domNode, previous.children, vnode.children, projectionOptions) || updated;
  524. updated = updateProperties(domNode, previous.properties, vnode.properties, projectionOptions) || updated;
  525. if(vnode.properties && vnode.properties.afterUpdate) {
  526. vnode.properties.afterUpdate(domNode, projectionOptions, vnode.vnodeSelector, vnode.properties, vnode.children);
  527. }
  528. }
  529. if(updated && vnode.properties && vnode.properties.updateAnimation) {
  530. vnode.properties.updateAnimation(domNode, vnode.properties, previous.properties);
  531. }
  532. vnode.domNode = previous.domNode;
  533. return textUpdated;
  534. };
  535. /**
  536. * Represents a {@link VNode} tree that has been rendered to a real DOM tree.
  537. * @interface Projection
  538. */
  539. var createProjection = function (vnode, projectionOptions) {
  540. if(!vnode.vnodeSelector) {
  541. throw new Error("Invalid vnode argument");
  542. }
  543. return {
  544. /**
  545. * Updates the projection with the new virtual DOM tree.
  546. * @param {VNode} updatedVnode - The updated virtual DOM tree. Note: The selector for the root of the tree must remain constant.
  547. * @memberof Projection#
  548. */
  549. update: function (updatedVnode) {
  550. if(vnode.vnodeSelector !== updatedVnode.vnodeSelector) {
  551. 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)");
  552. }
  553. updateDom(vnode, updatedVnode, projectionOptions);
  554. vnode = updatedVnode;
  555. },
  556. /**
  557. * The DOM node that is used as the root of this {@link Projection}.
  558. * @type {Element}
  559. * @memberof Projection#
  560. */
  561. domNode: vnode.domNode
  562. };
  563. };
  564. // Declaration of interfaces and callbacks, before the @exports maquette
  565. /**
  566. * A virtual representation of a DOM Node. Maquette assumes that {@link VNode} objects are never modified externally.
  567. * Instances of {@link VNode} can be created using {@link module:maquette.h}.
  568. * @interface VNode
  569. */
  570. /**
  571. * A CalculationCache object remembers the previous outcome of a calculation along with the inputs.
  572. * On subsequent calls the previous outcome is returned if the inputs are identical.
  573. * This object can be used to bypass both rendering and diffing of a virtual DOM subtree.
  574. * Instances of {@link CalculationCache} can be created using {@link module:maquette.createCache}.
  575. * @interface CalculationCache
  576. */
  577. /**
  578. * Keeps an array of result objects synchronized with an array of source objects.
  579. * Mapping provides a {@link Mapping#map} function that updates the {@link Mapping#results}.
  580. * The {@link Mapping#map} function can be called multiple times and the results will get created, removed and updated accordingly.
  581. * A {@link Mapping} can be used to keep an array of components (objects with a `renderMaquette` method) synchronized with an array of data.
  582. * Instances of {@link Mapping} can be created using {@link module:maquette.createMapping}.
  583. * @interface Mapping
  584. */
  585. /**
  586. * Used to create and update the DOM.
  587. * Use {@link Projector#append}, {@link Projector#merge}, {@link Projector#insertBefore} and {@link Projector#replace}
  588. * to create the DOM.
  589. * The `renderMaquetteFunction` callbacks will be called immediately to create the DOM. Afterwards, these functions
  590. * will be called again to update the DOM on the next animation-frame after:
  591. *
  592. * - The {@link Projector#scheduleRender} function was called
  593. * - An event handler (like `onclick`) on a rendered {@link VNode} was called.
  594. *
  595. * The projector stops when {@link Projector#stop} is called or when an error is thrown during rendering.
  596. * It is possible to use `window.onerror` to handle these errors.
  597. * Instances of {@link Projector} can be created using {@link module:maquette.createProjector}.
  598. * @interface Projector
  599. */
  600. /**
  601. * @callback enterAnimationCallback
  602. * @param {Element} element - Element that was just added to the DOM.
  603. * @param {Object} properties - The properties object that was supplied to the {@link module:maquette.h} method
  604. */
  605. /**
  606. * @callback exitAnimationCallback
  607. * @param {Element} element - Element that ought to be removed from to the DOM.
  608. * @param {function(Element)} removeElement - Function that removes the element from the DOM.
  609. * This argument is supplied purely for convenience.
  610. * You may use this function to remove the element when the animation is done.
  611. * @param {Object} properties - The properties object that was supplied to the {@link module:maquette.h} method that rendered this {@link VNode} the previous time.
  612. */
  613. /**
  614. * @callback updateAnimationCallback
  615. * @param {Element} element - Element that was modified in the DOM.
  616. * @param {Object} properties - The last properties object that was supplied to the {@link module:maquette.h} method
  617. * @param {Object} previousProperties - The previous properties object that was supplied to the {@link module:maquette.h} method
  618. */
  619. /**
  620. * @callback afterCreateCallback
  621. * @param {Element} element - The element that was added to the DOM.
  622. * @param {Object} projectionOptions - The projection options that were used see {@link module:maquette.createProjector}.
  623. * @param {string} vnodeSelector - The selector passed to the {@link module:maquette.h} function.
  624. * @param {Object} properties - The properties passed to the {@link module:maquette.h} function.
  625. * @param {VNode[]} children - The children that were created.
  626. * @param {Object} properties - The last properties object that was supplied to the {@link module:maquette.h} method
  627. * @param {Object} previousProperties - The previous properties object that was supplied to the {@link module:maquette.h} method
  628. */
  629. /**
  630. * @callback afterUpdateCallback
  631. * @param {Element} element - The element that may have been updated in the DOM.
  632. * @param {Object} projectionOptions - The projection options that were used see {@link module:maquette.createProjector}.
  633. * @param {string} vnodeSelector - The selector passed to the {@link module:maquette.h} function.
  634. * @param {Object} properties - The properties passed to the {@link module:maquette.h} function.
  635. * @param {VNode[]} children - The children for this node.
  636. */
  637. /**
  638. * Contains simple low-level utility functions to manipulate the real DOM. The singleton instance is available under {@link module:maquette.dom}.
  639. * @interface MaquetteDom
  640. */
  641. /**
  642. * The main object in maquette is the maquette object.
  643. * It is either bound to `window.maquette` or it can be obtained using {@link http://browserify.org/|browserify} or {@link http://requirejs.org/|requirejs}.
  644. * @exports maquette
  645. */
  646. var maquette = {
  647. /**
  648. * The `h` method is used to create a virtual DOM node.
  649. * This function is largely inspired by the mercuryjs and mithril frameworks.
  650. * The `h` stands for (virtual) hyperscript.
  651. *
  652. * @param {string} selector - Contains the tagName, id and fixed css classnames in CSS selector format.
  653. * It is formatted as follows: `tagname.cssclass1.cssclass2#id`.
  654. * @param {Object} [properties] - An object literal containing properties that will be placed on the DOM node.
  655. * @param {function} properties.<b>*</b> - Properties with functions values like `onclick:handleClick` are registered as event handlers
  656. * @param {String} properties.<b>*</b> - Properties with string values, like `href:"/"` are used as attributes
  657. * @param {object} properties.<b>*</b> - All non-string values are put on the DOM node as properties
  658. * @param {Object} properties.key - Used to uniquely identify a DOM node among siblings.
  659. * A key is required when there are more children with the same selector and these children are added or removed dynamically.
  660. * @param {Object} properties.classes - An object literal like `{important:true}` which allows css classes, like `important` to be added and removed dynamically.
  661. * @param {Object} properties.styles - An object literal like `{height:"100px"}` which allows styles to be changed dynamically. All values must be strings.
  662. * @param {(string|enterAnimationCallback)} properties.enterAnimation - The animation to perform when this node is added to an already existing parent.
  663. * {@link http://maquettejs.org/docs/animations.html|More about animations}.
  664. * When this value is a string, you must pass a `projectionOptions.transitions` object when creating the projector {@link module:maquette.createProjector}.
  665. * @param {(string|exitAnimationCallback)} properties.exitAnimation - The animation to perform when this node is removed while its parent remains.
  666. * When this value is a string, you must pass a `projectionOptions.transitions` object when creating the projector {@link module:maquette.createProjector}.
  667. * {@link http://maquettejs.org/docs/animations.html|More about animations}.
  668. * @param {updateAnimationCallback} properties.updateAnimation - The animation to perform when the properties of this node change.
  669. * This also includes attributes, styles, css classes. This callback is also invoked when node contains only text and that text changes.
  670. * {@link http://maquettejs.org/docs/animations.html|More about animations}.
  671. * @param {afterCreateCallback} properties.afterCreate - Callback that is executed after this node is added to the DOM. Childnodes and properties have already been applied.
  672. * @param {afterUpdateCallback} properties.afterUpdate - Callback that is executed every time this node may have been updated. Childnodes and properties have already been updated.
  673. * @param {Object[]} [children] - An array of virtual DOM nodes to add as child nodes.
  674. * This array may contain nested arrays, `null` or `undefined` values.
  675. * Nested arrays are flattened, `null` and `undefined` will be skipped.
  676. *
  677. * @returns {VNode} A VNode object, used to render a real DOM later. NOTE: There are {@link http://maquettejs.org/docs/rules.html|three basic rules} you should be aware of when updating the virtual DOM.
  678. */
  679. h: function (selector, properties, childrenArgs) {
  680. if (typeof selector !== "string") {
  681. throw new Error();
  682. }
  683. var childIndex = 1;
  684. if (properties && !properties.hasOwnProperty("vnodeSelector") && !Array.isArray(properties) && typeof properties === "object") {
  685. childIndex = 2;
  686. } else {
  687. // Optional properties argument was omitted
  688. properties = undefined;
  689. }
  690. var text = undefined;
  691. var children = undefined;
  692. var argsLength = arguments.length;
  693. // Recognize a common special case where there is only a single text node
  694. if(argsLength === childIndex + 1) {
  695. var onlyChild = arguments[childIndex];
  696. if (typeof onlyChild === "string") {
  697. text = onlyChild;
  698. } else if (onlyChild !== undefined && onlyChild.length === 1 && typeof onlyChild[0] === "string") {
  699. text = onlyChild[0];
  700. }
  701. }
  702. if (text === undefined) {
  703. children = [];
  704. for (;childIndex<arguments.length;childIndex++) {
  705. var child = arguments[childIndex];
  706. if(child === null || child === undefined) {
  707. continue;
  708. } else if(Array.isArray(child)) {
  709. appendChildren(selector, child, children);
  710. } else if(child.hasOwnProperty("vnodeSelector")) {
  711. children.push(child);
  712. } else {
  713. children.push(toTextVNode(child));
  714. }
  715. }
  716. }
  717. return {
  718. /**
  719. * The CSS selector containing tagname, css classnames and id. An empty string is used to denote a text node.
  720. * @memberof VNode#
  721. */
  722. vnodeSelector: selector,
  723. /**
  724. * Object containing attributes, properties, event handlers and more @see module:maquette.h
  725. * @memberof VNode#
  726. */
  727. properties: properties,
  728. /**
  729. * Array of VNodes to be used as children. This array is already flattened.
  730. * @memberof VNode#
  731. */
  732. children: children,
  733. /**
  734. * Used in a special case when a VNode only has one childnode which is a textnode. Only used in combination with children === undefined.
  735. * @memberof VNode#
  736. */
  737. text: text,
  738. /**
  739. * Used by maquette to store the domNode that was produced from this {@link VNode}.
  740. * @memberof VNode#
  741. */
  742. domNode: null
  743. };
  744. },
  745. /**
  746. * @type MaquetteDom
  747. */
  748. dom: {
  749. /**
  750. * Creates a real DOM tree from a {@link VNode}. The {@link Projection} object returned will contain the resulting DOM Node under the {@link Projection#domNode} property.
  751. * This is a low-level method. Users wil typically use a {@link Projector} instead.
  752. * @memberof MaquetteDom#
  753. * @param {VNode} vnode - The root of the virtual DOM tree that was created using the {@link module:maquette.h} function. NOTE: {@link VNode} objects may only be rendered once.
  754. * @param {Object} projectionOptions - Options to be used to create and update the projection, see {@link module:maquette.createProjector}.
  755. * @returns {Projection} The {@link Projection} which contains the DOM Node that was created.
  756. */
  757. create: function (vnode, projectionOptions) {
  758. projectionOptions = applyDefaultProjectionOptions(projectionOptions);
  759. createDom(vnode, document.createElement("div"), undefined, projectionOptions);
  760. return createProjection(vnode, projectionOptions);
  761. },
  762. /**
  763. * Appends a new childnode to the DOM which is generated from a {@link VNode}.
  764. * This is a low-level method. Users wil typically use a {@link Projector} instead.
  765. * @memberof MaquetteDom#
  766. * @param {Element} parentNode - The parent node for the new childNode.
  767. * @param {VNode} vnode - The root of the virtual DOM tree that was created using the {@link module:maquette.h} function. NOTE: {@link VNode} objects may only be rendered once.
  768. * @param {Object} projectionOptions - Options to be used to create and update the projection, see {@link module:maquette.createProjector}.
  769. * @returns {Projection} The {@link Projection} that was created.
  770. */
  771. append: function (parentNode, vnode, projectionOptions) {
  772. projectionOptions = applyDefaultProjectionOptions(projectionOptions);
  773. createDom(vnode, parentNode, undefined, projectionOptions);
  774. return createProjection(vnode, projectionOptions);
  775. },
  776. /**
  777. * Inserts a new DOM node which is generated from a {@link VNode}.
  778. * This is a low-level method. Users wil typically use a {@link Projector} instead.
  779. * @memberof MaquetteDom#
  780. * @param {Element} beforeNode - The node that the DOM Node is inserted before.
  781. * @param {VNode} vnode - The root of the virtual DOM tree that was created using the {@link module:maquette.h} function. NOTE: {@link VNode} objects may only be rendered once.
  782. * @param {Object} projectionOptions - Options to be used to create and update the projection, see {@link module:maquette.createProjector}.
  783. * @returns {Projection} The {@link Projection} that was created.
  784. */
  785. insertBefore: function(beforeNode, vnode, projectionOptions) {
  786. projectionOptions = applyDefaultProjectionOptions(projectionOptions);
  787. createDom(vnode, beforeNode.parentNode, beforeNode, projectionOptions);
  788. return createProjection(vnode, projectionOptions);
  789. },
  790. /**
  791. * Merges a new DOM node which is generated from a {@link VNode} with an existing DOM Node.
  792. * This means that the virtual DOM and real DOM have one overlapping element.
  793. * Therefore the selector for the root {@link VNode} will be ignored, but its properties and children will be applied to the Element provided
  794. * This is a low-level method. Users wil typically use a {@link Projector} instead.
  795. * @memberof MaquetteDom#
  796. * @param {Element} domNode - The existing element to adopt as the root of the new virtual DOM. Existing attributes and childnodes are preserved.
  797. * @param {VNode} vnode - The root of the virtual DOM tree that was created using the {@link module:maquette.h} function. NOTE: {@link VNode} objects may only be rendered once.
  798. * @param {Object} projectionOptions - Options to be used to create and update the projection, see {@link module:maquette.createProjector}.
  799. * @returns {Projection} The {@link Projection} that was created.
  800. */
  801. merge: function (element, vnode, options) {
  802. options = applyDefaultProjectionOptions(options);
  803. vnode.domNode = element;
  804. initPropertiesAndChildren(element, vnode, options);
  805. return createProjection(vnode, options);
  806. }
  807. },
  808. /**
  809. * Creates a {@link CalculationCache} object, useful for caching {@link VNode} trees.
  810. * In practice, caching of {@link VNode} trees is not needed, because achieving 60 frames per second is almost never a problem.
  811. * @returns {CalculationCache}
  812. */
  813. createCache: function () {
  814. var cachedInputs = undefined;
  815. var cachedOutcome = undefined;
  816. var result = {
  817. /**
  818. * Manually invalidates the cached outcome.
  819. * @memberof CalculationCache#
  820. */
  821. invalidate: function () {
  822. cachedOutcome = undefined;
  823. cachedInputs = undefined;
  824. },
  825. /**
  826. * If the inputs array matches the inputs array from the previous invocation, this method returns the result of the previous invocation.
  827. * Otherwise, the calculation function is invoked and its result is cached and returned.
  828. * Objects in the inputs array are compared using ===.
  829. * @param {Object[]} inputs - Array of objects that are to be compared using === with the inputs from the previous invocation.
  830. * These objects are assumed to be immutable primitive values.
  831. * @param {function} calculation - Function that takes zero arguments and returns an object (A {@link VNode} assumably) that can be cached.
  832. * @memberof CalculationCache#
  833. */
  834. result: function (inputs, calculation) {
  835. if(cachedInputs) {
  836. for(var i = 0; i < inputs.length; i++) {
  837. if(cachedInputs[i] !== inputs[i]) {
  838. cachedOutcome = undefined;
  839. }
  840. }
  841. }
  842. if(!cachedOutcome) {
  843. cachedOutcome = calculation();
  844. cachedInputs = inputs;
  845. }
  846. return cachedOutcome;
  847. }
  848. };
  849. return result;
  850. },
  851. /**
  852. * Creates a {@link Mapping} instance that keeps an array of result objects synchronized with an array of source objects.
  853. * @param {function} getSourceKey - `function(source)` that must return a key to identify each source object. The result must eather be a string or a number.
  854. * @param {function} createResult - `function(source, index)` that must create a new result object from a given source. This function is identical argument of `Array.map`.
  855. * @param {function} updateResult - `function(source, target, index)` that updates a result to an updated source.
  856. * @returns {Mapping}
  857. */
  858. createMapping: function(getSourceKey, createResult, updateResult /*, deleteTarget*/) {
  859. var keys = [];
  860. var results = [];
  861. return {
  862. /**
  863. * The array of results. These results will be synchronized with the latest array of sources that were provided using {@link Mapping#map}.
  864. * @type {Object[]}
  865. * @memberof Mapping#
  866. */
  867. results: results,
  868. /**
  869. * Maps a new array of sources and updates {@link Mapping#results}.
  870. * @param {Object[]} newSources - The new array of sources.
  871. * @memberof Mapping#
  872. */
  873. map: function(newSources) {
  874. var newKeys = newSources.map(getSourceKey);
  875. var oldTargets = results.slice();
  876. var oldIndex = 0;
  877. for (var i=0;i<newSources.length;i++) {
  878. var source = newSources[i];
  879. var sourceKey = newKeys[i];
  880. if (sourceKey === keys[oldIndex]) {
  881. results[i] = oldTargets[oldIndex];
  882. updateResult(source, oldTargets[oldIndex], i);
  883. oldIndex++;
  884. } else {
  885. var found = false;
  886. for (var j = 1; j < keys.length; j++) {
  887. var searchIndex = (oldIndex + j) % keys.length;
  888. if (keys[searchIndex] === sourceKey) {
  889. results[i] = oldTargets[searchIndex];
  890. updateResult(newSources[i], oldTargets[searchIndex], i);
  891. oldIndex = searchIndex + 1;
  892. found = true;
  893. break;
  894. }
  895. }
  896. if (!found) {
  897. results[i] = createResult(source, i);
  898. }
  899. }
  900. }
  901. results.length = newSources.length;
  902. keys = newKeys;
  903. }
  904. };
  905. },
  906. /**
  907. * Creates a {@link Projector} instance using the provided projectionOptions.
  908. * @param {Object} [projectionOptions] - Options that influence how the DOM is rendered and updated.
  909. * @param {Object} projectionOptions.transitions - A transition strategy to invoke when
  910. * enterAnimation and exitAnimation properties are provided as strings.
  911. * The module `cssTransitions` in the provided `css-transitions.js` file provides such a strategy.
  912. * A transition strategy is not needed when enterAnimation and exitAnimation properties are provided as functions.
  913. * @returns {Projector}
  914. */
  915. createProjector: function (projectionOptions) {
  916. projectionOptions = applyDefaultProjectionOptions(projectionOptions);
  917. projectionOptions.eventHandlerInterceptor = function (propertyName, functionPropertyArgument) {
  918. return function () {
  919. // intercept function calls (event handlers) to do a render afterwards.
  920. projector.scheduleRender();
  921. return functionPropertyArgument.apply(this, arguments);
  922. };
  923. };
  924. var renderCompleted = true;
  925. var scheduled;
  926. var stopped = false;
  927. var projections = [];
  928. var renderFunctions = []; // matches the projections array
  929. var doRender = function () {
  930. scheduled = undefined;
  931. if (!renderCompleted) {
  932. return; // The last render threw an error, it should be logged in the browser console.
  933. }
  934. var s = Date.now()
  935. renderCompleted = false;
  936. for(var i = 0; i < projections.length; i++) {
  937. var updatedVnode = renderFunctions[i]();
  938. projections[i].update(updatedVnode);
  939. }
  940. renderCompleted = true;
  941. if (Date.now()-s > 5)
  942. console.log("Render:", Date.now()-s)
  943. };
  944. var projector = {
  945. /**
  946. * Instructs the projector to re-render to the DOM at the next animation-frame using the registered `renderMaquette` functions.
  947. * This method is automatically called for you when event-handlers that are registered in the {@link VNode}s are invoked.
  948. * You need to call this method for instance when timeouts expire or AJAX responses arrive.
  949. * @memberof Projector#
  950. */
  951. scheduleRender: function () {
  952. if(!scheduled && !stopped) {
  953. scheduled = requestAnimationFrame(doRender);
  954. }
  955. },
  956. /**
  957. * Stops the projector. This means that the registered `renderMaquette` functions will not be called anymore.
  958. * Note that calling {@link Projector#stop} is not mandatory. A projector is a passive object that will get garbage collected as usual if it is no longer in scope.
  959. * @memberof Projector#
  960. */
  961. stop: function () {
  962. if(scheduled) {
  963. cancelAnimationFrame(scheduled);
  964. scheduled = undefined;
  965. }
  966. stopped = true;
  967. },
  968. /**
  969. * Resumes the projector. Use this method to resume rendering after stop was called or an error occurred during rendering.
  970. * @memberof Projector#
  971. */
  972. resume: function() {
  973. stopped = false;
  974. renderCompleted = true;
  975. projector.scheduleRender();
  976. },
  977. /**
  978. * Scans the document for `<script>` tags with `type="text/hyperscript"`.
  979. * The content of these scripts are registered as `renderMaquette` functions.
  980. * The result of evaluating these functions will be inserted into the DOM after the script.
  981. * These scripts can make use of variables that come from the `parameters` parameter.
  982. * @param {Element} rootNode - Element to start scanning at, example: `document.body`.
  983. * @param {Object} parameters - Variables to expose to the scripts. format: `{var1:value1, var2: value2}`
  984. * @memberof Projector#
  985. */
  986. evaluateHyperscript: function (rootNode, parameters) {
  987. var nodes = rootNode.querySelectorAll("script[type='text/hyperscript']");
  988. var functionParameters = ["maquette", "h", "enhancer"];
  989. var parameterValues = [maquette, maquette.h, projector];
  990. Object.keys(parameters).forEach(function (parameterName) {
  991. functionParameters.push(parameterName);
  992. parameterValues.push(parameters[parameterName]);
  993. });
  994. Array.prototype.forEach.call(nodes, function (node) {
  995. var func = new Function(functionParameters, "return " + node.textContent.trim());
  996. var renderFunction = function () {
  997. return func.apply(undefined, parameterValues);
  998. };
  999. projector.insertBefore(node, renderFunction);
  1000. });
  1001. },
  1002. /**
  1003. * Appends a new childnode to the DOM using the result from the provided `renderMaquetteFunction`.
  1004. * The `renderMaquetteFunction` will be invoked again to update the DOM when needed.
  1005. * @param {Element} parentNode - The parent node for the new childNode.
  1006. * @param {function} renderMaquetteFunction - Function with zero arguments that returns a {@link VNode} tree.
  1007. * @memberof Projector#
  1008. */
  1009. append: function (parentNode, renderMaquetteFunction) {
  1010. projections.push(maquette.dom.append(parentNode, renderMaquetteFunction(), projectionOptions));
  1011. renderFunctions.push(renderMaquetteFunction);
  1012. },
  1013. /**
  1014. * Inserts a new DOM node using the result from the provided `renderMaquetteFunction`.
  1015. * The `renderMaquetteFunction` will be invoked again to update the DOM when needed.
  1016. * @param {Element} beforeNode - The node that the DOM Node is inserted before.
  1017. * @param {function} renderMaquetteFunction - Function with zero arguments that returns a {@link VNode} tree.
  1018. * @memberof Projector#
  1019. */
  1020. insertBefore: function (beforeNode, renderMaquetteFunction) {
  1021. projections.push(maquette.dom.insertBefore(beforeNode, renderMaquetteFunction(), projectionOptions));
  1022. renderFunctions.push(renderMaquetteFunction);
  1023. },
  1024. /**
  1025. * Merges a new DOM node using the result from the provided `renderMaquetteFunction` with an existing DOM Node.
  1026. * This means that the virtual DOM and real DOM have one overlapping element.
  1027. * Therefore the selector for the root {@link VNode} will be ignored, but its properties and children will be applied to the Element provided
  1028. * The `renderMaquetteFunction` will be invoked again to update the DOM when needed.
  1029. * @param {Element} domNode - The existing element to adopt as the root of the new virtual DOM. Existing attributes and childnodes are preserved.
  1030. * @param {function} renderMaquetteFunction - Function with zero arguments that returns a {@link VNode} tree.
  1031. * @memberof Projector#
  1032. */
  1033. merge: function (domNode, renderMaquetteFunction) {
  1034. projections.push(maquette.dom.merge(domNode, renderMaquetteFunction(), projectionOptions));
  1035. renderFunctions.push(renderMaquetteFunction);
  1036. },
  1037. /**
  1038. * Replaces an existing DOM node with the result from the provided `renderMaquetteFunction`.
  1039. * The `renderMaquetteFunction` will be invoked again to update the DOM when needed.
  1040. * @param {Element} domNode - The DOM node to replace.
  1041. * @param {function} renderMaquetteFunction - Function with zero arguments that returns a {@link VNode} tree.
  1042. * @memberof Projector#
  1043. */
  1044. replace: function (domNode, renderMaquetteFunction) {
  1045. var vnode = renderMaquetteFunction();
  1046. createDom(vnode, domNode.parentNode, domNode, projectionOptions);
  1047. domNode.parentNode.removeChild(domNode);
  1048. projections.push(createProjection(vnode, projectionOptions));
  1049. renderFunctions.push(renderMaquetteFunction);
  1050. }
  1051. };
  1052. return projector;
  1053. }
  1054. };
  1055. if(typeof module !== "undefined" && module.exports) {
  1056. // Node and other CommonJS-like environments that support module.exports
  1057. module.exports = maquette;
  1058. } else if(typeof define === "function" && define.amd) {
  1059. // AMD / RequireJS
  1060. define(function () {
  1061. return maquette;
  1062. });
  1063. } else {
  1064. // Browser
  1065. window.maquette = maquette;
  1066. }
  1067. })(this);
  1068. /* ---- /1MaiL5gfBM1cyb4a8e3iiL8L5gXmoAJu27/js/lib/marked.min.js ---- */
  1069. /**
  1070. * marked - a markdown parser
  1071. * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed)
  1072. * https://github.com/chjj/marked
  1073. */
  1074. (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)}());
  1075. /* ---- /1MaiL5gfBM1cyb4a8e3iiL8L5gXmoAJu27/js/utils/Animation.coffee ---- */
  1076. (function() {
  1077. var Animation;
  1078. Animation = (function() {
  1079. function Animation() {}
  1080. Animation.prototype.slideDown = function(elem, props) {
  1081. var cstyle, h, margin_bottom, margin_top, padding_bottom, padding_top, transition;
  1082. if (props.disableAnimation) {
  1083. return;
  1084. }
  1085. h = elem.offsetHeight;
  1086. cstyle = window.getComputedStyle(elem);
  1087. margin_top = cstyle.marginTop;
  1088. margin_bottom = cstyle.marginBottom;
  1089. padding_top = cstyle.paddingTop;
  1090. padding_bottom = cstyle.paddingBottom;
  1091. transition = cstyle.transition;
  1092. elem.style.boxSizing = "border-box";
  1093. elem.style.overflow = "hidden";
  1094. elem.style.transform = "scale(0.8)";
  1095. elem.style.opacity = "0";
  1096. elem.style.height = "0px";
  1097. elem.style.marginTop = "0px";
  1098. elem.style.marginBottom = "0px";
  1099. elem.style.paddingTop = "0px";
  1100. elem.style.paddingBottom = "0px";
  1101. elem.style.transition = "none";
  1102. setTimeout((function() {
  1103. elem.className += " animate-back";
  1104. elem.style.height = h + "px";
  1105. elem.style.transform = "scale(1)";
  1106. elem.style.opacity = "1";
  1107. elem.style.marginTop = margin_top;
  1108. elem.style.marginBottom = margin_bottom;
  1109. elem.style.paddingTop = padding_top;
  1110. return elem.style.paddingBottom = padding_bottom;
  1111. }), 1);
  1112. return elem.addEventListener("transitionend", function() {
  1113. elem.classList.remove("animate-back");
  1114. elem.style.transition = elem.style.transform = elem.style.opacity = elem.style.height = null;
  1115. elem.style.boxSizing = elem.style.marginTop = elem.style.marginBottom = null;
  1116. return elem.style.paddingTop = elem.style.paddingBottom = elem.style.overflow = null;
  1117. });
  1118. };
  1119. Animation.prototype.slideUp = function(elem, remove_func, props) {
  1120. elem.className += " animate-back";
  1121. elem.style.boxSizing = "border-box";
  1122. elem.style.height = elem.offsetHeight + "px";
  1123. elem.style.overflow = "hidden";
  1124. elem.style.transform = "scale(1)";
  1125. elem.style.opacity = "1";
  1126. setTimeout((function() {
  1127. elem.style.height = "0px";
  1128. elem.style.marginTop = "0px";
  1129. elem.style.marginBottom = "0px";
  1130. elem.style.paddingTop = "0px";
  1131. elem.style.paddingBottom = "0px";
  1132. elem.style.transform = "scale(0.8)";
  1133. elem.style.borderTopWidth = "0px";
  1134. elem.style.borderBottomWidth = "0px";
  1135. return elem.style.opacity = "0";
  1136. }), 1);
  1137. return elem.addEventListener("transitionend", remove_func);
  1138. };
  1139. Animation.prototype.showRight = function(elem, props) {
  1140. elem.className += " animate";
  1141. elem.style.opacity = 0;
  1142. elem.style.transform = "TranslateX(-20px) Scale(1.01)";
  1143. setTimeout((function() {
  1144. elem.style.opacity = 1;
  1145. return elem.style.transform = "TranslateX(0px) Scale(1)";
  1146. }), 1);
  1147. return elem.addEventListener("transitionend", function() {
  1148. elem.classList.remove("animate");
  1149. return elem.style.transform = elem.style.opacity = null;
  1150. });
  1151. };
  1152. Animation.prototype.show = function(elem, props) {
  1153. var delay, _ref;
  1154. delay = ((_ref = arguments[arguments.length - 2]) != null ? _ref.delay : void 0) * 1000 || 1;
  1155. elem.className += " animate";
  1156. elem.style.opacity = 0;
  1157. setTimeout((function() {
  1158. return elem.style.opacity = 1;
  1159. }), delay);
  1160. return elem.addEventListener("transitionend", function() {
  1161. elem.classList.remove("animate");
  1162. return elem.style.opacity = null;
  1163. });
  1164. };
  1165. Animation.prototype.addVisibleClass = function(elem, props) {
  1166. return setTimeout(function() {
  1167. return elem.classList.add("visible");
  1168. });
  1169. };
  1170. Animation.prototype.termLines = function(elem, projection_options, selector, props) {
  1171. var back, delay, delay_step, line, lines, _i, _len;
  1172. lines = elem.innerHTML.split("\n");
  1173. delay = props.delay || 0;
  1174. delay_step = props.delay_step || 0.05;
  1175. back = [];
  1176. for (_i = 0, _len = lines.length; _i < _len; _i++) {
  1177. line = lines[_i];
  1178. line = line.replace(/(\.+)(.*?)$/, "<span class='dots'>$1</span><span class='result'>$2</span>", line);
  1179. back.push("<span style='transition-delay: " + delay + "s'>" + line + "</span>");
  1180. delay += delay_step;
  1181. }
  1182. setTimeout((function() {
  1183. return elem.classList.add("visible");
  1184. }), 100);
  1185. return elem.innerHTML = back.join("\n");
  1186. };
  1187. Animation.prototype.scramble = function(elem) {
  1188. var chars, frame, replaces, text_original, timer;
  1189. text_original = elem.value;
  1190. chars = elem.value.split("");
  1191. chars = chars.filter(function(char) {
  1192. return char !== "\n" && char !== "\r" && char !== " " && char !== "​";
  1193. });
  1194. replaces = ["⠋", '⠙', '⠹', '⠒', '⠔', '⠃', '⡳', '⠁', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
  1195. replaces.sort(function() {
  1196. return 0.5 - Math.random();
  1197. });
  1198. frame = 0;
  1199. return timer = setInterval((function() {
  1200. var char, i, _i, _ref;
  1201. for (i = _i = 0, _ref = Math.round(text_original.length / 20); 0 <= _ref ? _i <= _ref : _i >= _ref; i = 0 <= _ref ? ++_i : --_i) {
  1202. char = chars.shift();
  1203. elem.value = elem.value.replace(char, replaces[(frame + i) % replaces.length]);
  1204. }
  1205. if (chars.length === 0) {
  1206. clearInterval(timer);
  1207. }
  1208. return frame += 1;
  1209. }), 50);
  1210. };
  1211. /*
  1212. showScramble: (elem, props) ->
  1213. text_original = elem.innerText
  1214. chars = elem.innerText.split("")
  1215. * Convert characters to whitespace
  1216. clear_chars = chars.map (char) ->
  1217. if char != "\n" and char != "\r" and char != " " and char != "​"
  1218. return " "
  1219. else
  1220. return char
  1221. elem.innerText = clear_chars.join("")
  1222. replaces = ["|", "[", "]", "/", "\\", "*", "-", "$", "~", "^", "#", ">", "<", "(", ")", "+", "%", "=", "!"]
  1223. replaces.sort ->
  1224. return 0.5-Math.random()
  1225. frame = 0
  1226. timer = 0
  1227. replace_show = ->
  1228. for i in [0..10]
  1229. replace = replaces[Math.floor(Math.random()*(replaces.length-1))]
  1230. elem.innerText = elem.innerText.replace(" ", replace)
  1231. elem.innerText = elem.innerText.replace(replace, replaces[frame % (replaces.length-1)])
  1232. frame += 1
  1233. if frame > chars.length/10
  1234. clearInterval(timer)
  1235. timer = setInterval text_show, 20
  1236. text_show = ->
  1237. for i in [0..10]
  1238. clearInterval(timer)
  1239. timer = setInterval replace_show, 20
  1240. scramble2: (elem, props) ->
  1241. text_original = elem.innerText
  1242. chars = elem.innerText.split("")
  1243. chars_num = chars.length
  1244. frame = 0
  1245. timer = setInterval ( ->
  1246. for replace in ["|", "[", "]", "/", "\\", "*", "-", "$", "~", "^", "#", ">", "<", "(", ")", "+", "%", "=", "!"]
  1247. index = Math.round(Math.random()*chars_num)
  1248. if chars[index] != "\n" and chars[index] != "\r" and chars[index] != " " and chars[index] != "​" # Null character
  1249. chars[index] = replace
  1250. elem.innerText = chars.join("")
  1251. frame += 1
  1252. if frame > 100
  1253. clearInterval(timer)
  1254. ), 20
  1255. @
  1256. */
  1257. return Animation;
  1258. })();
  1259. window.Animation = new Animation();
  1260. }).call(this);
  1261. /* ---- /1MaiL5gfBM1cyb4a8e3iiL8L5gXmoAJu27/js/utils/Autocomplete.coffee ---- */
  1262. (function() {
  1263. var Autocomplete,
  1264. __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
  1265. Autocomplete = (function() {
  1266. function Autocomplete(_at_getValues, _at_attrs, _at_onChanged) {
  1267. this.getValues = _at_getValues;
  1268. this.attrs = _at_attrs != null ? _at_attrs : {};
  1269. this.onChanged = _at_onChanged != null ? _at_onChanged : null;
  1270. this.handleBlur = __bind(this.handleBlur, this);
  1271. this.handleFocus = __bind(this.handleFocus, this);
  1272. this.handleClick = __bind(this.handleClick, this);
  1273. this.handleKey = __bind(this.handleKey, this);
  1274. this.handleInput = __bind(this.handleInput, this);
  1275. this.filterValues = __bind(this.filterValues, this);
  1276. this.setNode = __bind(this.setNode, this);
  1277. this.attrs.oninput = this.handleInput;
  1278. this.attrs.onfocus = this.handleFocus;
  1279. this.attrs.onblur = this.handleBlur;
  1280. this.attrs.onkeydown = this.handleKey;
  1281. this.values = [];
  1282. this.selected_index = 0;
  1283. this.focus = false;
  1284. }
  1285. Autocomplete.prototype.setNode = function(node) {
  1286. return this.node = node;
  1287. };
  1288. Autocomplete.prototype.setValue = function(value) {
  1289. this.attrs.value = value;
  1290. if (this.onChanged) {
  1291. this.onChanged(value);
  1292. }
  1293. return Page.projector.scheduleRender();
  1294. };
  1295. Autocomplete.prototype.filterValues = function(filter) {
  1296. var current_value, distance, match, parts, re_highlight, res, row, value, values, _i, _len;
  1297. current_value = this.attrs.value;
  1298. values = this.getValues();
  1299. re_highlight = new RegExp("^(.*?)(" + filter.split("").join(")(.*?)(") + ")(.*?)$", "i");
  1300. res = [];
  1301. for (_i = 0, _len = values.length; _i < _len; _i++) {
  1302. value = values[_i];
  1303. distance = Text.distance(value, current_value);
  1304. if (distance !== false) {
  1305. match = value.match(re_highlight);
  1306. if (!match) {
  1307. continue;
  1308. }
  1309. parts = match.map(function(part, i) {
  1310. if (i % 2 === 0) {
  1311. return "<b>" + part + "</b>";
  1312. } else {
  1313. return part;
  1314. }
  1315. });
  1316. parts.shift();
  1317. res.push([parts.join(""), distance]);
  1318. }
  1319. }
  1320. res.sort(function(a, b) {
  1321. return a[1] - b[1];
  1322. });
  1323. this.values = (function() {
  1324. var _j, _len1, _ref, _results;
  1325. _ref = res.slice(0, 10);
  1326. _results = [];
  1327. for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) {
  1328. row = _ref[_j];
  1329. _results.push(row[0]);
  1330. }
  1331. return _results;
  1332. })();
  1333. return this.values;
  1334. };
  1335. Autocomplete.prototype.renderValue = function(node, projector_options, children, attrs) {
  1336. return node.innerHTML = attrs.key;
  1337. };
  1338. Autocomplete.prototype.handleInput = function(e) {
  1339. this.attrs.value = e.target.value;
  1340. this.selected_index = 0;
  1341. return this.focus = true;
  1342. };
  1343. Autocomplete.prototype.handleKey = function(e) {
  1344. if (e.keyCode === 38) {
  1345. this.selected_index = Math.max(0, this.selected_index - 1);
  1346. return false;
  1347. } else if (e.keyCode === 40) {
  1348. this.selected_index = Math.min(this.values.length - 1, this.selected_index + 1);
  1349. return false;
  1350. } else if (e.keyCode === 13) {
  1351. this.handleBlur(e);
  1352. return false;
  1353. }
  1354. };
  1355. Autocomplete.prototype.handleClick = function(e) {
  1356. if (e.currentTarget == null) {
  1357. e.currentTarget = e.explicitOriginalTarget;
  1358. }
  1359. this.attrs.value = e.currentTarget.textContent;
  1360. if (this.onChanged) {
  1361. this.onChanged(this.attrs.value);
  1362. }
  1363. this.focus = false;
  1364. Page.projector.scheduleRender();
  1365. return false;
  1366. };
  1367. Autocomplete.prototype.handleFocus = function(e) {
  1368. this.selected_index = 0;
  1369. return this.focus = true;
  1370. };
  1371. Autocomplete.prototype.handleBlur = function(e) {
  1372. var selected_value, values;
  1373. selected_value = this.node.querySelector(".values .value.selected");
  1374. if (selected_value) {
  1375. this.setValue(selected_value.textContent);
  1376. } else if (this.attrs.value) {
  1377. values = this.filterValues(this.attrs.value);
  1378. if (values.length > 0) {
  1379. this.setValue(values[0].replace(/<.*?>/g, ""));
  1380. } else {
  1381. this.setValue("");
  1382. }
  1383. } else {
  1384. this.setValue("");
  1385. }
  1386. return this.focus = false;
  1387. };
  1388. Autocomplete.prototype.render = function() {
  1389. return h("div.Autocomplete", {
  1390. "afterCreate": this.setNode
  1391. }, [
  1392. h("input.to", this.attrs), this.focus && this.attrs.value ? h("div.values", {
  1393. "exitAnimation": Animation.slideUp
  1394. }, [
  1395. this.filterValues(this.attrs.value).map((function(_this) {
  1396. return function(value, i) {
  1397. return h("a.value", {
  1398. "href": "#Select+Address",
  1399. "key": value,
  1400. "tabindex": "-1",
  1401. "afterCreate": _this.renderValue,
  1402. "onmousedown": _this.handleClick,
  1403. "classes": {
  1404. "selected": _this.selected_index === i
  1405. }
  1406. });
  1407. };
  1408. })(this))
  1409. ]) : void 0
  1410. ]);
  1411. };
  1412. return Autocomplete;
  1413. })();
  1414. window.Autocomplete = Autocomplete;
  1415. }).call(this);
  1416. /* ---- /1MaiL5gfBM1cyb4a8e3iiL8L5gXmoAJu27/js/utils/Class.coffee ---- */
  1417. (function() {
  1418. var Class,
  1419. __slice = [].slice;
  1420. Class = (function() {
  1421. function Class() {}
  1422. Class.prototype.trace = true;
  1423. Class.prototype.log = function() {
  1424. var args;
  1425. args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
  1426. if (!this.trace) {
  1427. return;
  1428. }
  1429. if (typeof console === 'undefined') {
  1430. return;
  1431. }
  1432. args.unshift("[" + this.constructor.name + "]");
  1433. console.log.apply(console, args);
  1434. return this;
  1435. };
  1436. Class.prototype.logStart = function() {
  1437. var args, name;
  1438. name = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
  1439. if (!this.trace) {
  1440. return;
  1441. }
  1442. this.logtimers || (this.logtimers = {});
  1443. this.logtimers[name] = +(new Date);
  1444. if (args.length > 0) {
  1445. this.log.apply(this, ["" + name].concat(__slice.call(args), ["(started)"]));
  1446. }
  1447. return this;
  1448. };
  1449. Class.prototype.logEnd = function() {
  1450. var args, ms, name;
  1451. name = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
  1452. ms = +(new Date) - this.logtimers[name];
  1453. this.log.apply(this, ["" + name].concat(__slice.call(args), ["(Done in " + ms + "ms)"]));
  1454. return this;
  1455. };
  1456. return Class;
  1457. })();
  1458. window.Class = Class;
  1459. }).call(this);
  1460. /* ---- /1MaiL5gfBM1cyb4a8e3iiL8L5gXmoAJu27/js/utils/Dollar.coffee ---- */
  1461. (function() {
  1462. window.$ = function(selector) {
  1463. if (selector.startsWith("#")) {
  1464. return document.getElementById(selector.replace("#", ""));
  1465. }
  1466. };
  1467. }).call(this);
  1468. /* ---- /1MaiL5gfBM1cyb4a8e3iiL8L5gXmoAJu27/js/utils/OrderManager.coffee ---- */
  1469. (function() {
  1470. var OrderManager,
  1471. __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
  1472. __extends = 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; },
  1473. __hasProp = {}.hasOwnProperty;
  1474. OrderManager = (function(_super) {
  1475. __extends(OrderManager, _super);
  1476. function OrderManager() {
  1477. this.execute = __bind(this.execute, this);
  1478. var timer_reorder;
  1479. timer_reorder = null;
  1480. this.entering = {};
  1481. this.exiting = {};
  1482. this;
  1483. }
  1484. OrderManager.prototype.registerEnter = function(elem, props, cb) {
  1485. return this.entering[props.key] = [elem, cb];
  1486. };
  1487. OrderManager.prototype.registerExit = function(elem, props, cb) {
  1488. return this.exiting[props.key] = [elem, cb];
  1489. };
  1490. OrderManager.prototype.animateChange = function(elem, before, after) {
  1491. var height;
  1492. height = elem.offsetHeight;
  1493. elem.style.width = elem.offsetWidth + "px";
  1494. elem.style.transition = "none";
  1495. elem.style.boxSizing = "border-box";
  1496. elem.style.float = "left";
  1497. elem.style.marginTop = 0 - height + "px";
  1498. elem.style.transform = "TranslateY(" + (before - after + height) + "px)";
  1499. setTimeout((function() {
  1500. elem.style.transition = null;
  1501. return elem.className += " animate-back";
  1502. }), 1);
  1503. return setTimeout((function() {
  1504. elem.style.transform = "TranslateY(0px)";
  1505. elem.style.marginTop = "0px";
  1506. return elem.addEventListener("transitionend", function() {
  1507. elem.classList.remove("animate-back");
  1508. return elem.style.boxSizing = elem.style.float = elem.style.marginTop = elem.style.transform = elem.style.width = null;
  1509. });
  1510. }), 2);
  1511. };
  1512. OrderManager.prototype.execute = function(elem, projection_options, selector, properties, childs) {
  1513. var child, child_elem, enteranim, exitanim, has_entering, has_exiting, key, moving, s, top_after, top_before, _i, _len, _ref, _ref1, _ref2, _ref3, _ref4;
  1514. s = Date.now();
  1515. has_entering = JSON.stringify(this.entering) !== "{}";
  1516. has_exiting = JSON.stringify(this.exiting) !== "{}";
  1517. if (!has_exiting && !has_entering) {
  1518. return false;
  1519. }
  1520. moving = {};
  1521. this.log(Date.now() - s);
  1522. if (childs.length < 5000) {
  1523. if (has_entering && has_exiting) {
  1524. for (_i = 0, _len = childs.length; _i < _len; _i++) {
  1525. child = childs[_i];
  1526. key = child.properties.key;
  1527. if (!key) {
  1528. continue;
  1529. }
  1530. if (!this.entering[key]) {
  1531. moving[key] = [child, child.domNode.offsetTop];
  1532. }
  1533. }
  1534. }
  1535. }
  1536. this.log(Date.now() - s);
  1537. _ref = this.exiting;
  1538. for (key in _ref) {
  1539. _ref1 = _ref[key], child_elem = _ref1[0], exitanim = _ref1[1];
  1540. if (!this.entering[key]) {
  1541. exitanim();
  1542. } else {
  1543. elem.removeChild(child_elem);
  1544. }
  1545. }
  1546. this.log(Date.now() - s);
  1547. _ref2 = this.entering;
  1548. for (key in _ref2) {
  1549. _ref3 = _ref2[key], child_elem = _ref3[0], enteranim = _ref3[1];
  1550. if (!this.exiting[key]) {
  1551. enteranim();
  1552. }
  1553. }
  1554. this.log(Date.now() - s);
  1555. for (key in moving) {
  1556. _ref4 = moving[key], child = _ref4[0], top_before = _ref4[1];
  1557. top_after = child.domNode.offsetTop;
  1558. console.log("animateChange", top_before, top_after);
  1559. if (top_before !== top_after) {
  1560. this.animateChange(child.domNode, top_before, top_after);
  1561. }
  1562. }
  1563. this.entering = {};
  1564. this.exiting = {};
  1565. return this.log(Date.now() - s, arguments);
  1566. };
  1567. return OrderManager;
  1568. })(Class);
  1569. window.OrderManager = OrderManager;
  1570. }).call(this);
  1571. /* ---- /1MaiL5gfBM1cyb4a8e3iiL8L5gXmoAJu27/js/utils/Prototypes.coffee ---- */
  1572. (function() {
  1573. var _base, _base1, _base2;
  1574. if ((_base = String.prototype).startsWith == null) {
  1575. _base.startsWith = function(s) {
  1576. return this.slice(0, s.length) === s;
  1577. };
  1578. }
  1579. if ((_base1 = String.prototype).endsWith == null) {
  1580. _base1.endsWith = function(s) {
  1581. return s === '' || this.slice(-s.length) === s;
  1582. };
  1583. }
  1584. if ((_base2 = String.prototype).repeat == null) {
  1585. _base2.repeat = function(count) {
  1586. return new Array(count + 1).join(this);
  1587. };
  1588. }
  1589. window.isEmpty = function(obj) {
  1590. var key;
  1591. for (key in obj) {
  1592. return false;
  1593. }
  1594. return true;
  1595. };
  1596. }).call(this);
  1597. /* ---- /1MaiL5gfBM1cyb4a8e3iiL8L5gXmoAJu27/js/utils/RateLimit.coffee ---- */
  1598. (function() {
  1599. var call_after_interval, limits;
  1600. limits = {};
  1601. call_after_interval = {};
  1602. window.RateLimit = function(interval, fn) {
  1603. if (!limits[fn]) {
  1604. call_after_interval[fn] = false;
  1605. fn();
  1606. return limits[fn] = setTimeout((function() {
  1607. if (call_after_interval[fn]) {
  1608. fn();
  1609. }
  1610. delete limits[fn];
  1611. return delete call_after_interval[fn];
  1612. }), interval);
  1613. } else {
  1614. return call_after_interval[fn] = true;
  1615. }
  1616. };
  1617. }).call(this);
  1618. /* ---- /1MaiL5gfBM1cyb4a8e3iiL8L5gXmoAJu27/js/utils/Text.coffee ---- */
  1619. (function() {
  1620. var MarkedRenderer, Text,
  1621. __extends = 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; },
  1622. __hasProp = {}.hasOwnProperty;
  1623. MarkedRenderer = (function(_super) {
  1624. __extends(MarkedRenderer, _super);
  1625. function MarkedRenderer() {
  1626. return MarkedRenderer.__super__.constructor.apply(this, arguments);
  1627. }
  1628. MarkedRenderer.prototype.image = function(href, title, text) {
  1629. return "<code>![" + text + "](" + href + ")</code>";
  1630. };
  1631. return MarkedRenderer;
  1632. })(marked.Renderer);
  1633. Text = (function() {
  1634. function Text() {}
  1635. Text.prototype.toColor = function(text) {
  1636. var hash, i, _i, _ref;
  1637. hash = 0;
  1638. for (i = _i = 0, _ref = text.length - 1; 0 <= _ref ? _i <= _ref : _i >= _ref; i = 0 <= _ref ? ++_i : --_i) {
  1639. hash += text.charCodeAt(i) * i;
  1640. hash = hash % 1000;
  1641. }
  1642. return "hsl(" + (hash % 360) + ",30%,50%)";
  1643. };
  1644. Text.prototype.renderMarked = function(text, options) {
  1645. if (options == null) {
  1646. options = {};
  1647. }
  1648. options["gfm"] = true;
  1649. options["breaks"] = true;
  1650. options["renderer"] = marked_renderer;
  1651. text = this.fixReply(text);
  1652. text = marked(text, options);
  1653. text = this.emailLinks(text);
  1654. return this.fixHtmlLinks(text);
  1655. };
  1656. Text.prototype.emailLinks = function(text) {
  1657. 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>");
  1658. };
  1659. Text.prototype.fixHtmlLinks = function(text) {
  1660. if (window.is_proxy) {
  1661. return text.replace(/href="http:\/\/(127.0.0.1|localhost):43110/g, 'href="http://zero');
  1662. } else {
  1663. return text.replace(/href="http:\/\/(127.0.0.1|localhost):43110/g, 'href="');
  1664. }
  1665. };
  1666. Text.prototype.fixLink = function(link) {
  1667. if (window.is_proxy) {
  1668. return link.replace(/http:\/\/(127.0.0.1|localhost):43110/, 'http://zero');
  1669. } else {
  1670. return link.replace(/http:\/\/(127.0.0.1|localhost):43110/, '');
  1671. }
  1672. };
  1673. Text.prototype.toUrl = function(text) {
  1674. return text.replace(/[^A-Za-z0-9]/g, "+").replace(/[+]+/g, "+").replace(/[+]+$/, "");
  1675. };
  1676. Text.prototype.fixReply = function(text) {
  1677. return text.replace(/(>.*\n)([^\n>])/gm, "$1\n$2");
  1678. };
  1679. Text.prototype.toBitcoinAddress = function(text) {
  1680. return text.replace(/[^A-Za-z0-9]/g, "");
  1681. };
  1682. Text.prototype.jsonEncode = function(obj) {
  1683. return unescape(encodeURIComponent(JSON.stringify(obj)));
  1684. };
  1685. Text.prototype.jsonDecode = function(obj) {
  1686. return JSON.parse(decodeURIComponent(escape(obj)));
  1687. };
  1688. Text.prototype.fileEncode = function(obj) {
  1689. if (typeof obj === "string") {
  1690. return btoa(unescape(encodeURIComponent(obj)));
  1691. } else {
  1692. return btoa(unescape(encodeURIComponent(JSON.stringify(obj, void 0, '\t'))));
  1693. }
  1694. };
  1695. Text.prototype.utf8Encode = function(s) {
  1696. return unescape(encodeURIComponent(s));
  1697. };
  1698. Text.prototype.utf8Decode = function(s) {
  1699. return decodeURIComponent(escape(s));
  1700. };
  1701. Text.prototype.distance = function(s1, s2) {
  1702. var char, extra_parts, key, match, next_find, next_find_i, val, _i, _len;
  1703. s1 = s1.toLocaleLowerCase();
  1704. s2 = s2.toLocaleLowerCase();
  1705. next_find_i = 0;
  1706. next_find = s2[0];
  1707. match = true;
  1708. extra_parts = {};
  1709. for (_i = 0, _len = s1.length; _i < _len; _i++) {
  1710. char = s1[_i];
  1711. if (char !== next_find) {
  1712. if (extra_parts[next_find_i]) {
  1713. extra_parts[next_find_i] += char;
  1714. } else {
  1715. extra_parts[next_find_i] = char;
  1716. }
  1717. } else {
  1718. next_find_i++;
  1719. next_find = s2[next_find_i];
  1720. }
  1721. }
  1722. if (extra_parts[next_find_i]) {
  1723. extra_parts[next_find_i] = "";
  1724. }
  1725. extra_parts = (function() {
  1726. var _results;
  1727. _results = [];
  1728. for (key in extra_parts) {
  1729. val = extra_parts[key];
  1730. _results.push(val);
  1731. }
  1732. return _results;
  1733. })();
  1734. if (next_find_i >= s2.length) {
  1735. return extra_parts.length + extra_parts.join("").length;
  1736. } else {
  1737. return false;
  1738. }
  1739. };
  1740. Text.prototype.parseQuery = function(query) {
  1741. var key, params, part, parts, val, _i, _len, _ref;
  1742. params = {};
  1743. parts = query.split('&');
  1744. for (_i = 0, _len = parts.length; _i < _len; _i++) {
  1745. part = parts[_i];
  1746. _ref = part.split("="), key = _ref[0], val = _ref[1];
  1747. if (val) {
  1748. params[decodeURIComponent(key)] = decodeURIComponent(val);
  1749. } else {
  1750. params["url"] = decodeURIComponent(key);
  1751. }
  1752. }
  1753. return params;
  1754. };
  1755. Text.prototype.encodeQuery = function(params) {
  1756. var back, key, val;
  1757. back = [];
  1758. if (params.url) {
  1759. back.push(params.url);
  1760. }
  1761. for (key in params) {
  1762. val = params[key];
  1763. if (!val || key === "url") {
  1764. continue;
  1765. }
  1766. back.push((encodeURIComponent(key)) + "=" + (encodeURIComponent(val)));
  1767. }
  1768. return back.join("&");
  1769. };
  1770. return Text;
  1771. })();
  1772. window.is_proxy = window.location.pathname === "/";
  1773. window.marked_renderer = new MarkedRenderer();
  1774. window.Text = new Text();
  1775. }).call(this);
  1776. /* ---- /1MaiL5gfBM1cyb4a8e3iiL8L5gXmoAJu27/js/utils/Time.coffee ---- */
  1777. (function() {
  1778. var Time;
  1779. Time = (function() {
  1780. function Time() {}
  1781. Time.prototype.since = function(timestamp) {
  1782. var back, now, secs;
  1783. now = +(new Date) / 1000;
  1784. if (timestamp > 1000000000000) {
  1785. timestamp = timestamp / 1000;
  1786. }
  1787. secs = now - timestamp;
  1788. if (secs < 60) {
  1789. back = "Just now";
  1790. } else if (secs < 60 * 60) {
  1791. back = (Math.round(secs / 60)) + " minutes ago";
  1792. } else if (secs < 60 * 60 * 24) {
  1793. back = (Math.round(secs / 60 / 60)) + " hours ago";
  1794. } else if (secs < 60 * 60 * 24 * 3) {
  1795. back = (Math.round(secs / 60 / 60 / 24)) + " days ago";
  1796. } else {
  1797. back = "on " + this.date(timestamp);
  1798. }
  1799. back = back.replace(/1 ([a-z]+)s/, "1 $1");
  1800. return back;
  1801. };
  1802. Time.prototype.date = function(timestamp, format) {
  1803. var display, parts;
  1804. if (format == null) {
  1805. format = "short";
  1806. }
  1807. if (timestamp > 1000000000000) {
  1808. timestamp = timestamp / 1000;
  1809. }
  1810. parts = (new Date(timestamp * 1000)).toString().split(" ");
  1811. if (format === "short") {
  1812. display = parts.slice(1, 4);
  1813. } else {
  1814. display = parts.slice(1, 5);
  1815. }
  1816. return display.join(" ").replace(/( [0-9]{4})/, ",$1");
  1817. };
  1818. Time.prototype.timestamp = function(date) {
  1819. if (date == null) {
  1820. date = "";
  1821. }
  1822. if (date === "now" || date === "") {
  1823. return parseInt(+(new Date) / 1000);
  1824. } else {
  1825. return parseInt(Date.parse(date) / 1000);
  1826. }
  1827. };
  1828. return Time;
  1829. })();
  1830. window.Time = new Time;
  1831. }).call(this);
  1832. /* ---- /1MaiL5gfBM1cyb4a8e3iiL8L5gXmoAJu27/js/utils/ZeroFrame.coffee ---- */
  1833. (function() {
  1834. var ZeroFrame,
  1835. __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
  1836. __extends = 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; },
  1837. __hasProp = {}.hasOwnProperty;
  1838. ZeroFrame = (function(_super) {
  1839. __extends(ZeroFrame, _super);
  1840. function ZeroFrame(url) {
  1841. this.onCloseWebsocket = __bind(this.onCloseWebsocket, this);
  1842. this.onOpenWebsocket = __bind(this.onOpenWebsocket, this);
  1843. this.onRequest = __bind(this.onRequest, this);
  1844. this.onMessage = __bind(this.onMessage, this);
  1845. this.url = url;
  1846. this.waiting_cb = {};
  1847. this.connect();
  1848. this.next_message_id = 1;
  1849. this.init();
  1850. }
  1851. ZeroFrame.prototype.init = function() {
  1852. return this;
  1853. };
  1854. ZeroFrame.prototype.connect = function() {
  1855. this.target = window.parent;
  1856. window.addEventListener("message", this.onMessage, false);
  1857. return this.cmd("innerReady");
  1858. };
  1859. ZeroFrame.prototype.onMessage = function(e) {
  1860. var cmd, message;
  1861. message = e.data;
  1862. cmd = message.cmd;
  1863. if (cmd === "response") {
  1864. if (this.waiting_cb[message.to] != null) {
  1865. return this.waiting_cb[message.to](message.result);
  1866. } else {
  1867. return this.log("Websocket callback not found:", message);
  1868. }
  1869. } else if (cmd === "wrapperReady") {
  1870. return this.cmd("innerReady");
  1871. } else if (cmd === "ping") {
  1872. return this.response(message.id, "pong");
  1873. } else if (cmd === "wrapperOpenedWebsocket") {
  1874. return this.onOpenWebsocket();
  1875. } else if (cmd === "wrapperClosedWebsocket") {
  1876. return this.onCloseWebsocket();
  1877. } else {
  1878. return this.onRequest(cmd, message.params);
  1879. }
  1880. };
  1881. ZeroFrame.prototype.onRequest = function(cmd, message) {
  1882. return this.log("Unknown request", message);
  1883. };
  1884. ZeroFrame.prototype.response = function(to, result) {
  1885. return this.send({
  1886. "cmd": "response",
  1887. "to": to,
  1888. "result": result
  1889. });
  1890. };
  1891. ZeroFrame.prototype.cmd = function(cmd, params, cb) {
  1892. if (params == null) {
  1893. params = {};
  1894. }
  1895. if (cb == null) {
  1896. cb = null;
  1897. }
  1898. return this.send({
  1899. "cmd": cmd,
  1900. "params": params
  1901. }, cb);
  1902. };
  1903. ZeroFrame.prototype.send = function(message, cb) {
  1904. if (cb == null) {
  1905. cb = null;
  1906. }
  1907. message.id = this.next_message_id;
  1908. this.next_message_id += 1;
  1909. this.target.postMessage(message, "*");
  1910. if (cb) {
  1911. return this.waiting_cb[message.id] = cb;
  1912. }
  1913. };
  1914. ZeroFrame.prototype.onOpenWebsocket = function() {
  1915. return this.log("Websocket open");
  1916. };
  1917. ZeroFrame.prototype.onCloseWebsocket = function() {
  1918. return this.log("Websocket close");
  1919. };
  1920. return ZeroFrame;
  1921. })(Class);
  1922. window.ZeroFrame = ZeroFrame;
  1923. }).call(this);
  1924. /* ---- /1MaiL5gfBM1cyb4a8e3iiL8L5gXmoAJu27/js/Leftbar.coffee ---- */
  1925. (function() {
  1926. var Leftbar,
  1927. __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
  1928. __extends = 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; },
  1929. __hasProp = {}.hasOwnProperty,
  1930. __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; };
  1931. Leftbar = (function(_super) {
  1932. __extends(Leftbar, _super);
  1933. function Leftbar() {
  1934. this.render = __bind(this.render, this);
  1935. this.handleLogoutClick = __bind(this.handleLogoutClick, this);
  1936. this.handleFolderClick = __bind(this.handleFolderClick, this);
  1937. this.handleNewMessageClick = __bind(this.handleNewMessageClick, this);
  1938. this.handleContactClick = __bind(this.handleContactClick, this);
  1939. this.contacts = [];
  1940. this.folder_active = "inbox";
  1941. this.reload_contacts = true;
  1942. this;
  1943. }
  1944. Leftbar.prototype.handleContactClick = function(e) {
  1945. Page.message_create.show(e.currentTarget.querySelector(".name").textContent);
  1946. return false;
  1947. };
  1948. Leftbar.prototype.handleNewMessageClick = function(e) {
  1949. Page.message_create.show();
  1950. return false;
  1951. };
  1952. Leftbar.prototype.handleFolderClick = function(e) {
  1953. var folder_name;
  1954. folder_name = e.currentTarget.href.replace(/.*\?/, "");
  1955. this.folder_active = folder_name.toLowerCase();
  1956. Page.message_lists.setActive(this.folder_active);
  1957. Page.cmd("wrapperReplaceState", [{}, "", folder_name]);
  1958. return false;
  1959. };
  1960. Leftbar.prototype.handleLogoutClick = function(e) {
  1961. Page.cmd("certSelect", [["zeroid.bit"]]);
  1962. Page.local_storage = {};
  1963. Page.saveLocalStorage(function() {
  1964. return Page.getLocalStorage();
  1965. });
  1966. return false;
  1967. };
  1968. Leftbar.prototype.loadContacts = function(cb) {
  1969. var address, addresses;
  1970. addresses = (function() {
  1971. var _results;
  1972. _results = [];
  1973. for (address in Page.local_storage.parsed.my_secret) {
  1974. _results.push(address);
  1975. }
  1976. return _results;
  1977. })();
  1978. return Page.users.getUsernames(addresses, function(rows) {
  1979. var auth_address, cert_user_id, contacts;
  1980. contacts = (function() {
  1981. var _results;
  1982. _results = [];
  1983. for (auth_address in rows) {
  1984. cert_user_id = rows[auth_address];
  1985. _results.push([cert_user_id, auth_address]);
  1986. }
  1987. return _results;
  1988. })();
  1989. return cb(contacts);
  1990. });
  1991. };
  1992. Leftbar.prototype.getContacts = function() {
  1993. if (this.reload_contacts) {
  1994. this.reload_contacts = false;
  1995. this.log("Reloading contacts");
  1996. Page.on_local_storage.then((function(_this) {
  1997. return function() {
  1998. var address, known_addresses, unknown_addresses, username;
  1999. known_addresses = (function() {
  2000. var _i, _len, _ref, _ref1, _results;
  2001. _ref = this.contacts;
  2002. _results = [];
  2003. for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  2004. _ref1 = _ref[_i], username = _ref1[0], address = _ref1[1];
  2005. _results.push(address);
  2006. }
  2007. return _results;
  2008. }).call(_this);
  2009. unknown_addresses = (function() {
  2010. var _results;
  2011. _results = [];
  2012. for (address in Page.local_storage.parsed.my_secret) {
  2013. if (__indexOf.call(known_addresses, address) < 0) {
  2014. _results.push(address);
  2015. }
  2016. }
  2017. return _results;
  2018. })();
  2019. if (unknown_addresses.length > 0) {
  2020. return _this.loadContacts(function(contacts) {
  2021. _this.log("Unknown contacts found, reloaded.");
  2022. contacts = contacts.sort();
  2023. _this.contacts = contacts;
  2024. return Page.projector.scheduleRender();
  2025. });
  2026. }
  2027. };
  2028. })(this));
  2029. }
  2030. return this.contacts;
  2031. };
  2032. Leftbar.prototype.render = function() {
  2033. var contacts, _ref, _ref1;
  2034. contacts = ((_ref = Page.site_info) != null ? _ref.cert_user_id : void 0) ? this.getContacts() : [];
  2035. return h("div.Leftbar", [
  2036. h("a.logo", {
  2037. href: "?Main"
  2038. }, ["ZeroMail_"]), h("a.button-create.newmessage", {
  2039. href: "#New+message",
  2040. onclick: this.handleNewMessageClick
  2041. }, ["New message"]), h("div.folders", [
  2042. h("a", {
  2043. key: "Inbox",
  2044. href: "?Inbox",
  2045. classes: {
  2046. "active": Page.message_lists.active === Page.message_lists.inbox
  2047. },
  2048. onclick: this.handleFolderClick
  2049. }, ["Inbox"]), h("a", {
  2050. key: "Sent",
  2051. href: "?Sent",
  2052. classes: {
  2053. "active": Page.message_lists.active === Page.message_lists.sent
  2054. },
  2055. onclick: this.handleFolderClick
  2056. }, ["Sent", h("span.quota", Page.user.formatQuota())])
  2057. ]), contacts.length > 0 ? [
  2058. h("h2", ["Contacts"]), h("div.contacts-wrapper", [
  2059. h("div.contacts", contacts.map((function(_this) {
  2060. return function(_arg) {
  2061. var address, username;
  2062. username = _arg[0], address = _arg[1];
  2063. return h("a.username", {
  2064. key: username,
  2065. href: Page.createUrl("to", username.replace("@zeroid.bit", "")),
  2066. onclick: _this.handleContactClick,
  2067. "enterAnimation": Animation.show
  2068. }, [
  2069. h("span.bullet", {
  2070. "style": "color: " + (Text.toColor(address))
  2071. }, ["•"]), h("span.name", [username.replace("@zeroid.bit", "")])
  2072. ]);
  2073. };
  2074. })(this)))
  2075. ])
  2076. ] : void 0, ((_ref1 = Page.site_info) != null ? _ref1.cert_user_id : void 0) ? h("a.logout.icon.icon-logout", {
  2077. href: "?Logout",
  2078. title: "Logout",
  2079. onclick: this.handleLogoutClick
  2080. }) : void 0
  2081. ]);
  2082. };
  2083. Leftbar.prototype.onSiteInfo = function(site_info) {
  2084. var action, inner_path, _ref;
  2085. if (site_info.event) {
  2086. _ref = site_info.event, action = _ref[0], inner_path = _ref[1];
  2087. if (action === "file_done" && inner_path.endsWith("data.json")) {
  2088. return this.reload_contacts = true;
  2089. }
  2090. }
  2091. };
  2092. return Leftbar;
  2093. })(Class);
  2094. window.Leftbar = Leftbar;
  2095. }).call(this);
  2096. /* ---- /1MaiL5gfBM1cyb4a8e3iiL8L5gXmoAJu27/js/Message.coffee ---- */
  2097. (function() {
  2098. var Message,
  2099. __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
  2100. Message = (function() {
  2101. function Message(_at_message_list, _at_row) {
  2102. this.message_list = _at_message_list;
  2103. this.row = _at_row;
  2104. this.renderShow = __bind(this.renderShow, this);
  2105. this.renderUsername = __bind(this.renderUsername, this);
  2106. this.renderUsernameLink = __bind(this.renderUsernameLink, this);
  2107. this.handleContactClick = __bind(this.handleContactClick, this);
  2108. this.renderBodyPreview = __bind(this.renderBodyPreview, this);
  2109. this.renderBody = __bind(this.renderBody, this);
  2110. this.handleReplyClick = __bind(this.handleReplyClick, this);
  2111. this.handleDeleteClick = __bind(this.handleDeleteClick, this);
  2112. this.handleListClick = __bind(this.handleListClick, this);
  2113. this.active = false;
  2114. this.selected = false;
  2115. this.deleted = false;
  2116. this.key = this.row.key;
  2117. if (this.row.folder === "sent" || Page.local_storage.read[this.row.date_added]) {
  2118. this.read = true;
  2119. } else {
  2120. this.read = false;
  2121. }
  2122. this;
  2123. }
  2124. Message.prototype.getBodyPreview = function() {
  2125. return this.row.body.slice(0, 81);
  2126. };
  2127. Message.prototype.markRead = function(read) {
  2128. if (read == null) {
  2129. read = true;
  2130. }
  2131. if (!this.read) {
  2132. Page.local_storage.read[this.row.date_added] = true;
  2133. Page.saveLocalStorage();
  2134. }
  2135. return this.read = read;
  2136. };
  2137. Message.prototype.handleListClick = function(e) {
  2138. var active_index, message, my_index, _i, _len, _ref;
  2139. this.markRead();
  2140. if (e && e.ctrlKey) {
  2141. this.selected = !this.selected;
  2142. if (this.message_list.message_lists.message_active) {
  2143. this.message_list.message_lists.message_active.active = false;
  2144. this.message_list.message_lists.message_active.selected = true;
  2145. this.message_list.message_lists.message_active = null;
  2146. Page.message_show.message = null;
  2147. }
  2148. this.message_list.updateSelected();
  2149. } else if (e && e.shiftKey) {
  2150. if (this.message_list.message_lists.message_active) {
  2151. active_index = this.message_list.messages.indexOf(this.message_list.message_lists.message_active);
  2152. my_index = this.message_list.messages.indexOf(this);
  2153. _ref = this.message_list.messages.slice(Math.min(active_index, my_index), +Math.max(active_index, my_index) + 1 || 9e9);
  2154. for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  2155. message = _ref[_i];
  2156. message.selected = true;
  2157. }
  2158. }
  2159. this.message_list.updateSelected();
  2160. } else {
  2161. this.message_list.setActiveMessage(this);
  2162. Page.message_show.setMessage(this);
  2163. }
  2164. return false;
  2165. };
  2166. Message.prototype.handleDeleteClick = function() {
  2167. this.message_list.deleteMessage(this);
  2168. this.message_list.save();
  2169. return false;
  2170. };
  2171. Message.prototype.handleReplyClick = function() {
  2172. Page.message_create.setReplyDetails();
  2173. Page.message_create.show();
  2174. return false;
  2175. };
  2176. Message.prototype.renderBody = function(node) {
  2177. return node.innerHTML = Text.renderMarked(this.row.body, {
  2178. "sanitize": true
  2179. });
  2180. };
  2181. Message.prototype.renderBodyPreview = function(node) {
  2182. return node.textContent = this.getBodyPreview();
  2183. };
  2184. Message.prototype.handleContactClick = function(e) {
  2185. Page.message_create.show(e.currentTarget.querySelector(".name").textContent);
  2186. return false;
  2187. };
  2188. Message.prototype.renderUsernameLink = function(username, address) {
  2189. var color;
  2190. color = Text.toColor(address);
  2191. if (username == null) {
  2192. username = "n/a";
  2193. }
  2194. if (username == null) {
  2195. username = "address";
  2196. }
  2197. return h("a.username", {
  2198. href: Page.createUrl("to", username.replace("@zeroid.bit", "")),
  2199. onclick: this.handleContactClick
  2200. }, this.renderUsername(username, address));
  2201. };
  2202. Message.prototype.renderUsername = function(username, address) {
  2203. var color;
  2204. color = Text.toColor(address);
  2205. return [
  2206. h("span.name", {
  2207. "title": address,
  2208. "style": "color: " + color
  2209. }, [username.replace("@zeroid.bit", "")])
  2210. ];
  2211. };
  2212. Message.prototype.renderList = function() {
  2213. return h("a.Message", {
  2214. "key": this.key,
  2215. "href": "#MessageShow:" + this.row.key,
  2216. "onclick": this.handleListClick,
  2217. "disableAnimation": this.row.disable_animation,
  2218. "enterAnimation": Animation.slideDown,
  2219. "exitAnimation": Animation.slideUp,
  2220. classes: {
  2221. "active": this.active,
  2222. "selected": this.selected,
  2223. "unread": !this.read
  2224. }
  2225. }, [
  2226. h("div.sent", [Time.since(this.row.date_added)]), h("div.subject", [this.row.subject]), this.row.folder === "sent" ? h("div.to.username", ["To: ", this.renderUsername(this.row.to, this.row.to_address)]) : h("div.from.username", ["From: ", this.renderUsername(this.row.from, this.row.from_address)]), h("div.preview", {
  2227. "afterCreate": this.renderBodyPreview,
  2228. "updateAnimation": this.renderBodyPreview
  2229. }, [this.row.body])
  2230. ]);
  2231. };
  2232. Message.prototype.renderShow = function() {
  2233. return h("div.Message", {
  2234. "key": this.key,
  2235. "enterAnimation": Animation.show,
  2236. "classes": {
  2237. "deleted": this.deleted
  2238. }
  2239. }, [
  2240. h("div.tools", [
  2241. h("a.icon.icon-reply", {
  2242. href: "#Reply",
  2243. "title": "Reply message",
  2244. onclick: this.handleReplyClick
  2245. }), h("a.icon.icon-trash", {
  2246. href: "#Delete",
  2247. "title": "Delete message",
  2248. onclick: this.handleDeleteClick
  2249. })
  2250. ]), h("div.subject", [this.row.subject]), h("div.sent", [Time.date(this.row.date_added, "full")]), this.row.folder === "sent" ? h("div.to.username", ["To: ", this.renderUsernameLink(this.row.to, this.row.to_address)]) : h("div.from.username", ["From: ", this.renderUsernameLink(this.row.from, this.row.from_address)]), h("div.body", {
  2251. "afterCreate": this.renderBody,
  2252. "updateAnimation": this.renderBody
  2253. }, [this.row.body])
  2254. ]);
  2255. };
  2256. return Message;
  2257. })();
  2258. window.Message = Message;
  2259. }).call(this);
  2260. /* ---- /1MaiL5gfBM1cyb4a8e3iiL8L5gXmoAJu27/js/MessageCreate.coffee ---- */
  2261. (function() {
  2262. var MessageCreate,
  2263. __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
  2264. __extends = 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; },
  2265. __hasProp = {}.hasOwnProperty;
  2266. MessageCreate = (function(_super) {
  2267. __extends(MessageCreate, _super);
  2268. function MessageCreate() {
  2269. this.render = __bind(this.render, this);
  2270. this.handleSendClick = __bind(this.handleSendClick, this);
  2271. this.handleInput = __bind(this.handleInput, this);
  2272. this.handleCloseClick = __bind(this.handleCloseClick, this);
  2273. this.handleTitleClick = __bind(this.handleTitleClick, this);
  2274. this.hide = __bind(this.hide, this);
  2275. this.show = __bind(this.show, this);
  2276. this.getTitle = __bind(this.getTitle, this);
  2277. this.getUsernames = __bind(this.getUsernames, this);
  2278. this.setReplyDetails = __bind(this.setReplyDetails, this);
  2279. this.setNode = __bind(this.setNode, this);
  2280. this.isFilled = __bind(this.isFilled, this);
  2281. this.isEmpty = __bind(this.isEmpty, this);
  2282. this.subject = "";
  2283. this.body = "";
  2284. this.minimized = true;
  2285. this.sending = false;
  2286. this.just_sent = false;
  2287. this.user_address = {};
  2288. this.update_usernames = true;
  2289. this.field_to = new Autocomplete(this.getUsernames, {
  2290. type: "text",
  2291. placeholder: "Username",
  2292. value: ""
  2293. });
  2294. this.node = null;
  2295. }
  2296. MessageCreate.property('to', {
  2297. get: function() {
  2298. return this.field_to.attrs.value;
  2299. },
  2300. set: function(to) {
  2301. return this.field_to.setValue(to);
  2302. }
  2303. });
  2304. MessageCreate.prototype.isEmpty = function() {
  2305. return !(this.body + this.subject + this.to);
  2306. };
  2307. MessageCreate.prototype.isFilled = function() {
  2308. return this.body !== "" && this.subject !== "" && this.to !== "" && Page.user.publickey;
  2309. };
  2310. MessageCreate.prototype.setNode = function(node) {
  2311. return this.node = node;
  2312. };
  2313. MessageCreate.prototype.setReplyDetails = function() {
  2314. var current_message;
  2315. current_message = Page.message_lists.message_active;
  2316. if (current_message.row.folder === "sent") {
  2317. this.to = current_message.row.to.replace("@zeroid.bit", "");
  2318. } else {
  2319. this.to = current_message.row.from.replace("@zeroid.bit", "");
  2320. }
  2321. return this.subject = "Re: " + current_message.row.subject.replace("Re: ", "");
  2322. };
  2323. MessageCreate.prototype.getUsernames = function() {
  2324. var address, username;
  2325. return (function() {
  2326. var _ref, _results;
  2327. _ref = this.user_address;
  2328. _results = [];
  2329. for (username in _ref) {
  2330. address = _ref[username];
  2331. _results.push(username.replace("@zeroid.bit", ""));
  2332. }
  2333. return _results;
  2334. }).call(this);
  2335. };
  2336. MessageCreate.prototype.getTitle = function() {
  2337. var title;
  2338. if (this.just_sent) {
  2339. title = "Message sent!";
  2340. } else if (this.isEmpty()) {
  2341. if (Page.message_lists.message_active) {
  2342. title = "Reply to this message";
  2343. } else {
  2344. title = "New message";
  2345. }
  2346. } else {
  2347. if (this.subject.startsWith("Re:")) {
  2348. title = "Reply to message";
  2349. } else {
  2350. title = "New message";
  2351. }
  2352. }
  2353. return title;
  2354. };
  2355. MessageCreate.prototype.updateUsernames = function() {
  2356. this.update_usernames = false;
  2357. return Page.users.getAll((function(_this) {
  2358. return function(user_address) {
  2359. return _this.user_address = user_address;
  2360. };
  2361. })(this));
  2362. };
  2363. MessageCreate.prototype.show = function(to, subject, body) {
  2364. if (to) {
  2365. this.to = to;
  2366. }
  2367. if (subject) {
  2368. this.subject = subject;
  2369. }
  2370. if (body) {
  2371. this.body = body;
  2372. }
  2373. this.minimized = false;
  2374. document.body.classList.add("MessageCreate-opened");
  2375. if (!this.to) {
  2376. this.node.querySelector(".to").focus();
  2377. } else if (!this.subject) {
  2378. this.node.querySelector(".subject").focus();
  2379. } else if (!this.body) {
  2380. this.node.querySelector(".body").focus();
  2381. }
  2382. if (this.update_usernames) {
  2383. this.updateUsernames();
  2384. }
  2385. return false;
  2386. };
  2387. MessageCreate.prototype.hide = function() {
  2388. document.body.classList.remove("MessageCreate-opened");
  2389. return this.minimized = true;
  2390. };
  2391. MessageCreate.prototype.handleTitleClick = function(e) {
  2392. e.cancelBubble = true;
  2393. if (this.minimized) {
  2394. if (this.isEmpty() && Page.message_lists.message_active) {
  2395. this.setReplyDetails();
  2396. }
  2397. this.show();
  2398. } else {
  2399. this.hide();
  2400. }
  2401. return false;
  2402. };
  2403. MessageCreate.prototype.handleCloseClick = function(e) {
  2404. e.cancelBubble = true;
  2405. this.hide();
  2406. this.to = "";
  2407. this.subject = "";
  2408. this.body = "";
  2409. return false;
  2410. };
  2411. MessageCreate.prototype.handleInput = function(e) {
  2412. this[e.target.name] = e.target.value;
  2413. return false;
  2414. };
  2415. MessageCreate.prototype.handleSendClick = function(e) {
  2416. var to;
  2417. to = this.to;
  2418. if (to.indexOf("@") === -1) {
  2419. to += "@zeroid.bit";
  2420. }
  2421. if (!this.user_address[to]) {
  2422. to = "";
  2423. this.node.querySelector(".to").focus();
  2424. return false;
  2425. }
  2426. Animation.scramble(this.node.querySelector(".to"));
  2427. Animation.scramble(this.node.querySelector(".subject"));
  2428. Animation.scramble(this.node.querySelector(".body"));
  2429. this.sending = true;
  2430. this.log("Sending message", to, this.user_address[to]);
  2431. Page.user.getSecret(this.user_address[to], (function(_this) {
  2432. return function(aes_key) {
  2433. var message;
  2434. if (!aes_key) {
  2435. _this.sending = false;
  2436. return false;
  2437. }
  2438. message = {
  2439. "subject": _this.subject,
  2440. "body": _this.body,
  2441. "to": to
  2442. };
  2443. _this.log("Encrypting to", aes_key);
  2444. return Page.cmd("aesEncrypt", [Text.jsonEncode(message), aes_key], function(res) {
  2445. var encrypted, iv;
  2446. aes_key = res[0], iv = res[1], encrypted = res[2];
  2447. Page.user.data.message[Page.user.getNewIndex("message")] = iv + "," + encrypted;
  2448. return Page.user.saveData().then(function(send_res) {
  2449. _this.sending = false;
  2450. if (send_res) {
  2451. _this.hide();
  2452. _this.just_sent = true;
  2453. if (_this.user_address[message.to] === Page.site_info.auth_address) {
  2454. _this.log("Sent message to myself, reload inbox");
  2455. Page.message_lists.inbox.reload = true;
  2456. }
  2457. return setTimeout((function() {
  2458. _this.just_sent = false;
  2459. _this.to = "";
  2460. _this.subject = "";
  2461. _this.body = "";
  2462. Page.leftbar.reload_contacts = true;
  2463. return Page.projector.scheduleRender();
  2464. }), 4000);
  2465. } else {
  2466. _this.node.querySelector(".to").value = _this.to;
  2467. _this.node.querySelector(".subject").value = _this.subject;
  2468. return _this.node.querySelector(".body").value = _this.body;
  2469. }
  2470. });
  2471. });
  2472. };
  2473. })(this));
  2474. return false;
  2475. };
  2476. MessageCreate.prototype.render = function() {
  2477. return h("div.MessageCreate", {
  2478. classes: {
  2479. minimized: this.minimized,
  2480. empty: this.isEmpty(),
  2481. sent: this.just_sent
  2482. },
  2483. afterCreate: this.setNode
  2484. }, [
  2485. h("a.titlebar", {
  2486. "href": "#New+message",
  2487. onclick: this.handleTitleClick
  2488. }, [
  2489. h("span.text", [this.getTitle()]), h("span.buttons", [
  2490. h("a.minimize", {
  2491. href: "#Minimize",
  2492. onclick: this.handleTitleClick
  2493. }, ["_"]), h("a.close", {
  2494. href: "#Close",
  2495. onclick: this.handleCloseClick
  2496. }, ["×"])
  2497. ])
  2498. ]), h("label.label-to", ["To:"]), this.field_to.render(), h("input.subject", {
  2499. type: "text",
  2500. placeholder: "Subject",
  2501. name: "subject",
  2502. value: this.subject,
  2503. oninput: this.handleInput
  2504. }), h("textarea.body", {
  2505. placeholder: "Message",
  2506. name: "body",
  2507. value: this.body,
  2508. oninput: this.handleInput
  2509. }), h("a.button.button-submit.button-send", {
  2510. href: "#Send",
  2511. classes: {
  2512. "disabled": !this.isFilled(),
  2513. "loading": this.sending || this.just_sent
  2514. },
  2515. onclick: this.handleSendClick
  2516. }, ["Encrypt & Send message"])
  2517. ]);
  2518. };
  2519. MessageCreate.prototype.onSiteInfo = function(site_info) {
  2520. var _ref;
  2521. if (((_ref = site_info.event) != null ? _ref[0] : void 0) === "file_done") {
  2522. return this.update_usernames = true;
  2523. }
  2524. };
  2525. return MessageCreate;
  2526. })(Class);
  2527. window.MessageCreate = MessageCreate;
  2528. }).call(this);
  2529. /* ---- /1MaiL5gfBM1cyb4a8e3iiL8L5gXmoAJu27/js/MessageList.coffee ---- */
  2530. (function() {
  2531. var MessageList,
  2532. __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
  2533. __extends = 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; },
  2534. __hasProp = {}.hasOwnProperty;
  2535. MessageList = (function(_super) {
  2536. __extends(MessageList, _super);
  2537. function MessageList(_at_message_lists) {
  2538. this.message_lists = _at_message_lists;
  2539. this.render = __bind(this.render, this);
  2540. this.handleMoreClick = __bind(this.handleMoreClick, this);
  2541. this.title = "Unknown";
  2542. this.loading = false;
  2543. this.loaded = false;
  2544. this.has_more = false;
  2545. this.loading_message = "Loading...";
  2546. this.messages = [];
  2547. this.selected = [];
  2548. this.message_db = {};
  2549. }
  2550. MessageList.prototype.getMessages = function() {
  2551. return this.messages;
  2552. };
  2553. MessageList.prototype.setActiveMessage = function(message) {
  2554. if (this.message_lists.message_active) {
  2555. this.message_lists.message_active.active = false;
  2556. }
  2557. message.active = true;
  2558. this.message_lists.message_active = message;
  2559. return this.deselectMessages();
  2560. };
  2561. MessageList.prototype.deselectMessages = function() {
  2562. var message, _i, _len, _ref;
  2563. _ref = this.selected;
  2564. for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  2565. message = _ref[_i];
  2566. message.selected = false;
  2567. }
  2568. return this.updateSelected();
  2569. };
  2570. MessageList.prototype.updateSelected = function() {
  2571. var message;
  2572. return this.selected = (function() {
  2573. var _i, _len, _ref, _results;
  2574. _ref = this.messages;
  2575. _results = [];
  2576. for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  2577. message = _ref[_i];
  2578. if (message.selected) {
  2579. _results.push(message);
  2580. }
  2581. }
  2582. return _results;
  2583. }).call(this);
  2584. };
  2585. MessageList.prototype.addMessage = function(message_row, index) {
  2586. var message;
  2587. if (index == null) {
  2588. index = -1;
  2589. }
  2590. message = new Message(this, message_row);
  2591. this.message_db[message_row.key] = message;
  2592. if (index >= 0) {
  2593. this.messages.splice(index, 0, message);
  2594. } else {
  2595. this.messages.push(message);
  2596. }
  2597. return message;
  2598. };
  2599. MessageList.prototype.deleteMessage = function(message) {
  2600. var index;
  2601. message.deleted = true;
  2602. index = this.messages.indexOf(message);
  2603. if (index > -1) {
  2604. return this.messages.splice(index, 1);
  2605. }
  2606. };
  2607. MessageList.prototype.syncMessages = function(message_rows) {
  2608. var current_obj, last_obj, message_row, _i, _len, _results;
  2609. last_obj = null;
  2610. _results = [];
  2611. for (_i = 0, _len = message_rows.length; _i < _len; _i++) {
  2612. message_row = message_rows[_i];
  2613. current_obj = this.message_db[message_row.key];
  2614. if (current_obj) {
  2615. current_obj.row = message_row;
  2616. _results.push(last_obj = current_obj);
  2617. } else {
  2618. if (last_obj) {
  2619. _results.push(last_obj = this.addMessage(message_row, this.messages.indexOf(last_obj) + 1));
  2620. } else {
  2621. _results.push(last_obj = this.addMessage(message_row, 0));
  2622. }
  2623. }
  2624. }
  2625. return _results;
  2626. };
  2627. MessageList.prototype.setLoadingMessage = function(_at_loading_message) {
  2628. this.loading_message = _at_loading_message;
  2629. return Page.projector.scheduleRender();
  2630. };
  2631. MessageList.prototype.handleMoreClick = function() {
  2632. this.reload = true;
  2633. this.getMessages("nolimit");
  2634. return false;
  2635. };
  2636. MessageList.prototype.render = function() {
  2637. var messages, _ref;
  2638. messages = ((_ref = Page.site_info) != null ? _ref.cert_user_id : void 0) ? this.getMessages() : [];
  2639. if (messages.length > 0) {
  2640. return h("div.MessageList", {
  2641. "key": this.title,
  2642. "enterAnimation": Animation.show
  2643. }, messages.map(function(message) {
  2644. return message.renderList();
  2645. }), h("a.more", {
  2646. href: "#More",
  2647. classes: {
  2648. "visible": this.has_more,
  2649. "loading": this.loading
  2650. },
  2651. onclick: this.handleMoreClick
  2652. }, "Load more messages"));
  2653. } else if (this.loading) {
  2654. return h("div.MessageList.empty", {
  2655. "key": this.title + ".loading",
  2656. "enterAnimation": Animation.show,
  2657. "afterCreate": Animation.show,
  2658. "delay": 1
  2659. }, [this.title + ": " + this.loading_message, h("span.cursor", ["_"])]);
  2660. } else {
  2661. return h("div.MessageList.empty", {
  2662. "key": this.title + ".empty",
  2663. "enterAnimation": Animation.show,
  2664. "afterCreate": Animation.show,
  2665. "delay": 0.5
  2666. }, [this.title + ": No messages", h("span.cursor", ["_"])]);
  2667. }
  2668. };
  2669. return MessageList;
  2670. })(Class);
  2671. window.MessageList = MessageList;
  2672. }).call(this);
  2673. /* ---- /1MaiL5gfBM1cyb4a8e3iiL8L5gXmoAJu27/js/MessageListInbox.coffee ---- */
  2674. (function() {
  2675. var MessageListInbox,
  2676. __extends = 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; },
  2677. __hasProp = {}.hasOwnProperty,
  2678. __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; };
  2679. MessageListInbox = (function(_super) {
  2680. __extends(MessageListInbox, _super);
  2681. function MessageListInbox() {
  2682. MessageListInbox.__super__.constructor.apply(this, arguments);
  2683. this.reload = true;
  2684. this.loading = false;
  2685. this.loading_message = "Loading...";
  2686. this.nolimit_loaded = false;
  2687. this.messages = [];
  2688. this.my_aes_keys = {};
  2689. this.title = "Inbox";
  2690. }
  2691. MessageListInbox.prototype.getParsedDb = function(cb) {
  2692. return Page.on_local_storage.then((function(_this) {
  2693. return function() {
  2694. return cb(Page.local_storage.parsed);
  2695. };
  2696. })(this));
  2697. };
  2698. MessageListInbox.prototype.decryptKnownAesKeys = function(parsed_db, cb) {
  2699. var dates, directories, load_keys, query, secret_id, user_address, where;
  2700. load_keys = ((function() {
  2701. var _ref, _results;
  2702. if (!this.my_aes_keys[user_address]) {
  2703. _ref = parsed_db.my_secret;
  2704. _results = [];
  2705. for (user_address in _ref) {
  2706. secret_id = _ref[user_address];
  2707. _results.push([user_address, secret_id]);
  2708. }
  2709. return _results;
  2710. }
  2711. }).call(this));
  2712. if (load_keys.length > 0) {
  2713. this.log("Loading keys", load_keys.length);
  2714. directories = (function() {
  2715. var _i, _len, _ref, _results;
  2716. _results = [];
  2717. for (_i = 0, _len = load_keys.length; _i < _len; _i++) {
  2718. _ref = load_keys[_i], user_address = _ref[0], secret_id = _ref[1];
  2719. _results.push("'" + user_address + "'");
  2720. }
  2721. return _results;
  2722. })();
  2723. dates = (function() {
  2724. var _i, _len, _ref, _results;
  2725. _results = [];
  2726. for (_i = 0, _len = load_keys.length; _i < _len; _i++) {
  2727. _ref = load_keys[_i], user_address = _ref[0], secret_id = _ref[1];
  2728. _results.push(parseInt(secret_id));
  2729. }
  2730. return _results;
  2731. })();
  2732. where = "directory IN (" + (directories.join(',')) + ") AND date_added IN (" + (dates.join(',')) + ")";
  2733. query = "SELECT * FROM secret LEFT JOIN json USING (json_id) WHERE " + where;
  2734. return Page.cmd("dbQuery", query, (function(_this) {
  2735. return function(rows) {
  2736. var row;
  2737. return Page.cmd("eciesDecrypt", [
  2738. (function() {
  2739. var _i, _len, _results;
  2740. _results = [];
  2741. for (_i = 0, _len = rows.length; _i < _len; _i++) {
  2742. row = rows[_i];
  2743. _results.push(row.encrypted);
  2744. }
  2745. return _results;
  2746. })()
  2747. ], function(decrypted_keys) {
  2748. var decrypted_key, i, _i, _len;
  2749. for (i = _i = 0, _len = decrypted_keys.length; _i < _len; i = ++_i) {
  2750. decrypted_key = decrypted_keys[i];
  2751. if (!decrypted_key) {
  2752. continue;
  2753. }
  2754. _this.my_aes_keys[rows[i].directory] = decrypted_key;
  2755. }
  2756. return cb(i);
  2757. });
  2758. };
  2759. })(this));
  2760. } else {
  2761. return cb(false);
  2762. }
  2763. };
  2764. MessageListInbox.prototype.decryptNewSecrets = function(parsed_db, cb) {
  2765. var known_addresses, last_parsed, query, user_address, user_last_parsed, where, _ref;
  2766. last_parsed = 0;
  2767. known_addresses = [];
  2768. _ref = parsed_db.last_secret;
  2769. for (user_address in _ref) {
  2770. user_last_parsed = _ref[user_address];
  2771. last_parsed = Math.max(user_last_parsed, last_parsed);
  2772. known_addresses.push("'" + user_address + "'");
  2773. }
  2774. this.log("Last parsed secret:", Date(last_parsed));
  2775. if (known_addresses.length > 0) {
  2776. where = "WHERE date_added > " + (last_parsed - 60 * 60 * 24 * 1000) + " OR directory NOT IN (" + (known_addresses.join(",")) + ")";
  2777. } else {
  2778. where = "";
  2779. }
  2780. query = "SELECT * FROM secret\nLEFT JOIN json USING (json_id)\n" + where + "\nORDER BY date_added ASC";
  2781. return Page.cmd("dbQuery", [query], (function(_this) {
  2782. return function(db_res) {
  2783. var db_rows, row, secrets, _i, _len;
  2784. if (!db_res.length) {
  2785. cb(false);
  2786. return false;
  2787. }
  2788. db_rows = [];
  2789. for (_i = 0, _len = db_res.length; _i < _len; _i++) {
  2790. row = db_res[_i];
  2791. if ((parsed_db.last_secret[row.directory] == null) || parsed_db.last_secret[row.directory] < row.date_added) {
  2792. db_rows.push(row);
  2793. }
  2794. }
  2795. secrets = (function() {
  2796. var _j, _len1, _results;
  2797. _results = [];
  2798. for (_j = 0, _len1 = db_rows.length; _j < _len1; _j++) {
  2799. row = db_rows[_j];
  2800. _results.push(row.encrypted);
  2801. }
  2802. return _results;
  2803. })();
  2804. return Page.cmd("eciesDecrypt", [secrets], function(aes_keys) {
  2805. var aes_key, db_row, i, new_secrets, _j, _len1;
  2806. new_secrets = {};
  2807. for (i = _j = 0, _len1 = aes_keys.length; _j < _len1; i = ++_j) {
  2808. aes_key = aes_keys[i];
  2809. db_row = db_rows[i];
  2810. if (aes_key) {
  2811. new_secrets[db_row.directory] = db_row.date_added;
  2812. parsed_db.my_secret[db_row.directory] = db_row.date_added;
  2813. _this.my_aes_keys[db_row.directory] = aes_key;
  2814. }
  2815. parsed_db.last_secret[db_row.directory] = db_row.date_added;
  2816. }
  2817. return cb(new_secrets);
  2818. });
  2819. };
  2820. })(this));
  2821. };
  2822. MessageListInbox.prototype.decryptNewMessages = function(parsed_db, new_secrets, cb) {
  2823. var aes_key, found, group, last_parsed, new_addresses, parsed_sql, query, user_address, where, _ref, _ref1;
  2824. parsed_sql = [];
  2825. group = [];
  2826. _ref = parsed_db.last_message;
  2827. for (user_address in _ref) {
  2828. last_parsed = _ref[user_address];
  2829. group.push("(directory = '" + user_address + "' AND date_added > " + last_parsed + ")");
  2830. if (group.length === 100) {
  2831. parsed_sql.push("(" + group.join(" OR ") + ")");
  2832. group = [];
  2833. }
  2834. }
  2835. if (group.length > 0) {
  2836. parsed_sql.push("(" + group.join(" OR ") + ")");
  2837. }
  2838. new_addresses = [];
  2839. _ref1 = this.my_aes_keys;
  2840. for (user_address in _ref1) {
  2841. aes_key = _ref1[user_address];
  2842. if (!parsed_db.last_message[user_address]) {
  2843. new_addresses.push("'" + user_address + "'");
  2844. }
  2845. }
  2846. if (parsed_sql.length > 0) {
  2847. where = "WHERE " + (parsed_sql.join(' OR ')) + " OR directory IN (" + (new_addresses.join(",")) + ")";
  2848. } else {
  2849. where = "WHERE directory IN (" + (new_addresses.join(",")) + ")";
  2850. }
  2851. query = "SELECT * FROM message\nLEFT JOIN json USING (json_id)\n" + where + "\nORDER BY date_added ASC";
  2852. found = 0;
  2853. return Page.cmd("dbQuery", [query], (function(_this) {
  2854. return function(db_res) {
  2855. var address, aes_keys, encrypted_texts, row;
  2856. if (db_res.length === 0) {
  2857. cb(found);
  2858. return;
  2859. }
  2860. aes_keys = (function() {
  2861. var _ref2, _results;
  2862. _ref2 = this.my_aes_keys;
  2863. _results = [];
  2864. for (address in _ref2) {
  2865. aes_key = _ref2[address];
  2866. _results.push(aes_key);
  2867. }
  2868. return _results;
  2869. }).call(_this);
  2870. encrypted_texts = (function() {
  2871. var _i, _len, _results;
  2872. _results = [];
  2873. for (_i = 0, _len = db_res.length; _i < _len; _i++) {
  2874. row = db_res[_i];
  2875. _results.push(row.encrypted.split(","));
  2876. }
  2877. return _results;
  2878. })();
  2879. return Page.cmd("aesDecrypt", [encrypted_texts, aes_keys], function(decrypted_texts) {
  2880. var db_row, decrypted_text, i, _i, _len, _ref2;
  2881. for (i = _i = 0, _len = decrypted_texts.length; _i < _len; i = ++_i) {
  2882. decrypted_text = decrypted_texts[i];
  2883. db_row = db_res[i];
  2884. if (!parsed_db.my_message[db_row.directory]) {
  2885. parsed_db.my_message[db_row.directory] = [];
  2886. }
  2887. if (decrypted_text && (_ref2 = db_row.date_added, __indexOf.call(parsed_db.my_message[db_row.directory], _ref2) < 0)) {
  2888. parsed_db.my_message[db_row.directory].push(db_row.date_added);
  2889. found += 1;
  2890. }
  2891. parsed_db.last_message[db_row.directory] = db_row.date_added;
  2892. }
  2893. return cb(found);
  2894. });
  2895. };
  2896. })(this));
  2897. };
  2898. MessageListInbox.prototype.loadMessages = function(parsed_db, limit, cb) {
  2899. var address, ids, my_message_ids, query, _ref;
  2900. my_message_ids = [];
  2901. _ref = parsed_db.my_message;
  2902. for (address in _ref) {
  2903. ids = _ref[address];
  2904. my_message_ids = my_message_ids.concat(ids);
  2905. }
  2906. query = "SELECT message.*, json.directory, keyvalue.value AS username FROM message\nLEFT JOIN json USING (json_id)\nLEFT JOIN json AS json_content ON json_content.directory = json.directory AND json_content.file_name = \"content.json\"\nLEFT JOIN keyvalue ON keyvalue.json_id = json_content.json_id AND keyvalue.key = \"cert_user_id\"\nWHERE date_added IN (" + (my_message_ids.join(",")) + ") AND date_added NOT IN (" + (Page.local_storage.deleted.join(",")) + ")\nORDER BY date_added DESC";
  2907. if (limit) {
  2908. query += " LIMIT " + (limit + 1);
  2909. }
  2910. return Page.cmd("dbQuery", [query], (function(_this) {
  2911. return function(db_rows) {
  2912. var aes_key, aes_keys, encrypted_messages, row;
  2913. aes_keys = (function() {
  2914. var _ref1, _results;
  2915. _ref1 = this.my_aes_keys;
  2916. _results = [];
  2917. for (address in _ref1) {
  2918. aes_key = _ref1[address];
  2919. _results.push(aes_key);
  2920. }
  2921. return _results;
  2922. }).call(_this);
  2923. encrypted_messages = (function() {
  2924. var _i, _len, _results;
  2925. _results = [];
  2926. for (_i = 0, _len = db_rows.length; _i < _len; _i++) {
  2927. row = db_rows[_i];
  2928. _results.push(row.encrypted.split(","));
  2929. }
  2930. return _results;
  2931. })();
  2932. return Page.cmd("aesDecrypt", [encrypted_messages, aes_keys], function(decrypted_messages) {
  2933. var db_row, decrypted_message, i, message_row, message_rows, _i, _len;
  2934. message_rows = [];
  2935. for (i = _i = 0, _len = decrypted_messages.length; _i < _len; i = ++_i) {
  2936. decrypted_message = decrypted_messages[i];
  2937. if (!decrypted_message) {
  2938. continue;
  2939. }
  2940. db_row = db_rows[i];
  2941. message_row = Text.jsonDecode(decrypted_message);
  2942. message_row.date_added = db_row.date_added;
  2943. message_row.key = "inbox-" + db_row.directory + "-" + message_row.date_added;
  2944. message_row.message_id = db_row.date_added;
  2945. message_row.from = db_row.username;
  2946. message_row.from_address = db_row.directory;
  2947. message_row.folder = "inbox";
  2948. if (!limit) {
  2949. message_row.disable_animation = true;
  2950. }
  2951. if (i < limit || !limit) {
  2952. message_rows.push(message_row);
  2953. }
  2954. message_rows.push(message_row);
  2955. }
  2956. _this.syncMessages(message_rows);
  2957. _this.has_more = limit && decrypted_messages.length >= limit && !_this.nolimit_loaded;
  2958. Page.projector.scheduleRender();
  2959. return cb(message_rows);
  2960. });
  2961. };
  2962. })(this));
  2963. };
  2964. MessageListInbox.prototype.getMessages = function(mode) {
  2965. var limit;
  2966. if (mode == null) {
  2967. mode = "normal";
  2968. }
  2969. if (mode === "nolimit") {
  2970. limit = null;
  2971. this.nolimit_loaded = true;
  2972. } else {
  2973. limit = 15;
  2974. }
  2975. if (this.reload && Page.site_info) {
  2976. this.loading = true;
  2977. this.reload = false;
  2978. this.logStart("getMessages");
  2979. Page.on_local_storage.then((function(_this) {
  2980. return function() {
  2981. var parsed_db;
  2982. parsed_db = Page.local_storage.parsed;
  2983. _this.setLoadingMessage("Loading known AES keys...");
  2984. return _this.decryptKnownAesKeys(parsed_db, function(loaded_keys) {
  2985. _this.log("Loaded known AES keys");
  2986. _this.setLoadingMessage("Decrypting new secrets...");
  2987. return _this.decryptNewSecrets(parsed_db, function(new_secrets) {
  2988. _this.log("New secrets found");
  2989. if (!isEmpty(new_secrets)) {
  2990. Page.leftbar.reload_contacts = true;
  2991. }
  2992. _this.setLoadingMessage("Decrypting new messages...");
  2993. return _this.decryptNewMessages(parsed_db, new_secrets, function(found) {
  2994. _this.log("New messages found", found);
  2995. _this.setLoadingMessage("Loading messages...");
  2996. if (!found && _this.messages.length > 0 && mode !== "nolimit") {
  2997. _this.logEnd("getMessages", "No new messages in mode " + mode);
  2998. Page.local_storage.parsed = parsed_db;
  2999. _this.loading = false;
  3000. _this.loaded = true;
  3001. return false;
  3002. }
  3003. return _this.loadMessages(parsed_db, limit, function(message_rows) {
  3004. _this.logEnd("getMessages", "Loaded messages in mode " + mode, message_rows.length);
  3005. Page.local_storage.parsed = parsed_db;
  3006. Page.saveLocalStorage();
  3007. _this.loading = false;
  3008. return _this.loaded = true;
  3009. });
  3010. });
  3011. });
  3012. });
  3013. };
  3014. })(this));
  3015. }
  3016. return this.messages;
  3017. };
  3018. MessageListInbox.prototype.deleteMessage = function(message) {
  3019. var _ref;
  3020. MessageListInbox.__super__.deleteMessage.apply(this, arguments);
  3021. if (_ref = message.row.message_id, __indexOf.call(Page.local_storage.deleted, _ref) < 0) {
  3022. return Page.local_storage.deleted.push(message.row.message_id);
  3023. }
  3024. };
  3025. MessageListInbox.prototype.save = function() {
  3026. return Page.saveLocalStorage();
  3027. };
  3028. return MessageListInbox;
  3029. })(MessageList);
  3030. window.MessageListInbox = MessageListInbox;
  3031. }).call(this);
  3032. /* ---- /1MaiL5gfBM1cyb4a8e3iiL8L5gXmoAJu27/js/MessageListSent.coffee ---- */
  3033. (function() {
  3034. var MessageListSent,
  3035. __extends = 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; },
  3036. __hasProp = {}.hasOwnProperty,
  3037. __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; };
  3038. MessageListSent = (function(_super) {
  3039. __extends(MessageListSent, _super);
  3040. function MessageListSent() {
  3041. MessageListSent.__super__.constructor.apply(this, arguments);
  3042. this.reload = true;
  3043. this.loading = false;
  3044. this.nolimit_loaded = false;
  3045. this.cleanup = false;
  3046. this.messages = [];
  3047. this.title = "Sent";
  3048. }
  3049. MessageListSent.prototype.getMessages = function(mode, cb) {
  3050. var limit, query;
  3051. if (mode == null) {
  3052. mode = "normal";
  3053. }
  3054. if (cb == null) {
  3055. cb = null;
  3056. }
  3057. if (mode === "nolimit") {
  3058. limit = null;
  3059. this.nolimit_loaded = true;
  3060. } else {
  3061. limit = 15;
  3062. }
  3063. if (this.reload && Page.site_info && Page.site_info.cert_user_id && !this.loading) {
  3064. this.reload = false;
  3065. this.loading = true;
  3066. query = "SELECT date_added, encrypted\nFROM message\nLEFT JOIN json USING (json_id)\nWHERE ?\nORDER BY date_added DESC";
  3067. if (limit) {
  3068. query += " LIMIT " + (limit + 1);
  3069. }
  3070. Page.cmd("dbQuery", [
  3071. query, {
  3072. "json.directory": Page.site_info.auth_address
  3073. }
  3074. ], (function(_this) {
  3075. return function(db_rows) {
  3076. var encrypted_messages, row;
  3077. encrypted_messages = (function() {
  3078. var _i, _len, _results;
  3079. _results = [];
  3080. for (_i = 0, _len = db_rows.length; _i < _len; _i++) {
  3081. row = db_rows[_i];
  3082. _results.push(row.encrypted.split(","));
  3083. }
  3084. return _results;
  3085. })();
  3086. _this.setLoadingMessage("Decrypting sent secrets...");
  3087. return Page.user.getDecryptedSecretsSent(function(sent_secrets) {
  3088. var address, aes_key, keys;
  3089. keys = (function() {
  3090. var _results;
  3091. _results = [];
  3092. for (address in sent_secrets) {
  3093. aes_key = sent_secrets[address];
  3094. _results.push(aes_key.replace(/.*:/, ""));
  3095. }
  3096. return _results;
  3097. })();
  3098. _this.setLoadingMessage("Decrypting sent messages...");
  3099. return Page.cmd("aesDecrypt", [encrypted_messages, keys], function(decrypted_messages) {
  3100. var decrypted_message, i, message_row, message_rows, usernames, _i, _len, _ref;
  3101. message_rows = [];
  3102. usernames = [];
  3103. for (i = _i = 0, _len = decrypted_messages.length; _i < _len; i = ++_i) {
  3104. decrypted_message = decrypted_messages[i];
  3105. if (!decrypted_message) {
  3106. continue;
  3107. }
  3108. message_row = Text.jsonDecode(decrypted_message);
  3109. message_row.date_added = db_rows[i].date_added;
  3110. message_row.key = "sent-" + message_row.date_added;
  3111. message_row.message_id = db_rows[i].date_added;
  3112. message_row.sender = "Unknown";
  3113. message_row.folder = "sent";
  3114. if (!limit) {
  3115. message_row.disable_animation = true;
  3116. }
  3117. if (i < limit || !limit) {
  3118. message_rows.push(message_row);
  3119. }
  3120. if (_ref = message_row.to, __indexOf.call(usernames, _ref) < 0) {
  3121. usernames.push(message_row.to);
  3122. }
  3123. }
  3124. return Page.users.getAddress(usernames, function(addresses) {
  3125. var _j, _len1;
  3126. for (_j = 0, _len1 = message_rows.length; _j < _len1; _j++) {
  3127. message_row = message_rows[_j];
  3128. message_row.to_address = addresses[message_row.to];
  3129. if (message_row.to_address == null) {
  3130. message_row.to_address = "";
  3131. }
  3132. }
  3133. _this.syncMessages(message_rows);
  3134. _this.has_more = limit && decrypted_messages.length > limit && !_this.nolimit_loaded;
  3135. Page.projector.scheduleRender();
  3136. _this.loading = false;
  3137. _this.loaded = true;
  3138. if (cb) {
  3139. return cb(true);
  3140. }
  3141. });
  3142. });
  3143. });
  3144. };
  3145. })(this));
  3146. } else {
  3147. if (cb) {
  3148. cb(false);
  3149. }
  3150. }
  3151. return this.messages;
  3152. };
  3153. MessageListSent.prototype.cleanupSecretsSent = function(cb) {
  3154. if (this.has_more) {
  3155. this.reload = true;
  3156. }
  3157. return this.getMessages("nolimit", (function(_this) {
  3158. return function() {
  3159. var message_nums;
  3160. message_nums = _this.getMessagesBySender();
  3161. return Page.user.getDecryptedSecretsSent(function(secrets_sent) {
  3162. var address, secret, secret_id;
  3163. for (address in secrets_sent) {
  3164. secret = secrets_sent[address];
  3165. if (message_nums[address]) {
  3166. continue;
  3167. }
  3168. delete secrets_sent[address];
  3169. _this.log("Cleanup sent secret sent", address);
  3170. if (secret.indexOf(":") === -1) {
  3171. continue;
  3172. }
  3173. secret_id = Base64Number.toNumber(secret.replace(/:.*/, ""));
  3174. _this.log("Cleanup secret", address, secret_id);
  3175. delete Page.user.data.secret[secret_id.toString()];
  3176. }
  3177. return Page.cmd("eciesEncrypt", [JSON.stringify(secrets_sent)], function(secrets_sent_encrypted) {
  3178. if (!secrets_sent_encrypted) {
  3179. if (cb) {
  3180. cb();
  3181. }
  3182. return false;
  3183. }
  3184. Page.user.data["secrets_sent"] = secrets_sent_encrypted;
  3185. if (cb) {
  3186. return cb();
  3187. }
  3188. });
  3189. });
  3190. };
  3191. })(this));
  3192. };
  3193. MessageListSent.prototype.getMessagesBySender = function() {
  3194. var message, messages, _i, _len, _name, _ref;
  3195. messages = {};
  3196. _ref = this.messages;
  3197. for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  3198. message = _ref[_i];
  3199. if (messages[_name = message.row.to_address] == null) {
  3200. messages[_name] = [];
  3201. }
  3202. messages[message.row.to_address].push(message);
  3203. }
  3204. return messages;
  3205. };
  3206. MessageListSent.prototype.deleteMessage = function(message) {
  3207. var senders;
  3208. MessageListSent.__super__.deleteMessage.apply(this, arguments);
  3209. delete Page.user.data.message[message.row.message_id];
  3210. if (!this.has_more) {
  3211. senders = this.getMessagesBySender();
  3212. if (!senders[message.row.to_address]) {
  3213. this.log("Removing sent secrets to user", message.row.to);
  3214. return this.cleanup = true;
  3215. }
  3216. }
  3217. };
  3218. MessageListSent.prototype.save = function() {
  3219. if (this.cleanup) {
  3220. this.cleanupSecretsSent((function(_this) {
  3221. return function() {
  3222. return Page.user.saveData().then(function(res) {
  3223. return _this.log("Delete result", res);
  3224. });
  3225. };
  3226. })(this));
  3227. return this.cleanup = false;
  3228. } else {
  3229. return Page.user.saveData().then((function(_this) {
  3230. return function(res) {
  3231. return _this.log("Delete result", res);
  3232. };
  3233. })(this));
  3234. }
  3235. };
  3236. return MessageListSent;
  3237. })(MessageList);
  3238. window.MessageListSent = MessageListSent;
  3239. }).call(this);
  3240. /* ---- /1MaiL5gfBM1cyb4a8e3iiL8L5gXmoAJu27/js/MessageLists.coffee ---- */
  3241. (function() {
  3242. var MessageLists,
  3243. __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
  3244. __extends = 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; },
  3245. __hasProp = {}.hasOwnProperty;
  3246. MessageLists = (function(_super) {
  3247. __extends(MessageLists, _super);
  3248. function MessageLists() {
  3249. this.render = __bind(this.render, this);
  3250. this.inbox = new MessageListInbox(this);
  3251. this.sent = new MessageListSent(this);
  3252. this.active = this.inbox;
  3253. this.message_active = null;
  3254. }
  3255. MessageLists.prototype.getActive = function() {
  3256. return this.active;
  3257. };
  3258. MessageLists.prototype.setActive = function(name) {
  3259. this.active.deselectMessages();
  3260. return this.active = this[name];
  3261. };
  3262. MessageLists.prototype.getActiveMessage = function() {
  3263. return this.getActive().message_active;
  3264. };
  3265. MessageLists.prototype.render = function() {
  3266. return h("div.MessageLists", [this.active.render()]);
  3267. };
  3268. MessageLists.prototype.onSiteInfo = function(site_info) {
  3269. this.sent.reload = true;
  3270. return this.inbox.reload = true;
  3271. };
  3272. return MessageLists;
  3273. })(Class);
  3274. window.MessageLists = MessageLists;
  3275. }).call(this);
  3276. /* ---- /1MaiL5gfBM1cyb4a8e3iiL8L5gXmoAJu27/js/MessageShow.coffee ---- */
  3277. (function() {
  3278. var MessageShow,
  3279. __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
  3280. __extends = 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; },
  3281. __hasProp = {}.hasOwnProperty;
  3282. MessageShow = (function(_super) {
  3283. __extends(MessageShow, _super);
  3284. function MessageShow() {
  3285. this.render = __bind(this.render, this);
  3286. this.message = null;
  3287. }
  3288. MessageShow.prototype.setMessage = function(message) {
  3289. this.message = message;
  3290. return Page.projector.scheduleRender();
  3291. };
  3292. MessageShow.prototype.handleMultiDeleteClick = function() {
  3293. var message, _i, _len, _ref;
  3294. _ref = Page.message_lists.active.selected;
  3295. for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  3296. message = _ref[_i];
  3297. Page.message_lists.active.deleteMessage(message);
  3298. }
  3299. Page.message_lists.active.save();
  3300. Page.message_lists.active.deselectMessages();
  3301. return false;
  3302. };
  3303. MessageShow.prototype.render = function() {
  3304. var _ref;
  3305. console.log("MessageShow render");
  3306. return h("div.MessageShow", [
  3307. Page.site_info && (!Page.site_info.cert_user_id || (!Page.user.publickey && Page.user.inited)) ? start_screen.renderNocert() : Page.message_lists.getActive().selected.length > 0 ? h("div.selected", {
  3308. "enterAnimation": Animation.show
  3309. }, [
  3310. h("a.icon.icon-trash.button-delete", {
  3311. href: "#Delete",
  3312. "title": "Delete messages",
  3313. onclick: this.handleMultiDeleteClick
  3314. }, ["Delete " + (Page.message_lists.getActive().selected.length) + " selected messages"])
  3315. ]) : this.message ? this.message.renderShow() : Page.message_lists.getActive().messages.length > 0 || !Page.message_lists.getActive().loaded ? h("div.empty", {
  3316. "enterAnimation": Animation.show
  3317. }, ["No message selected"]) : ((_ref = Page.site_info) != null ? _ref.cert_user_id : void 0) && Page.user.loaded.result ? start_screen.renderNomessage() : h("div")
  3318. ]);
  3319. };
  3320. return MessageShow;
  3321. })(Class);
  3322. window.MessageShow = MessageShow;
  3323. }).call(this);
  3324. /* ---- /1MaiL5gfBM1cyb4a8e3iiL8L5gXmoAJu27/js/StartScreen.coffee ---- */
  3325. (function() {
  3326. var StartScreen,
  3327. bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
  3328. 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; },
  3329. hasProp = {}.hasOwnProperty;
  3330. StartScreen = (function(superClass) {
  3331. extend(StartScreen, superClass);
  3332. function StartScreen() {
  3333. this.renderNomessage = bind(this.renderNomessage, this);
  3334. this.renderNocert = bind(this.renderNocert, this);
  3335. this.renderBody = bind(this.renderBody, this);
  3336. this;
  3337. }
  3338. StartScreen.prototype.addDots = function(s) {
  3339. return s = ".".repeat(18 - s.length) + s;
  3340. };
  3341. StartScreen.prototype.getTermLines = function() {
  3342. var end_messages, end_publickeys, end_version, lines, percent, server_info, site_info;
  3343. lines = [];
  3344. server_info = Page.server_info;
  3345. site_info = Page.site_info;
  3346. end_version = server_info.version + " r" + server_info.rev;
  3347. if (server_info.rev > 630) {
  3348. end_version += " [OK]";
  3349. } else {
  3350. end_version += " [FAIL]";
  3351. }
  3352. if (site_info.bad_files === 0) {
  3353. end_publickeys = "[DONE]";
  3354. } else {
  3355. if (site_info.workers > 0) {
  3356. percent = Math.round(100 - (site_info.bad_files / site_info.started_task_num) * 100);
  3357. end_publickeys = "[ " + percent + "%]";
  3358. } else {
  3359. end_publickeys = "[BAD:" + site_info.bad_files + "]";
  3360. }
  3361. }
  3362. end_messages = "";
  3363. if (site_info.bad_files === 0) {
  3364. end_messages = "[DONE]";
  3365. } else {
  3366. if (site_info.workers > 0) {
  3367. percent = Math.round(100 - (site_info.bad_files / site_info.started_task_num) * 100);
  3368. end_messages += "[ " + percent + "%]";
  3369. } else {
  3370. end_messages += "[BAD:" + site_info.bad_files + "]";
  3371. }
  3372. }
  3373. lines.push("Checking ZeroNet version......................." + (this.addDots(end_version)));
  3374. lines.push("Checking public keys in database..............." + (this.addDots(end_publickeys)));
  3375. lines.push("Checking messages in database.................." + (this.addDots(end_messages)));
  3376. lines.push("Checking current user's public key in database........[NOT FOUND]");
  3377. return lines.join("\n");
  3378. };
  3379. StartScreen.prototype.handleCertselect = function() {
  3380. Page.cmd("certSelect", [["zeroid.bit"]]);
  3381. return false;
  3382. };
  3383. StartScreen.prototype.handleCreate = function() {
  3384. Page.user.createData();
  3385. return false;
  3386. };
  3387. StartScreen.prototype.renderBody = function(node) {
  3388. return node.innerHTML = Text.renderMarked(node.textContent, {
  3389. "sanitize": true
  3390. });
  3391. };
  3392. StartScreen.prototype.renderNocert = function() {
  3393. this.log("renderNocert");
  3394. return h("div.StartScreen.nocert", {
  3395. "key": "nocert",
  3396. "afterCreate": Animation.addVisibleClass,
  3397. "exitAnimation": Animation.slideUp
  3398. }, [
  3399. h("div.banner.term", {
  3400. "afterCreate": Animation.termLines
  3401. }, ["W E L C O M E T O \n\n" + ($('#banner').textContent) + "\n\n\n"]), Page.server_info && Page.site_info ? h("div.term", {
  3402. "afterCreate": Animation.termLines,
  3403. "delay": 1,
  3404. "delay_step": 0.2
  3405. }, [this.getTermLines()]) : void 0, Page.server_info && Page.site_info ? Page.server_info.rev < 630 ? h("a.button.button-submit.button-certselect.disabled", {
  3406. "href": "#Update",
  3407. "afterCreate": Animation.show,
  3408. "delay": 0,
  3409. "style": "margin-left: -150px"
  3410. }, ["Please update your ZeroNet client!"]) : !Page.site_info.cert_user_id ? h("a.button.button-submit.button-certselect", {
  3411. "key": "certselect",
  3412. "href": "#Select+username",
  3413. "afterCreate": Animation.show,
  3414. "delay": 1,
  3415. onclick: this.handleCertselect
  3416. }, ["Select username"]) : [
  3417. h("div.term", {
  3418. "key": "username-term",
  3419. "afterCreate": Animation.termLines
  3420. }, ["Selected username: " + Page.site_info.cert_user_id + ('.'.repeat(Math.max(22 - Page.site_info.cert_user_id.length, 0))) + "......[NO MAILBOX FOUND]"]), h("a.button.button-submit.button-certselect", {
  3421. "key": "create",
  3422. "href": "#Create+data",
  3423. "afterCreate": Animation.show,
  3424. "delay": 1,
  3425. onclick: this.handleCreate
  3426. }, ["Create my mailbox"])
  3427. ] : void 0
  3428. ]);
  3429. };
  3430. StartScreen.prototype.renderNomessage = function() {
  3431. this.log("renderNomessage");
  3432. return h("div.StartScreen.nomessage", {
  3433. "key": "nomessage",
  3434. "enterAnimation": Animation.slideDown
  3435. }, [
  3436. h("div.subject", ["Successful registration!"]), h("div.from", [
  3437. "From: ", h("a.username", {
  3438. "href": "#"
  3439. }, "zeromail")
  3440. ]), h("div.body", {
  3441. afterCreate: this.renderBody
  3442. }, ["Hello " + (Page.site_info.cert_user_id.replace(/@.*/, "")) + "!\n\nWelcome to the ZeroNet family. From now on anyone is able to message you in a simple and secure way.\n\n_Best regards: The users of ZeroNet_\n\n###### PS: To keep your identity safe don't forget to backup your **data/users.json** file!"])
  3443. ]);
  3444. };
  3445. return StartScreen;
  3446. })(Class);
  3447. window.start_screen = new StartScreen();
  3448. }).call(this);
  3449. /* ---- /1MaiL5gfBM1cyb4a8e3iiL8L5gXmoAJu27/js/User.coffee ---- */
  3450. (function() {
  3451. var User,
  3452. __extends = 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; },
  3453. __hasProp = {}.hasOwnProperty;
  3454. User = (function(_super) {
  3455. __extends(User, _super);
  3456. function User() {
  3457. this.data = null;
  3458. this.publickey = null;
  3459. this.data_size = null;
  3460. this.file_rules = null;
  3461. this.loading = false;
  3462. this.inited = false;
  3463. this.loaded = new Promise();
  3464. this.loaded.then((function(_this) {
  3465. return function(res) {
  3466. _this.loading = false;
  3467. _this.log("Loaded", res);
  3468. return Page.projector.scheduleRender();
  3469. };
  3470. })(this));
  3471. }
  3472. User.prototype.getInnerPath = function(file_name) {
  3473. if (file_name == null) {
  3474. file_name = "data.json";
  3475. }
  3476. return "data/users/" + Page.site_info.auth_address + "/" + file_name;
  3477. };
  3478. User.prototype.getNewIndex = function(node) {
  3479. var i, new_index, _i;
  3480. new_index = Date.now();
  3481. for (i = _i = 0; _i <= 100; i = ++_i) {
  3482. if (!this.data[node][new_index + i]) {
  3483. return new_index + i;
  3484. }
  3485. }
  3486. };
  3487. User.prototype.getDecryptedSecretsSent = function(cb) {
  3488. var _ref;
  3489. if (!((_ref = this.data) != null ? _ref.secrets_sent : void 0)) {
  3490. cb(false);
  3491. return false;
  3492. }
  3493. return Page.cmd("eciesDecrypt", [this.data.secrets_sent], (function(_this) {
  3494. return function(decrypted) {
  3495. if (decrypted) {
  3496. return cb(JSON.parse(decrypted));
  3497. } else {
  3498. return cb(false);
  3499. }
  3500. };
  3501. })(this));
  3502. };
  3503. User.prototype.getPublickey = function(user_address, cb) {
  3504. return Page.cmd("fileGet", {
  3505. "inner_path": "data/users/" + user_address + "/content.json",
  3506. "required": false
  3507. }, (function(_this) {
  3508. return function(res) {
  3509. var data;
  3510. data = JSON.parse(res);
  3511. if (data != null ? data.publickey : void 0) {
  3512. return cb(data.publickey);
  3513. } else {
  3514. return Page.cmd("fileGet", {
  3515. "inner_path": "data/users/" + user_address + "/data.json",
  3516. "required": false
  3517. }, function(res) {
  3518. data = JSON.parse(res);
  3519. if (data != null ? data.publickey : void 0) {
  3520. return cb(data.publickey);
  3521. } else {
  3522. return Page.users.getArchived(function(archived) {
  3523. var _ref;
  3524. return cb((_ref = archived[user_address]) != null ? _ref["publickey"] : void 0);
  3525. });
  3526. }
  3527. });
  3528. }
  3529. };
  3530. })(this));
  3531. };
  3532. User.prototype.addSecret = function(secrets_sent, user_address, cb) {
  3533. return this.getPublickey(user_address, (function(_this) {
  3534. return function(publickey) {
  3535. if (!publickey) {
  3536. cb(false);
  3537. return Page.cmd("wrapperNotification", ["error", "No publickey for user " + user_address]);
  3538. }
  3539. return Page.cmd("aesEncrypt", [""], function(res) {
  3540. var encrypted, iv, key;
  3541. key = res[0], iv = res[1], encrypted = res[2];
  3542. return Page.cmd("eciesEncrypt", [key, publickey], function(secret) {
  3543. var secret_index;
  3544. secret_index = _this.getNewIndex("secret");
  3545. _this.data.secret[secret_index] = secret;
  3546. secrets_sent[user_address] = Base64Number.fromNumber(secret_index) + ":" + key;
  3547. return Page.cmd("eciesEncrypt", [JSON.stringify(secrets_sent)], function(secrets_sent_encrypted) {
  3548. if (!secrets_sent_encrypted) {
  3549. return cb(false);
  3550. }
  3551. _this.data["secrets_sent"] = secrets_sent_encrypted;
  3552. return cb(key);
  3553. });
  3554. });
  3555. });
  3556. };
  3557. })(this));
  3558. };
  3559. User.prototype.getSecret = function(user_address, cb) {
  3560. return this.getDecryptedSecretsSent((function(_this) {
  3561. return function(secrets_sent) {
  3562. if (!secrets_sent) {
  3563. secrets_sent = {};
  3564. }
  3565. if (secrets_sent[user_address]) {
  3566. return cb(secrets_sent[user_address].replace(/.*:/, ""));
  3567. } else {
  3568. _this.log("Creating new secret for " + user_address);
  3569. return _this.addSecret(secrets_sent, user_address, function(aes_key) {
  3570. return cb(aes_key);
  3571. });
  3572. }
  3573. };
  3574. })(this));
  3575. };
  3576. User.prototype.loadData = function(cb) {
  3577. var inner_path;
  3578. inner_path = this.getInnerPath();
  3579. this.log("Loading user file", inner_path);
  3580. return Page.cmd("fileGet", {
  3581. "inner_path": inner_path,
  3582. "required": false
  3583. }, (function(_this) {
  3584. return function(get_res) {
  3585. if (get_res) {
  3586. _this.data_size = get_res.length;
  3587. _this.data = JSON.parse(get_res);
  3588. _this.publickey = _this.data.publickey;
  3589. _this.loaded.resolve();
  3590. if (cb) {
  3591. cb(true);
  3592. }
  3593. _this.inited = true;
  3594. return Page.projector.scheduleRender();
  3595. } else {
  3596. return _this.getPublickey(Page.site_info.auth_address, function(get_res) {
  3597. if (get_res) {
  3598. _this.publickey = get_res;
  3599. }
  3600. _this.data = {
  3601. "secret": {},
  3602. "secrets_sent": "",
  3603. "publickey": _this.publickey,
  3604. "message": {},
  3605. "date_added": Date.now()
  3606. };
  3607. _this.loaded.resolve();
  3608. _this.inited = true;
  3609. if (cb) {
  3610. cb(false);
  3611. }
  3612. return Page.projector.scheduleRender();
  3613. });
  3614. }
  3615. };
  3616. })(this));
  3617. };
  3618. User.prototype.createData = function() {
  3619. var inner_path;
  3620. inner_path = this.getInnerPath();
  3621. this.log("Creating user file", inner_path);
  3622. this.data = {
  3623. "secret": {},
  3624. "secrets_sent": "",
  3625. "publickey": null,
  3626. "message": {},
  3627. "date_added": Date.now()
  3628. };
  3629. return Page.cmd("userPublickey", [], (function(_this) {
  3630. return function(publickey_res) {
  3631. if (publickey_res.error) {
  3632. Page.cmd("wrapperNotification", ["error", "Publickey read error: " + publickey_res.error]);
  3633. return _this.loaded.fail();
  3634. } else {
  3635. _this.data.publickey = publickey_res;
  3636. return _this.saveData().then(function(save_res) {
  3637. return _this.loaded.resolve(save_res);
  3638. });
  3639. }
  3640. };
  3641. })(this));
  3642. };
  3643. User.prototype.saveData = function(publish) {
  3644. var inner_path, promise;
  3645. if (publish == null) {
  3646. publish = true;
  3647. }
  3648. promise = new Promise();
  3649. inner_path = this.getInnerPath();
  3650. this.data_size = Text.fileEncode(this.data).length;
  3651. Page.cmd("fileWrite", [inner_path, Text.fileEncode(this.data)], (function(_this) {
  3652. return function(write_res) {
  3653. if (write_res !== "ok") {
  3654. Page.cmd("wrapperNotification", ["error", "File write error: " + write_res]);
  3655. promise.fail();
  3656. return false;
  3657. }
  3658. return Page.cmd("sitePublish", {
  3659. "inner_path": inner_path
  3660. }, function(publish_res) {
  3661. if (publish_res === "ok") {
  3662. Page.message_lists.sent.reload = true;
  3663. Page.projector.scheduleRender();
  3664. return promise.resolve();
  3665. } else {
  3666. return promise.resolve();
  3667. }
  3668. });
  3669. };
  3670. })(this));
  3671. return promise;
  3672. };
  3673. User.prototype.formatQuota = function() {
  3674. if (!this.file_rules) {
  3675. if (Page.site_info) {
  3676. this.file_rules = {};
  3677. Page.cmd("fileRules", this.getInnerPath(), (function(_this) {
  3678. return function(res) {
  3679. return _this.file_rules = res;
  3680. };
  3681. })(this));
  3682. }
  3683. return " ";
  3684. } else {
  3685. if (this.file_rules.max_size) {
  3686. return (parseInt(this.data_size / 1024 + 1)) + "k/" + (parseInt(this.file_rules.max_size / 1024)) + "k";
  3687. } else {
  3688. return " ";
  3689. }
  3690. }
  3691. };
  3692. User.prototype.onSiteInfo = function(site_info) {
  3693. var _ref;
  3694. if (!this.loading && site_info.event && site_info.event[0] === "file_done" && site_info.event[1] === this.getInnerPath()) {
  3695. this.loadData();
  3696. }
  3697. if (!this.data && !this.loading && site_info.cert_user_id && (!site_info.event || ((_ref = site_info.event) != null ? _ref[0] : void 0) === "cert_changed")) {
  3698. this.loadData();
  3699. }
  3700. if (!site_info.cert_user_id) {
  3701. return this.data = null;
  3702. }
  3703. };
  3704. return User;
  3705. })(Class);
  3706. window.User = User;
  3707. }).call(this);
  3708. /* ---- /1MaiL5gfBM1cyb4a8e3iiL8L5gXmoAJu27/js/Users.coffee ---- */
  3709. (function() {
  3710. var Users,
  3711. __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
  3712. __extends = 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; },
  3713. __hasProp = {}.hasOwnProperty,
  3714. __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; };
  3715. Users = (function(_super) {
  3716. __extends(Users, _super);
  3717. function Users() {
  3718. this.getUsernames = __bind(this.getUsernames, this);
  3719. this.getArchived = __bind(this.getArchived, this);
  3720. this.user_address = {};
  3721. this.archived = null;
  3722. }
  3723. Users.prototype.getArchived = function(cb) {
  3724. if (this.archived) {
  3725. return cb(this.archived);
  3726. }
  3727. return Page.cmd("fileGet", "data/archived.json", (function(_this) {
  3728. return function(res) {
  3729. _this.archived = JSON.parse(res);
  3730. return cb(_this.archived);
  3731. };
  3732. })(this));
  3733. };
  3734. Users.prototype.getUsernames = function(addresses, cb) {
  3735. var query;
  3736. query = "SELECT directory, value AS cert_user_id\nFROM json\nLEFT JOIN keyvalue USING (json_id)\nWHERE ? AND file_name = 'content.json' AND key = 'cert_user_id'";
  3737. return Page.cmd("dbQuery", [
  3738. query, {
  3739. directory: addresses
  3740. }
  3741. ], (function(_this) {
  3742. return function(rows) {
  3743. var row, usernames, _i, _len;
  3744. usernames = {};
  3745. for (_i = 0, _len = rows.length; _i < _len; _i++) {
  3746. row = rows[_i];
  3747. usernames[row.directory] = row.cert_user_id;
  3748. _this.user_address[row.cert_user_id] = row.directory;
  3749. }
  3750. if (rows.length === addresses.length) {
  3751. cb(usernames);
  3752. return;
  3753. }
  3754. _this.log("Not found all username in sql, try to find in archived file");
  3755. return _this.getArchived(function(archived) {
  3756. var auth_address;
  3757. for (auth_address in archived) {
  3758. row = archived[auth_address];
  3759. _this.user_address[row.cert_user_id] = auth_address;
  3760. if (__indexOf.call(addresses, auth_address) >= 0) {
  3761. if (usernames[auth_address] == null) {
  3762. usernames[auth_address] = row.cert_user_id;
  3763. }
  3764. }
  3765. }
  3766. return cb(usernames);
  3767. });
  3768. };
  3769. })(this));
  3770. };
  3771. Users.prototype.getAddress = function(usernames, cb) {
  3772. var query, unknown_address, username;
  3773. unknown_address = (function() {
  3774. var _i, _len, _results;
  3775. _results = [];
  3776. for (_i = 0, _len = usernames.length; _i < _len; _i++) {
  3777. username = usernames[_i];
  3778. if (this.user_address[username] == null) {
  3779. _results.push(username);
  3780. }
  3781. }
  3782. return _results;
  3783. }).call(this);
  3784. if (unknown_address.length === 0) {
  3785. cb(this.user_address);
  3786. return;
  3787. }
  3788. query = "SELECT value, directory\nFROM keyvalue\nLEFT JOIN json USING (json_id)\nWHERE ?";
  3789. return Page.cmd("dbQuery", [
  3790. query, {
  3791. "key": "cert_user_id",
  3792. "value": unknown_address
  3793. }
  3794. ], (function(_this) {
  3795. return function(rows) {
  3796. var row, _i, _len;
  3797. for (_i = 0, _len = rows.length; _i < _len; _i++) {
  3798. row = rows[_i];
  3799. _this.user_address[row.value] = row.directory;
  3800. }
  3801. return cb(_this.user_address);
  3802. };
  3803. })(this));
  3804. };
  3805. Users.prototype.getAll = function(cb) {
  3806. return Page.cmd("dbQuery", ["SELECT value, directory FROM keyvalue LEFT JOIN json USING (json_id) WHERE key = 'cert_user_id'"], (function(_this) {
  3807. return function(rows) {
  3808. var row, _i, _len;
  3809. if (rows.error) {
  3810. return false;
  3811. }
  3812. _this.user_address = {};
  3813. for (_i = 0, _len = rows.length; _i < _len; _i++) {
  3814. row = rows[_i];
  3815. _this.user_address[row.value] = row.directory;
  3816. }
  3817. return _this.getArchived(function(archived) {
  3818. var auth_address;
  3819. for (auth_address in archived) {
  3820. row = archived[auth_address];
  3821. _this.user_address[row.cert_user_id] = auth_address;
  3822. }
  3823. return cb(_this.user_address);
  3824. });
  3825. };
  3826. })(this));
  3827. };
  3828. return Users;
  3829. })(Class);
  3830. window.Users = Users;
  3831. }).call(this);
  3832. /* ---- /1MaiL5gfBM1cyb4a8e3iiL8L5gXmoAJu27/js/ZeroMail.coffee ---- */
  3833. (function() {
  3834. var ZeroMail,
  3835. __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
  3836. __extends = 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; },
  3837. __hasProp = {}.hasOwnProperty;
  3838. window.h = maquette.h;
  3839. ZeroMail = (function(_super) {
  3840. __extends(ZeroMail, _super);
  3841. function ZeroMail() {
  3842. this.onOpenWebsocket = __bind(this.onOpenWebsocket, this);
  3843. return ZeroMail.__super__.constructor.apply(this, arguments);
  3844. }
  3845. ZeroMail.prototype.init = function() {
  3846. this.params = {};
  3847. this.site_info = null;
  3848. this.on_site_info = new Promise();
  3849. this.on_local_storage = new Promise();
  3850. this.server_info = null;
  3851. this.user = new User();
  3852. this.users = new Users();
  3853. return this.local_storage = null;
  3854. };
  3855. ZeroMail.prototype.createProjector = function() {
  3856. this.leftbar = new Leftbar();
  3857. this.message_lists = new MessageLists();
  3858. this.message_show = new MessageShow();
  3859. this.message_create = new MessageCreate();
  3860. this.projector = maquette.createProjector();
  3861. if (base.href.indexOf("?") === -1) {
  3862. this.route("");
  3863. } else {
  3864. this.route(base.href.replace(/.*?\?/, ""));
  3865. }
  3866. this.projector.replace($("#MessageLists"), this.message_lists.render);
  3867. this.projector.replace($("#MessageShow"), this.message_show.render);
  3868. this.projector.replace($("#Leftbar"), this.leftbar.render);
  3869. this.projector.merge($("#MessageCreate"), this.message_create.render);
  3870. return setInterval((function() {
  3871. return Page.projector.scheduleRender();
  3872. }), 60 * 1000);
  3873. };
  3874. ZeroMail.prototype.route = function(query) {
  3875. this.params = Text.parseQuery(query);
  3876. this.log("Route", this.params);
  3877. if (this.params.to) {
  3878. this.on_site_info.then((function(_this) {
  3879. return function() {
  3880. return _this.message_create.show(_this.params.to);
  3881. };
  3882. })(this));
  3883. this.cmd("wrapperReplaceState", [{}, "", this.createUrl("to", "")]);
  3884. }
  3885. if (this.params.url === "Sent") {
  3886. return this.message_lists.setActive("sent");
  3887. }
  3888. };
  3889. ZeroMail.prototype.createUrl = function(key, val) {
  3890. var params, vals;
  3891. params = JSON.parse(JSON.stringify(this.params));
  3892. if (typeof key === "Object") {
  3893. vals = key;
  3894. for (key in keys) {
  3895. val = keys[key];
  3896. params[key] = val;
  3897. }
  3898. } else {
  3899. params[key] = val;
  3900. }
  3901. return "?" + Text.encodeQuery(params);
  3902. };
  3903. ZeroMail.prototype.getLocalStorage = function() {
  3904. return this.on_site_info.then((function(_this) {
  3905. return function() {
  3906. return _this.cmd("wrapperGetLocalStorage", [], function(_at_local_storage) {
  3907. var _base, _base1, _base2, _base3, _base4, _base5, _base6;
  3908. _this.local_storage = _at_local_storage;
  3909. if (_this.local_storage == null) {
  3910. _this.local_storage = {};
  3911. }
  3912. if ((_base = _this.local_storage).read == null) {
  3913. _base.read = {};
  3914. }
  3915. if ((_base1 = _this.local_storage).deleted == null) {
  3916. _base1.deleted = [];
  3917. }
  3918. if ((_base2 = _this.local_storage).parsed == null) {
  3919. _base2.parsed = {};
  3920. }
  3921. if ((_this.local_storage.parsed.version != null) < 1) {
  3922. _this.local_storage.parsed = {
  3923. "version": 1
  3924. };
  3925. console.log("Reindexing...");
  3926. }
  3927. if ((_base3 = _this.local_storage.parsed).last_secret == null) {
  3928. _base3.last_secret = {};
  3929. }
  3930. if ((_base4 = _this.local_storage.parsed).last_message == null) {
  3931. _base4.last_message = {};
  3932. }
  3933. if ((_base5 = _this.local_storage.parsed).my_secret == null) {
  3934. _base5.my_secret = {};
  3935. }
  3936. if ((_base6 = _this.local_storage.parsed).my_message == null) {
  3937. _base6.my_message = {};
  3938. }
  3939. return _this.on_local_storage.resolve(_this.local_storage);
  3940. });
  3941. };
  3942. })(this));
  3943. };
  3944. ZeroMail.prototype.saveLocalStorage = function(cb) {
  3945. if (this.local_storage) {
  3946. return this.cmd("wrapperSetLocalStorage", this.local_storage, (function(_this) {
  3947. return function(res) {
  3948. if (cb) {
  3949. return cb(res);
  3950. }
  3951. };
  3952. })(this));
  3953. }
  3954. };
  3955. ZeroMail.prototype.onOpenWebsocket = function(e) {
  3956. this.cmd("siteInfo", {}, (function(_this) {
  3957. return function(site_info) {
  3958. return _this.setSiteInfo(site_info);
  3959. };
  3960. })(this));
  3961. return this.cmd("serverInfo", {}, (function(_this) {
  3962. return function(server_info) {
  3963. return _this.setServerInfo(server_info);
  3964. };
  3965. })(this));
  3966. };
  3967. ZeroMail.prototype.onRequest = function(cmd, params) {
  3968. if (cmd === "setSiteInfo") {
  3969. return this.setSiteInfo(params);
  3970. } else {
  3971. return this.log("Unknown command", params);
  3972. }
  3973. };
  3974. ZeroMail.prototype.setSiteInfo = function(site_info) {
  3975. var limit_interval, _ref;
  3976. this.site_info = site_info;
  3977. if (((_ref = site_info.event) != null ? _ref[0] : void 0) === "cert_changed") {
  3978. this.getLocalStorage();
  3979. }
  3980. if (site_info.tasks > 20) {
  3981. limit_interval = 60000;
  3982. } else {
  3983. limit_interval = 6000;
  3984. }
  3985. RateLimit(limit_interval, (function(_this) {
  3986. return function() {
  3987. _this.log("onSiteInfo RateLimit");
  3988. _this.leftbar.onSiteInfo(site_info);
  3989. _this.user.onSiteInfo(site_info);
  3990. _this.message_create.onSiteInfo(site_info);
  3991. return _this.message_lists.onSiteInfo(site_info);
  3992. };
  3993. })(this));
  3994. this.projector.scheduleRender();
  3995. this.getLocalStorage();
  3996. return this.on_site_info.resolve();
  3997. };
  3998. ZeroMail.prototype.setServerInfo = function(server_info) {
  3999. this.server_info = server_info;
  4000. return this.projector.scheduleRender();
  4001. };
  4002. return ZeroMail;
  4003. })(ZeroFrame);
  4004. window.Page = new ZeroMail();
  4005. window.Page.createProjector();
  4006. }).call(this);