123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374moduletypeDECODER=sigtype_tvalreturn:'msg->'msgtvalfloat:floattvalint:inttvalstring:stringtvalbool:booltvalfield:string->'msgt->'msgtvalmap:('a->'b)->'at->'btendmoduletypeENCODER=sigtypetvalstring:string->tvalbool:bool->tvalobject_:(string*t)list->tendmoduletypeWEB_APPLICATION=sigtype_decodertypeencodermoduleAttribute:sigtype'msgt=|Styleofstring*string|Attributeofstring*string|Propertyofstring*encoder|Onofstring*'msgdecoderendmoduleDom:sigtype'msgt=|Textofstring|Nodeofstring*'msgAttribute.tlist*'msgtlistendmoduleCommand:sigtype'msgt=|None|Batchof'msgtlist|Httpofstring(* type: GET, POST, ... *)*string(* url *)*string(* data to be sent with the request *)*((string,int)result->'msg)(* response text or status e.g. 404 for not found *)endmoduleSubscription:sigtype'msgt=|None|Batchof'msgtlist|Rootofstring*'msgdecoder(* events on the root element *)endendmoduletypeBROWSER=sigmoduleDecoder:DECODERmoduleEncoder:ENCODERmoduleMake:functor(Vapp:WEB_APPLICATIONwithtype'msgdecoder='msgDecoder.tandtypeencoder=Encoder.t)->sigvalsandbox:'model->('model->'msgVapp.Dom.t)->('msg->'model->'model)->unitvalelement:'aDecoder.t->('a->'model*'msgVapp.Command.t)->('model->'msgVapp.Dom.t)->('msg->'model->'model*'msgVapp.Command.t)->('model->'msgVapp.Subscription.t)->unitendendmoduleMake(Browser:BROWSER)=structmoduleDecoder=Browser.DecodermoduleEncoder=Browser.Encodertype'msgdecoder='msgDecoder.ttypeencoder=Encoder.tmoduleAttribute=structtype'msgt=|Styleofstring*string|Attributeofstring*string|Propertyofstring*encoder|Onofstring*'msgdecoderletstyle(name:string)(value:string):'msgt=Style(name,value)letattribute(name:string)(value:string):'msgt=Attribute(name,value)letproperty(name:string)(value:encoder):'msgt=Property(name,value)leton(name:string)(handler:'msgdecoder):'msgt=On(name,handler)letstring_property(name:string)(value:string):'msgt=propertyname(Encoder.stringvalue)letbool_property(name:string)(value:bool):'msgt=propertyname(Encoder.boolvalue)letplaceholder(value:string):'msgt=attribute"placeholder"valueletvalue(value:string):'msgt=string_property"value"valueletchecked(value:bool):'msgt=bool_property"checked"valuelettype_(value:string):'msgt=attribute"type"valueletclass_(value:string):'msgt=attribute"class"valueletonClick(msg:'msg):'msgt=on"click"(Decoder.returnmsg)letonDoubleClick(msg:'msg):'msgt=on"doubleclick"(Decoder.returnmsg)letonMouseDown(msg:'msg):'msgt=on"mousedown"(Decoder.returnmsg)letonMouseUp(msg:'msg):'msgt=on"mouseup"(Decoder.returnmsg)letonMouseEnter(msg:'msg):'msgt=on"mouseenter"(Decoder.returnmsg)letonMouseLeave(msg:'msg):'msgt=on"mouseleave"(Decoder.returnmsg)letonMouseOver(msg:'msg):'msgt=on"mouseover"(Decoder.returnmsg)letonMouseOut(msg:'msg):'msgt=on"mouseout"(Decoder.returnmsg)letonKeyDown(f:string->'msg):'msgt=on"keydown"Decoder.(mapf(field"key"string))letonKeyUp(f:string->'msg):'msgt=on"keyup"Decoder.(mapf(field"key"string))letonInput(f:string->'msg):'msgt=on"input"Decoder.(field"target"(mapf(field"value"string)))letonCheck(f:bool->'msg):'msgt=on"click"Decoder.(field"target"(mapf(field"checked"bool)))endmoduleDom=structtype'msgt=|Textofstring|Nodeofstring*'msgAttribute.tlist*'msgtlisttype'msgattributes='msgAttribute.tlisttype'msgchildren='msgtlistlettext(s:string):'msgt=Textsletnode(tag:string)(attrs:'msgattributes)(children:'msgchildren):'msgt=Node(tag,attrs,children)letdiv(attrs:'msgattributes)(children:'msgchildren):'msgt=node"div"attrschildrenletspan(attrs:'msgattributes)(children:'msgchildren):'msgt=node"span"attrschildrenletpre(attrs:'msgattributes)(children:'msgchildren):'msgt=node"pre"attrschildrenletp(attrs:'msgattributes)(children:'msgchildren):'msgt=node"p"attrschildrenletol(attrs:'msgattributes)(children:'msgchildren):'msgt=node"ol"attrschildrenletul(attrs:'msgattributes)(children:'msgchildren):'msgt=node"ul"attrschildrenletli(attrs:'msgattributes)(children:'msgchildren):'msgt=node"li"attrschildrenleth1(attrs:'msgattributes)(children:'msgchildren):'msgt=node"h1"attrschildrenleth2(attrs:'msgattributes)(children:'msgchildren):'msgt=node"h2"attrschildrenleth3(attrs:'msgattributes)(children:'msgchildren):'msgt=node"h3"attrschildrenleth4(attrs:'msgattributes)(children:'msgchildren):'msgt=node"h4"attrschildrenleth5(attrs:'msgattributes)(children:'msgchildren):'msgt=node"h5"attrschildrenleth6(attrs:'msgattributes)(children:'msgchildren):'msgt=node"h6"attrschildrenletb(attrs:'msgattributes)(children:'msgchildren):'msgt=node"b"attrschildrenleti(attrs:'msgattributes)(children:'msgchildren):'msgt=node"i"attrschildrenletstrong(attrs:'msgattributes)(children:'msgchildren):'msgt=node"strong"attrschildrenletbutton(attrs:'msgattributes)(children:'msgchildren):'msgt=node"button"attrschildrenletinput(attrs:'msgattributes)(children:'msgchildren):'msgt=node"input"attrschildrenlettextarea(attrs:'msgattributes)(children:'msgchildren):'msgt=node"textarea"attrschildrenendmoduleCommand=structtype'msgt=|None|Batchof'msgtlist|Httpofstring(* type: GET, POST, ... *)*string(* url *)*string(* data to be sent with the request *)*((string,int)result->'msg)(* response text or status e.g. 404 for not found *)lethttp_get(url:string)(handler:(string,int)result->'msg):'msgt=Http("GET",url,"",handler)endmoduleSubscription=structtype'msgt=|None|Batchof'msgtlist|Rootofstring*'msgdecoder(* events on the root element *)endend