model.js 287 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040
  1. /**
  2. * TinyMCE version 6.8.6 (TBD)
  3. */
  4. (function () {
  5. 'use strict';
  6. var global$1 = tinymce.util.Tools.resolve('tinymce.ModelManager');
  7. const hasProto = (v, constructor, predicate) => {
  8. var _a;
  9. if (predicate(v, constructor.prototype)) {
  10. return true;
  11. } else {
  12. return ((_a = v.constructor) === null || _a === void 0 ? void 0 : _a.name) === constructor.name;
  13. }
  14. };
  15. const typeOf = x => {
  16. const t = typeof x;
  17. if (x === null) {
  18. return 'null';
  19. } else if (t === 'object' && Array.isArray(x)) {
  20. return 'array';
  21. } else if (t === 'object' && hasProto(x, String, (o, proto) => proto.isPrototypeOf(o))) {
  22. return 'string';
  23. } else {
  24. return t;
  25. }
  26. };
  27. const isType$1 = type => value => typeOf(value) === type;
  28. const isSimpleType = type => value => typeof value === type;
  29. const eq$2 = t => a => t === a;
  30. const isString = isType$1('string');
  31. const isObject = isType$1('object');
  32. const isArray = isType$1('array');
  33. const isNull = eq$2(null);
  34. const isBoolean = isSimpleType('boolean');
  35. const isUndefined = eq$2(undefined);
  36. const isNullable = a => a === null || a === undefined;
  37. const isNonNullable = a => !isNullable(a);
  38. const isFunction = isSimpleType('function');
  39. const isNumber = isSimpleType('number');
  40. const noop = () => {
  41. };
  42. const compose = (fa, fb) => {
  43. return (...args) => {
  44. return fa(fb.apply(null, args));
  45. };
  46. };
  47. const compose1 = (fbc, fab) => a => fbc(fab(a));
  48. const constant = value => {
  49. return () => {
  50. return value;
  51. };
  52. };
  53. const identity = x => {
  54. return x;
  55. };
  56. const tripleEquals = (a, b) => {
  57. return a === b;
  58. };
  59. function curry(fn, ...initialArgs) {
  60. return (...restArgs) => {
  61. const all = initialArgs.concat(restArgs);
  62. return fn.apply(null, all);
  63. };
  64. }
  65. const not = f => t => !f(t);
  66. const die = msg => {
  67. return () => {
  68. throw new Error(msg);
  69. };
  70. };
  71. const apply = f => {
  72. return f();
  73. };
  74. const never = constant(false);
  75. const always = constant(true);
  76. class Optional {
  77. constructor(tag, value) {
  78. this.tag = tag;
  79. this.value = value;
  80. }
  81. static some(value) {
  82. return new Optional(true, value);
  83. }
  84. static none() {
  85. return Optional.singletonNone;
  86. }
  87. fold(onNone, onSome) {
  88. if (this.tag) {
  89. return onSome(this.value);
  90. } else {
  91. return onNone();
  92. }
  93. }
  94. isSome() {
  95. return this.tag;
  96. }
  97. isNone() {
  98. return !this.tag;
  99. }
  100. map(mapper) {
  101. if (this.tag) {
  102. return Optional.some(mapper(this.value));
  103. } else {
  104. return Optional.none();
  105. }
  106. }
  107. bind(binder) {
  108. if (this.tag) {
  109. return binder(this.value);
  110. } else {
  111. return Optional.none();
  112. }
  113. }
  114. exists(predicate) {
  115. return this.tag && predicate(this.value);
  116. }
  117. forall(predicate) {
  118. return !this.tag || predicate(this.value);
  119. }
  120. filter(predicate) {
  121. if (!this.tag || predicate(this.value)) {
  122. return this;
  123. } else {
  124. return Optional.none();
  125. }
  126. }
  127. getOr(replacement) {
  128. return this.tag ? this.value : replacement;
  129. }
  130. or(replacement) {
  131. return this.tag ? this : replacement;
  132. }
  133. getOrThunk(thunk) {
  134. return this.tag ? this.value : thunk();
  135. }
  136. orThunk(thunk) {
  137. return this.tag ? this : thunk();
  138. }
  139. getOrDie(message) {
  140. if (!this.tag) {
  141. throw new Error(message !== null && message !== void 0 ? message : 'Called getOrDie on None');
  142. } else {
  143. return this.value;
  144. }
  145. }
  146. static from(value) {
  147. return isNonNullable(value) ? Optional.some(value) : Optional.none();
  148. }
  149. getOrNull() {
  150. return this.tag ? this.value : null;
  151. }
  152. getOrUndefined() {
  153. return this.value;
  154. }
  155. each(worker) {
  156. if (this.tag) {
  157. worker(this.value);
  158. }
  159. }
  160. toArray() {
  161. return this.tag ? [this.value] : [];
  162. }
  163. toString() {
  164. return this.tag ? `some(${ this.value })` : 'none()';
  165. }
  166. }
  167. Optional.singletonNone = new Optional(false);
  168. const nativeSlice = Array.prototype.slice;
  169. const nativeIndexOf = Array.prototype.indexOf;
  170. const nativePush = Array.prototype.push;
  171. const rawIndexOf = (ts, t) => nativeIndexOf.call(ts, t);
  172. const contains$2 = (xs, x) => rawIndexOf(xs, x) > -1;
  173. const exists = (xs, pred) => {
  174. for (let i = 0, len = xs.length; i < len; i++) {
  175. const x = xs[i];
  176. if (pred(x, i)) {
  177. return true;
  178. }
  179. }
  180. return false;
  181. };
  182. const range$1 = (num, f) => {
  183. const r = [];
  184. for (let i = 0; i < num; i++) {
  185. r.push(f(i));
  186. }
  187. return r;
  188. };
  189. const map$1 = (xs, f) => {
  190. const len = xs.length;
  191. const r = new Array(len);
  192. for (let i = 0; i < len; i++) {
  193. const x = xs[i];
  194. r[i] = f(x, i);
  195. }
  196. return r;
  197. };
  198. const each$2 = (xs, f) => {
  199. for (let i = 0, len = xs.length; i < len; i++) {
  200. const x = xs[i];
  201. f(x, i);
  202. }
  203. };
  204. const eachr = (xs, f) => {
  205. for (let i = xs.length - 1; i >= 0; i--) {
  206. const x = xs[i];
  207. f(x, i);
  208. }
  209. };
  210. const partition = (xs, pred) => {
  211. const pass = [];
  212. const fail = [];
  213. for (let i = 0, len = xs.length; i < len; i++) {
  214. const x = xs[i];
  215. const arr = pred(x, i) ? pass : fail;
  216. arr.push(x);
  217. }
  218. return {
  219. pass,
  220. fail
  221. };
  222. };
  223. const filter$2 = (xs, pred) => {
  224. const r = [];
  225. for (let i = 0, len = xs.length; i < len; i++) {
  226. const x = xs[i];
  227. if (pred(x, i)) {
  228. r.push(x);
  229. }
  230. }
  231. return r;
  232. };
  233. const foldr = (xs, f, acc) => {
  234. eachr(xs, (x, i) => {
  235. acc = f(acc, x, i);
  236. });
  237. return acc;
  238. };
  239. const foldl = (xs, f, acc) => {
  240. each$2(xs, (x, i) => {
  241. acc = f(acc, x, i);
  242. });
  243. return acc;
  244. };
  245. const findUntil = (xs, pred, until) => {
  246. for (let i = 0, len = xs.length; i < len; i++) {
  247. const x = xs[i];
  248. if (pred(x, i)) {
  249. return Optional.some(x);
  250. } else if (until(x, i)) {
  251. break;
  252. }
  253. }
  254. return Optional.none();
  255. };
  256. const find$1 = (xs, pred) => {
  257. return findUntil(xs, pred, never);
  258. };
  259. const findIndex = (xs, pred) => {
  260. for (let i = 0, len = xs.length; i < len; i++) {
  261. const x = xs[i];
  262. if (pred(x, i)) {
  263. return Optional.some(i);
  264. }
  265. }
  266. return Optional.none();
  267. };
  268. const flatten = xs => {
  269. const r = [];
  270. for (let i = 0, len = xs.length; i < len; ++i) {
  271. if (!isArray(xs[i])) {
  272. throw new Error('Arr.flatten item ' + i + ' was not an array, input: ' + xs);
  273. }
  274. nativePush.apply(r, xs[i]);
  275. }
  276. return r;
  277. };
  278. const bind$2 = (xs, f) => flatten(map$1(xs, f));
  279. const forall = (xs, pred) => {
  280. for (let i = 0, len = xs.length; i < len; ++i) {
  281. const x = xs[i];
  282. if (pred(x, i) !== true) {
  283. return false;
  284. }
  285. }
  286. return true;
  287. };
  288. const reverse = xs => {
  289. const r = nativeSlice.call(xs, 0);
  290. r.reverse();
  291. return r;
  292. };
  293. const mapToObject = (xs, f) => {
  294. const r = {};
  295. for (let i = 0, len = xs.length; i < len; i++) {
  296. const x = xs[i];
  297. r[String(x)] = f(x, i);
  298. }
  299. return r;
  300. };
  301. const sort$1 = (xs, comparator) => {
  302. const copy = nativeSlice.call(xs, 0);
  303. copy.sort(comparator);
  304. return copy;
  305. };
  306. const get$d = (xs, i) => i >= 0 && i < xs.length ? Optional.some(xs[i]) : Optional.none();
  307. const head = xs => get$d(xs, 0);
  308. const last$2 = xs => get$d(xs, xs.length - 1);
  309. const findMap = (arr, f) => {
  310. for (let i = 0; i < arr.length; i++) {
  311. const r = f(arr[i], i);
  312. if (r.isSome()) {
  313. return r;
  314. }
  315. }
  316. return Optional.none();
  317. };
  318. const keys = Object.keys;
  319. const hasOwnProperty = Object.hasOwnProperty;
  320. const each$1 = (obj, f) => {
  321. const props = keys(obj);
  322. for (let k = 0, len = props.length; k < len; k++) {
  323. const i = props[k];
  324. const x = obj[i];
  325. f(x, i);
  326. }
  327. };
  328. const map = (obj, f) => {
  329. return tupleMap(obj, (x, i) => ({
  330. k: i,
  331. v: f(x, i)
  332. }));
  333. };
  334. const tupleMap = (obj, f) => {
  335. const r = {};
  336. each$1(obj, (x, i) => {
  337. const tuple = f(x, i);
  338. r[tuple.k] = tuple.v;
  339. });
  340. return r;
  341. };
  342. const objAcc = r => (x, i) => {
  343. r[i] = x;
  344. };
  345. const internalFilter = (obj, pred, onTrue, onFalse) => {
  346. each$1(obj, (x, i) => {
  347. (pred(x, i) ? onTrue : onFalse)(x, i);
  348. });
  349. };
  350. const filter$1 = (obj, pred) => {
  351. const t = {};
  352. internalFilter(obj, pred, objAcc(t), noop);
  353. return t;
  354. };
  355. const mapToArray = (obj, f) => {
  356. const r = [];
  357. each$1(obj, (value, name) => {
  358. r.push(f(value, name));
  359. });
  360. return r;
  361. };
  362. const values = obj => {
  363. return mapToArray(obj, identity);
  364. };
  365. const get$c = (obj, key) => {
  366. return has$1(obj, key) ? Optional.from(obj[key]) : Optional.none();
  367. };
  368. const has$1 = (obj, key) => hasOwnProperty.call(obj, key);
  369. const hasNonNullableKey = (obj, key) => has$1(obj, key) && obj[key] !== undefined && obj[key] !== null;
  370. const isEmpty = r => {
  371. for (const x in r) {
  372. if (hasOwnProperty.call(r, x)) {
  373. return false;
  374. }
  375. }
  376. return true;
  377. };
  378. const Global = typeof window !== 'undefined' ? window : Function('return this;')();
  379. const path = (parts, scope) => {
  380. let o = scope !== undefined && scope !== null ? scope : Global;
  381. for (let i = 0; i < parts.length && o !== undefined && o !== null; ++i) {
  382. o = o[parts[i]];
  383. }
  384. return o;
  385. };
  386. const resolve$2 = (p, scope) => {
  387. const parts = p.split('.');
  388. return path(parts, scope);
  389. };
  390. const unsafe = (name, scope) => {
  391. return resolve$2(name, scope);
  392. };
  393. const getOrDie = (name, scope) => {
  394. const actual = unsafe(name, scope);
  395. if (actual === undefined || actual === null) {
  396. throw new Error(name + ' not available on this browser');
  397. }
  398. return actual;
  399. };
  400. const getPrototypeOf = Object.getPrototypeOf;
  401. const sandHTMLElement = scope => {
  402. return getOrDie('HTMLElement', scope);
  403. };
  404. const isPrototypeOf = x => {
  405. const scope = resolve$2('ownerDocument.defaultView', x);
  406. return isObject(x) && (sandHTMLElement(scope).prototype.isPrototypeOf(x) || /^HTML\w*Element$/.test(getPrototypeOf(x).constructor.name));
  407. };
  408. const COMMENT = 8;
  409. const DOCUMENT = 9;
  410. const DOCUMENT_FRAGMENT = 11;
  411. const ELEMENT = 1;
  412. const TEXT = 3;
  413. const name = element => {
  414. const r = element.dom.nodeName;
  415. return r.toLowerCase();
  416. };
  417. const type = element => element.dom.nodeType;
  418. const isType = t => element => type(element) === t;
  419. const isComment = element => type(element) === COMMENT || name(element) === '#comment';
  420. const isHTMLElement = element => isElement(element) && isPrototypeOf(element.dom);
  421. const isElement = isType(ELEMENT);
  422. const isText = isType(TEXT);
  423. const isDocument = isType(DOCUMENT);
  424. const isDocumentFragment = isType(DOCUMENT_FRAGMENT);
  425. const isTag = tag => e => isElement(e) && name(e) === tag;
  426. const rawSet = (dom, key, value) => {
  427. if (isString(value) || isBoolean(value) || isNumber(value)) {
  428. dom.setAttribute(key, value + '');
  429. } else {
  430. console.error('Invalid call to Attribute.set. Key ', key, ':: Value ', value, ':: Element ', dom);
  431. throw new Error('Attribute value was not simple');
  432. }
  433. };
  434. const set$2 = (element, key, value) => {
  435. rawSet(element.dom, key, value);
  436. };
  437. const setAll$1 = (element, attrs) => {
  438. const dom = element.dom;
  439. each$1(attrs, (v, k) => {
  440. rawSet(dom, k, v);
  441. });
  442. };
  443. const setOptions = (element, attrs) => {
  444. each$1(attrs, (v, k) => {
  445. v.fold(() => {
  446. remove$7(element, k);
  447. }, value => {
  448. rawSet(element.dom, k, value);
  449. });
  450. });
  451. };
  452. const get$b = (element, key) => {
  453. const v = element.dom.getAttribute(key);
  454. return v === null ? undefined : v;
  455. };
  456. const getOpt = (element, key) => Optional.from(get$b(element, key));
  457. const remove$7 = (element, key) => {
  458. element.dom.removeAttribute(key);
  459. };
  460. const clone$2 = element => foldl(element.dom.attributes, (acc, attr) => {
  461. acc[attr.name] = attr.value;
  462. return acc;
  463. }, {});
  464. const fromHtml$1 = (html, scope) => {
  465. const doc = scope || document;
  466. const div = doc.createElement('div');
  467. div.innerHTML = html;
  468. if (!div.hasChildNodes() || div.childNodes.length > 1) {
  469. const message = 'HTML does not have a single root node';
  470. console.error(message, html);
  471. throw new Error(message);
  472. }
  473. return fromDom$1(div.childNodes[0]);
  474. };
  475. const fromTag = (tag, scope) => {
  476. const doc = scope || document;
  477. const node = doc.createElement(tag);
  478. return fromDom$1(node);
  479. };
  480. const fromText = (text, scope) => {
  481. const doc = scope || document;
  482. const node = doc.createTextNode(text);
  483. return fromDom$1(node);
  484. };
  485. const fromDom$1 = node => {
  486. if (node === null || node === undefined) {
  487. throw new Error('Node cannot be null or undefined');
  488. }
  489. return { dom: node };
  490. };
  491. const fromPoint$1 = (docElm, x, y) => Optional.from(docElm.dom.elementFromPoint(x, y)).map(fromDom$1);
  492. const SugarElement = {
  493. fromHtml: fromHtml$1,
  494. fromTag,
  495. fromText,
  496. fromDom: fromDom$1,
  497. fromPoint: fromPoint$1
  498. };
  499. const is$2 = (element, selector) => {
  500. const dom = element.dom;
  501. if (dom.nodeType !== ELEMENT) {
  502. return false;
  503. } else {
  504. const elem = dom;
  505. if (elem.matches !== undefined) {
  506. return elem.matches(selector);
  507. } else if (elem.msMatchesSelector !== undefined) {
  508. return elem.msMatchesSelector(selector);
  509. } else if (elem.webkitMatchesSelector !== undefined) {
  510. return elem.webkitMatchesSelector(selector);
  511. } else if (elem.mozMatchesSelector !== undefined) {
  512. return elem.mozMatchesSelector(selector);
  513. } else {
  514. throw new Error('Browser lacks native selectors');
  515. }
  516. }
  517. };
  518. const bypassSelector = dom => dom.nodeType !== ELEMENT && dom.nodeType !== DOCUMENT && dom.nodeType !== DOCUMENT_FRAGMENT || dom.childElementCount === 0;
  519. const all$1 = (selector, scope) => {
  520. const base = scope === undefined ? document : scope.dom;
  521. return bypassSelector(base) ? [] : map$1(base.querySelectorAll(selector), SugarElement.fromDom);
  522. };
  523. const one = (selector, scope) => {
  524. const base = scope === undefined ? document : scope.dom;
  525. return bypassSelector(base) ? Optional.none() : Optional.from(base.querySelector(selector)).map(SugarElement.fromDom);
  526. };
  527. const eq$1 = (e1, e2) => e1.dom === e2.dom;
  528. const contains$1 = (e1, e2) => {
  529. const d1 = e1.dom;
  530. const d2 = e2.dom;
  531. return d1 === d2 ? false : d1.contains(d2);
  532. };
  533. const is$1 = is$2;
  534. const owner = element => SugarElement.fromDom(element.dom.ownerDocument);
  535. const documentOrOwner = dos => isDocument(dos) ? dos : owner(dos);
  536. const documentElement = element => SugarElement.fromDom(documentOrOwner(element).dom.documentElement);
  537. const defaultView = element => SugarElement.fromDom(documentOrOwner(element).dom.defaultView);
  538. const parent = element => Optional.from(element.dom.parentNode).map(SugarElement.fromDom);
  539. const parentElement = element => Optional.from(element.dom.parentElement).map(SugarElement.fromDom);
  540. const parents = (element, isRoot) => {
  541. const stop = isFunction(isRoot) ? isRoot : never;
  542. let dom = element.dom;
  543. const ret = [];
  544. while (dom.parentNode !== null && dom.parentNode !== undefined) {
  545. const rawParent = dom.parentNode;
  546. const p = SugarElement.fromDom(rawParent);
  547. ret.push(p);
  548. if (stop(p) === true) {
  549. break;
  550. } else {
  551. dom = rawParent;
  552. }
  553. }
  554. return ret;
  555. };
  556. const prevSibling = element => Optional.from(element.dom.previousSibling).map(SugarElement.fromDom);
  557. const nextSibling = element => Optional.from(element.dom.nextSibling).map(SugarElement.fromDom);
  558. const children$2 = element => map$1(element.dom.childNodes, SugarElement.fromDom);
  559. const child$2 = (element, index) => {
  560. const cs = element.dom.childNodes;
  561. return Optional.from(cs[index]).map(SugarElement.fromDom);
  562. };
  563. const firstChild = element => child$2(element, 0);
  564. const before$3 = (marker, element) => {
  565. const parent$1 = parent(marker);
  566. parent$1.each(v => {
  567. v.dom.insertBefore(element.dom, marker.dom);
  568. });
  569. };
  570. const after$5 = (marker, element) => {
  571. const sibling = nextSibling(marker);
  572. sibling.fold(() => {
  573. const parent$1 = parent(marker);
  574. parent$1.each(v => {
  575. append$1(v, element);
  576. });
  577. }, v => {
  578. before$3(v, element);
  579. });
  580. };
  581. const prepend = (parent, element) => {
  582. const firstChild$1 = firstChild(parent);
  583. firstChild$1.fold(() => {
  584. append$1(parent, element);
  585. }, v => {
  586. parent.dom.insertBefore(element.dom, v.dom);
  587. });
  588. };
  589. const append$1 = (parent, element) => {
  590. parent.dom.appendChild(element.dom);
  591. };
  592. const appendAt = (parent, element, index) => {
  593. child$2(parent, index).fold(() => {
  594. append$1(parent, element);
  595. }, v => {
  596. before$3(v, element);
  597. });
  598. };
  599. const wrap = (element, wrapper) => {
  600. before$3(element, wrapper);
  601. append$1(wrapper, element);
  602. };
  603. const after$4 = (marker, elements) => {
  604. each$2(elements, (x, i) => {
  605. const e = i === 0 ? marker : elements[i - 1];
  606. after$5(e, x);
  607. });
  608. };
  609. const append = (parent, elements) => {
  610. each$2(elements, x => {
  611. append$1(parent, x);
  612. });
  613. };
  614. const empty = element => {
  615. element.dom.textContent = '';
  616. each$2(children$2(element), rogue => {
  617. remove$6(rogue);
  618. });
  619. };
  620. const remove$6 = element => {
  621. const dom = element.dom;
  622. if (dom.parentNode !== null) {
  623. dom.parentNode.removeChild(dom);
  624. }
  625. };
  626. const unwrap = wrapper => {
  627. const children = children$2(wrapper);
  628. if (children.length > 0) {
  629. after$4(wrapper, children);
  630. }
  631. remove$6(wrapper);
  632. };
  633. const clone$1 = (original, isDeep) => SugarElement.fromDom(original.dom.cloneNode(isDeep));
  634. const shallow = original => clone$1(original, false);
  635. const deep = original => clone$1(original, true);
  636. const shallowAs = (original, tag) => {
  637. const nu = SugarElement.fromTag(tag);
  638. const attributes = clone$2(original);
  639. setAll$1(nu, attributes);
  640. return nu;
  641. };
  642. const copy$2 = (original, tag) => {
  643. const nu = shallowAs(original, tag);
  644. const cloneChildren = children$2(deep(original));
  645. append(nu, cloneChildren);
  646. return nu;
  647. };
  648. const mutate$1 = (original, tag) => {
  649. const nu = shallowAs(original, tag);
  650. after$5(original, nu);
  651. const children = children$2(original);
  652. append(nu, children);
  653. remove$6(original);
  654. return nu;
  655. };
  656. const validSectionList = [
  657. 'tfoot',
  658. 'thead',
  659. 'tbody',
  660. 'colgroup'
  661. ];
  662. const isValidSection = parentName => contains$2(validSectionList, parentName);
  663. const grid = (rows, columns) => ({
  664. rows,
  665. columns
  666. });
  667. const address = (row, column) => ({
  668. row,
  669. column
  670. });
  671. const detail = (element, rowspan, colspan) => ({
  672. element,
  673. rowspan,
  674. colspan
  675. });
  676. const detailnew = (element, rowspan, colspan, isNew) => ({
  677. element,
  678. rowspan,
  679. colspan,
  680. isNew
  681. });
  682. const extended = (element, rowspan, colspan, row, column, isLocked) => ({
  683. element,
  684. rowspan,
  685. colspan,
  686. row,
  687. column,
  688. isLocked
  689. });
  690. const rowdetail = (element, cells, section) => ({
  691. element,
  692. cells,
  693. section
  694. });
  695. const rowdetailnew = (element, cells, section, isNew) => ({
  696. element,
  697. cells,
  698. section,
  699. isNew
  700. });
  701. const elementnew = (element, isNew, isLocked) => ({
  702. element,
  703. isNew,
  704. isLocked
  705. });
  706. const rowcells = (element, cells, section, isNew) => ({
  707. element,
  708. cells,
  709. section,
  710. isNew
  711. });
  712. const bounds = (startRow, startCol, finishRow, finishCol) => ({
  713. startRow,
  714. startCol,
  715. finishRow,
  716. finishCol
  717. });
  718. const columnext = (element, colspan, column) => ({
  719. element,
  720. colspan,
  721. column
  722. });
  723. const colgroup = (element, columns) => ({
  724. element,
  725. columns
  726. });
  727. const isShadowRoot = dos => isDocumentFragment(dos) && isNonNullable(dos.dom.host);
  728. const supported = isFunction(Element.prototype.attachShadow) && isFunction(Node.prototype.getRootNode);
  729. const isSupported$1 = constant(supported);
  730. const getRootNode = supported ? e => SugarElement.fromDom(e.dom.getRootNode()) : documentOrOwner;
  731. const getShadowRoot = e => {
  732. const r = getRootNode(e);
  733. return isShadowRoot(r) ? Optional.some(r) : Optional.none();
  734. };
  735. const getShadowHost = e => SugarElement.fromDom(e.dom.host);
  736. const getOriginalEventTarget = event => {
  737. if (isSupported$1() && isNonNullable(event.target)) {
  738. const el = SugarElement.fromDom(event.target);
  739. if (isElement(el) && isOpenShadowHost(el)) {
  740. if (event.composed && event.composedPath) {
  741. const composedPath = event.composedPath();
  742. if (composedPath) {
  743. return head(composedPath);
  744. }
  745. }
  746. }
  747. }
  748. return Optional.from(event.target);
  749. };
  750. const isOpenShadowHost = element => isNonNullable(element.dom.shadowRoot);
  751. const inBody = element => {
  752. const dom = isText(element) ? element.dom.parentNode : element.dom;
  753. if (dom === undefined || dom === null || dom.ownerDocument === null) {
  754. return false;
  755. }
  756. const doc = dom.ownerDocument;
  757. return getShadowRoot(SugarElement.fromDom(dom)).fold(() => doc.body.contains(dom), compose1(inBody, getShadowHost));
  758. };
  759. const body$1 = () => getBody$1(SugarElement.fromDom(document));
  760. const getBody$1 = doc => {
  761. const b = doc.dom.body;
  762. if (b === null || b === undefined) {
  763. throw new Error('Body is not available yet');
  764. }
  765. return SugarElement.fromDom(b);
  766. };
  767. const ancestors$4 = (scope, predicate, isRoot) => filter$2(parents(scope, isRoot), predicate);
  768. const children$1 = (scope, predicate) => filter$2(children$2(scope), predicate);
  769. const descendants$1 = (scope, predicate) => {
  770. let result = [];
  771. each$2(children$2(scope), x => {
  772. if (predicate(x)) {
  773. result = result.concat([x]);
  774. }
  775. result = result.concat(descendants$1(x, predicate));
  776. });
  777. return result;
  778. };
  779. const ancestors$3 = (scope, selector, isRoot) => ancestors$4(scope, e => is$2(e, selector), isRoot);
  780. const children = (scope, selector) => children$1(scope, e => is$2(e, selector));
  781. const descendants = (scope, selector) => all$1(selector, scope);
  782. var ClosestOrAncestor = (is, ancestor, scope, a, isRoot) => {
  783. if (is(scope, a)) {
  784. return Optional.some(scope);
  785. } else if (isFunction(isRoot) && isRoot(scope)) {
  786. return Optional.none();
  787. } else {
  788. return ancestor(scope, a, isRoot);
  789. }
  790. };
  791. const ancestor$2 = (scope, predicate, isRoot) => {
  792. let element = scope.dom;
  793. const stop = isFunction(isRoot) ? isRoot : never;
  794. while (element.parentNode) {
  795. element = element.parentNode;
  796. const el = SugarElement.fromDom(element);
  797. if (predicate(el)) {
  798. return Optional.some(el);
  799. } else if (stop(el)) {
  800. break;
  801. }
  802. }
  803. return Optional.none();
  804. };
  805. const closest$2 = (scope, predicate, isRoot) => {
  806. const is = (s, test) => test(s);
  807. return ClosestOrAncestor(is, ancestor$2, scope, predicate, isRoot);
  808. };
  809. const child$1 = (scope, predicate) => {
  810. const pred = node => predicate(SugarElement.fromDom(node));
  811. const result = find$1(scope.dom.childNodes, pred);
  812. return result.map(SugarElement.fromDom);
  813. };
  814. const descendant$1 = (scope, predicate) => {
  815. const descend = node => {
  816. for (let i = 0; i < node.childNodes.length; i++) {
  817. const child = SugarElement.fromDom(node.childNodes[i]);
  818. if (predicate(child)) {
  819. return Optional.some(child);
  820. }
  821. const res = descend(node.childNodes[i]);
  822. if (res.isSome()) {
  823. return res;
  824. }
  825. }
  826. return Optional.none();
  827. };
  828. return descend(scope.dom);
  829. };
  830. const ancestor$1 = (scope, selector, isRoot) => ancestor$2(scope, e => is$2(e, selector), isRoot);
  831. const child = (scope, selector) => child$1(scope, e => is$2(e, selector));
  832. const descendant = (scope, selector) => one(selector, scope);
  833. const closest$1 = (scope, selector, isRoot) => {
  834. const is = (element, selector) => is$2(element, selector);
  835. return ClosestOrAncestor(is, ancestor$1, scope, selector, isRoot);
  836. };
  837. const is = (lhs, rhs, comparator = tripleEquals) => lhs.exists(left => comparator(left, rhs));
  838. const cat = arr => {
  839. const r = [];
  840. const push = x => {
  841. r.push(x);
  842. };
  843. for (let i = 0; i < arr.length; i++) {
  844. arr[i].each(push);
  845. }
  846. return r;
  847. };
  848. const bindFrom = (a, f) => a !== undefined && a !== null ? f(a) : Optional.none();
  849. const someIf = (b, a) => b ? Optional.some(a) : Optional.none();
  850. const checkRange = (str, substr, start) => substr === '' || str.length >= substr.length && str.substr(start, start + substr.length) === substr;
  851. const contains = (str, substr, start = 0, end) => {
  852. const idx = str.indexOf(substr, start);
  853. if (idx !== -1) {
  854. return isUndefined(end) ? true : idx + substr.length <= end;
  855. } else {
  856. return false;
  857. }
  858. };
  859. const startsWith = (str, prefix) => {
  860. return checkRange(str, prefix, 0);
  861. };
  862. const endsWith = (str, suffix) => {
  863. return checkRange(str, suffix, str.length - suffix.length);
  864. };
  865. const blank = r => s => s.replace(r, '');
  866. const trim = blank(/^\s+|\s+$/g);
  867. const isNotEmpty = s => s.length > 0;
  868. const toFloat = value => {
  869. const num = parseFloat(value);
  870. return isNaN(num) ? Optional.none() : Optional.some(num);
  871. };
  872. const isSupported = dom => dom.style !== undefined && isFunction(dom.style.getPropertyValue);
  873. const internalSet = (dom, property, value) => {
  874. if (!isString(value)) {
  875. console.error('Invalid call to CSS.set. Property ', property, ':: Value ', value, ':: Element ', dom);
  876. throw new Error('CSS value must be a string: ' + value);
  877. }
  878. if (isSupported(dom)) {
  879. dom.style.setProperty(property, value);
  880. }
  881. };
  882. const internalRemove = (dom, property) => {
  883. if (isSupported(dom)) {
  884. dom.style.removeProperty(property);
  885. }
  886. };
  887. const set$1 = (element, property, value) => {
  888. const dom = element.dom;
  889. internalSet(dom, property, value);
  890. };
  891. const setAll = (element, css) => {
  892. const dom = element.dom;
  893. each$1(css, (v, k) => {
  894. internalSet(dom, k, v);
  895. });
  896. };
  897. const get$a = (element, property) => {
  898. const dom = element.dom;
  899. const styles = window.getComputedStyle(dom);
  900. const r = styles.getPropertyValue(property);
  901. return r === '' && !inBody(element) ? getUnsafeProperty(dom, property) : r;
  902. };
  903. const getUnsafeProperty = (dom, property) => isSupported(dom) ? dom.style.getPropertyValue(property) : '';
  904. const getRaw$2 = (element, property) => {
  905. const dom = element.dom;
  906. const raw = getUnsafeProperty(dom, property);
  907. return Optional.from(raw).filter(r => r.length > 0);
  908. };
  909. const remove$5 = (element, property) => {
  910. const dom = element.dom;
  911. internalRemove(dom, property);
  912. if (is(getOpt(element, 'style').map(trim), '')) {
  913. remove$7(element, 'style');
  914. }
  915. };
  916. const copy$1 = (source, target) => {
  917. const sourceDom = source.dom;
  918. const targetDom = target.dom;
  919. if (isSupported(sourceDom) && isSupported(targetDom)) {
  920. targetDom.style.cssText = sourceDom.style.cssText;
  921. }
  922. };
  923. const getAttrValue = (cell, name, fallback = 0) => getOpt(cell, name).map(value => parseInt(value, 10)).getOr(fallback);
  924. const getSpan = (cell, type) => getAttrValue(cell, type, 1);
  925. const hasColspan = cellOrCol => {
  926. if (isTag('col')(cellOrCol)) {
  927. return getAttrValue(cellOrCol, 'span', 1) > 1;
  928. } else {
  929. return getSpan(cellOrCol, 'colspan') > 1;
  930. }
  931. };
  932. const hasRowspan = cell => getSpan(cell, 'rowspan') > 1;
  933. const getCssValue = (element, property) => parseInt(get$a(element, property), 10);
  934. const minWidth = constant(10);
  935. const minHeight = constant(10);
  936. const firstLayer = (scope, selector) => {
  937. return filterFirstLayer(scope, selector, always);
  938. };
  939. const filterFirstLayer = (scope, selector, predicate) => {
  940. return bind$2(children$2(scope), x => {
  941. if (is$2(x, selector)) {
  942. return predicate(x) ? [x] : [];
  943. } else {
  944. return filterFirstLayer(x, selector, predicate);
  945. }
  946. });
  947. };
  948. const lookup = (tags, element, isRoot = never) => {
  949. if (isRoot(element)) {
  950. return Optional.none();
  951. }
  952. if (contains$2(tags, name(element))) {
  953. return Optional.some(element);
  954. }
  955. const isRootOrUpperTable = elm => is$2(elm, 'table') || isRoot(elm);
  956. return ancestor$1(element, tags.join(','), isRootOrUpperTable);
  957. };
  958. const cell = (element, isRoot) => lookup([
  959. 'td',
  960. 'th'
  961. ], element, isRoot);
  962. const cells$1 = ancestor => firstLayer(ancestor, 'th,td');
  963. const columns$1 = ancestor => {
  964. if (is$2(ancestor, 'colgroup')) {
  965. return children(ancestor, 'col');
  966. } else {
  967. return bind$2(columnGroups(ancestor), columnGroup => children(columnGroup, 'col'));
  968. }
  969. };
  970. const table = (element, isRoot) => closest$1(element, 'table', isRoot);
  971. const rows$1 = ancestor => firstLayer(ancestor, 'tr');
  972. const columnGroups = ancestor => table(ancestor).fold(constant([]), table => children(table, 'colgroup'));
  973. const fromRowsOrColGroups = (elems, getSection) => map$1(elems, row => {
  974. if (name(row) === 'colgroup') {
  975. const cells = map$1(columns$1(row), column => {
  976. const colspan = getAttrValue(column, 'span', 1);
  977. return detail(column, 1, colspan);
  978. });
  979. return rowdetail(row, cells, 'colgroup');
  980. } else {
  981. const cells = map$1(cells$1(row), cell => {
  982. const rowspan = getAttrValue(cell, 'rowspan', 1);
  983. const colspan = getAttrValue(cell, 'colspan', 1);
  984. return detail(cell, rowspan, colspan);
  985. });
  986. return rowdetail(row, cells, getSection(row));
  987. }
  988. });
  989. const getParentSection = group => parent(group).map(parent => {
  990. const parentName = name(parent);
  991. return isValidSection(parentName) ? parentName : 'tbody';
  992. }).getOr('tbody');
  993. const fromTable$1 = table => {
  994. const rows = rows$1(table);
  995. const columnGroups$1 = columnGroups(table);
  996. const elems = [
  997. ...columnGroups$1,
  998. ...rows
  999. ];
  1000. return fromRowsOrColGroups(elems, getParentSection);
  1001. };
  1002. const fromPastedRows = (elems, section) => fromRowsOrColGroups(elems, () => section);
  1003. const cached = f => {
  1004. let called = false;
  1005. let r;
  1006. return (...args) => {
  1007. if (!called) {
  1008. called = true;
  1009. r = f.apply(null, args);
  1010. }
  1011. return r;
  1012. };
  1013. };
  1014. const DeviceType = (os, browser, userAgent, mediaMatch) => {
  1015. const isiPad = os.isiOS() && /ipad/i.test(userAgent) === true;
  1016. const isiPhone = os.isiOS() && !isiPad;
  1017. const isMobile = os.isiOS() || os.isAndroid();
  1018. const isTouch = isMobile || mediaMatch('(pointer:coarse)');
  1019. const isTablet = isiPad || !isiPhone && isMobile && mediaMatch('(min-device-width:768px)');
  1020. const isPhone = isiPhone || isMobile && !isTablet;
  1021. const iOSwebview = browser.isSafari() && os.isiOS() && /safari/i.test(userAgent) === false;
  1022. const isDesktop = !isPhone && !isTablet && !iOSwebview;
  1023. return {
  1024. isiPad: constant(isiPad),
  1025. isiPhone: constant(isiPhone),
  1026. isTablet: constant(isTablet),
  1027. isPhone: constant(isPhone),
  1028. isTouch: constant(isTouch),
  1029. isAndroid: os.isAndroid,
  1030. isiOS: os.isiOS,
  1031. isWebView: constant(iOSwebview),
  1032. isDesktop: constant(isDesktop)
  1033. };
  1034. };
  1035. const firstMatch = (regexes, s) => {
  1036. for (let i = 0; i < regexes.length; i++) {
  1037. const x = regexes[i];
  1038. if (x.test(s)) {
  1039. return x;
  1040. }
  1041. }
  1042. return undefined;
  1043. };
  1044. const find = (regexes, agent) => {
  1045. const r = firstMatch(regexes, agent);
  1046. if (!r) {
  1047. return {
  1048. major: 0,
  1049. minor: 0
  1050. };
  1051. }
  1052. const group = i => {
  1053. return Number(agent.replace(r, '$' + i));
  1054. };
  1055. return nu$2(group(1), group(2));
  1056. };
  1057. const detect$5 = (versionRegexes, agent) => {
  1058. const cleanedAgent = String(agent).toLowerCase();
  1059. if (versionRegexes.length === 0) {
  1060. return unknown$2();
  1061. }
  1062. return find(versionRegexes, cleanedAgent);
  1063. };
  1064. const unknown$2 = () => {
  1065. return nu$2(0, 0);
  1066. };
  1067. const nu$2 = (major, minor) => {
  1068. return {
  1069. major,
  1070. minor
  1071. };
  1072. };
  1073. const Version = {
  1074. nu: nu$2,
  1075. detect: detect$5,
  1076. unknown: unknown$2
  1077. };
  1078. const detectBrowser$1 = (browsers, userAgentData) => {
  1079. return findMap(userAgentData.brands, uaBrand => {
  1080. const lcBrand = uaBrand.brand.toLowerCase();
  1081. return find$1(browsers, browser => {
  1082. var _a;
  1083. return lcBrand === ((_a = browser.brand) === null || _a === void 0 ? void 0 : _a.toLowerCase());
  1084. }).map(info => ({
  1085. current: info.name,
  1086. version: Version.nu(parseInt(uaBrand.version, 10), 0)
  1087. }));
  1088. });
  1089. };
  1090. const detect$4 = (candidates, userAgent) => {
  1091. const agent = String(userAgent).toLowerCase();
  1092. return find$1(candidates, candidate => {
  1093. return candidate.search(agent);
  1094. });
  1095. };
  1096. const detectBrowser = (browsers, userAgent) => {
  1097. return detect$4(browsers, userAgent).map(browser => {
  1098. const version = Version.detect(browser.versionRegexes, userAgent);
  1099. return {
  1100. current: browser.name,
  1101. version
  1102. };
  1103. });
  1104. };
  1105. const detectOs = (oses, userAgent) => {
  1106. return detect$4(oses, userAgent).map(os => {
  1107. const version = Version.detect(os.versionRegexes, userAgent);
  1108. return {
  1109. current: os.name,
  1110. version
  1111. };
  1112. });
  1113. };
  1114. const normalVersionRegex = /.*?version\/\ ?([0-9]+)\.([0-9]+).*/;
  1115. const checkContains = target => {
  1116. return uastring => {
  1117. return contains(uastring, target);
  1118. };
  1119. };
  1120. const browsers = [
  1121. {
  1122. name: 'Edge',
  1123. versionRegexes: [/.*?edge\/ ?([0-9]+)\.([0-9]+)$/],
  1124. search: uastring => {
  1125. return contains(uastring, 'edge/') && contains(uastring, 'chrome') && contains(uastring, 'safari') && contains(uastring, 'applewebkit');
  1126. }
  1127. },
  1128. {
  1129. name: 'Chromium',
  1130. brand: 'Chromium',
  1131. versionRegexes: [
  1132. /.*?chrome\/([0-9]+)\.([0-9]+).*/,
  1133. normalVersionRegex
  1134. ],
  1135. search: uastring => {
  1136. return contains(uastring, 'chrome') && !contains(uastring, 'chromeframe');
  1137. }
  1138. },
  1139. {
  1140. name: 'IE',
  1141. versionRegexes: [
  1142. /.*?msie\ ?([0-9]+)\.([0-9]+).*/,
  1143. /.*?rv:([0-9]+)\.([0-9]+).*/
  1144. ],
  1145. search: uastring => {
  1146. return contains(uastring, 'msie') || contains(uastring, 'trident');
  1147. }
  1148. },
  1149. {
  1150. name: 'Opera',
  1151. versionRegexes: [
  1152. normalVersionRegex,
  1153. /.*?opera\/([0-9]+)\.([0-9]+).*/
  1154. ],
  1155. search: checkContains('opera')
  1156. },
  1157. {
  1158. name: 'Firefox',
  1159. versionRegexes: [/.*?firefox\/\ ?([0-9]+)\.([0-9]+).*/],
  1160. search: checkContains('firefox')
  1161. },
  1162. {
  1163. name: 'Safari',
  1164. versionRegexes: [
  1165. normalVersionRegex,
  1166. /.*?cpu os ([0-9]+)_([0-9]+).*/
  1167. ],
  1168. search: uastring => {
  1169. return (contains(uastring, 'safari') || contains(uastring, 'mobile/')) && contains(uastring, 'applewebkit');
  1170. }
  1171. }
  1172. ];
  1173. const oses = [
  1174. {
  1175. name: 'Windows',
  1176. search: checkContains('win'),
  1177. versionRegexes: [/.*?windows\ nt\ ?([0-9]+)\.([0-9]+).*/]
  1178. },
  1179. {
  1180. name: 'iOS',
  1181. search: uastring => {
  1182. return contains(uastring, 'iphone') || contains(uastring, 'ipad');
  1183. },
  1184. versionRegexes: [
  1185. /.*?version\/\ ?([0-9]+)\.([0-9]+).*/,
  1186. /.*cpu os ([0-9]+)_([0-9]+).*/,
  1187. /.*cpu iphone os ([0-9]+)_([0-9]+).*/
  1188. ]
  1189. },
  1190. {
  1191. name: 'Android',
  1192. search: checkContains('android'),
  1193. versionRegexes: [/.*?android\ ?([0-9]+)\.([0-9]+).*/]
  1194. },
  1195. {
  1196. name: 'macOS',
  1197. search: checkContains('mac os x'),
  1198. versionRegexes: [/.*?mac\ os\ x\ ?([0-9]+)_([0-9]+).*/]
  1199. },
  1200. {
  1201. name: 'Linux',
  1202. search: checkContains('linux'),
  1203. versionRegexes: []
  1204. },
  1205. {
  1206. name: 'Solaris',
  1207. search: checkContains('sunos'),
  1208. versionRegexes: []
  1209. },
  1210. {
  1211. name: 'FreeBSD',
  1212. search: checkContains('freebsd'),
  1213. versionRegexes: []
  1214. },
  1215. {
  1216. name: 'ChromeOS',
  1217. search: checkContains('cros'),
  1218. versionRegexes: [/.*?chrome\/([0-9]+)\.([0-9]+).*/]
  1219. }
  1220. ];
  1221. const PlatformInfo = {
  1222. browsers: constant(browsers),
  1223. oses: constant(oses)
  1224. };
  1225. const edge = 'Edge';
  1226. const chromium = 'Chromium';
  1227. const ie = 'IE';
  1228. const opera = 'Opera';
  1229. const firefox = 'Firefox';
  1230. const safari = 'Safari';
  1231. const unknown$1 = () => {
  1232. return nu$1({
  1233. current: undefined,
  1234. version: Version.unknown()
  1235. });
  1236. };
  1237. const nu$1 = info => {
  1238. const current = info.current;
  1239. const version = info.version;
  1240. const isBrowser = name => () => current === name;
  1241. return {
  1242. current,
  1243. version,
  1244. isEdge: isBrowser(edge),
  1245. isChromium: isBrowser(chromium),
  1246. isIE: isBrowser(ie),
  1247. isOpera: isBrowser(opera),
  1248. isFirefox: isBrowser(firefox),
  1249. isSafari: isBrowser(safari)
  1250. };
  1251. };
  1252. const Browser = {
  1253. unknown: unknown$1,
  1254. nu: nu$1,
  1255. edge: constant(edge),
  1256. chromium: constant(chromium),
  1257. ie: constant(ie),
  1258. opera: constant(opera),
  1259. firefox: constant(firefox),
  1260. safari: constant(safari)
  1261. };
  1262. const windows = 'Windows';
  1263. const ios = 'iOS';
  1264. const android = 'Android';
  1265. const linux = 'Linux';
  1266. const macos = 'macOS';
  1267. const solaris = 'Solaris';
  1268. const freebsd = 'FreeBSD';
  1269. const chromeos = 'ChromeOS';
  1270. const unknown = () => {
  1271. return nu({
  1272. current: undefined,
  1273. version: Version.unknown()
  1274. });
  1275. };
  1276. const nu = info => {
  1277. const current = info.current;
  1278. const version = info.version;
  1279. const isOS = name => () => current === name;
  1280. return {
  1281. current,
  1282. version,
  1283. isWindows: isOS(windows),
  1284. isiOS: isOS(ios),
  1285. isAndroid: isOS(android),
  1286. isMacOS: isOS(macos),
  1287. isLinux: isOS(linux),
  1288. isSolaris: isOS(solaris),
  1289. isFreeBSD: isOS(freebsd),
  1290. isChromeOS: isOS(chromeos)
  1291. };
  1292. };
  1293. const OperatingSystem = {
  1294. unknown,
  1295. nu,
  1296. windows: constant(windows),
  1297. ios: constant(ios),
  1298. android: constant(android),
  1299. linux: constant(linux),
  1300. macos: constant(macos),
  1301. solaris: constant(solaris),
  1302. freebsd: constant(freebsd),
  1303. chromeos: constant(chromeos)
  1304. };
  1305. const detect$3 = (userAgent, userAgentDataOpt, mediaMatch) => {
  1306. const browsers = PlatformInfo.browsers();
  1307. const oses = PlatformInfo.oses();
  1308. const browser = userAgentDataOpt.bind(userAgentData => detectBrowser$1(browsers, userAgentData)).orThunk(() => detectBrowser(browsers, userAgent)).fold(Browser.unknown, Browser.nu);
  1309. const os = detectOs(oses, userAgent).fold(OperatingSystem.unknown, OperatingSystem.nu);
  1310. const deviceType = DeviceType(os, browser, userAgent, mediaMatch);
  1311. return {
  1312. browser,
  1313. os,
  1314. deviceType
  1315. };
  1316. };
  1317. const PlatformDetection = { detect: detect$3 };
  1318. const mediaMatch = query => window.matchMedia(query).matches;
  1319. let platform = cached(() => PlatformDetection.detect(navigator.userAgent, Optional.from(navigator.userAgentData), mediaMatch));
  1320. const detect$2 = () => platform();
  1321. const Dimension = (name, getOffset) => {
  1322. const set = (element, h) => {
  1323. if (!isNumber(h) && !h.match(/^[0-9]+$/)) {
  1324. throw new Error(name + '.set accepts only positive integer values. Value was ' + h);
  1325. }
  1326. const dom = element.dom;
  1327. if (isSupported(dom)) {
  1328. dom.style[name] = h + 'px';
  1329. }
  1330. };
  1331. const get = element => {
  1332. const r = getOffset(element);
  1333. if (r <= 0 || r === null) {
  1334. const css = get$a(element, name);
  1335. return parseFloat(css) || 0;
  1336. }
  1337. return r;
  1338. };
  1339. const getOuter = get;
  1340. const aggregate = (element, properties) => foldl(properties, (acc, property) => {
  1341. const val = get$a(element, property);
  1342. const value = val === undefined ? 0 : parseInt(val, 10);
  1343. return isNaN(value) ? acc : acc + value;
  1344. }, 0);
  1345. const max = (element, value, properties) => {
  1346. const cumulativeInclusions = aggregate(element, properties);
  1347. const absoluteMax = value > cumulativeInclusions ? value - cumulativeInclusions : 0;
  1348. return absoluteMax;
  1349. };
  1350. return {
  1351. set,
  1352. get,
  1353. getOuter,
  1354. aggregate,
  1355. max
  1356. };
  1357. };
  1358. const toNumber = (px, fallback) => toFloat(px).getOr(fallback);
  1359. const getProp = (element, name, fallback) => toNumber(get$a(element, name), fallback);
  1360. const calcContentBoxSize = (element, size, upper, lower) => {
  1361. const paddingUpper = getProp(element, `padding-${ upper }`, 0);
  1362. const paddingLower = getProp(element, `padding-${ lower }`, 0);
  1363. const borderUpper = getProp(element, `border-${ upper }-width`, 0);
  1364. const borderLower = getProp(element, `border-${ lower }-width`, 0);
  1365. return size - paddingUpper - paddingLower - borderUpper - borderLower;
  1366. };
  1367. const getCalculatedWidth = (element, boxSizing) => {
  1368. const dom = element.dom;
  1369. const width = dom.getBoundingClientRect().width || dom.offsetWidth;
  1370. return boxSizing === 'border-box' ? width : calcContentBoxSize(element, width, 'left', 'right');
  1371. };
  1372. const getHeight$1 = element => getProp(element, 'height', element.dom.offsetHeight);
  1373. const getWidth = element => getProp(element, 'width', element.dom.offsetWidth);
  1374. const getInnerWidth = element => getCalculatedWidth(element, 'content-box');
  1375. const api$2 = Dimension('width', element => element.dom.offsetWidth);
  1376. const get$9 = element => api$2.get(element);
  1377. const getOuter$2 = element => api$2.getOuter(element);
  1378. const getInner = getInnerWidth;
  1379. const getRuntime$1 = getWidth;
  1380. const addCells = (gridRow, index, cells) => {
  1381. const existingCells = gridRow.cells;
  1382. const before = existingCells.slice(0, index);
  1383. const after = existingCells.slice(index);
  1384. const newCells = before.concat(cells).concat(after);
  1385. return setCells(gridRow, newCells);
  1386. };
  1387. const addCell = (gridRow, index, cell) => addCells(gridRow, index, [cell]);
  1388. const mutateCell = (gridRow, index, cell) => {
  1389. const cells = gridRow.cells;
  1390. cells[index] = cell;
  1391. };
  1392. const setCells = (gridRow, cells) => rowcells(gridRow.element, cells, gridRow.section, gridRow.isNew);
  1393. const mapCells = (gridRow, f) => {
  1394. const cells = gridRow.cells;
  1395. const r = map$1(cells, f);
  1396. return rowcells(gridRow.element, r, gridRow.section, gridRow.isNew);
  1397. };
  1398. const getCell = (gridRow, index) => gridRow.cells[index];
  1399. const getCellElement = (gridRow, index) => getCell(gridRow, index).element;
  1400. const cellLength = gridRow => gridRow.cells.length;
  1401. const extractGridDetails = grid => {
  1402. const result = partition(grid, row => row.section === 'colgroup');
  1403. return {
  1404. rows: result.fail,
  1405. cols: result.pass
  1406. };
  1407. };
  1408. const clone = (gridRow, cloneRow, cloneCell) => {
  1409. const newCells = map$1(gridRow.cells, cloneCell);
  1410. return rowcells(cloneRow(gridRow.element), newCells, gridRow.section, true);
  1411. };
  1412. const LOCKED_COL_ATTR = 'data-snooker-locked-cols';
  1413. const getLockedColumnsFromTable = table => getOpt(table, LOCKED_COL_ATTR).bind(lockedColStr => Optional.from(lockedColStr.match(/\d+/g))).map(lockedCols => mapToObject(lockedCols, always));
  1414. const getLockedColumnsFromGrid = grid => {
  1415. const locked = foldl(extractGridDetails(grid).rows, (acc, row) => {
  1416. each$2(row.cells, (cell, idx) => {
  1417. if (cell.isLocked) {
  1418. acc[idx] = true;
  1419. }
  1420. });
  1421. return acc;
  1422. }, {});
  1423. const lockedArr = mapToArray(locked, (_val, key) => parseInt(key, 10));
  1424. return sort$1(lockedArr);
  1425. };
  1426. const key = (row, column) => {
  1427. return row + ',' + column;
  1428. };
  1429. const getAt = (warehouse, row, column) => Optional.from(warehouse.access[key(row, column)]);
  1430. const findItem = (warehouse, item, comparator) => {
  1431. const filtered = filterItems(warehouse, detail => {
  1432. return comparator(item, detail.element);
  1433. });
  1434. return filtered.length > 0 ? Optional.some(filtered[0]) : Optional.none();
  1435. };
  1436. const filterItems = (warehouse, predicate) => {
  1437. const all = bind$2(warehouse.all, r => {
  1438. return r.cells;
  1439. });
  1440. return filter$2(all, predicate);
  1441. };
  1442. const generateColumns = rowData => {
  1443. const columnsGroup = {};
  1444. let index = 0;
  1445. each$2(rowData.cells, column => {
  1446. const colspan = column.colspan;
  1447. range$1(colspan, columnIndex => {
  1448. const colIndex = index + columnIndex;
  1449. columnsGroup[colIndex] = columnext(column.element, colspan, colIndex);
  1450. });
  1451. index += colspan;
  1452. });
  1453. return columnsGroup;
  1454. };
  1455. const generate$1 = list => {
  1456. const access = {};
  1457. const cells = [];
  1458. const tableOpt = head(list).map(rowData => rowData.element).bind(table);
  1459. const lockedColumns = tableOpt.bind(getLockedColumnsFromTable).getOr({});
  1460. let maxRows = 0;
  1461. let maxColumns = 0;
  1462. let rowCount = 0;
  1463. const {
  1464. pass: colgroupRows,
  1465. fail: rows
  1466. } = partition(list, rowData => rowData.section === 'colgroup');
  1467. each$2(rows, rowData => {
  1468. const currentRow = [];
  1469. each$2(rowData.cells, rowCell => {
  1470. let start = 0;
  1471. while (access[key(rowCount, start)] !== undefined) {
  1472. start++;
  1473. }
  1474. const isLocked = hasNonNullableKey(lockedColumns, start.toString());
  1475. const current = extended(rowCell.element, rowCell.rowspan, rowCell.colspan, rowCount, start, isLocked);
  1476. for (let occupiedColumnPosition = 0; occupiedColumnPosition < rowCell.colspan; occupiedColumnPosition++) {
  1477. for (let occupiedRowPosition = 0; occupiedRowPosition < rowCell.rowspan; occupiedRowPosition++) {
  1478. const rowPosition = rowCount + occupiedRowPosition;
  1479. const columnPosition = start + occupiedColumnPosition;
  1480. const newpos = key(rowPosition, columnPosition);
  1481. access[newpos] = current;
  1482. maxColumns = Math.max(maxColumns, columnPosition + 1);
  1483. }
  1484. }
  1485. currentRow.push(current);
  1486. });
  1487. maxRows++;
  1488. cells.push(rowdetail(rowData.element, currentRow, rowData.section));
  1489. rowCount++;
  1490. });
  1491. const {columns, colgroups} = last$2(colgroupRows).map(rowData => {
  1492. const columns = generateColumns(rowData);
  1493. const colgroup$1 = colgroup(rowData.element, values(columns));
  1494. return {
  1495. colgroups: [colgroup$1],
  1496. columns
  1497. };
  1498. }).getOrThunk(() => ({
  1499. colgroups: [],
  1500. columns: {}
  1501. }));
  1502. const grid$1 = grid(maxRows, maxColumns);
  1503. return {
  1504. grid: grid$1,
  1505. access,
  1506. all: cells,
  1507. columns,
  1508. colgroups
  1509. };
  1510. };
  1511. const fromTable = table => {
  1512. const list = fromTable$1(table);
  1513. return generate$1(list);
  1514. };
  1515. const justCells = warehouse => bind$2(warehouse.all, w => w.cells);
  1516. const justColumns = warehouse => values(warehouse.columns);
  1517. const hasColumns = warehouse => keys(warehouse.columns).length > 0;
  1518. const getColumnAt = (warehouse, columnIndex) => Optional.from(warehouse.columns[columnIndex]);
  1519. const Warehouse = {
  1520. fromTable,
  1521. generate: generate$1,
  1522. getAt,
  1523. findItem,
  1524. filterItems,
  1525. justCells,
  1526. justColumns,
  1527. hasColumns,
  1528. getColumnAt
  1529. };
  1530. const columns = (warehouse, isValidCell = always) => {
  1531. const grid = warehouse.grid;
  1532. const cols = range$1(grid.columns, identity);
  1533. const rowsArr = range$1(grid.rows, identity);
  1534. return map$1(cols, col => {
  1535. const getBlock = () => bind$2(rowsArr, r => Warehouse.getAt(warehouse, r, col).filter(detail => detail.column === col).toArray());
  1536. const isValid = detail => detail.colspan === 1 && isValidCell(detail.element);
  1537. const getFallback = () => Warehouse.getAt(warehouse, 0, col);
  1538. return decide(getBlock, isValid, getFallback);
  1539. });
  1540. };
  1541. const decide = (getBlock, isValid, getFallback) => {
  1542. const inBlock = getBlock();
  1543. const validInBlock = find$1(inBlock, isValid);
  1544. const detailOption = validInBlock.orThunk(() => Optional.from(inBlock[0]).orThunk(getFallback));
  1545. return detailOption.map(detail => detail.element);
  1546. };
  1547. const rows = warehouse => {
  1548. const grid = warehouse.grid;
  1549. const rowsArr = range$1(grid.rows, identity);
  1550. const cols = range$1(grid.columns, identity);
  1551. return map$1(rowsArr, row => {
  1552. const getBlock = () => bind$2(cols, c => Warehouse.getAt(warehouse, row, c).filter(detail => detail.row === row).fold(constant([]), detail => [detail]));
  1553. const isSingle = detail => detail.rowspan === 1;
  1554. const getFallback = () => Warehouse.getAt(warehouse, row, 0);
  1555. return decide(getBlock, isSingle, getFallback);
  1556. });
  1557. };
  1558. const deduce = (xs, index) => {
  1559. if (index < 0 || index >= xs.length - 1) {
  1560. return Optional.none();
  1561. }
  1562. const current = xs[index].fold(() => {
  1563. const rest = reverse(xs.slice(0, index));
  1564. return findMap(rest, (a, i) => a.map(aa => ({
  1565. value: aa,
  1566. delta: i + 1
  1567. })));
  1568. }, c => Optional.some({
  1569. value: c,
  1570. delta: 0
  1571. }));
  1572. const next = xs[index + 1].fold(() => {
  1573. const rest = xs.slice(index + 1);
  1574. return findMap(rest, (a, i) => a.map(aa => ({
  1575. value: aa,
  1576. delta: i + 1
  1577. })));
  1578. }, n => Optional.some({
  1579. value: n,
  1580. delta: 1
  1581. }));
  1582. return current.bind(c => next.map(n => {
  1583. const extras = n.delta + c.delta;
  1584. return Math.abs(n.value - c.value) / extras;
  1585. }));
  1586. };
  1587. const onDirection = (isLtr, isRtl) => element => getDirection(element) === 'rtl' ? isRtl : isLtr;
  1588. const getDirection = element => get$a(element, 'direction') === 'rtl' ? 'rtl' : 'ltr';
  1589. const api$1 = Dimension('height', element => {
  1590. const dom = element.dom;
  1591. return inBody(element) ? dom.getBoundingClientRect().height : dom.offsetHeight;
  1592. });
  1593. const get$8 = element => api$1.get(element);
  1594. const getOuter$1 = element => api$1.getOuter(element);
  1595. const getRuntime = getHeight$1;
  1596. const r = (left, top) => {
  1597. const translate = (x, y) => r(left + x, top + y);
  1598. return {
  1599. left,
  1600. top,
  1601. translate
  1602. };
  1603. };
  1604. const SugarPosition = r;
  1605. const boxPosition = dom => {
  1606. const box = dom.getBoundingClientRect();
  1607. return SugarPosition(box.left, box.top);
  1608. };
  1609. const firstDefinedOrZero = (a, b) => {
  1610. if (a !== undefined) {
  1611. return a;
  1612. } else {
  1613. return b !== undefined ? b : 0;
  1614. }
  1615. };
  1616. const absolute = element => {
  1617. const doc = element.dom.ownerDocument;
  1618. const body = doc.body;
  1619. const win = doc.defaultView;
  1620. const html = doc.documentElement;
  1621. if (body === element.dom) {
  1622. return SugarPosition(body.offsetLeft, body.offsetTop);
  1623. }
  1624. const scrollTop = firstDefinedOrZero(win === null || win === void 0 ? void 0 : win.pageYOffset, html.scrollTop);
  1625. const scrollLeft = firstDefinedOrZero(win === null || win === void 0 ? void 0 : win.pageXOffset, html.scrollLeft);
  1626. const clientTop = firstDefinedOrZero(html.clientTop, body.clientTop);
  1627. const clientLeft = firstDefinedOrZero(html.clientLeft, body.clientLeft);
  1628. return viewport(element).translate(scrollLeft - clientLeft, scrollTop - clientTop);
  1629. };
  1630. const viewport = element => {
  1631. const dom = element.dom;
  1632. const doc = dom.ownerDocument;
  1633. const body = doc.body;
  1634. if (body === dom) {
  1635. return SugarPosition(body.offsetLeft, body.offsetTop);
  1636. }
  1637. if (!inBody(element)) {
  1638. return SugarPosition(0, 0);
  1639. }
  1640. return boxPosition(dom);
  1641. };
  1642. const rowInfo = (row, y) => ({
  1643. row,
  1644. y
  1645. });
  1646. const colInfo = (col, x) => ({
  1647. col,
  1648. x
  1649. });
  1650. const rtlEdge = cell => {
  1651. const pos = absolute(cell);
  1652. return pos.left + getOuter$2(cell);
  1653. };
  1654. const ltrEdge = cell => {
  1655. return absolute(cell).left;
  1656. };
  1657. const getLeftEdge = (index, cell) => {
  1658. return colInfo(index, ltrEdge(cell));
  1659. };
  1660. const getRightEdge = (index, cell) => {
  1661. return colInfo(index, rtlEdge(cell));
  1662. };
  1663. const getTop$1 = cell => {
  1664. return absolute(cell).top;
  1665. };
  1666. const getTopEdge = (index, cell) => {
  1667. return rowInfo(index, getTop$1(cell));
  1668. };
  1669. const getBottomEdge = (index, cell) => {
  1670. return rowInfo(index, getTop$1(cell) + getOuter$1(cell));
  1671. };
  1672. const findPositions = (getInnerEdge, getOuterEdge, array) => {
  1673. if (array.length === 0) {
  1674. return [];
  1675. }
  1676. const lines = map$1(array.slice(1), (cellOption, index) => {
  1677. return cellOption.map(cell => {
  1678. return getInnerEdge(index, cell);
  1679. });
  1680. });
  1681. const lastLine = array[array.length - 1].map(cell => {
  1682. return getOuterEdge(array.length - 1, cell);
  1683. });
  1684. return lines.concat([lastLine]);
  1685. };
  1686. const negate = step => {
  1687. return -step;
  1688. };
  1689. const height = {
  1690. delta: identity,
  1691. positions: optElements => findPositions(getTopEdge, getBottomEdge, optElements),
  1692. edge: getTop$1
  1693. };
  1694. const ltr$1 = {
  1695. delta: identity,
  1696. edge: ltrEdge,
  1697. positions: optElements => findPositions(getLeftEdge, getRightEdge, optElements)
  1698. };
  1699. const rtl$1 = {
  1700. delta: negate,
  1701. edge: rtlEdge,
  1702. positions: optElements => findPositions(getRightEdge, getLeftEdge, optElements)
  1703. };
  1704. const detect$1 = onDirection(ltr$1, rtl$1);
  1705. const width = {
  1706. delta: (amount, table) => detect$1(table).delta(amount, table),
  1707. positions: (cols, table) => detect$1(table).positions(cols, table),
  1708. edge: cell => detect$1(cell).edge(cell)
  1709. };
  1710. const units = {
  1711. unsupportedLength: [
  1712. 'em',
  1713. 'ex',
  1714. 'cap',
  1715. 'ch',
  1716. 'ic',
  1717. 'rem',
  1718. 'lh',
  1719. 'rlh',
  1720. 'vw',
  1721. 'vh',
  1722. 'vi',
  1723. 'vb',
  1724. 'vmin',
  1725. 'vmax',
  1726. 'cm',
  1727. 'mm',
  1728. 'Q',
  1729. 'in',
  1730. 'pc',
  1731. 'pt',
  1732. 'px'
  1733. ],
  1734. fixed: [
  1735. 'px',
  1736. 'pt'
  1737. ],
  1738. relative: ['%'],
  1739. empty: ['']
  1740. };
  1741. const pattern = (() => {
  1742. const decimalDigits = '[0-9]+';
  1743. const signedInteger = '[+-]?' + decimalDigits;
  1744. const exponentPart = '[eE]' + signedInteger;
  1745. const dot = '\\.';
  1746. const opt = input => `(?:${ input })?`;
  1747. const unsignedDecimalLiteral = [
  1748. 'Infinity',
  1749. decimalDigits + dot + opt(decimalDigits) + opt(exponentPart),
  1750. dot + decimalDigits + opt(exponentPart),
  1751. decimalDigits + opt(exponentPart)
  1752. ].join('|');
  1753. const float = `[+-]?(?:${ unsignedDecimalLiteral })`;
  1754. return new RegExp(`^(${ float })(.*)$`);
  1755. })();
  1756. const isUnit = (unit, accepted) => exists(accepted, acc => exists(units[acc], check => unit === check));
  1757. const parse = (input, accepted) => {
  1758. const match = Optional.from(pattern.exec(input));
  1759. return match.bind(array => {
  1760. const value = Number(array[1]);
  1761. const unitRaw = array[2];
  1762. if (isUnit(unitRaw, accepted)) {
  1763. return Optional.some({
  1764. value,
  1765. unit: unitRaw
  1766. });
  1767. } else {
  1768. return Optional.none();
  1769. }
  1770. });
  1771. };
  1772. const rPercentageBasedSizeRegex = /(\d+(\.\d+)?)%/;
  1773. const rPixelBasedSizeRegex = /(\d+(\.\d+)?)px|em/;
  1774. const isCol$2 = isTag('col');
  1775. const getPercentSize = (elm, outerGetter, innerGetter) => {
  1776. const relativeParent = parentElement(elm).getOrThunk(() => getBody$1(owner(elm)));
  1777. return outerGetter(elm) / innerGetter(relativeParent) * 100;
  1778. };
  1779. const setPixelWidth = (cell, amount) => {
  1780. set$1(cell, 'width', amount + 'px');
  1781. };
  1782. const setPercentageWidth = (cell, amount) => {
  1783. set$1(cell, 'width', amount + '%');
  1784. };
  1785. const setHeight = (cell, amount) => {
  1786. set$1(cell, 'height', amount + 'px');
  1787. };
  1788. const getHeightValue = cell => getRuntime(cell) + 'px';
  1789. const convert = (cell, number, getter, setter) => {
  1790. const newSize = table(cell).map(table => {
  1791. const total = getter(table);
  1792. return Math.floor(number / 100 * total);
  1793. }).getOr(number);
  1794. setter(cell, newSize);
  1795. return newSize;
  1796. };
  1797. const normalizePixelSize = (value, cell, getter, setter) => {
  1798. const number = parseFloat(value);
  1799. return endsWith(value, '%') && name(cell) !== 'table' ? convert(cell, number, getter, setter) : number;
  1800. };
  1801. const getTotalHeight = cell => {
  1802. const value = getHeightValue(cell);
  1803. if (!value) {
  1804. return get$8(cell);
  1805. }
  1806. return normalizePixelSize(value, cell, get$8, setHeight);
  1807. };
  1808. const get$7 = (cell, type, f) => {
  1809. const v = f(cell);
  1810. const span = getSpan(cell, type);
  1811. return v / span;
  1812. };
  1813. const getRaw$1 = (element, prop) => {
  1814. return getRaw$2(element, prop).orThunk(() => {
  1815. return getOpt(element, prop).map(val => val + 'px');
  1816. });
  1817. };
  1818. const getRawWidth$1 = element => getRaw$1(element, 'width');
  1819. const getRawHeight = element => getRaw$1(element, 'height');
  1820. const getPercentageWidth = cell => getPercentSize(cell, get$9, getInner);
  1821. const getPixelWidth$1 = cell => isCol$2(cell) ? get$9(cell) : getRuntime$1(cell);
  1822. const getHeight = cell => {
  1823. return get$7(cell, 'rowspan', getTotalHeight);
  1824. };
  1825. const getGenericWidth = cell => {
  1826. const width = getRawWidth$1(cell);
  1827. return width.bind(w => parse(w, [
  1828. 'fixed',
  1829. 'relative',
  1830. 'empty'
  1831. ]));
  1832. };
  1833. const setGenericWidth = (cell, amount, unit) => {
  1834. set$1(cell, 'width', amount + unit);
  1835. };
  1836. const getPixelTableWidth = table => get$9(table) + 'px';
  1837. const getPercentTableWidth = table => getPercentSize(table, get$9, getInner) + '%';
  1838. const isPercentSizing$1 = table => getRawWidth$1(table).exists(size => rPercentageBasedSizeRegex.test(size));
  1839. const isPixelSizing$1 = table => getRawWidth$1(table).exists(size => rPixelBasedSizeRegex.test(size));
  1840. const isNoneSizing$1 = table => getRawWidth$1(table).isNone();
  1841. const percentageBasedSizeRegex = constant(rPercentageBasedSizeRegex);
  1842. const isCol$1 = isTag('col');
  1843. const getRawW = cell => {
  1844. return getRawWidth$1(cell).getOrThunk(() => getPixelWidth$1(cell) + 'px');
  1845. };
  1846. const getRawH = cell => {
  1847. return getRawHeight(cell).getOrThunk(() => getHeight(cell) + 'px');
  1848. };
  1849. const justCols = warehouse => map$1(Warehouse.justColumns(warehouse), column => Optional.from(column.element));
  1850. const isValidColumn = cell => {
  1851. const browser = detect$2().browser;
  1852. const supportsColWidths = browser.isChromium() || browser.isFirefox();
  1853. return isCol$1(cell) ? supportsColWidths : true;
  1854. };
  1855. const getDimension = (cellOpt, index, backups, filter, getter, fallback) => cellOpt.filter(filter).fold(() => fallback(deduce(backups, index)), cell => getter(cell));
  1856. const getWidthFrom = (warehouse, table, getWidth, fallback) => {
  1857. const columnCells = columns(warehouse);
  1858. const columns$1 = Warehouse.hasColumns(warehouse) ? justCols(warehouse) : columnCells;
  1859. const backups = [Optional.some(width.edge(table))].concat(map$1(width.positions(columnCells, table), pos => pos.map(p => p.x)));
  1860. const colFilter = not(hasColspan);
  1861. return map$1(columns$1, (cellOption, c) => {
  1862. return getDimension(cellOption, c, backups, colFilter, column => {
  1863. if (isValidColumn(column)) {
  1864. return getWidth(column);
  1865. } else {
  1866. const cell = bindFrom(columnCells[c], identity);
  1867. return getDimension(cell, c, backups, colFilter, cell => fallback(Optional.some(get$9(cell))), fallback);
  1868. }
  1869. }, fallback);
  1870. });
  1871. };
  1872. const getDeduced = deduced => {
  1873. return deduced.map(d => {
  1874. return d + 'px';
  1875. }).getOr('');
  1876. };
  1877. const getRawWidths = (warehouse, table) => {
  1878. return getWidthFrom(warehouse, table, getRawW, getDeduced);
  1879. };
  1880. const getPercentageWidths = (warehouse, table, tableSize) => {
  1881. return getWidthFrom(warehouse, table, getPercentageWidth, deduced => {
  1882. return deduced.fold(() => {
  1883. return tableSize.minCellWidth();
  1884. }, cellWidth => {
  1885. return cellWidth / tableSize.pixelWidth() * 100;
  1886. });
  1887. });
  1888. };
  1889. const getPixelWidths = (warehouse, table, tableSize) => {
  1890. return getWidthFrom(warehouse, table, getPixelWidth$1, deduced => {
  1891. return deduced.getOrThunk(tableSize.minCellWidth);
  1892. });
  1893. };
  1894. const getHeightFrom = (warehouse, table, direction, getHeight, fallback) => {
  1895. const rows$1 = rows(warehouse);
  1896. const backups = [Optional.some(direction.edge(table))].concat(map$1(direction.positions(rows$1, table), pos => pos.map(p => p.y)));
  1897. return map$1(rows$1, (cellOption, c) => {
  1898. return getDimension(cellOption, c, backups, not(hasRowspan), getHeight, fallback);
  1899. });
  1900. };
  1901. const getPixelHeights = (warehouse, table, direction) => {
  1902. return getHeightFrom(warehouse, table, direction, getHeight, deduced => {
  1903. return deduced.getOrThunk(minHeight);
  1904. });
  1905. };
  1906. const getRawHeights = (warehouse, table, direction) => {
  1907. return getHeightFrom(warehouse, table, direction, getRawH, getDeduced);
  1908. };
  1909. const widthLookup = (table, getter) => () => {
  1910. if (inBody(table)) {
  1911. return getter(table);
  1912. } else {
  1913. return parseFloat(getRaw$2(table, 'width').getOr('0'));
  1914. }
  1915. };
  1916. const noneSize = table => {
  1917. const getWidth = widthLookup(table, get$9);
  1918. const zero = constant(0);
  1919. const getWidths = (warehouse, tableSize) => getPixelWidths(warehouse, table, tableSize);
  1920. return {
  1921. width: getWidth,
  1922. pixelWidth: getWidth,
  1923. getWidths,
  1924. getCellDelta: zero,
  1925. singleColumnWidth: constant([0]),
  1926. minCellWidth: zero,
  1927. setElementWidth: noop,
  1928. adjustTableWidth: noop,
  1929. isRelative: true,
  1930. label: 'none'
  1931. };
  1932. };
  1933. const percentageSize = table => {
  1934. const getFloatWidth = widthLookup(table, elem => parseFloat(getPercentTableWidth(elem)));
  1935. const getWidth = widthLookup(table, get$9);
  1936. const getCellDelta = delta => delta / getWidth() * 100;
  1937. const singleColumnWidth = (w, _delta) => [100 - w];
  1938. const minCellWidth = () => minWidth() / getWidth() * 100;
  1939. const adjustTableWidth = delta => {
  1940. const currentWidth = getFloatWidth();
  1941. const change = delta / 100 * currentWidth;
  1942. const newWidth = currentWidth + change;
  1943. setPercentageWidth(table, newWidth);
  1944. };
  1945. const getWidths = (warehouse, tableSize) => getPercentageWidths(warehouse, table, tableSize);
  1946. return {
  1947. width: getFloatWidth,
  1948. pixelWidth: getWidth,
  1949. getWidths,
  1950. getCellDelta,
  1951. singleColumnWidth,
  1952. minCellWidth,
  1953. setElementWidth: setPercentageWidth,
  1954. adjustTableWidth,
  1955. isRelative: true,
  1956. label: 'percent'
  1957. };
  1958. };
  1959. const pixelSize = table => {
  1960. const getWidth = widthLookup(table, get$9);
  1961. const getCellDelta = identity;
  1962. const singleColumnWidth = (w, delta) => {
  1963. const newNext = Math.max(minWidth(), w + delta);
  1964. return [newNext - w];
  1965. };
  1966. const adjustTableWidth = delta => {
  1967. const newWidth = getWidth() + delta;
  1968. setPixelWidth(table, newWidth);
  1969. };
  1970. const getWidths = (warehouse, tableSize) => getPixelWidths(warehouse, table, tableSize);
  1971. return {
  1972. width: getWidth,
  1973. pixelWidth: getWidth,
  1974. getWidths,
  1975. getCellDelta,
  1976. singleColumnWidth,
  1977. minCellWidth: minWidth,
  1978. setElementWidth: setPixelWidth,
  1979. adjustTableWidth,
  1980. isRelative: false,
  1981. label: 'pixel'
  1982. };
  1983. };
  1984. const chooseSize = (element, width) => {
  1985. const percentMatch = percentageBasedSizeRegex().exec(width);
  1986. if (percentMatch !== null) {
  1987. return percentageSize(element);
  1988. } else {
  1989. return pixelSize(element);
  1990. }
  1991. };
  1992. const getTableSize = table => {
  1993. const width = getRawWidth$1(table);
  1994. return width.fold(() => noneSize(table), w => chooseSize(table, w));
  1995. };
  1996. const TableSize = {
  1997. getTableSize,
  1998. pixelSize,
  1999. percentageSize,
  2000. noneSize
  2001. };
  2002. const statsStruct = (minRow, minCol, maxRow, maxCol, allCells, selectedCells) => ({
  2003. minRow,
  2004. minCol,
  2005. maxRow,
  2006. maxCol,
  2007. allCells,
  2008. selectedCells
  2009. });
  2010. const findSelectedStats = (house, isSelected) => {
  2011. const totalColumns = house.grid.columns;
  2012. const totalRows = house.grid.rows;
  2013. let minRow = totalRows;
  2014. let minCol = totalColumns;
  2015. let maxRow = 0;
  2016. let maxCol = 0;
  2017. const allCells = [];
  2018. const selectedCells = [];
  2019. each$1(house.access, detail => {
  2020. allCells.push(detail);
  2021. if (isSelected(detail)) {
  2022. selectedCells.push(detail);
  2023. const startRow = detail.row;
  2024. const endRow = startRow + detail.rowspan - 1;
  2025. const startCol = detail.column;
  2026. const endCol = startCol + detail.colspan - 1;
  2027. if (startRow < minRow) {
  2028. minRow = startRow;
  2029. } else if (endRow > maxRow) {
  2030. maxRow = endRow;
  2031. }
  2032. if (startCol < minCol) {
  2033. minCol = startCol;
  2034. } else if (endCol > maxCol) {
  2035. maxCol = endCol;
  2036. }
  2037. }
  2038. });
  2039. return statsStruct(minRow, minCol, maxRow, maxCol, allCells, selectedCells);
  2040. };
  2041. const makeCell = (list, seenSelected, rowIndex) => {
  2042. const row = list[rowIndex].element;
  2043. const td = SugarElement.fromTag('td');
  2044. append$1(td, SugarElement.fromTag('br'));
  2045. const f = seenSelected ? append$1 : prepend;
  2046. f(row, td);
  2047. };
  2048. const fillInGaps = (list, house, stats, isSelected) => {
  2049. const rows = filter$2(list, row => row.section !== 'colgroup');
  2050. const totalColumns = house.grid.columns;
  2051. const totalRows = house.grid.rows;
  2052. for (let i = 0; i < totalRows; i++) {
  2053. let seenSelected = false;
  2054. for (let j = 0; j < totalColumns; j++) {
  2055. if (!(i < stats.minRow || i > stats.maxRow || j < stats.minCol || j > stats.maxCol)) {
  2056. const needCell = Warehouse.getAt(house, i, j).filter(isSelected).isNone();
  2057. if (needCell) {
  2058. makeCell(rows, seenSelected, i);
  2059. } else {
  2060. seenSelected = true;
  2061. }
  2062. }
  2063. }
  2064. }
  2065. };
  2066. const clean = (replica, stats, house, widthDelta) => {
  2067. each$1(house.columns, col => {
  2068. if (col.column < stats.minCol || col.column > stats.maxCol) {
  2069. remove$6(col.element);
  2070. }
  2071. });
  2072. const emptyRows = filter$2(firstLayer(replica, 'tr'), row => row.dom.childElementCount === 0);
  2073. each$2(emptyRows, remove$6);
  2074. if (stats.minCol === stats.maxCol || stats.minRow === stats.maxRow) {
  2075. each$2(firstLayer(replica, 'th,td'), cell => {
  2076. remove$7(cell, 'rowspan');
  2077. remove$7(cell, 'colspan');
  2078. });
  2079. }
  2080. remove$7(replica, LOCKED_COL_ATTR);
  2081. remove$7(replica, 'data-snooker-col-series');
  2082. const tableSize = TableSize.getTableSize(replica);
  2083. tableSize.adjustTableWidth(widthDelta);
  2084. };
  2085. const getTableWidthDelta = (table, warehouse, tableSize, stats) => {
  2086. if (stats.minCol === 0 && warehouse.grid.columns === stats.maxCol + 1) {
  2087. return 0;
  2088. }
  2089. const colWidths = getPixelWidths(warehouse, table, tableSize);
  2090. const allColsWidth = foldl(colWidths, (acc, width) => acc + width, 0);
  2091. const selectedColsWidth = foldl(colWidths.slice(stats.minCol, stats.maxCol + 1), (acc, width) => acc + width, 0);
  2092. const newWidth = selectedColsWidth / allColsWidth * tableSize.pixelWidth();
  2093. const delta = newWidth - tableSize.pixelWidth();
  2094. return tableSize.getCellDelta(delta);
  2095. };
  2096. const extract$1 = (table, selectedSelector) => {
  2097. const isSelected = detail => is$2(detail.element, selectedSelector);
  2098. const replica = deep(table);
  2099. const list = fromTable$1(replica);
  2100. const tableSize = TableSize.getTableSize(table);
  2101. const replicaHouse = Warehouse.generate(list);
  2102. const replicaStats = findSelectedStats(replicaHouse, isSelected);
  2103. const selector = 'th:not(' + selectedSelector + ')' + ',td:not(' + selectedSelector + ')';
  2104. const unselectedCells = filterFirstLayer(replica, 'th,td', cell => is$2(cell, selector));
  2105. each$2(unselectedCells, remove$6);
  2106. fillInGaps(list, replicaHouse, replicaStats, isSelected);
  2107. const house = Warehouse.fromTable(table);
  2108. const widthDelta = getTableWidthDelta(table, house, tableSize, replicaStats);
  2109. clean(replica, replicaStats, replicaHouse, widthDelta);
  2110. return replica;
  2111. };
  2112. const nbsp = '\xA0';
  2113. const NodeValue = (is, name) => {
  2114. const get = element => {
  2115. if (!is(element)) {
  2116. throw new Error('Can only get ' + name + ' value of a ' + name + ' node');
  2117. }
  2118. return getOption(element).getOr('');
  2119. };
  2120. const getOption = element => is(element) ? Optional.from(element.dom.nodeValue) : Optional.none();
  2121. const set = (element, value) => {
  2122. if (!is(element)) {
  2123. throw new Error('Can only set raw ' + name + ' value of a ' + name + ' node');
  2124. }
  2125. element.dom.nodeValue = value;
  2126. };
  2127. return {
  2128. get,
  2129. getOption,
  2130. set
  2131. };
  2132. };
  2133. const api = NodeValue(isText, 'text');
  2134. const get$6 = element => api.get(element);
  2135. const getOption = element => api.getOption(element);
  2136. const set = (element, value) => api.set(element, value);
  2137. const getEnd = element => name(element) === 'img' ? 1 : getOption(element).fold(() => children$2(element).length, v => v.length);
  2138. const isTextNodeWithCursorPosition = el => getOption(el).filter(text => text.trim().length !== 0 || text.indexOf(nbsp) > -1).isSome();
  2139. const isContentEditableFalse = elem => isHTMLElement(elem) && get$b(elem, 'contenteditable') === 'false';
  2140. const elementsWithCursorPosition = [
  2141. 'img',
  2142. 'br'
  2143. ];
  2144. const isCursorPosition = elem => {
  2145. const hasCursorPosition = isTextNodeWithCursorPosition(elem);
  2146. return hasCursorPosition || contains$2(elementsWithCursorPosition, name(elem)) || isContentEditableFalse(elem);
  2147. };
  2148. const first = element => descendant$1(element, isCursorPosition);
  2149. const last$1 = element => descendantRtl(element, isCursorPosition);
  2150. const descendantRtl = (scope, predicate) => {
  2151. const descend = element => {
  2152. const children = children$2(element);
  2153. for (let i = children.length - 1; i >= 0; i--) {
  2154. const child = children[i];
  2155. if (predicate(child)) {
  2156. return Optional.some(child);
  2157. }
  2158. const res = descend(child);
  2159. if (res.isSome()) {
  2160. return res;
  2161. }
  2162. }
  2163. return Optional.none();
  2164. };
  2165. return descend(scope);
  2166. };
  2167. const transferableAttributes = {
  2168. scope: [
  2169. 'row',
  2170. 'col'
  2171. ]
  2172. };
  2173. const createCell = doc => () => {
  2174. const td = SugarElement.fromTag('td', doc.dom);
  2175. append$1(td, SugarElement.fromTag('br', doc.dom));
  2176. return td;
  2177. };
  2178. const createCol = doc => () => {
  2179. return SugarElement.fromTag('col', doc.dom);
  2180. };
  2181. const createColgroup = doc => () => {
  2182. return SugarElement.fromTag('colgroup', doc.dom);
  2183. };
  2184. const createRow$1 = doc => () => {
  2185. return SugarElement.fromTag('tr', doc.dom);
  2186. };
  2187. const replace$1 = (cell, tag, attrs) => {
  2188. const replica = copy$2(cell, tag);
  2189. each$1(attrs, (v, k) => {
  2190. if (v === null) {
  2191. remove$7(replica, k);
  2192. } else {
  2193. set$2(replica, k, v);
  2194. }
  2195. });
  2196. return replica;
  2197. };
  2198. const pasteReplace = cell => {
  2199. return cell;
  2200. };
  2201. const cloneFormats = (oldCell, newCell, formats) => {
  2202. const first$1 = first(oldCell);
  2203. return first$1.map(firstText => {
  2204. const formatSelector = formats.join(',');
  2205. const parents = ancestors$3(firstText, formatSelector, element => {
  2206. return eq$1(element, oldCell);
  2207. });
  2208. return foldr(parents, (last, parent) => {
  2209. const clonedFormat = shallow(parent);
  2210. append$1(last, clonedFormat);
  2211. return clonedFormat;
  2212. }, newCell);
  2213. }).getOr(newCell);
  2214. };
  2215. const cloneAppropriateAttributes = (original, clone) => {
  2216. each$1(transferableAttributes, (validAttributes, attributeName) => getOpt(original, attributeName).filter(attribute => contains$2(validAttributes, attribute)).each(attribute => set$2(clone, attributeName, attribute)));
  2217. };
  2218. const cellOperations = (mutate, doc, formatsToClone) => {
  2219. const cloneCss = (prev, clone) => {
  2220. copy$1(prev.element, clone);
  2221. remove$5(clone, 'height');
  2222. if (prev.colspan !== 1) {
  2223. remove$5(clone, 'width');
  2224. }
  2225. };
  2226. const newCell = prev => {
  2227. const td = SugarElement.fromTag(name(prev.element), doc.dom);
  2228. const formats = formatsToClone.getOr([
  2229. 'strong',
  2230. 'em',
  2231. 'b',
  2232. 'i',
  2233. 'span',
  2234. 'font',
  2235. 'h1',
  2236. 'h2',
  2237. 'h3',
  2238. 'h4',
  2239. 'h5',
  2240. 'h6',
  2241. 'p',
  2242. 'div'
  2243. ]);
  2244. const lastNode = formats.length > 0 ? cloneFormats(prev.element, td, formats) : td;
  2245. append$1(lastNode, SugarElement.fromTag('br'));
  2246. cloneCss(prev, td);
  2247. cloneAppropriateAttributes(prev.element, td);
  2248. mutate(prev.element, td);
  2249. return td;
  2250. };
  2251. const newCol = prev => {
  2252. const col = SugarElement.fromTag(name(prev.element), doc.dom);
  2253. cloneCss(prev, col);
  2254. mutate(prev.element, col);
  2255. return col;
  2256. };
  2257. return {
  2258. col: newCol,
  2259. colgroup: createColgroup(doc),
  2260. row: createRow$1(doc),
  2261. cell: newCell,
  2262. replace: replace$1,
  2263. colGap: createCol(doc),
  2264. gap: createCell(doc)
  2265. };
  2266. };
  2267. const paste$1 = doc => {
  2268. return {
  2269. col: createCol(doc),
  2270. colgroup: createColgroup(doc),
  2271. row: createRow$1(doc),
  2272. cell: createCell(doc),
  2273. replace: pasteReplace,
  2274. colGap: createCol(doc),
  2275. gap: createCell(doc)
  2276. };
  2277. };
  2278. const fromHtml = (html, scope) => {
  2279. const doc = scope || document;
  2280. const div = doc.createElement('div');
  2281. div.innerHTML = html;
  2282. return children$2(SugarElement.fromDom(div));
  2283. };
  2284. const fromDom = nodes => map$1(nodes, SugarElement.fromDom);
  2285. const option = name => editor => editor.options.get(name);
  2286. const defaultWidth = '100%';
  2287. const getPixelForcedWidth = editor => {
  2288. var _a;
  2289. const dom = editor.dom;
  2290. const parentBlock = (_a = dom.getParent(editor.selection.getStart(), dom.isBlock)) !== null && _a !== void 0 ? _a : editor.getBody();
  2291. return getInner(SugarElement.fromDom(parentBlock)) + 'px';
  2292. };
  2293. const determineDefaultTableStyles = (editor, defaultStyles) => {
  2294. if (isTableResponsiveForced(editor) || !shouldStyleWithCss(editor)) {
  2295. return defaultStyles;
  2296. } else if (isTablePixelsForced(editor)) {
  2297. return {
  2298. ...defaultStyles,
  2299. width: getPixelForcedWidth(editor)
  2300. };
  2301. } else {
  2302. return {
  2303. ...defaultStyles,
  2304. width: defaultWidth
  2305. };
  2306. }
  2307. };
  2308. const determineDefaultTableAttributes = (editor, defaultAttributes) => {
  2309. if (isTableResponsiveForced(editor) || shouldStyleWithCss(editor)) {
  2310. return defaultAttributes;
  2311. } else if (isTablePixelsForced(editor)) {
  2312. return {
  2313. ...defaultAttributes,
  2314. width: getPixelForcedWidth(editor)
  2315. };
  2316. } else {
  2317. return {
  2318. ...defaultAttributes,
  2319. width: defaultWidth
  2320. };
  2321. }
  2322. };
  2323. const register = editor => {
  2324. const registerOption = editor.options.register;
  2325. registerOption('table_clone_elements', { processor: 'string[]' });
  2326. registerOption('table_use_colgroups', {
  2327. processor: 'boolean',
  2328. default: true
  2329. });
  2330. registerOption('table_header_type', {
  2331. processor: value => {
  2332. const valid = contains$2([
  2333. 'section',
  2334. 'cells',
  2335. 'sectionCells',
  2336. 'auto'
  2337. ], value);
  2338. return valid ? {
  2339. value,
  2340. valid
  2341. } : {
  2342. valid: false,
  2343. message: 'Must be one of: section, cells, sectionCells or auto.'
  2344. };
  2345. },
  2346. default: 'section'
  2347. });
  2348. registerOption('table_sizing_mode', {
  2349. processor: 'string',
  2350. default: 'auto'
  2351. });
  2352. registerOption('table_default_attributes', {
  2353. processor: 'object',
  2354. default: { border: '1' }
  2355. });
  2356. registerOption('table_default_styles', {
  2357. processor: 'object',
  2358. default: { 'border-collapse': 'collapse' }
  2359. });
  2360. registerOption('table_column_resizing', {
  2361. processor: value => {
  2362. const valid = contains$2([
  2363. 'preservetable',
  2364. 'resizetable'
  2365. ], value);
  2366. return valid ? {
  2367. value,
  2368. valid
  2369. } : {
  2370. valid: false,
  2371. message: 'Must be preservetable, or resizetable.'
  2372. };
  2373. },
  2374. default: 'preservetable'
  2375. });
  2376. registerOption('table_resize_bars', {
  2377. processor: 'boolean',
  2378. default: true
  2379. });
  2380. registerOption('table_style_by_css', {
  2381. processor: 'boolean',
  2382. default: true
  2383. });
  2384. registerOption('table_merge_content_on_paste', {
  2385. processor: 'boolean',
  2386. default: true
  2387. });
  2388. };
  2389. const getTableCloneElements = editor => {
  2390. return Optional.from(editor.options.get('table_clone_elements'));
  2391. };
  2392. const hasTableObjectResizing = editor => {
  2393. const objectResizing = editor.options.get('object_resizing');
  2394. return contains$2(objectResizing.split(','), 'table');
  2395. };
  2396. const getTableHeaderType = option('table_header_type');
  2397. const getTableColumnResizingBehaviour = option('table_column_resizing');
  2398. const isPreserveTableColumnResizing = editor => getTableColumnResizingBehaviour(editor) === 'preservetable';
  2399. const isResizeTableColumnResizing = editor => getTableColumnResizingBehaviour(editor) === 'resizetable';
  2400. const getTableSizingMode = option('table_sizing_mode');
  2401. const isTablePercentagesForced = editor => getTableSizingMode(editor) === 'relative';
  2402. const isTablePixelsForced = editor => getTableSizingMode(editor) === 'fixed';
  2403. const isTableResponsiveForced = editor => getTableSizingMode(editor) === 'responsive';
  2404. const hasTableResizeBars = option('table_resize_bars');
  2405. const shouldStyleWithCss = option('table_style_by_css');
  2406. const shouldMergeContentOnPaste = option('table_merge_content_on_paste');
  2407. const getTableDefaultAttributes = editor => {
  2408. const options = editor.options;
  2409. const defaultAttributes = options.get('table_default_attributes');
  2410. return options.isSet('table_default_attributes') ? defaultAttributes : determineDefaultTableAttributes(editor, defaultAttributes);
  2411. };
  2412. const getTableDefaultStyles = editor => {
  2413. const options = editor.options;
  2414. const defaultStyles = options.get('table_default_styles');
  2415. return options.isSet('table_default_styles') ? defaultStyles : determineDefaultTableStyles(editor, defaultStyles);
  2416. };
  2417. const tableUseColumnGroup = option('table_use_colgroups');
  2418. const closest = target => closest$1(target, '[contenteditable]');
  2419. const isEditable$1 = (element, assumeEditable = false) => {
  2420. if (inBody(element)) {
  2421. return element.dom.isContentEditable;
  2422. } else {
  2423. return closest(element).fold(constant(assumeEditable), editable => getRaw(editable) === 'true');
  2424. }
  2425. };
  2426. const getRaw = element => element.dom.contentEditable;
  2427. const getBody = editor => SugarElement.fromDom(editor.getBody());
  2428. const getIsRoot = editor => element => eq$1(element, getBody(editor));
  2429. const removeDataStyle = table => {
  2430. remove$7(table, 'data-mce-style');
  2431. const removeStyleAttribute = element => remove$7(element, 'data-mce-style');
  2432. each$2(cells$1(table), removeStyleAttribute);
  2433. each$2(columns$1(table), removeStyleAttribute);
  2434. each$2(rows$1(table), removeStyleAttribute);
  2435. };
  2436. const getSelectionStart = editor => SugarElement.fromDom(editor.selection.getStart());
  2437. const getPixelWidth = elm => elm.getBoundingClientRect().width;
  2438. const getPixelHeight = elm => elm.getBoundingClientRect().height;
  2439. const getRawWidth = (editor, elm) => {
  2440. const raw = editor.dom.getStyle(elm, 'width') || editor.dom.getAttrib(elm, 'width');
  2441. return Optional.from(raw).filter(isNotEmpty);
  2442. };
  2443. const isPercentage$1 = value => /^(\d+(\.\d+)?)%$/.test(value);
  2444. const isPixel = value => /^(\d+(\.\d+)?)px$/.test(value);
  2445. const isInEditableContext$1 = cell => closest$2(cell, isTag('table')).exists(isEditable$1);
  2446. const inSelection = (bounds, detail) => {
  2447. const leftEdge = detail.column;
  2448. const rightEdge = detail.column + detail.colspan - 1;
  2449. const topEdge = detail.row;
  2450. const bottomEdge = detail.row + detail.rowspan - 1;
  2451. return leftEdge <= bounds.finishCol && rightEdge >= bounds.startCol && (topEdge <= bounds.finishRow && bottomEdge >= bounds.startRow);
  2452. };
  2453. const isWithin = (bounds, detail) => {
  2454. return detail.column >= bounds.startCol && detail.column + detail.colspan - 1 <= bounds.finishCol && detail.row >= bounds.startRow && detail.row + detail.rowspan - 1 <= bounds.finishRow;
  2455. };
  2456. const isRectangular = (warehouse, bounds) => {
  2457. let isRect = true;
  2458. const detailIsWithin = curry(isWithin, bounds);
  2459. for (let i = bounds.startRow; i <= bounds.finishRow; i++) {
  2460. for (let j = bounds.startCol; j <= bounds.finishCol; j++) {
  2461. isRect = isRect && Warehouse.getAt(warehouse, i, j).exists(detailIsWithin);
  2462. }
  2463. }
  2464. return isRect ? Optional.some(bounds) : Optional.none();
  2465. };
  2466. const getBounds = (detailA, detailB) => {
  2467. return bounds(Math.min(detailA.row, detailB.row), Math.min(detailA.column, detailB.column), Math.max(detailA.row + detailA.rowspan - 1, detailB.row + detailB.rowspan - 1), Math.max(detailA.column + detailA.colspan - 1, detailB.column + detailB.colspan - 1));
  2468. };
  2469. const getAnyBox = (warehouse, startCell, finishCell) => {
  2470. const startCoords = Warehouse.findItem(warehouse, startCell, eq$1);
  2471. const finishCoords = Warehouse.findItem(warehouse, finishCell, eq$1);
  2472. return startCoords.bind(sc => {
  2473. return finishCoords.map(fc => {
  2474. return getBounds(sc, fc);
  2475. });
  2476. });
  2477. };
  2478. const getBox$1 = (warehouse, startCell, finishCell) => {
  2479. return getAnyBox(warehouse, startCell, finishCell).bind(bounds => {
  2480. return isRectangular(warehouse, bounds);
  2481. });
  2482. };
  2483. const moveBy$1 = (warehouse, cell, row, column) => {
  2484. return Warehouse.findItem(warehouse, cell, eq$1).bind(detail => {
  2485. const startRow = row > 0 ? detail.row + detail.rowspan - 1 : detail.row;
  2486. const startCol = column > 0 ? detail.column + detail.colspan - 1 : detail.column;
  2487. const dest = Warehouse.getAt(warehouse, startRow + row, startCol + column);
  2488. return dest.map(d => {
  2489. return d.element;
  2490. });
  2491. });
  2492. };
  2493. const intercepts$1 = (warehouse, start, finish) => {
  2494. return getAnyBox(warehouse, start, finish).map(bounds => {
  2495. const inside = Warehouse.filterItems(warehouse, curry(inSelection, bounds));
  2496. return map$1(inside, detail => {
  2497. return detail.element;
  2498. });
  2499. });
  2500. };
  2501. const parentCell = (warehouse, innerCell) => {
  2502. const isContainedBy = (c1, c2) => {
  2503. return contains$1(c2, c1);
  2504. };
  2505. return Warehouse.findItem(warehouse, innerCell, isContainedBy).map(detail => {
  2506. return detail.element;
  2507. });
  2508. };
  2509. const moveBy = (cell, deltaRow, deltaColumn) => {
  2510. return table(cell).bind(table => {
  2511. const warehouse = getWarehouse(table);
  2512. return moveBy$1(warehouse, cell, deltaRow, deltaColumn);
  2513. });
  2514. };
  2515. const intercepts = (table, first, last) => {
  2516. const warehouse = getWarehouse(table);
  2517. return intercepts$1(warehouse, first, last);
  2518. };
  2519. const nestedIntercepts = (table, first, firstTable, last, lastTable) => {
  2520. const warehouse = getWarehouse(table);
  2521. const optStartCell = eq$1(table, firstTable) ? Optional.some(first) : parentCell(warehouse, first);
  2522. const optLastCell = eq$1(table, lastTable) ? Optional.some(last) : parentCell(warehouse, last);
  2523. return optStartCell.bind(startCell => optLastCell.bind(lastCell => intercepts$1(warehouse, startCell, lastCell)));
  2524. };
  2525. const getBox = (table, first, last) => {
  2526. const warehouse = getWarehouse(table);
  2527. return getBox$1(warehouse, first, last);
  2528. };
  2529. const getWarehouse = Warehouse.fromTable;
  2530. var TagBoundaries = [
  2531. 'body',
  2532. 'p',
  2533. 'div',
  2534. 'article',
  2535. 'aside',
  2536. 'figcaption',
  2537. 'figure',
  2538. 'footer',
  2539. 'header',
  2540. 'nav',
  2541. 'section',
  2542. 'ol',
  2543. 'ul',
  2544. 'li',
  2545. 'table',
  2546. 'thead',
  2547. 'tbody',
  2548. 'tfoot',
  2549. 'caption',
  2550. 'tr',
  2551. 'td',
  2552. 'th',
  2553. 'h1',
  2554. 'h2',
  2555. 'h3',
  2556. 'h4',
  2557. 'h5',
  2558. 'h6',
  2559. 'blockquote',
  2560. 'pre',
  2561. 'address'
  2562. ];
  2563. var DomUniverse = () => {
  2564. const clone = element => {
  2565. return SugarElement.fromDom(element.dom.cloneNode(false));
  2566. };
  2567. const document = element => documentOrOwner(element).dom;
  2568. const isBoundary = element => {
  2569. if (!isElement(element)) {
  2570. return false;
  2571. }
  2572. if (name(element) === 'body') {
  2573. return true;
  2574. }
  2575. return contains$2(TagBoundaries, name(element));
  2576. };
  2577. const isEmptyTag = element => {
  2578. if (!isElement(element)) {
  2579. return false;
  2580. }
  2581. return contains$2([
  2582. 'br',
  2583. 'img',
  2584. 'hr',
  2585. 'input'
  2586. ], name(element));
  2587. };
  2588. const isNonEditable = element => isElement(element) && get$b(element, 'contenteditable') === 'false';
  2589. const comparePosition = (element, other) => {
  2590. return element.dom.compareDocumentPosition(other.dom);
  2591. };
  2592. const copyAttributesTo = (source, destination) => {
  2593. const as = clone$2(source);
  2594. setAll$1(destination, as);
  2595. };
  2596. const isSpecial = element => {
  2597. const tag = name(element);
  2598. return contains$2([
  2599. 'script',
  2600. 'noscript',
  2601. 'iframe',
  2602. 'noframes',
  2603. 'noembed',
  2604. 'title',
  2605. 'style',
  2606. 'textarea',
  2607. 'xmp'
  2608. ], tag);
  2609. };
  2610. const getLanguage = element => isElement(element) ? getOpt(element, 'lang') : Optional.none();
  2611. return {
  2612. up: constant({
  2613. selector: ancestor$1,
  2614. closest: closest$1,
  2615. predicate: ancestor$2,
  2616. all: parents
  2617. }),
  2618. down: constant({
  2619. selector: descendants,
  2620. predicate: descendants$1
  2621. }),
  2622. styles: constant({
  2623. get: get$a,
  2624. getRaw: getRaw$2,
  2625. set: set$1,
  2626. remove: remove$5
  2627. }),
  2628. attrs: constant({
  2629. get: get$b,
  2630. set: set$2,
  2631. remove: remove$7,
  2632. copyTo: copyAttributesTo
  2633. }),
  2634. insert: constant({
  2635. before: before$3,
  2636. after: after$5,
  2637. afterAll: after$4,
  2638. append: append$1,
  2639. appendAll: append,
  2640. prepend: prepend,
  2641. wrap: wrap
  2642. }),
  2643. remove: constant({
  2644. unwrap: unwrap,
  2645. remove: remove$6
  2646. }),
  2647. create: constant({
  2648. nu: SugarElement.fromTag,
  2649. clone,
  2650. text: SugarElement.fromText
  2651. }),
  2652. query: constant({
  2653. comparePosition,
  2654. prevSibling: prevSibling,
  2655. nextSibling: nextSibling
  2656. }),
  2657. property: constant({
  2658. children: children$2,
  2659. name: name,
  2660. parent: parent,
  2661. document,
  2662. isText: isText,
  2663. isComment: isComment,
  2664. isElement: isElement,
  2665. isSpecial,
  2666. getLanguage,
  2667. getText: get$6,
  2668. setText: set,
  2669. isBoundary,
  2670. isEmptyTag,
  2671. isNonEditable
  2672. }),
  2673. eq: eq$1,
  2674. is: is$1
  2675. };
  2676. };
  2677. const all = (universe, look, elements, f) => {
  2678. const head = elements[0];
  2679. const tail = elements.slice(1);
  2680. return f(universe, look, head, tail);
  2681. };
  2682. const oneAll = (universe, look, elements) => {
  2683. return elements.length > 0 ? all(universe, look, elements, unsafeOne) : Optional.none();
  2684. };
  2685. const unsafeOne = (universe, look, head, tail) => {
  2686. const start = look(universe, head);
  2687. return foldr(tail, (b, a) => {
  2688. const current = look(universe, a);
  2689. return commonElement(universe, b, current);
  2690. }, start);
  2691. };
  2692. const commonElement = (universe, start, end) => {
  2693. return start.bind(s => {
  2694. return end.filter(curry(universe.eq, s));
  2695. });
  2696. };
  2697. const eq = (universe, item) => {
  2698. return curry(universe.eq, item);
  2699. };
  2700. const ancestors$2 = (universe, start, end, isRoot = never) => {
  2701. const ps1 = [start].concat(universe.up().all(start));
  2702. const ps2 = [end].concat(universe.up().all(end));
  2703. const prune = path => {
  2704. const index = findIndex(path, isRoot);
  2705. return index.fold(() => {
  2706. return path;
  2707. }, ind => {
  2708. return path.slice(0, ind + 1);
  2709. });
  2710. };
  2711. const pruned1 = prune(ps1);
  2712. const pruned2 = prune(ps2);
  2713. const shared = find$1(pruned1, x => {
  2714. return exists(pruned2, eq(universe, x));
  2715. });
  2716. return {
  2717. firstpath: pruned1,
  2718. secondpath: pruned2,
  2719. shared
  2720. };
  2721. };
  2722. const sharedOne$1 = oneAll;
  2723. const ancestors$1 = ancestors$2;
  2724. const universe$3 = DomUniverse();
  2725. const sharedOne = (look, elements) => {
  2726. return sharedOne$1(universe$3, (_universe, element) => {
  2727. return look(element);
  2728. }, elements);
  2729. };
  2730. const ancestors = (start, finish, isRoot) => {
  2731. return ancestors$1(universe$3, start, finish, isRoot);
  2732. };
  2733. const lookupTable = container => {
  2734. return ancestor$1(container, 'table');
  2735. };
  2736. const identify = (start, finish, isRoot) => {
  2737. const getIsRoot = rootTable => {
  2738. return element => {
  2739. return isRoot !== undefined && isRoot(element) || eq$1(element, rootTable);
  2740. };
  2741. };
  2742. if (eq$1(start, finish)) {
  2743. return Optional.some({
  2744. boxes: Optional.some([start]),
  2745. start,
  2746. finish
  2747. });
  2748. } else {
  2749. return lookupTable(start).bind(startTable => {
  2750. return lookupTable(finish).bind(finishTable => {
  2751. if (eq$1(startTable, finishTable)) {
  2752. return Optional.some({
  2753. boxes: intercepts(startTable, start, finish),
  2754. start,
  2755. finish
  2756. });
  2757. } else if (contains$1(startTable, finishTable)) {
  2758. const ancestorCells = ancestors$3(finish, 'td,th', getIsRoot(startTable));
  2759. const finishCell = ancestorCells.length > 0 ? ancestorCells[ancestorCells.length - 1] : finish;
  2760. return Optional.some({
  2761. boxes: nestedIntercepts(startTable, start, startTable, finish, finishTable),
  2762. start,
  2763. finish: finishCell
  2764. });
  2765. } else if (contains$1(finishTable, startTable)) {
  2766. const ancestorCells = ancestors$3(start, 'td,th', getIsRoot(finishTable));
  2767. const startCell = ancestorCells.length > 0 ? ancestorCells[ancestorCells.length - 1] : start;
  2768. return Optional.some({
  2769. boxes: nestedIntercepts(finishTable, start, startTable, finish, finishTable),
  2770. start,
  2771. finish: startCell
  2772. });
  2773. } else {
  2774. return ancestors(start, finish).shared.bind(lca => {
  2775. return closest$1(lca, 'table', isRoot).bind(lcaTable => {
  2776. const finishAncestorCells = ancestors$3(finish, 'td,th', getIsRoot(lcaTable));
  2777. const finishCell = finishAncestorCells.length > 0 ? finishAncestorCells[finishAncestorCells.length - 1] : finish;
  2778. const startAncestorCells = ancestors$3(start, 'td,th', getIsRoot(lcaTable));
  2779. const startCell = startAncestorCells.length > 0 ? startAncestorCells[startAncestorCells.length - 1] : start;
  2780. return Optional.some({
  2781. boxes: nestedIntercepts(lcaTable, start, startTable, finish, finishTable),
  2782. start: startCell,
  2783. finish: finishCell
  2784. });
  2785. });
  2786. });
  2787. }
  2788. });
  2789. });
  2790. }
  2791. };
  2792. const retrieve$1 = (container, selector) => {
  2793. const sels = descendants(container, selector);
  2794. return sels.length > 0 ? Optional.some(sels) : Optional.none();
  2795. };
  2796. const getLast = (boxes, lastSelectedSelector) => {
  2797. return find$1(boxes, box => {
  2798. return is$2(box, lastSelectedSelector);
  2799. });
  2800. };
  2801. const getEdges = (container, firstSelectedSelector, lastSelectedSelector) => {
  2802. return descendant(container, firstSelectedSelector).bind(first => {
  2803. return descendant(container, lastSelectedSelector).bind(last => {
  2804. return sharedOne(lookupTable, [
  2805. first,
  2806. last
  2807. ]).map(table => {
  2808. return {
  2809. first,
  2810. last,
  2811. table
  2812. };
  2813. });
  2814. });
  2815. });
  2816. };
  2817. const expandTo = (finish, firstSelectedSelector) => {
  2818. return ancestor$1(finish, 'table').bind(table => {
  2819. return descendant(table, firstSelectedSelector).bind(start => {
  2820. return identify(start, finish).bind(identified => {
  2821. return identified.boxes.map(boxes => {
  2822. return {
  2823. boxes,
  2824. start: identified.start,
  2825. finish: identified.finish
  2826. };
  2827. });
  2828. });
  2829. });
  2830. });
  2831. };
  2832. const shiftSelection = (boxes, deltaRow, deltaColumn, firstSelectedSelector, lastSelectedSelector) => {
  2833. return getLast(boxes, lastSelectedSelector).bind(last => {
  2834. return moveBy(last, deltaRow, deltaColumn).bind(finish => {
  2835. return expandTo(finish, firstSelectedSelector);
  2836. });
  2837. });
  2838. };
  2839. const retrieve = (container, selector) => {
  2840. return retrieve$1(container, selector);
  2841. };
  2842. const retrieveBox = (container, firstSelectedSelector, lastSelectedSelector) => {
  2843. return getEdges(container, firstSelectedSelector, lastSelectedSelector).bind(edges => {
  2844. const isRoot = ancestor => {
  2845. return eq$1(container, ancestor);
  2846. };
  2847. const sectionSelector = 'thead,tfoot,tbody,table';
  2848. const firstAncestor = ancestor$1(edges.first, sectionSelector, isRoot);
  2849. const lastAncestor = ancestor$1(edges.last, sectionSelector, isRoot);
  2850. return firstAncestor.bind(fA => {
  2851. return lastAncestor.bind(lA => {
  2852. return eq$1(fA, lA) ? getBox(edges.table, edges.first, edges.last) : Optional.none();
  2853. });
  2854. });
  2855. });
  2856. };
  2857. const selection = identity;
  2858. const unmergable = selectedCells => {
  2859. const hasSpan = (elem, type) => getOpt(elem, type).exists(span => parseInt(span, 10) > 1);
  2860. const hasRowOrColSpan = elem => hasSpan(elem, 'rowspan') || hasSpan(elem, 'colspan');
  2861. return selectedCells.length > 0 && forall(selectedCells, hasRowOrColSpan) ? Optional.some(selectedCells) : Optional.none();
  2862. };
  2863. const mergable = (table, selectedCells, ephemera) => {
  2864. if (selectedCells.length <= 1) {
  2865. return Optional.none();
  2866. } else {
  2867. return retrieveBox(table, ephemera.firstSelectedSelector, ephemera.lastSelectedSelector).map(bounds => ({
  2868. bounds,
  2869. cells: selectedCells
  2870. }));
  2871. }
  2872. };
  2873. const strSelected = 'data-mce-selected';
  2874. const strSelectedSelector = 'td[' + strSelected + '],th[' + strSelected + ']';
  2875. const strAttributeSelector = '[' + strSelected + ']';
  2876. const strFirstSelected = 'data-mce-first-selected';
  2877. const strFirstSelectedSelector = 'td[' + strFirstSelected + '],th[' + strFirstSelected + ']';
  2878. const strLastSelected = 'data-mce-last-selected';
  2879. const strLastSelectedSelector = 'td[' + strLastSelected + '],th[' + strLastSelected + ']';
  2880. const attributeSelector = strAttributeSelector;
  2881. const ephemera = {
  2882. selected: strSelected,
  2883. selectedSelector: strSelectedSelector,
  2884. firstSelected: strFirstSelected,
  2885. firstSelectedSelector: strFirstSelectedSelector,
  2886. lastSelected: strLastSelected,
  2887. lastSelectedSelector: strLastSelectedSelector
  2888. };
  2889. const forMenu = (selectedCells, table, cell) => ({
  2890. element: cell,
  2891. mergable: mergable(table, selectedCells, ephemera),
  2892. unmergable: unmergable(selectedCells),
  2893. selection: selection(selectedCells)
  2894. });
  2895. const paste = (element, clipboard, generators) => ({
  2896. element,
  2897. clipboard,
  2898. generators
  2899. });
  2900. const pasteRows = (selectedCells, _cell, clipboard, generators) => ({
  2901. selection: selection(selectedCells),
  2902. clipboard,
  2903. generators
  2904. });
  2905. const getSelectionCellFallback = element => table(element).bind(table => retrieve(table, ephemera.firstSelectedSelector)).fold(constant(element), cells => cells[0]);
  2906. const getSelectionFromSelector = selector => (initCell, isRoot) => {
  2907. const cellName = name(initCell);
  2908. const cell = cellName === 'col' || cellName === 'colgroup' ? getSelectionCellFallback(initCell) : initCell;
  2909. return closest$1(cell, selector, isRoot);
  2910. };
  2911. const getSelectionCellOrCaption = getSelectionFromSelector('th,td,caption');
  2912. const getSelectionCell = getSelectionFromSelector('th,td');
  2913. const getCellsFromSelection = editor => fromDom(editor.model.table.getSelectedCells());
  2914. const getCellsFromFakeSelection = editor => filter$2(getCellsFromSelection(editor), cell => is$2(cell, ephemera.selectedSelector));
  2915. const extractSelected = cells => {
  2916. return table(cells[0]).map(table => {
  2917. const replica = extract$1(table, attributeSelector);
  2918. removeDataStyle(replica);
  2919. return [replica];
  2920. });
  2921. };
  2922. const serializeElements = (editor, elements) => map$1(elements, elm => editor.selection.serializer.serialize(elm.dom, {})).join('');
  2923. const getTextContent = elements => map$1(elements, element => element.dom.innerText).join('');
  2924. const registerEvents = (editor, actions) => {
  2925. editor.on('BeforeGetContent', e => {
  2926. const multiCellContext = cells => {
  2927. e.preventDefault();
  2928. extractSelected(cells).each(elements => {
  2929. e.content = e.format === 'text' ? getTextContent(elements) : serializeElements(editor, elements);
  2930. });
  2931. };
  2932. if (e.selection === true) {
  2933. const cells = getCellsFromFakeSelection(editor);
  2934. if (cells.length >= 1) {
  2935. multiCellContext(cells);
  2936. }
  2937. }
  2938. });
  2939. editor.on('BeforeSetContent', e => {
  2940. if (e.selection === true && e.paste === true) {
  2941. const selectedCells = getCellsFromSelection(editor);
  2942. head(selectedCells).each(cell => {
  2943. table(cell).each(table => {
  2944. const elements = filter$2(fromHtml(e.content), content => {
  2945. return name(content) !== 'meta';
  2946. });
  2947. const isTable = isTag('table');
  2948. if (shouldMergeContentOnPaste(editor) && elements.length === 1 && isTable(elements[0])) {
  2949. e.preventDefault();
  2950. const doc = SugarElement.fromDom(editor.getDoc());
  2951. const generators = paste$1(doc);
  2952. const targets = paste(cell, elements[0], generators);
  2953. actions.pasteCells(table, targets).each(() => {
  2954. editor.focus();
  2955. });
  2956. }
  2957. });
  2958. });
  2959. }
  2960. });
  2961. };
  2962. const point = (element, offset) => ({
  2963. element,
  2964. offset
  2965. });
  2966. const scan$1 = (universe, element, direction) => {
  2967. if (universe.property().isText(element) && universe.property().getText(element).trim().length === 0 || universe.property().isComment(element)) {
  2968. return direction(element).bind(elem => {
  2969. return scan$1(universe, elem, direction).orThunk(() => {
  2970. return Optional.some(elem);
  2971. });
  2972. });
  2973. } else {
  2974. return Optional.none();
  2975. }
  2976. };
  2977. const toEnd = (universe, element) => {
  2978. if (universe.property().isText(element)) {
  2979. return universe.property().getText(element).length;
  2980. }
  2981. const children = universe.property().children(element);
  2982. return children.length;
  2983. };
  2984. const freefallRtl$2 = (universe, element) => {
  2985. const candidate = scan$1(universe, element, universe.query().prevSibling).getOr(element);
  2986. if (universe.property().isText(candidate)) {
  2987. return point(candidate, toEnd(universe, candidate));
  2988. }
  2989. const children = universe.property().children(candidate);
  2990. return children.length > 0 ? freefallRtl$2(universe, children[children.length - 1]) : point(candidate, toEnd(universe, candidate));
  2991. };
  2992. const freefallRtl$1 = freefallRtl$2;
  2993. const universe$2 = DomUniverse();
  2994. const freefallRtl = element => {
  2995. return freefallRtl$1(universe$2, element);
  2996. };
  2997. const halve = (main, other) => {
  2998. if (!hasColspan(main)) {
  2999. const width = getGenericWidth(main);
  3000. width.each(w => {
  3001. const newWidth = w.value / 2;
  3002. setGenericWidth(main, newWidth, w.unit);
  3003. setGenericWidth(other, newWidth, w.unit);
  3004. });
  3005. }
  3006. };
  3007. const zero = array => map$1(array, constant(0));
  3008. const surround = (sizes, startIndex, endIndex, results, f) => f(sizes.slice(0, startIndex)).concat(results).concat(f(sizes.slice(endIndex)));
  3009. const clampDeltaHelper = predicate => (sizes, index, delta, minCellSize) => {
  3010. if (!predicate(delta)) {
  3011. return delta;
  3012. } else {
  3013. const newSize = Math.max(minCellSize, sizes[index] - Math.abs(delta));
  3014. const diff = Math.abs(newSize - sizes[index]);
  3015. return delta >= 0 ? diff : -diff;
  3016. }
  3017. };
  3018. const clampNegativeDelta = clampDeltaHelper(delta => delta < 0);
  3019. const clampDelta = clampDeltaHelper(always);
  3020. const resizeTable = () => {
  3021. const calcFixedDeltas = (sizes, index, next, delta, minCellSize) => {
  3022. const clampedDelta = clampNegativeDelta(sizes, index, delta, minCellSize);
  3023. return surround(sizes, index, next + 1, [
  3024. clampedDelta,
  3025. 0
  3026. ], zero);
  3027. };
  3028. const calcRelativeDeltas = (sizes, index, delta, minCellSize) => {
  3029. const ratio = (100 + delta) / 100;
  3030. const newThis = Math.max(minCellSize, (sizes[index] + delta) / ratio);
  3031. return map$1(sizes, (size, idx) => {
  3032. const newSize = idx === index ? newThis : size / ratio;
  3033. return newSize - size;
  3034. });
  3035. };
  3036. const calcLeftEdgeDeltas = (sizes, index, next, delta, minCellSize, isRelative) => {
  3037. if (isRelative) {
  3038. return calcRelativeDeltas(sizes, index, delta, minCellSize);
  3039. } else {
  3040. return calcFixedDeltas(sizes, index, next, delta, minCellSize);
  3041. }
  3042. };
  3043. const calcMiddleDeltas = (sizes, _prev, index, next, delta, minCellSize, isRelative) => calcLeftEdgeDeltas(sizes, index, next, delta, minCellSize, isRelative);
  3044. const resizeTable = (resizer, delta) => resizer(delta);
  3045. const calcRightEdgeDeltas = (sizes, _prev, index, delta, minCellSize, isRelative) => {
  3046. if (isRelative) {
  3047. return calcRelativeDeltas(sizes, index, delta, minCellSize);
  3048. } else {
  3049. const clampedDelta = clampNegativeDelta(sizes, index, delta, minCellSize);
  3050. return zero(sizes.slice(0, index)).concat([clampedDelta]);
  3051. }
  3052. };
  3053. const calcRedestributedWidths = (sizes, totalWidth, pixelDelta, isRelative) => {
  3054. if (isRelative) {
  3055. const tableWidth = totalWidth + pixelDelta;
  3056. const ratio = tableWidth / totalWidth;
  3057. const newSizes = map$1(sizes, size => size / ratio);
  3058. return {
  3059. delta: ratio * 100 - 100,
  3060. newSizes
  3061. };
  3062. } else {
  3063. return {
  3064. delta: pixelDelta,
  3065. newSizes: sizes
  3066. };
  3067. }
  3068. };
  3069. return {
  3070. resizeTable,
  3071. clampTableDelta: clampNegativeDelta,
  3072. calcLeftEdgeDeltas,
  3073. calcMiddleDeltas,
  3074. calcRightEdgeDeltas,
  3075. calcRedestributedWidths
  3076. };
  3077. };
  3078. const preserveTable = () => {
  3079. const calcLeftEdgeDeltas = (sizes, index, next, delta, minCellSize) => {
  3080. const idx = delta >= 0 ? next : index;
  3081. const clampedDelta = clampDelta(sizes, idx, delta, minCellSize);
  3082. return surround(sizes, index, next + 1, [
  3083. clampedDelta,
  3084. -clampedDelta
  3085. ], zero);
  3086. };
  3087. const calcMiddleDeltas = (sizes, _prev, index, next, delta, minCellSize) => calcLeftEdgeDeltas(sizes, index, next, delta, minCellSize);
  3088. const resizeTable = (resizer, delta, isLastColumn) => {
  3089. if (isLastColumn) {
  3090. resizer(delta);
  3091. }
  3092. };
  3093. const calcRightEdgeDeltas = (sizes, _prev, _index, delta, _minCellSize, isRelative) => {
  3094. if (isRelative) {
  3095. return zero(sizes);
  3096. } else {
  3097. const diff = delta / sizes.length;
  3098. return map$1(sizes, constant(diff));
  3099. }
  3100. };
  3101. const clampTableDelta = (sizes, index, delta, minCellSize, isLastColumn) => {
  3102. if (isLastColumn) {
  3103. if (delta >= 0) {
  3104. return delta;
  3105. } else {
  3106. const maxDelta = foldl(sizes, (a, b) => a + b - minCellSize, 0);
  3107. return Math.max(-maxDelta, delta);
  3108. }
  3109. } else {
  3110. return clampNegativeDelta(sizes, index, delta, minCellSize);
  3111. }
  3112. };
  3113. const calcRedestributedWidths = (sizes, _totalWidth, _pixelDelta, _isRelative) => ({
  3114. delta: 0,
  3115. newSizes: sizes
  3116. });
  3117. return {
  3118. resizeTable,
  3119. clampTableDelta,
  3120. calcLeftEdgeDeltas,
  3121. calcMiddleDeltas,
  3122. calcRightEdgeDeltas,
  3123. calcRedestributedWidths
  3124. };
  3125. };
  3126. const getGridSize = table => {
  3127. const warehouse = Warehouse.fromTable(table);
  3128. return warehouse.grid;
  3129. };
  3130. const isHeaderCell = isTag('th');
  3131. const isHeaderCells = cells => forall(cells, cell => isHeaderCell(cell.element));
  3132. const getRowHeaderType = (isHeaderRow, isHeaderCells) => {
  3133. if (isHeaderRow && isHeaderCells) {
  3134. return 'sectionCells';
  3135. } else if (isHeaderRow) {
  3136. return 'section';
  3137. } else {
  3138. return 'cells';
  3139. }
  3140. };
  3141. const getRowType = row => {
  3142. const isHeaderRow = row.section === 'thead';
  3143. const isHeaderCells = is(findCommonCellType(row.cells), 'th');
  3144. if (row.section === 'tfoot') {
  3145. return { type: 'footer' };
  3146. } else if (isHeaderRow || isHeaderCells) {
  3147. return {
  3148. type: 'header',
  3149. subType: getRowHeaderType(isHeaderRow, isHeaderCells)
  3150. };
  3151. } else {
  3152. return { type: 'body' };
  3153. }
  3154. };
  3155. const findCommonCellType = cells => {
  3156. const headerCells = filter$2(cells, cell => isHeaderCell(cell.element));
  3157. if (headerCells.length === 0) {
  3158. return Optional.some('td');
  3159. } else if (headerCells.length === cells.length) {
  3160. return Optional.some('th');
  3161. } else {
  3162. return Optional.none();
  3163. }
  3164. };
  3165. const findCommonRowType = rows => {
  3166. const rowTypes = map$1(rows, row => getRowType(row).type);
  3167. const hasHeader = contains$2(rowTypes, 'header');
  3168. const hasFooter = contains$2(rowTypes, 'footer');
  3169. if (!hasHeader && !hasFooter) {
  3170. return Optional.some('body');
  3171. } else {
  3172. const hasBody = contains$2(rowTypes, 'body');
  3173. if (hasHeader && !hasBody && !hasFooter) {
  3174. return Optional.some('header');
  3175. } else if (!hasHeader && !hasBody && hasFooter) {
  3176. return Optional.some('footer');
  3177. } else {
  3178. return Optional.none();
  3179. }
  3180. }
  3181. };
  3182. const findTableRowHeaderType = warehouse => findMap(warehouse.all, row => {
  3183. const rowType = getRowType(row);
  3184. return rowType.type === 'header' ? Optional.from(rowType.subType) : Optional.none();
  3185. });
  3186. const transformCell = (cell, comparator, substitution) => elementnew(substitution(cell.element, comparator), true, cell.isLocked);
  3187. const transformRow = (row, section) => row.section !== section ? rowcells(row.element, row.cells, section, row.isNew) : row;
  3188. const section = () => ({
  3189. transformRow,
  3190. transformCell: (cell, comparator, substitution) => {
  3191. const newCell = substitution(cell.element, comparator);
  3192. const fixedCell = name(newCell) !== 'td' ? mutate$1(newCell, 'td') : newCell;
  3193. return elementnew(fixedCell, cell.isNew, cell.isLocked);
  3194. }
  3195. });
  3196. const sectionCells = () => ({
  3197. transformRow,
  3198. transformCell
  3199. });
  3200. const cells = () => ({
  3201. transformRow: (row, section) => {
  3202. const newSection = section === 'thead' ? 'tbody' : section;
  3203. return transformRow(row, newSection);
  3204. },
  3205. transformCell
  3206. });
  3207. const fallback = () => ({
  3208. transformRow: identity,
  3209. transformCell
  3210. });
  3211. const getTableSectionType = (table, fallback) => {
  3212. const warehouse = Warehouse.fromTable(table);
  3213. const type = findTableRowHeaderType(warehouse).getOr(fallback);
  3214. switch (type) {
  3215. case 'section':
  3216. return section();
  3217. case 'sectionCells':
  3218. return sectionCells();
  3219. case 'cells':
  3220. return cells();
  3221. }
  3222. };
  3223. const TableSection = {
  3224. getTableSectionType,
  3225. section,
  3226. sectionCells,
  3227. cells,
  3228. fallback
  3229. };
  3230. const setIfNot = (element, property, value, ignore) => {
  3231. if (value === ignore) {
  3232. remove$7(element, property);
  3233. } else {
  3234. set$2(element, property, value);
  3235. }
  3236. };
  3237. const insert$1 = (table, selector, element) => {
  3238. last$2(children(table, selector)).fold(() => prepend(table, element), child => after$5(child, element));
  3239. };
  3240. const generateSection = (table, sectionName) => {
  3241. const section = child(table, sectionName).getOrThunk(() => {
  3242. const newSection = SugarElement.fromTag(sectionName, owner(table).dom);
  3243. if (sectionName === 'thead') {
  3244. insert$1(table, 'caption,colgroup', newSection);
  3245. } else if (sectionName === 'colgroup') {
  3246. insert$1(table, 'caption', newSection);
  3247. } else {
  3248. append$1(table, newSection);
  3249. }
  3250. return newSection;
  3251. });
  3252. empty(section);
  3253. return section;
  3254. };
  3255. const render$1 = (table, grid) => {
  3256. const newRows = [];
  3257. const newCells = [];
  3258. const syncRows = gridSection => map$1(gridSection, row => {
  3259. if (row.isNew) {
  3260. newRows.push(row.element);
  3261. }
  3262. const tr = row.element;
  3263. empty(tr);
  3264. each$2(row.cells, cell => {
  3265. if (cell.isNew) {
  3266. newCells.push(cell.element);
  3267. }
  3268. setIfNot(cell.element, 'colspan', cell.colspan, 1);
  3269. setIfNot(cell.element, 'rowspan', cell.rowspan, 1);
  3270. append$1(tr, cell.element);
  3271. });
  3272. return tr;
  3273. });
  3274. const syncColGroup = gridSection => bind$2(gridSection, colGroup => map$1(colGroup.cells, col => {
  3275. setIfNot(col.element, 'span', col.colspan, 1);
  3276. return col.element;
  3277. }));
  3278. const renderSection = (gridSection, sectionName) => {
  3279. const section = generateSection(table, sectionName);
  3280. const sync = sectionName === 'colgroup' ? syncColGroup : syncRows;
  3281. const sectionElems = sync(gridSection);
  3282. append(section, sectionElems);
  3283. };
  3284. const removeSection = sectionName => {
  3285. child(table, sectionName).each(remove$6);
  3286. };
  3287. const renderOrRemoveSection = (gridSection, sectionName) => {
  3288. if (gridSection.length > 0) {
  3289. renderSection(gridSection, sectionName);
  3290. } else {
  3291. removeSection(sectionName);
  3292. }
  3293. };
  3294. const headSection = [];
  3295. const bodySection = [];
  3296. const footSection = [];
  3297. const columnGroupsSection = [];
  3298. each$2(grid, row => {
  3299. switch (row.section) {
  3300. case 'thead':
  3301. headSection.push(row);
  3302. break;
  3303. case 'tbody':
  3304. bodySection.push(row);
  3305. break;
  3306. case 'tfoot':
  3307. footSection.push(row);
  3308. break;
  3309. case 'colgroup':
  3310. columnGroupsSection.push(row);
  3311. break;
  3312. }
  3313. });
  3314. renderOrRemoveSection(columnGroupsSection, 'colgroup');
  3315. renderOrRemoveSection(headSection, 'thead');
  3316. renderOrRemoveSection(bodySection, 'tbody');
  3317. renderOrRemoveSection(footSection, 'tfoot');
  3318. return {
  3319. newRows,
  3320. newCells
  3321. };
  3322. };
  3323. const copy = grid => map$1(grid, row => {
  3324. const tr = shallow(row.element);
  3325. each$2(row.cells, cell => {
  3326. const clonedCell = deep(cell.element);
  3327. setIfNot(clonedCell, 'colspan', cell.colspan, 1);
  3328. setIfNot(clonedCell, 'rowspan', cell.rowspan, 1);
  3329. append$1(tr, clonedCell);
  3330. });
  3331. return tr;
  3332. });
  3333. const getColumn = (grid, index) => {
  3334. return map$1(grid, row => {
  3335. return getCell(row, index);
  3336. });
  3337. };
  3338. const getRow = (grid, index) => {
  3339. return grid[index];
  3340. };
  3341. const findDiff = (xs, comp) => {
  3342. if (xs.length === 0) {
  3343. return 0;
  3344. }
  3345. const first = xs[0];
  3346. const index = findIndex(xs, x => {
  3347. return !comp(first.element, x.element);
  3348. });
  3349. return index.getOr(xs.length);
  3350. };
  3351. const subgrid = (grid, row, column, comparator) => {
  3352. const gridRow = getRow(grid, row);
  3353. const isColRow = gridRow.section === 'colgroup';
  3354. const colspan = findDiff(gridRow.cells.slice(column), comparator);
  3355. const rowspan = isColRow ? 1 : findDiff(getColumn(grid.slice(row), column), comparator);
  3356. return {
  3357. colspan,
  3358. rowspan
  3359. };
  3360. };
  3361. const toDetails = (grid, comparator) => {
  3362. const seen = map$1(grid, row => map$1(row.cells, never));
  3363. const updateSeen = (rowIndex, columnIndex, rowspan, colspan) => {
  3364. for (let row = rowIndex; row < rowIndex + rowspan; row++) {
  3365. for (let column = columnIndex; column < columnIndex + colspan; column++) {
  3366. seen[row][column] = true;
  3367. }
  3368. }
  3369. };
  3370. return map$1(grid, (row, rowIndex) => {
  3371. const details = bind$2(row.cells, (cell, columnIndex) => {
  3372. if (seen[rowIndex][columnIndex] === false) {
  3373. const result = subgrid(grid, rowIndex, columnIndex, comparator);
  3374. updateSeen(rowIndex, columnIndex, result.rowspan, result.colspan);
  3375. return [detailnew(cell.element, result.rowspan, result.colspan, cell.isNew)];
  3376. } else {
  3377. return [];
  3378. }
  3379. });
  3380. return rowdetailnew(row.element, details, row.section, row.isNew);
  3381. });
  3382. };
  3383. const toGrid = (warehouse, generators, isNew) => {
  3384. const grid = [];
  3385. each$2(warehouse.colgroups, colgroup => {
  3386. const colgroupCols = [];
  3387. for (let columnIndex = 0; columnIndex < warehouse.grid.columns; columnIndex++) {
  3388. const element = Warehouse.getColumnAt(warehouse, columnIndex).map(column => elementnew(column.element, isNew, false)).getOrThunk(() => elementnew(generators.colGap(), true, false));
  3389. colgroupCols.push(element);
  3390. }
  3391. grid.push(rowcells(colgroup.element, colgroupCols, 'colgroup', isNew));
  3392. });
  3393. for (let rowIndex = 0; rowIndex < warehouse.grid.rows; rowIndex++) {
  3394. const rowCells = [];
  3395. for (let columnIndex = 0; columnIndex < warehouse.grid.columns; columnIndex++) {
  3396. const element = Warehouse.getAt(warehouse, rowIndex, columnIndex).map(item => elementnew(item.element, isNew, item.isLocked)).getOrThunk(() => elementnew(generators.gap(), true, false));
  3397. rowCells.push(element);
  3398. }
  3399. const rowDetail = warehouse.all[rowIndex];
  3400. const row = rowcells(rowDetail.element, rowCells, rowDetail.section, isNew);
  3401. grid.push(row);
  3402. }
  3403. return grid;
  3404. };
  3405. const fromWarehouse = (warehouse, generators) => toGrid(warehouse, generators, false);
  3406. const toDetailList = grid => toDetails(grid, eq$1);
  3407. const findInWarehouse = (warehouse, element) => findMap(warehouse.all, r => find$1(r.cells, e => eq$1(element, e.element)));
  3408. const extractCells = (warehouse, target, predicate) => {
  3409. const details = map$1(target.selection, cell$1 => {
  3410. return cell(cell$1).bind(lc => findInWarehouse(warehouse, lc)).filter(predicate);
  3411. });
  3412. const cells = cat(details);
  3413. return someIf(cells.length > 0, cells);
  3414. };
  3415. const run = (operation, extract, adjustment, postAction, genWrappers) => (table, target, generators, behaviours) => {
  3416. const warehouse = Warehouse.fromTable(table);
  3417. const tableSection = Optional.from(behaviours === null || behaviours === void 0 ? void 0 : behaviours.section).getOrThunk(TableSection.fallback);
  3418. const output = extract(warehouse, target).map(info => {
  3419. const model = fromWarehouse(warehouse, generators);
  3420. const result = operation(model, info, eq$1, genWrappers(generators), tableSection);
  3421. const lockedColumns = getLockedColumnsFromGrid(result.grid);
  3422. const grid = toDetailList(result.grid);
  3423. return {
  3424. info,
  3425. grid,
  3426. cursor: result.cursor,
  3427. lockedColumns
  3428. };
  3429. });
  3430. return output.bind(out => {
  3431. const newElements = render$1(table, out.grid);
  3432. const tableSizing = Optional.from(behaviours === null || behaviours === void 0 ? void 0 : behaviours.sizing).getOrThunk(() => TableSize.getTableSize(table));
  3433. const resizing = Optional.from(behaviours === null || behaviours === void 0 ? void 0 : behaviours.resize).getOrThunk(preserveTable);
  3434. adjustment(table, out.grid, out.info, {
  3435. sizing: tableSizing,
  3436. resize: resizing,
  3437. section: tableSection
  3438. });
  3439. postAction(table);
  3440. remove$7(table, LOCKED_COL_ATTR);
  3441. if (out.lockedColumns.length > 0) {
  3442. set$2(table, LOCKED_COL_ATTR, out.lockedColumns.join(','));
  3443. }
  3444. return Optional.some({
  3445. cursor: out.cursor,
  3446. newRows: newElements.newRows,
  3447. newCells: newElements.newCells
  3448. });
  3449. });
  3450. };
  3451. const onPaste = (warehouse, target) => cell(target.element).bind(cell => findInWarehouse(warehouse, cell).map(details => {
  3452. const value = {
  3453. ...details,
  3454. generators: target.generators,
  3455. clipboard: target.clipboard
  3456. };
  3457. return value;
  3458. }));
  3459. const onPasteByEditor = (warehouse, target) => extractCells(warehouse, target, always).map(cells => ({
  3460. cells,
  3461. generators: target.generators,
  3462. clipboard: target.clipboard
  3463. }));
  3464. const onMergable = (_warehouse, target) => target.mergable;
  3465. const onUnmergable = (_warehouse, target) => target.unmergable;
  3466. const onCells = (warehouse, target) => extractCells(warehouse, target, always);
  3467. const onUnlockedCells = (warehouse, target) => extractCells(warehouse, target, detail => !detail.isLocked);
  3468. const isUnlockedTableCell = (warehouse, cell) => findInWarehouse(warehouse, cell).exists(detail => !detail.isLocked);
  3469. const allUnlocked = (warehouse, cells) => forall(cells, cell => isUnlockedTableCell(warehouse, cell));
  3470. const onUnlockedMergable = (warehouse, target) => onMergable(warehouse, target).filter(mergeable => allUnlocked(warehouse, mergeable.cells));
  3471. const onUnlockedUnmergable = (warehouse, target) => onUnmergable(warehouse, target).filter(cells => allUnlocked(warehouse, cells));
  3472. const merge$2 = (grid, bounds, comparator, substitution) => {
  3473. const rows = extractGridDetails(grid).rows;
  3474. if (rows.length === 0) {
  3475. return grid;
  3476. }
  3477. for (let i = bounds.startRow; i <= bounds.finishRow; i++) {
  3478. for (let j = bounds.startCol; j <= bounds.finishCol; j++) {
  3479. const row = rows[i];
  3480. const isLocked = getCell(row, j).isLocked;
  3481. mutateCell(row, j, elementnew(substitution(), false, isLocked));
  3482. }
  3483. }
  3484. return grid;
  3485. };
  3486. const unmerge = (grid, target, comparator, substitution) => {
  3487. const rows = extractGridDetails(grid).rows;
  3488. let first = true;
  3489. for (let i = 0; i < rows.length; i++) {
  3490. for (let j = 0; j < cellLength(rows[0]); j++) {
  3491. const row = rows[i];
  3492. const currentCell = getCell(row, j);
  3493. const currentCellElm = currentCell.element;
  3494. const isToReplace = comparator(currentCellElm, target);
  3495. if (isToReplace && !first) {
  3496. mutateCell(row, j, elementnew(substitution(), true, currentCell.isLocked));
  3497. } else if (isToReplace) {
  3498. first = false;
  3499. }
  3500. }
  3501. }
  3502. return grid;
  3503. };
  3504. const uniqueCells = (row, comparator) => {
  3505. return foldl(row, (rest, cell) => {
  3506. return exists(rest, currentCell => {
  3507. return comparator(currentCell.element, cell.element);
  3508. }) ? rest : rest.concat([cell]);
  3509. }, []);
  3510. };
  3511. const splitCols = (grid, index, comparator, substitution) => {
  3512. if (index > 0 && index < grid[0].cells.length) {
  3513. each$2(grid, row => {
  3514. const prevCell = row.cells[index - 1];
  3515. let offset = 0;
  3516. const substitute = substitution();
  3517. while (row.cells.length > index + offset && comparator(prevCell.element, row.cells[index + offset].element)) {
  3518. mutateCell(row, index + offset, elementnew(substitute, true, row.cells[index + offset].isLocked));
  3519. offset++;
  3520. }
  3521. });
  3522. }
  3523. return grid;
  3524. };
  3525. const splitRows = (grid, index, comparator, substitution) => {
  3526. const rows = extractGridDetails(grid).rows;
  3527. if (index > 0 && index < rows.length) {
  3528. const rowPrevCells = rows[index - 1].cells;
  3529. const cells = uniqueCells(rowPrevCells, comparator);
  3530. each$2(cells, cell => {
  3531. let replacement = Optional.none();
  3532. for (let i = index; i < rows.length; i++) {
  3533. for (let j = 0; j < cellLength(rows[0]); j++) {
  3534. const row = rows[i];
  3535. const current = getCell(row, j);
  3536. const isToReplace = comparator(current.element, cell.element);
  3537. if (isToReplace) {
  3538. if (replacement.isNone()) {
  3539. replacement = Optional.some(substitution());
  3540. }
  3541. replacement.each(sub => {
  3542. mutateCell(row, j, elementnew(sub, true, current.isLocked));
  3543. });
  3544. }
  3545. }
  3546. }
  3547. });
  3548. }
  3549. return grid;
  3550. };
  3551. const value$1 = value => {
  3552. const applyHelper = fn => fn(value);
  3553. const constHelper = constant(value);
  3554. const outputHelper = () => output;
  3555. const output = {
  3556. tag: true,
  3557. inner: value,
  3558. fold: (_onError, onValue) => onValue(value),
  3559. isValue: always,
  3560. isError: never,
  3561. map: mapper => Result.value(mapper(value)),
  3562. mapError: outputHelper,
  3563. bind: applyHelper,
  3564. exists: applyHelper,
  3565. forall: applyHelper,
  3566. getOr: constHelper,
  3567. or: outputHelper,
  3568. getOrThunk: constHelper,
  3569. orThunk: outputHelper,
  3570. getOrDie: constHelper,
  3571. each: fn => {
  3572. fn(value);
  3573. },
  3574. toOptional: () => Optional.some(value)
  3575. };
  3576. return output;
  3577. };
  3578. const error = error => {
  3579. const outputHelper = () => output;
  3580. const output = {
  3581. tag: false,
  3582. inner: error,
  3583. fold: (onError, _onValue) => onError(error),
  3584. isValue: never,
  3585. isError: always,
  3586. map: outputHelper,
  3587. mapError: mapper => Result.error(mapper(error)),
  3588. bind: outputHelper,
  3589. exists: never,
  3590. forall: always,
  3591. getOr: identity,
  3592. or: identity,
  3593. getOrThunk: apply,
  3594. orThunk: apply,
  3595. getOrDie: die(String(error)),
  3596. each: noop,
  3597. toOptional: Optional.none
  3598. };
  3599. return output;
  3600. };
  3601. const fromOption = (optional, err) => optional.fold(() => error(err), value$1);
  3602. const Result = {
  3603. value: value$1,
  3604. error,
  3605. fromOption
  3606. };
  3607. const measure = (startAddress, gridA, gridB) => {
  3608. if (startAddress.row >= gridA.length || startAddress.column > cellLength(gridA[0])) {
  3609. return Result.error('invalid start address out of table bounds, row: ' + startAddress.row + ', column: ' + startAddress.column);
  3610. }
  3611. const rowRemainder = gridA.slice(startAddress.row);
  3612. const colRemainder = rowRemainder[0].cells.slice(startAddress.column);
  3613. const colRequired = cellLength(gridB[0]);
  3614. const rowRequired = gridB.length;
  3615. return Result.value({
  3616. rowDelta: rowRemainder.length - rowRequired,
  3617. colDelta: colRemainder.length - colRequired
  3618. });
  3619. };
  3620. const measureWidth = (gridA, gridB) => {
  3621. const colLengthA = cellLength(gridA[0]);
  3622. const colLengthB = cellLength(gridB[0]);
  3623. return {
  3624. rowDelta: 0,
  3625. colDelta: colLengthA - colLengthB
  3626. };
  3627. };
  3628. const measureHeight = (gridA, gridB) => {
  3629. const rowLengthA = gridA.length;
  3630. const rowLengthB = gridB.length;
  3631. return {
  3632. rowDelta: rowLengthA - rowLengthB,
  3633. colDelta: 0
  3634. };
  3635. };
  3636. const generateElements = (amount, row, generators, isLocked) => {
  3637. const generator = row.section === 'colgroup' ? generators.col : generators.cell;
  3638. return range$1(amount, idx => elementnew(generator(), true, isLocked(idx)));
  3639. };
  3640. const rowFill = (grid, amount, generators, lockedColumns) => {
  3641. const exampleRow = grid[grid.length - 1];
  3642. return grid.concat(range$1(amount, () => {
  3643. const generator = exampleRow.section === 'colgroup' ? generators.colgroup : generators.row;
  3644. const row = clone(exampleRow, generator, identity);
  3645. const elements = generateElements(row.cells.length, row, generators, idx => has$1(lockedColumns, idx.toString()));
  3646. return setCells(row, elements);
  3647. }));
  3648. };
  3649. const colFill = (grid, amount, generators, startIndex) => map$1(grid, row => {
  3650. const newChildren = generateElements(amount, row, generators, never);
  3651. return addCells(row, startIndex, newChildren);
  3652. });
  3653. const lockedColFill = (grid, generators, lockedColumns) => map$1(grid, row => {
  3654. return foldl(lockedColumns, (acc, colNum) => {
  3655. const newChild = generateElements(1, row, generators, always)[0];
  3656. return addCell(acc, colNum, newChild);
  3657. }, row);
  3658. });
  3659. const tailor = (gridA, delta, generators) => {
  3660. const fillCols = delta.colDelta < 0 ? colFill : identity;
  3661. const fillRows = delta.rowDelta < 0 ? rowFill : identity;
  3662. const lockedColumns = getLockedColumnsFromGrid(gridA);
  3663. const gridWidth = cellLength(gridA[0]);
  3664. const isLastColLocked = exists(lockedColumns, locked => locked === gridWidth - 1);
  3665. const modifiedCols = fillCols(gridA, Math.abs(delta.colDelta), generators, isLastColLocked ? gridWidth - 1 : gridWidth);
  3666. const newLockedColumns = getLockedColumnsFromGrid(modifiedCols);
  3667. return fillRows(modifiedCols, Math.abs(delta.rowDelta), generators, mapToObject(newLockedColumns, always));
  3668. };
  3669. const isSpanning = (grid, row, col, comparator) => {
  3670. const candidate = getCell(grid[row], col);
  3671. const matching = curry(comparator, candidate.element);
  3672. const currentRow = grid[row];
  3673. return grid.length > 1 && cellLength(currentRow) > 1 && (col > 0 && matching(getCellElement(currentRow, col - 1)) || col < currentRow.cells.length - 1 && matching(getCellElement(currentRow, col + 1)) || row > 0 && matching(getCellElement(grid[row - 1], col)) || row < grid.length - 1 && matching(getCellElement(grid[row + 1], col)));
  3674. };
  3675. const mergeTables = (startAddress, gridA, gridBRows, generator, comparator, lockedColumns) => {
  3676. const startRow = startAddress.row;
  3677. const startCol = startAddress.column;
  3678. const mergeHeight = gridBRows.length;
  3679. const mergeWidth = cellLength(gridBRows[0]);
  3680. const endRow = startRow + mergeHeight;
  3681. const endCol = startCol + mergeWidth + lockedColumns.length;
  3682. const lockedColumnObj = mapToObject(lockedColumns, always);
  3683. for (let r = startRow; r < endRow; r++) {
  3684. let skippedCol = 0;
  3685. for (let c = startCol; c < endCol; c++) {
  3686. if (lockedColumnObj[c]) {
  3687. skippedCol++;
  3688. continue;
  3689. }
  3690. if (isSpanning(gridA, r, c, comparator)) {
  3691. unmerge(gridA, getCellElement(gridA[r], c), comparator, generator.cell);
  3692. }
  3693. const gridBColIndex = c - startCol - skippedCol;
  3694. const newCell = getCell(gridBRows[r - startRow], gridBColIndex);
  3695. const newCellElm = newCell.element;
  3696. const replacement = generator.replace(newCellElm);
  3697. mutateCell(gridA[r], c, elementnew(replacement, true, newCell.isLocked));
  3698. }
  3699. }
  3700. return gridA;
  3701. };
  3702. const getValidStartAddress = (currentStartAddress, grid, lockedColumns) => {
  3703. const gridColLength = cellLength(grid[0]);
  3704. const adjustedRowAddress = extractGridDetails(grid).cols.length + currentStartAddress.row;
  3705. const possibleColAddresses = range$1(gridColLength - currentStartAddress.column, num => num + currentStartAddress.column);
  3706. const validColAddress = find$1(possibleColAddresses, num => forall(lockedColumns, col => col !== num)).getOr(gridColLength - 1);
  3707. return {
  3708. row: adjustedRowAddress,
  3709. column: validColAddress
  3710. };
  3711. };
  3712. const getLockedColumnsWithinBounds = (startAddress, rows, lockedColumns) => filter$2(lockedColumns, colNum => colNum >= startAddress.column && colNum <= cellLength(rows[0]) + startAddress.column);
  3713. const merge$1 = (startAddress, gridA, gridB, generator, comparator) => {
  3714. const lockedColumns = getLockedColumnsFromGrid(gridA);
  3715. const validStartAddress = getValidStartAddress(startAddress, gridA, lockedColumns);
  3716. const gridBRows = extractGridDetails(gridB).rows;
  3717. const lockedColumnsWithinBounds = getLockedColumnsWithinBounds(validStartAddress, gridBRows, lockedColumns);
  3718. const result = measure(validStartAddress, gridA, gridBRows);
  3719. return result.map(diff => {
  3720. const delta = {
  3721. ...diff,
  3722. colDelta: diff.colDelta - lockedColumnsWithinBounds.length
  3723. };
  3724. const fittedGrid = tailor(gridA, delta, generator);
  3725. const newLockedColumns = getLockedColumnsFromGrid(fittedGrid);
  3726. const newLockedColumnsWithinBounds = getLockedColumnsWithinBounds(validStartAddress, gridBRows, newLockedColumns);
  3727. return mergeTables(validStartAddress, fittedGrid, gridBRows, generator, comparator, newLockedColumnsWithinBounds);
  3728. });
  3729. };
  3730. const insertCols = (index, gridA, gridB, generator, comparator) => {
  3731. splitCols(gridA, index, comparator, generator.cell);
  3732. const delta = measureHeight(gridB, gridA);
  3733. const fittedNewGrid = tailor(gridB, delta, generator);
  3734. const secondDelta = measureHeight(gridA, fittedNewGrid);
  3735. const fittedOldGrid = tailor(gridA, secondDelta, generator);
  3736. return map$1(fittedOldGrid, (gridRow, i) => {
  3737. return addCells(gridRow, index, fittedNewGrid[i].cells);
  3738. });
  3739. };
  3740. const insertRows = (index, gridA, gridB, generator, comparator) => {
  3741. splitRows(gridA, index, comparator, generator.cell);
  3742. const locked = getLockedColumnsFromGrid(gridA);
  3743. const diff = measureWidth(gridA, gridB);
  3744. const delta = {
  3745. ...diff,
  3746. colDelta: diff.colDelta - locked.length
  3747. };
  3748. const fittedOldGrid = tailor(gridA, delta, generator);
  3749. const {
  3750. cols: oldCols,
  3751. rows: oldRows
  3752. } = extractGridDetails(fittedOldGrid);
  3753. const newLocked = getLockedColumnsFromGrid(fittedOldGrid);
  3754. const secondDiff = measureWidth(gridB, gridA);
  3755. const secondDelta = {
  3756. ...secondDiff,
  3757. colDelta: secondDiff.colDelta + newLocked.length
  3758. };
  3759. const fittedGridB = lockedColFill(gridB, generator, newLocked);
  3760. const fittedNewGrid = tailor(fittedGridB, secondDelta, generator);
  3761. return [
  3762. ...oldCols,
  3763. ...oldRows.slice(0, index),
  3764. ...fittedNewGrid,
  3765. ...oldRows.slice(index, oldRows.length)
  3766. ];
  3767. };
  3768. const cloneRow = (row, cloneCell, comparator, substitution) => clone(row, elem => substitution(elem, comparator), cloneCell);
  3769. const insertRowAt = (grid, index, example, comparator, substitution) => {
  3770. const {rows, cols} = extractGridDetails(grid);
  3771. const before = rows.slice(0, index);
  3772. const after = rows.slice(index);
  3773. const newRow = cloneRow(rows[example], (ex, c) => {
  3774. const withinSpan = index > 0 && index < rows.length && comparator(getCellElement(rows[index - 1], c), getCellElement(rows[index], c));
  3775. const ret = withinSpan ? getCell(rows[index], c) : elementnew(substitution(ex.element, comparator), true, ex.isLocked);
  3776. return ret;
  3777. }, comparator, substitution);
  3778. return [
  3779. ...cols,
  3780. ...before,
  3781. newRow,
  3782. ...after
  3783. ];
  3784. };
  3785. const getElementFor = (row, column, section, withinSpan, example, comparator, substitution) => {
  3786. if (section === 'colgroup' || !withinSpan) {
  3787. const cell = getCell(row, example);
  3788. return elementnew(substitution(cell.element, comparator), true, false);
  3789. } else {
  3790. return getCell(row, column);
  3791. }
  3792. };
  3793. const insertColumnAt = (grid, index, example, comparator, substitution) => map$1(grid, row => {
  3794. const withinSpan = index > 0 && index < cellLength(row) && comparator(getCellElement(row, index - 1), getCellElement(row, index));
  3795. const sub = getElementFor(row, index, row.section, withinSpan, example, comparator, substitution);
  3796. return addCell(row, index, sub);
  3797. });
  3798. const deleteColumnsAt = (grid, columns) => bind$2(grid, row => {
  3799. const existingCells = row.cells;
  3800. const cells = foldr(columns, (acc, column) => column >= 0 && column < acc.length ? acc.slice(0, column).concat(acc.slice(column + 1)) : acc, existingCells);
  3801. return cells.length > 0 ? [rowcells(row.element, cells, row.section, row.isNew)] : [];
  3802. });
  3803. const deleteRowsAt = (grid, start, finish) => {
  3804. const {rows, cols} = extractGridDetails(grid);
  3805. return [
  3806. ...cols,
  3807. ...rows.slice(0, start),
  3808. ...rows.slice(finish + 1)
  3809. ];
  3810. };
  3811. const notInStartRow = (grid, rowIndex, colIndex, comparator) => getCellElement(grid[rowIndex], colIndex) !== undefined && (rowIndex > 0 && comparator(getCellElement(grid[rowIndex - 1], colIndex), getCellElement(grid[rowIndex], colIndex)));
  3812. const notInStartColumn = (row, index, comparator) => index > 0 && comparator(getCellElement(row, index - 1), getCellElement(row, index));
  3813. const isDuplicatedCell = (grid, rowIndex, colIndex, comparator) => notInStartRow(grid, rowIndex, colIndex, comparator) || notInStartColumn(grid[rowIndex], colIndex, comparator);
  3814. const rowReplacerPredicate = (targetRow, columnHeaders) => {
  3815. const entireTableIsHeader = forall(columnHeaders, identity) && isHeaderCells(targetRow.cells);
  3816. return entireTableIsHeader ? always : (cell, _rowIndex, colIndex) => {
  3817. const type = name(cell.element);
  3818. return !(type === 'th' && columnHeaders[colIndex]);
  3819. };
  3820. };
  3821. const columnReplacePredicate = (targetColumn, rowHeaders) => {
  3822. const entireTableIsHeader = forall(rowHeaders, identity) && isHeaderCells(targetColumn);
  3823. return entireTableIsHeader ? always : (cell, rowIndex, _colIndex) => {
  3824. const type = name(cell.element);
  3825. return !(type === 'th' && rowHeaders[rowIndex]);
  3826. };
  3827. };
  3828. const determineScope = (applyScope, cell, newScope, isInHeader) => {
  3829. const hasSpan = scope => scope === 'row' ? hasRowspan(cell) : hasColspan(cell);
  3830. const getScope = scope => hasSpan(scope) ? `${ scope }group` : scope;
  3831. if (applyScope) {
  3832. return isHeaderCell(cell) ? getScope(newScope) : null;
  3833. } else if (isInHeader && isHeaderCell(cell)) {
  3834. const oppositeScope = newScope === 'row' ? 'col' : 'row';
  3835. return getScope(oppositeScope);
  3836. } else {
  3837. return null;
  3838. }
  3839. };
  3840. const rowScopeGenerator = (applyScope, columnHeaders) => (cell, rowIndex, columnIndex) => Optional.some(determineScope(applyScope, cell.element, 'col', columnHeaders[columnIndex]));
  3841. const columnScopeGenerator = (applyScope, rowHeaders) => (cell, rowIndex) => Optional.some(determineScope(applyScope, cell.element, 'row', rowHeaders[rowIndex]));
  3842. const replace = (cell, comparator, substitute) => elementnew(substitute(cell.element, comparator), true, cell.isLocked);
  3843. const replaceIn = (grid, targets, comparator, substitute, replacer, genScope, shouldReplace) => {
  3844. const isTarget = cell => {
  3845. return exists(targets, target => {
  3846. return comparator(cell.element, target.element);
  3847. });
  3848. };
  3849. return map$1(grid, (row, rowIndex) => {
  3850. return mapCells(row, (cell, colIndex) => {
  3851. if (isTarget(cell)) {
  3852. const newCell = shouldReplace(cell, rowIndex, colIndex) ? replacer(cell, comparator, substitute) : cell;
  3853. genScope(newCell, rowIndex, colIndex).each(scope => {
  3854. setOptions(newCell.element, { scope: Optional.from(scope) });
  3855. });
  3856. return newCell;
  3857. } else {
  3858. return cell;
  3859. }
  3860. });
  3861. });
  3862. };
  3863. const getColumnCells = (rows, columnIndex, comparator) => bind$2(rows, (row, i) => {
  3864. return isDuplicatedCell(rows, i, columnIndex, comparator) ? [] : [getCell(row, columnIndex)];
  3865. });
  3866. const getRowCells = (rows, rowIndex, comparator) => {
  3867. const targetRow = rows[rowIndex];
  3868. return bind$2(targetRow.cells, (item, i) => {
  3869. return isDuplicatedCell(rows, rowIndex, i, comparator) ? [] : [item];
  3870. });
  3871. };
  3872. const replaceColumns = (grid, indexes, applyScope, comparator, substitution) => {
  3873. const rows = extractGridDetails(grid).rows;
  3874. const targets = bind$2(indexes, index => getColumnCells(rows, index, comparator));
  3875. const rowHeaders = map$1(rows, row => isHeaderCells(row.cells));
  3876. const shouldReplaceCell = columnReplacePredicate(targets, rowHeaders);
  3877. const scopeGenerator = columnScopeGenerator(applyScope, rowHeaders);
  3878. return replaceIn(grid, targets, comparator, substitution, replace, scopeGenerator, shouldReplaceCell);
  3879. };
  3880. const replaceRows = (grid, indexes, section, applyScope, comparator, substitution, tableSection) => {
  3881. const {cols, rows} = extractGridDetails(grid);
  3882. const targetRow = rows[indexes[0]];
  3883. const targets = bind$2(indexes, index => getRowCells(rows, index, comparator));
  3884. const columnHeaders = map$1(targetRow.cells, (_cell, index) => isHeaderCells(getColumnCells(rows, index, comparator)));
  3885. const newRows = [...rows];
  3886. each$2(indexes, index => {
  3887. newRows[index] = tableSection.transformRow(rows[index], section);
  3888. });
  3889. const newGrid = [
  3890. ...cols,
  3891. ...newRows
  3892. ];
  3893. const shouldReplaceCell = rowReplacerPredicate(targetRow, columnHeaders);
  3894. const scopeGenerator = rowScopeGenerator(applyScope, columnHeaders);
  3895. return replaceIn(newGrid, targets, comparator, substitution, tableSection.transformCell, scopeGenerator, shouldReplaceCell);
  3896. };
  3897. const replaceCells = (grid, details, comparator, substitution) => {
  3898. const rows = extractGridDetails(grid).rows;
  3899. const targetCells = map$1(details, detail => getCell(rows[detail.row], detail.column));
  3900. return replaceIn(grid, targetCells, comparator, substitution, replace, Optional.none, always);
  3901. };
  3902. const generate = cases => {
  3903. if (!isArray(cases)) {
  3904. throw new Error('cases must be an array');
  3905. }
  3906. if (cases.length === 0) {
  3907. throw new Error('there must be at least one case');
  3908. }
  3909. const constructors = [];
  3910. const adt = {};
  3911. each$2(cases, (acase, count) => {
  3912. const keys$1 = keys(acase);
  3913. if (keys$1.length !== 1) {
  3914. throw new Error('one and only one name per case');
  3915. }
  3916. const key = keys$1[0];
  3917. const value = acase[key];
  3918. if (adt[key] !== undefined) {
  3919. throw new Error('duplicate key detected:' + key);
  3920. } else if (key === 'cata') {
  3921. throw new Error('cannot have a case named cata (sorry)');
  3922. } else if (!isArray(value)) {
  3923. throw new Error('case arguments must be an array');
  3924. }
  3925. constructors.push(key);
  3926. adt[key] = (...args) => {
  3927. const argLength = args.length;
  3928. if (argLength !== value.length) {
  3929. throw new Error('Wrong number of arguments to case ' + key + '. Expected ' + value.length + ' (' + value + '), got ' + argLength);
  3930. }
  3931. const match = branches => {
  3932. const branchKeys = keys(branches);
  3933. if (constructors.length !== branchKeys.length) {
  3934. throw new Error('Wrong number of arguments to match. Expected: ' + constructors.join(',') + '\nActual: ' + branchKeys.join(','));
  3935. }
  3936. const allReqd = forall(constructors, reqKey => {
  3937. return contains$2(branchKeys, reqKey);
  3938. });
  3939. if (!allReqd) {
  3940. throw new Error('Not all branches were specified when using match. Specified: ' + branchKeys.join(', ') + '\nRequired: ' + constructors.join(', '));
  3941. }
  3942. return branches[key].apply(null, args);
  3943. };
  3944. return {
  3945. fold: (...foldArgs) => {
  3946. if (foldArgs.length !== cases.length) {
  3947. throw new Error('Wrong number of arguments to fold. Expected ' + cases.length + ', got ' + foldArgs.length);
  3948. }
  3949. const target = foldArgs[count];
  3950. return target.apply(null, args);
  3951. },
  3952. match,
  3953. log: label => {
  3954. console.log(label, {
  3955. constructors,
  3956. constructor: key,
  3957. params: args
  3958. });
  3959. }
  3960. };
  3961. };
  3962. });
  3963. return adt;
  3964. };
  3965. const Adt = { generate };
  3966. const adt$6 = Adt.generate([
  3967. { none: [] },
  3968. { only: ['index'] },
  3969. {
  3970. left: [
  3971. 'index',
  3972. 'next'
  3973. ]
  3974. },
  3975. {
  3976. middle: [
  3977. 'prev',
  3978. 'index',
  3979. 'next'
  3980. ]
  3981. },
  3982. {
  3983. right: [
  3984. 'prev',
  3985. 'index'
  3986. ]
  3987. }
  3988. ]);
  3989. const ColumnContext = { ...adt$6 };
  3990. const neighbours = (input, index) => {
  3991. if (input.length === 0) {
  3992. return ColumnContext.none();
  3993. }
  3994. if (input.length === 1) {
  3995. return ColumnContext.only(0);
  3996. }
  3997. if (index === 0) {
  3998. return ColumnContext.left(0, 1);
  3999. }
  4000. if (index === input.length - 1) {
  4001. return ColumnContext.right(index - 1, index);
  4002. }
  4003. if (index > 0 && index < input.length - 1) {
  4004. return ColumnContext.middle(index - 1, index, index + 1);
  4005. }
  4006. return ColumnContext.none();
  4007. };
  4008. const determine = (input, column, step, tableSize, resize) => {
  4009. const result = input.slice(0);
  4010. const context = neighbours(input, column);
  4011. const onNone = constant(map$1(result, constant(0)));
  4012. const onOnly = index => tableSize.singleColumnWidth(result[index], step);
  4013. const onLeft = (index, next) => resize.calcLeftEdgeDeltas(result, index, next, step, tableSize.minCellWidth(), tableSize.isRelative);
  4014. const onMiddle = (prev, index, next) => resize.calcMiddleDeltas(result, prev, index, next, step, tableSize.minCellWidth(), tableSize.isRelative);
  4015. const onRight = (prev, index) => resize.calcRightEdgeDeltas(result, prev, index, step, tableSize.minCellWidth(), tableSize.isRelative);
  4016. return context.fold(onNone, onOnly, onLeft, onMiddle, onRight);
  4017. };
  4018. const total = (start, end, measures) => {
  4019. let r = 0;
  4020. for (let i = start; i < end; i++) {
  4021. r += measures[i] !== undefined ? measures[i] : 0;
  4022. }
  4023. return r;
  4024. };
  4025. const recalculateWidthForCells = (warehouse, widths) => {
  4026. const all = Warehouse.justCells(warehouse);
  4027. return map$1(all, cell => {
  4028. const width = total(cell.column, cell.column + cell.colspan, widths);
  4029. return {
  4030. element: cell.element,
  4031. width,
  4032. colspan: cell.colspan
  4033. };
  4034. });
  4035. };
  4036. const recalculateWidthForColumns = (warehouse, widths) => {
  4037. const groups = Warehouse.justColumns(warehouse);
  4038. return map$1(groups, (column, index) => ({
  4039. element: column.element,
  4040. width: widths[index],
  4041. colspan: column.colspan
  4042. }));
  4043. };
  4044. const recalculateHeightForCells = (warehouse, heights) => {
  4045. const all = Warehouse.justCells(warehouse);
  4046. return map$1(all, cell => {
  4047. const height = total(cell.row, cell.row + cell.rowspan, heights);
  4048. return {
  4049. element: cell.element,
  4050. height,
  4051. rowspan: cell.rowspan
  4052. };
  4053. });
  4054. };
  4055. const matchRowHeight = (warehouse, heights) => {
  4056. return map$1(warehouse.all, (row, i) => {
  4057. return {
  4058. element: row.element,
  4059. height: heights[i]
  4060. };
  4061. });
  4062. };
  4063. const sumUp = newSize => foldr(newSize, (b, a) => b + a, 0);
  4064. const recalculate = (warehouse, widths) => {
  4065. if (Warehouse.hasColumns(warehouse)) {
  4066. return recalculateWidthForColumns(warehouse, widths);
  4067. } else {
  4068. return recalculateWidthForCells(warehouse, widths);
  4069. }
  4070. };
  4071. const recalculateAndApply = (warehouse, widths, tableSize) => {
  4072. const newSizes = recalculate(warehouse, widths);
  4073. each$2(newSizes, cell => {
  4074. tableSize.setElementWidth(cell.element, cell.width);
  4075. });
  4076. };
  4077. const adjustWidth = (table, delta, index, resizing, tableSize) => {
  4078. const warehouse = Warehouse.fromTable(table);
  4079. const step = tableSize.getCellDelta(delta);
  4080. const widths = tableSize.getWidths(warehouse, tableSize);
  4081. const isLastColumn = index === warehouse.grid.columns - 1;
  4082. const clampedStep = resizing.clampTableDelta(widths, index, step, tableSize.minCellWidth(), isLastColumn);
  4083. const deltas = determine(widths, index, clampedStep, tableSize, resizing);
  4084. const newWidths = map$1(deltas, (dx, i) => dx + widths[i]);
  4085. recalculateAndApply(warehouse, newWidths, tableSize);
  4086. resizing.resizeTable(tableSize.adjustTableWidth, clampedStep, isLastColumn);
  4087. };
  4088. const adjustHeight = (table, delta, index, direction) => {
  4089. const warehouse = Warehouse.fromTable(table);
  4090. const heights = getPixelHeights(warehouse, table, direction);
  4091. const newHeights = map$1(heights, (dy, i) => index === i ? Math.max(delta + dy, minHeight()) : dy);
  4092. const newCellSizes = recalculateHeightForCells(warehouse, newHeights);
  4093. const newRowSizes = matchRowHeight(warehouse, newHeights);
  4094. each$2(newRowSizes, row => {
  4095. setHeight(row.element, row.height);
  4096. });
  4097. each$2(newCellSizes, cell => {
  4098. setHeight(cell.element, cell.height);
  4099. });
  4100. const total = sumUp(newHeights);
  4101. setHeight(table, total);
  4102. };
  4103. const adjustAndRedistributeWidths$1 = (_table, list, details, tableSize, resizeBehaviour) => {
  4104. const warehouse = Warehouse.generate(list);
  4105. const sizes = tableSize.getWidths(warehouse, tableSize);
  4106. const tablePixelWidth = tableSize.pixelWidth();
  4107. const {newSizes, delta} = resizeBehaviour.calcRedestributedWidths(sizes, tablePixelWidth, details.pixelDelta, tableSize.isRelative);
  4108. recalculateAndApply(warehouse, newSizes, tableSize);
  4109. tableSize.adjustTableWidth(delta);
  4110. };
  4111. const adjustWidthTo = (_table, list, _info, tableSize) => {
  4112. const warehouse = Warehouse.generate(list);
  4113. const widths = tableSize.getWidths(warehouse, tableSize);
  4114. recalculateAndApply(warehouse, widths, tableSize);
  4115. };
  4116. const uniqueColumns = details => {
  4117. const uniqueCheck = (rest, detail) => {
  4118. const columnExists = exists(rest, currentDetail => currentDetail.column === detail.column);
  4119. return columnExists ? rest : rest.concat([detail]);
  4120. };
  4121. return foldl(details, uniqueCheck, []).sort((detailA, detailB) => detailA.column - detailB.column);
  4122. };
  4123. const isCol = isTag('col');
  4124. const isColgroup = isTag('colgroup');
  4125. const isRow$1 = element => name(element) === 'tr' || isColgroup(element);
  4126. const elementToData = element => {
  4127. const colspan = getAttrValue(element, 'colspan', 1);
  4128. const rowspan = getAttrValue(element, 'rowspan', 1);
  4129. return {
  4130. element,
  4131. colspan,
  4132. rowspan
  4133. };
  4134. };
  4135. const modification = (generators, toData = elementToData) => {
  4136. const nuCell = data => isCol(data.element) ? generators.col(data) : generators.cell(data);
  4137. const nuRow = data => isColgroup(data.element) ? generators.colgroup(data) : generators.row(data);
  4138. const add = element => {
  4139. if (isRow$1(element)) {
  4140. return nuRow({ element });
  4141. } else {
  4142. const cell = element;
  4143. const replacement = nuCell(toData(cell));
  4144. recent = Optional.some({
  4145. item: cell,
  4146. replacement
  4147. });
  4148. return replacement;
  4149. }
  4150. };
  4151. let recent = Optional.none();
  4152. const getOrInit = (element, comparator) => {
  4153. return recent.fold(() => {
  4154. return add(element);
  4155. }, p => {
  4156. return comparator(element, p.item) ? p.replacement : add(element);
  4157. });
  4158. };
  4159. return { getOrInit };
  4160. };
  4161. const transform$1 = tag => {
  4162. return generators => {
  4163. const list = [];
  4164. const find = (element, comparator) => {
  4165. return find$1(list, x => {
  4166. return comparator(x.item, element);
  4167. });
  4168. };
  4169. const makeNew = element => {
  4170. const attrs = tag === 'td' ? { scope: null } : {};
  4171. const cell = generators.replace(element, tag, attrs);
  4172. list.push({
  4173. item: element,
  4174. sub: cell
  4175. });
  4176. return cell;
  4177. };
  4178. const replaceOrInit = (element, comparator) => {
  4179. if (isRow$1(element) || isCol(element)) {
  4180. return element;
  4181. } else {
  4182. const cell = element;
  4183. return find(cell, comparator).fold(() => {
  4184. return makeNew(cell);
  4185. }, p => {
  4186. return comparator(element, p.item) ? p.sub : makeNew(cell);
  4187. });
  4188. }
  4189. };
  4190. return { replaceOrInit };
  4191. };
  4192. };
  4193. const getScopeAttribute = cell => getOpt(cell, 'scope').map(attribute => attribute.substr(0, 3));
  4194. const merging = generators => {
  4195. const unmerge = cell => {
  4196. const scope = getScopeAttribute(cell);
  4197. scope.each(attribute => set$2(cell, 'scope', attribute));
  4198. return () => {
  4199. const raw = generators.cell({
  4200. element: cell,
  4201. colspan: 1,
  4202. rowspan: 1
  4203. });
  4204. remove$5(raw, 'width');
  4205. remove$5(cell, 'width');
  4206. scope.each(attribute => set$2(raw, 'scope', attribute));
  4207. return raw;
  4208. };
  4209. };
  4210. const merge = cells => {
  4211. const getScopeProperty = () => {
  4212. const stringAttributes = cat(map$1(cells, getScopeAttribute));
  4213. if (stringAttributes.length === 0) {
  4214. return Optional.none();
  4215. } else {
  4216. const baseScope = stringAttributes[0];
  4217. const scopes = [
  4218. 'row',
  4219. 'col'
  4220. ];
  4221. const isMixed = exists(stringAttributes, attribute => {
  4222. return attribute !== baseScope && contains$2(scopes, attribute);
  4223. });
  4224. return isMixed ? Optional.none() : Optional.from(baseScope);
  4225. }
  4226. };
  4227. remove$5(cells[0], 'width');
  4228. getScopeProperty().fold(() => remove$7(cells[0], 'scope'), attribute => set$2(cells[0], 'scope', attribute + 'group'));
  4229. return constant(cells[0]);
  4230. };
  4231. return {
  4232. unmerge,
  4233. merge
  4234. };
  4235. };
  4236. const Generators = {
  4237. modification,
  4238. transform: transform$1,
  4239. merging
  4240. };
  4241. const blockList = [
  4242. 'body',
  4243. 'p',
  4244. 'div',
  4245. 'article',
  4246. 'aside',
  4247. 'figcaption',
  4248. 'figure',
  4249. 'footer',
  4250. 'header',
  4251. 'nav',
  4252. 'section',
  4253. 'ol',
  4254. 'ul',
  4255. 'table',
  4256. 'thead',
  4257. 'tfoot',
  4258. 'tbody',
  4259. 'caption',
  4260. 'tr',
  4261. 'td',
  4262. 'th',
  4263. 'h1',
  4264. 'h2',
  4265. 'h3',
  4266. 'h4',
  4267. 'h5',
  4268. 'h6',
  4269. 'blockquote',
  4270. 'pre',
  4271. 'address'
  4272. ];
  4273. const isList$1 = (universe, item) => {
  4274. const tagName = universe.property().name(item);
  4275. return contains$2([
  4276. 'ol',
  4277. 'ul'
  4278. ], tagName);
  4279. };
  4280. const isBlock$1 = (universe, item) => {
  4281. const tagName = universe.property().name(item);
  4282. return contains$2(blockList, tagName);
  4283. };
  4284. const isEmptyTag$1 = (universe, item) => {
  4285. return contains$2([
  4286. 'br',
  4287. 'img',
  4288. 'hr',
  4289. 'input'
  4290. ], universe.property().name(item));
  4291. };
  4292. const universe$1 = DomUniverse();
  4293. const isBlock = element => {
  4294. return isBlock$1(universe$1, element);
  4295. };
  4296. const isList = element => {
  4297. return isList$1(universe$1, element);
  4298. };
  4299. const isEmptyTag = element => {
  4300. return isEmptyTag$1(universe$1, element);
  4301. };
  4302. const merge = cells => {
  4303. const isBr = isTag('br');
  4304. const advancedBr = children => {
  4305. return forall(children, c => {
  4306. return isBr(c) || isText(c) && get$6(c).trim().length === 0;
  4307. });
  4308. };
  4309. const isListItem = el => {
  4310. return name(el) === 'li' || ancestor$2(el, isList).isSome();
  4311. };
  4312. const siblingIsBlock = el => {
  4313. return nextSibling(el).map(rightSibling => {
  4314. if (isBlock(rightSibling)) {
  4315. return true;
  4316. }
  4317. if (isEmptyTag(rightSibling)) {
  4318. return name(rightSibling) === 'img' ? false : true;
  4319. }
  4320. return false;
  4321. }).getOr(false);
  4322. };
  4323. const markCell = cell => {
  4324. return last$1(cell).bind(rightEdge => {
  4325. const rightSiblingIsBlock = siblingIsBlock(rightEdge);
  4326. return parent(rightEdge).map(parent => {
  4327. return rightSiblingIsBlock === true || isListItem(parent) || isBr(rightEdge) || isBlock(parent) && !eq$1(cell, parent) ? [] : [SugarElement.fromTag('br')];
  4328. });
  4329. }).getOr([]);
  4330. };
  4331. const markContent = () => {
  4332. const content = bind$2(cells, cell => {
  4333. const children = children$2(cell);
  4334. return advancedBr(children) ? [] : children.concat(markCell(cell));
  4335. });
  4336. return content.length === 0 ? [SugarElement.fromTag('br')] : content;
  4337. };
  4338. const contents = markContent();
  4339. empty(cells[0]);
  4340. append(cells[0], contents);
  4341. };
  4342. const isEditable = elem => isEditable$1(elem, true);
  4343. const prune = table => {
  4344. const cells = cells$1(table);
  4345. if (cells.length === 0) {
  4346. remove$6(table);
  4347. }
  4348. };
  4349. const outcome = (grid, cursor) => ({
  4350. grid,
  4351. cursor
  4352. });
  4353. const findEditableCursorPosition = rows => findMap(rows, row => findMap(row.cells, cell => {
  4354. const elem = cell.element;
  4355. return someIf(isEditable(elem), elem);
  4356. }));
  4357. const elementFromGrid = (grid, row, column) => {
  4358. var _a, _b;
  4359. const rows = extractGridDetails(grid).rows;
  4360. return Optional.from((_b = (_a = rows[row]) === null || _a === void 0 ? void 0 : _a.cells[column]) === null || _b === void 0 ? void 0 : _b.element).filter(isEditable).orThunk(() => findEditableCursorPosition(rows));
  4361. };
  4362. const bundle = (grid, row, column) => {
  4363. const cursorElement = elementFromGrid(grid, row, column);
  4364. return outcome(grid, cursorElement);
  4365. };
  4366. const uniqueRows = details => {
  4367. const rowCompilation = (rest, detail) => {
  4368. const rowExists = exists(rest, currentDetail => currentDetail.row === detail.row);
  4369. return rowExists ? rest : rest.concat([detail]);
  4370. };
  4371. return foldl(details, rowCompilation, []).sort((detailA, detailB) => detailA.row - detailB.row);
  4372. };
  4373. const opInsertRowsBefore = (grid, details, comparator, genWrappers) => {
  4374. const targetIndex = details[0].row;
  4375. const rows = uniqueRows(details);
  4376. const newGrid = foldr(rows, (acc, row) => {
  4377. const newG = insertRowAt(acc.grid, targetIndex, row.row + acc.delta, comparator, genWrappers.getOrInit);
  4378. return {
  4379. grid: newG,
  4380. delta: acc.delta + 1
  4381. };
  4382. }, {
  4383. grid,
  4384. delta: 0
  4385. }).grid;
  4386. return bundle(newGrid, targetIndex, details[0].column);
  4387. };
  4388. const opInsertRowsAfter = (grid, details, comparator, genWrappers) => {
  4389. const rows = uniqueRows(details);
  4390. const target = rows[rows.length - 1];
  4391. const targetIndex = target.row + target.rowspan;
  4392. const newGrid = foldr(rows, (newG, row) => {
  4393. return insertRowAt(newG, targetIndex, row.row, comparator, genWrappers.getOrInit);
  4394. }, grid);
  4395. return bundle(newGrid, targetIndex, details[0].column);
  4396. };
  4397. const opInsertColumnsBefore = (grid, extractDetail, comparator, genWrappers) => {
  4398. const details = extractDetail.details;
  4399. const columns = uniqueColumns(details);
  4400. const targetIndex = columns[0].column;
  4401. const newGrid = foldr(columns, (acc, col) => {
  4402. const newG = insertColumnAt(acc.grid, targetIndex, col.column + acc.delta, comparator, genWrappers.getOrInit);
  4403. return {
  4404. grid: newG,
  4405. delta: acc.delta + 1
  4406. };
  4407. }, {
  4408. grid,
  4409. delta: 0
  4410. }).grid;
  4411. return bundle(newGrid, details[0].row, targetIndex);
  4412. };
  4413. const opInsertColumnsAfter = (grid, extractDetail, comparator, genWrappers) => {
  4414. const details = extractDetail.details;
  4415. const target = details[details.length - 1];
  4416. const targetIndex = target.column + target.colspan;
  4417. const columns = uniqueColumns(details);
  4418. const newGrid = foldr(columns, (newG, col) => {
  4419. return insertColumnAt(newG, targetIndex, col.column, comparator, genWrappers.getOrInit);
  4420. }, grid);
  4421. return bundle(newGrid, details[0].row, targetIndex);
  4422. };
  4423. const opMakeColumnsHeader = (initialGrid, details, comparator, genWrappers) => {
  4424. const columns = uniqueColumns(details);
  4425. const columnIndexes = map$1(columns, detail => detail.column);
  4426. const newGrid = replaceColumns(initialGrid, columnIndexes, true, comparator, genWrappers.replaceOrInit);
  4427. return bundle(newGrid, details[0].row, details[0].column);
  4428. };
  4429. const opMakeCellsHeader = (initialGrid, details, comparator, genWrappers) => {
  4430. const newGrid = replaceCells(initialGrid, details, comparator, genWrappers.replaceOrInit);
  4431. return bundle(newGrid, details[0].row, details[0].column);
  4432. };
  4433. const opUnmakeColumnsHeader = (initialGrid, details, comparator, genWrappers) => {
  4434. const columns = uniqueColumns(details);
  4435. const columnIndexes = map$1(columns, detail => detail.column);
  4436. const newGrid = replaceColumns(initialGrid, columnIndexes, false, comparator, genWrappers.replaceOrInit);
  4437. return bundle(newGrid, details[0].row, details[0].column);
  4438. };
  4439. const opUnmakeCellsHeader = (initialGrid, details, comparator, genWrappers) => {
  4440. const newGrid = replaceCells(initialGrid, details, comparator, genWrappers.replaceOrInit);
  4441. return bundle(newGrid, details[0].row, details[0].column);
  4442. };
  4443. const makeRowsSection = (section, applyScope) => (initialGrid, details, comparator, genWrappers, tableSection) => {
  4444. const rows = uniqueRows(details);
  4445. const rowIndexes = map$1(rows, detail => detail.row);
  4446. const newGrid = replaceRows(initialGrid, rowIndexes, section, applyScope, comparator, genWrappers.replaceOrInit, tableSection);
  4447. return bundle(newGrid, details[0].row, details[0].column);
  4448. };
  4449. const opMakeRowsHeader = makeRowsSection('thead', true);
  4450. const opMakeRowsBody = makeRowsSection('tbody', false);
  4451. const opMakeRowsFooter = makeRowsSection('tfoot', false);
  4452. const opEraseColumns = (grid, extractDetail, _comparator, _genWrappers) => {
  4453. const columns = uniqueColumns(extractDetail.details);
  4454. const newGrid = deleteColumnsAt(grid, map$1(columns, column => column.column));
  4455. const maxColIndex = newGrid.length > 0 ? newGrid[0].cells.length - 1 : 0;
  4456. return bundle(newGrid, columns[0].row, Math.min(columns[0].column, maxColIndex));
  4457. };
  4458. const opEraseRows = (grid, details, _comparator, _genWrappers) => {
  4459. const rows = uniqueRows(details);
  4460. const newGrid = deleteRowsAt(grid, rows[0].row, rows[rows.length - 1].row);
  4461. const maxRowIndex = newGrid.length > 0 ? newGrid.length - 1 : 0;
  4462. return bundle(newGrid, Math.min(details[0].row, maxRowIndex), details[0].column);
  4463. };
  4464. const opMergeCells = (grid, mergable, comparator, genWrappers) => {
  4465. const cells = mergable.cells;
  4466. merge(cells);
  4467. const newGrid = merge$2(grid, mergable.bounds, comparator, genWrappers.merge(cells));
  4468. return outcome(newGrid, Optional.from(cells[0]));
  4469. };
  4470. const opUnmergeCells = (grid, unmergable, comparator, genWrappers) => {
  4471. const unmerge$1 = (b, cell) => unmerge(b, cell, comparator, genWrappers.unmerge(cell));
  4472. const newGrid = foldr(unmergable, unmerge$1, grid);
  4473. return outcome(newGrid, Optional.from(unmergable[0]));
  4474. };
  4475. const opPasteCells = (grid, pasteDetails, comparator, _genWrappers) => {
  4476. const gridify = (table, generators) => {
  4477. const wh = Warehouse.fromTable(table);
  4478. return toGrid(wh, generators, true);
  4479. };
  4480. const gridB = gridify(pasteDetails.clipboard, pasteDetails.generators);
  4481. const startAddress = address(pasteDetails.row, pasteDetails.column);
  4482. const mergedGrid = merge$1(startAddress, grid, gridB, pasteDetails.generators, comparator);
  4483. return mergedGrid.fold(() => outcome(grid, Optional.some(pasteDetails.element)), newGrid => {
  4484. return bundle(newGrid, pasteDetails.row, pasteDetails.column);
  4485. });
  4486. };
  4487. const gridifyRows = (rows, generators, context) => {
  4488. const pasteDetails = fromPastedRows(rows, context.section);
  4489. const wh = Warehouse.generate(pasteDetails);
  4490. return toGrid(wh, generators, true);
  4491. };
  4492. const opPasteColsBefore = (grid, pasteDetails, comparator, _genWrappers) => {
  4493. const rows = extractGridDetails(grid).rows;
  4494. const index = pasteDetails.cells[0].column;
  4495. const context = rows[pasteDetails.cells[0].row];
  4496. const gridB = gridifyRows(pasteDetails.clipboard, pasteDetails.generators, context);
  4497. const mergedGrid = insertCols(index, grid, gridB, pasteDetails.generators, comparator);
  4498. return bundle(mergedGrid, pasteDetails.cells[0].row, pasteDetails.cells[0].column);
  4499. };
  4500. const opPasteColsAfter = (grid, pasteDetails, comparator, _genWrappers) => {
  4501. const rows = extractGridDetails(grid).rows;
  4502. const index = pasteDetails.cells[pasteDetails.cells.length - 1].column + pasteDetails.cells[pasteDetails.cells.length - 1].colspan;
  4503. const context = rows[pasteDetails.cells[0].row];
  4504. const gridB = gridifyRows(pasteDetails.clipboard, pasteDetails.generators, context);
  4505. const mergedGrid = insertCols(index, grid, gridB, pasteDetails.generators, comparator);
  4506. return bundle(mergedGrid, pasteDetails.cells[0].row, pasteDetails.cells[0].column);
  4507. };
  4508. const opPasteRowsBefore = (grid, pasteDetails, comparator, _genWrappers) => {
  4509. const rows = extractGridDetails(grid).rows;
  4510. const index = pasteDetails.cells[0].row;
  4511. const context = rows[index];
  4512. const gridB = gridifyRows(pasteDetails.clipboard, pasteDetails.generators, context);
  4513. const mergedGrid = insertRows(index, grid, gridB, pasteDetails.generators, comparator);
  4514. return bundle(mergedGrid, pasteDetails.cells[0].row, pasteDetails.cells[0].column);
  4515. };
  4516. const opPasteRowsAfter = (grid, pasteDetails, comparator, _genWrappers) => {
  4517. const rows = extractGridDetails(grid).rows;
  4518. const index = pasteDetails.cells[pasteDetails.cells.length - 1].row + pasteDetails.cells[pasteDetails.cells.length - 1].rowspan;
  4519. const context = rows[pasteDetails.cells[0].row];
  4520. const gridB = gridifyRows(pasteDetails.clipboard, pasteDetails.generators, context);
  4521. const mergedGrid = insertRows(index, grid, gridB, pasteDetails.generators, comparator);
  4522. return bundle(mergedGrid, pasteDetails.cells[0].row, pasteDetails.cells[0].column);
  4523. };
  4524. const opGetColumnsType = (table, target) => {
  4525. const house = Warehouse.fromTable(table);
  4526. const details = onCells(house, target);
  4527. return details.bind(selectedCells => {
  4528. const lastSelectedCell = selectedCells[selectedCells.length - 1];
  4529. const minColRange = selectedCells[0].column;
  4530. const maxColRange = lastSelectedCell.column + lastSelectedCell.colspan;
  4531. const selectedColumnCells = flatten(map$1(house.all, row => filter$2(row.cells, cell => cell.column >= minColRange && cell.column < maxColRange)));
  4532. return findCommonCellType(selectedColumnCells);
  4533. }).getOr('');
  4534. };
  4535. const opGetCellsType = (table, target) => {
  4536. const house = Warehouse.fromTable(table);
  4537. const details = onCells(house, target);
  4538. return details.bind(findCommonCellType).getOr('');
  4539. };
  4540. const opGetRowsType = (table, target) => {
  4541. const house = Warehouse.fromTable(table);
  4542. const details = onCells(house, target);
  4543. return details.bind(selectedCells => {
  4544. const lastSelectedCell = selectedCells[selectedCells.length - 1];
  4545. const minRowRange = selectedCells[0].row;
  4546. const maxRowRange = lastSelectedCell.row + lastSelectedCell.rowspan;
  4547. const selectedRows = house.all.slice(minRowRange, maxRowRange);
  4548. return findCommonRowType(selectedRows);
  4549. }).getOr('');
  4550. };
  4551. const resize = (table, list, details, behaviours) => adjustWidthTo(table, list, details, behaviours.sizing);
  4552. const adjustAndRedistributeWidths = (table, list, details, behaviours) => adjustAndRedistributeWidths$1(table, list, details, behaviours.sizing, behaviours.resize);
  4553. const firstColumnIsLocked = (_warehouse, details) => exists(details, detail => detail.column === 0 && detail.isLocked);
  4554. const lastColumnIsLocked = (warehouse, details) => exists(details, detail => detail.column + detail.colspan >= warehouse.grid.columns && detail.isLocked);
  4555. const getColumnsWidth = (warehouse, details) => {
  4556. const columns$1 = columns(warehouse);
  4557. const uniqueCols = uniqueColumns(details);
  4558. return foldl(uniqueCols, (acc, detail) => {
  4559. const column = columns$1[detail.column];
  4560. const colWidth = column.map(getOuter$2).getOr(0);
  4561. return acc + colWidth;
  4562. }, 0);
  4563. };
  4564. const insertColumnsExtractor = before => (warehouse, target) => onCells(warehouse, target).filter(details => {
  4565. const checkLocked = before ? firstColumnIsLocked : lastColumnIsLocked;
  4566. return !checkLocked(warehouse, details);
  4567. }).map(details => ({
  4568. details,
  4569. pixelDelta: getColumnsWidth(warehouse, details)
  4570. }));
  4571. const eraseColumnsExtractor = (warehouse, target) => onUnlockedCells(warehouse, target).map(details => ({
  4572. details,
  4573. pixelDelta: -getColumnsWidth(warehouse, details)
  4574. }));
  4575. const pasteColumnsExtractor = before => (warehouse, target) => onPasteByEditor(warehouse, target).filter(details => {
  4576. const checkLocked = before ? firstColumnIsLocked : lastColumnIsLocked;
  4577. return !checkLocked(warehouse, details.cells);
  4578. });
  4579. const headerCellGenerator = Generators.transform('th');
  4580. const bodyCellGenerator = Generators.transform('td');
  4581. const insertRowsBefore = run(opInsertRowsBefore, onCells, noop, noop, Generators.modification);
  4582. const insertRowsAfter = run(opInsertRowsAfter, onCells, noop, noop, Generators.modification);
  4583. const insertColumnsBefore = run(opInsertColumnsBefore, insertColumnsExtractor(true), adjustAndRedistributeWidths, noop, Generators.modification);
  4584. const insertColumnsAfter = run(opInsertColumnsAfter, insertColumnsExtractor(false), adjustAndRedistributeWidths, noop, Generators.modification);
  4585. const eraseColumns = run(opEraseColumns, eraseColumnsExtractor, adjustAndRedistributeWidths, prune, Generators.modification);
  4586. const eraseRows = run(opEraseRows, onCells, noop, prune, Generators.modification);
  4587. const makeColumnsHeader = run(opMakeColumnsHeader, onUnlockedCells, noop, noop, headerCellGenerator);
  4588. const unmakeColumnsHeader = run(opUnmakeColumnsHeader, onUnlockedCells, noop, noop, bodyCellGenerator);
  4589. const makeRowsHeader = run(opMakeRowsHeader, onUnlockedCells, noop, noop, headerCellGenerator);
  4590. const makeRowsBody = run(opMakeRowsBody, onUnlockedCells, noop, noop, bodyCellGenerator);
  4591. const makeRowsFooter = run(opMakeRowsFooter, onUnlockedCells, noop, noop, bodyCellGenerator);
  4592. const makeCellsHeader = run(opMakeCellsHeader, onUnlockedCells, noop, noop, headerCellGenerator);
  4593. const unmakeCellsHeader = run(opUnmakeCellsHeader, onUnlockedCells, noop, noop, bodyCellGenerator);
  4594. const mergeCells = run(opMergeCells, onUnlockedMergable, resize, noop, Generators.merging);
  4595. const unmergeCells = run(opUnmergeCells, onUnlockedUnmergable, resize, noop, Generators.merging);
  4596. const pasteCells = run(opPasteCells, onPaste, resize, noop, Generators.modification);
  4597. const pasteColsBefore = run(opPasteColsBefore, pasteColumnsExtractor(true), noop, noop, Generators.modification);
  4598. const pasteColsAfter = run(opPasteColsAfter, pasteColumnsExtractor(false), noop, noop, Generators.modification);
  4599. const pasteRowsBefore = run(opPasteRowsBefore, onPasteByEditor, noop, noop, Generators.modification);
  4600. const pasteRowsAfter = run(opPasteRowsAfter, onPasteByEditor, noop, noop, Generators.modification);
  4601. const getColumnsType = opGetColumnsType;
  4602. const getCellsType = opGetCellsType;
  4603. const getRowsType = opGetRowsType;
  4604. const fireNewRow = (editor, row) => editor.dispatch('NewRow', { node: row });
  4605. const fireNewCell = (editor, cell) => editor.dispatch('NewCell', { node: cell });
  4606. const fireTableModified = (editor, table, data) => {
  4607. editor.dispatch('TableModified', {
  4608. ...data,
  4609. table
  4610. });
  4611. };
  4612. const fireTableSelectionChange = (editor, cells, start, finish, otherCells) => {
  4613. editor.dispatch('TableSelectionChange', {
  4614. cells,
  4615. start,
  4616. finish,
  4617. otherCells
  4618. });
  4619. };
  4620. const fireTableSelectionClear = editor => {
  4621. editor.dispatch('TableSelectionClear');
  4622. };
  4623. const fireObjectResizeStart = (editor, target, width, height, origin) => {
  4624. editor.dispatch('ObjectResizeStart', {
  4625. target,
  4626. width,
  4627. height,
  4628. origin
  4629. });
  4630. };
  4631. const fireObjectResized = (editor, target, width, height, origin) => {
  4632. editor.dispatch('ObjectResized', {
  4633. target,
  4634. width,
  4635. height,
  4636. origin
  4637. });
  4638. };
  4639. const styleModified = {
  4640. structure: false,
  4641. style: true
  4642. };
  4643. const structureModified = {
  4644. structure: true,
  4645. style: false
  4646. };
  4647. const styleAndStructureModified = {
  4648. structure: true,
  4649. style: true
  4650. };
  4651. const get$5 = (editor, table) => {
  4652. if (isTablePercentagesForced(editor)) {
  4653. return TableSize.percentageSize(table);
  4654. } else if (isTablePixelsForced(editor)) {
  4655. return TableSize.pixelSize(table);
  4656. } else {
  4657. return TableSize.getTableSize(table);
  4658. }
  4659. };
  4660. const TableActions = (editor, resizeHandler, cellSelectionHandler) => {
  4661. const isTableBody = editor => name(getBody(editor)) === 'table';
  4662. const lastRowGuard = table => !isTableBody(editor) || getGridSize(table).rows > 1;
  4663. const lastColumnGuard = table => !isTableBody(editor) || getGridSize(table).columns > 1;
  4664. const cloneFormats = getTableCloneElements(editor);
  4665. const colMutationOp = isResizeTableColumnResizing(editor) ? noop : halve;
  4666. const getTableSectionType = table => {
  4667. switch (getTableHeaderType(editor)) {
  4668. case 'section':
  4669. return TableSection.section();
  4670. case 'sectionCells':
  4671. return TableSection.sectionCells();
  4672. case 'cells':
  4673. return TableSection.cells();
  4674. default:
  4675. return TableSection.getTableSectionType(table, 'section');
  4676. }
  4677. };
  4678. const setSelectionFromAction = (table, result) => result.cursor.fold(() => {
  4679. const cells = cells$1(table);
  4680. return head(cells).filter(inBody).map(firstCell => {
  4681. cellSelectionHandler.clearSelectedCells(table.dom);
  4682. const rng = editor.dom.createRng();
  4683. rng.selectNode(firstCell.dom);
  4684. editor.selection.setRng(rng);
  4685. set$2(firstCell, 'data-mce-selected', '1');
  4686. return rng;
  4687. });
  4688. }, cell => {
  4689. const des = freefallRtl(cell);
  4690. const rng = editor.dom.createRng();
  4691. rng.setStart(des.element.dom, des.offset);
  4692. rng.setEnd(des.element.dom, des.offset);
  4693. editor.selection.setRng(rng);
  4694. cellSelectionHandler.clearSelectedCells(table.dom);
  4695. return Optional.some(rng);
  4696. });
  4697. const execute = (operation, guard, mutate, effect) => (table, target, noEvents = false) => {
  4698. removeDataStyle(table);
  4699. const doc = SugarElement.fromDom(editor.getDoc());
  4700. const generators = cellOperations(mutate, doc, cloneFormats);
  4701. const behaviours = {
  4702. sizing: get$5(editor, table),
  4703. resize: isResizeTableColumnResizing(editor) ? resizeTable() : preserveTable(),
  4704. section: getTableSectionType(table)
  4705. };
  4706. return guard(table) ? operation(table, target, generators, behaviours).bind(result => {
  4707. resizeHandler.refresh(table.dom);
  4708. each$2(result.newRows, row => {
  4709. fireNewRow(editor, row.dom);
  4710. });
  4711. each$2(result.newCells, cell => {
  4712. fireNewCell(editor, cell.dom);
  4713. });
  4714. const range = setSelectionFromAction(table, result);
  4715. if (inBody(table)) {
  4716. removeDataStyle(table);
  4717. if (!noEvents) {
  4718. fireTableModified(editor, table.dom, effect);
  4719. }
  4720. }
  4721. return range.map(rng => ({
  4722. rng,
  4723. effect
  4724. }));
  4725. }) : Optional.none();
  4726. };
  4727. const deleteRow = execute(eraseRows, lastRowGuard, noop, structureModified);
  4728. const deleteColumn = execute(eraseColumns, lastColumnGuard, noop, structureModified);
  4729. const insertRowsBefore$1 = execute(insertRowsBefore, always, noop, structureModified);
  4730. const insertRowsAfter$1 = execute(insertRowsAfter, always, noop, structureModified);
  4731. const insertColumnsBefore$1 = execute(insertColumnsBefore, always, colMutationOp, structureModified);
  4732. const insertColumnsAfter$1 = execute(insertColumnsAfter, always, colMutationOp, structureModified);
  4733. const mergeCells$1 = execute(mergeCells, always, noop, structureModified);
  4734. const unmergeCells$1 = execute(unmergeCells, always, noop, structureModified);
  4735. const pasteColsBefore$1 = execute(pasteColsBefore, always, noop, structureModified);
  4736. const pasteColsAfter$1 = execute(pasteColsAfter, always, noop, structureModified);
  4737. const pasteRowsBefore$1 = execute(pasteRowsBefore, always, noop, structureModified);
  4738. const pasteRowsAfter$1 = execute(pasteRowsAfter, always, noop, structureModified);
  4739. const pasteCells$1 = execute(pasteCells, always, noop, styleAndStructureModified);
  4740. const makeCellsHeader$1 = execute(makeCellsHeader, always, noop, structureModified);
  4741. const unmakeCellsHeader$1 = execute(unmakeCellsHeader, always, noop, structureModified);
  4742. const makeColumnsHeader$1 = execute(makeColumnsHeader, always, noop, structureModified);
  4743. const unmakeColumnsHeader$1 = execute(unmakeColumnsHeader, always, noop, structureModified);
  4744. const makeRowsHeader$1 = execute(makeRowsHeader, always, noop, structureModified);
  4745. const makeRowsBody$1 = execute(makeRowsBody, always, noop, structureModified);
  4746. const makeRowsFooter$1 = execute(makeRowsFooter, always, noop, structureModified);
  4747. const getTableCellType = getCellsType;
  4748. const getTableColType = getColumnsType;
  4749. const getTableRowType = getRowsType;
  4750. return {
  4751. deleteRow,
  4752. deleteColumn,
  4753. insertRowsBefore: insertRowsBefore$1,
  4754. insertRowsAfter: insertRowsAfter$1,
  4755. insertColumnsBefore: insertColumnsBefore$1,
  4756. insertColumnsAfter: insertColumnsAfter$1,
  4757. mergeCells: mergeCells$1,
  4758. unmergeCells: unmergeCells$1,
  4759. pasteColsBefore: pasteColsBefore$1,
  4760. pasteColsAfter: pasteColsAfter$1,
  4761. pasteRowsBefore: pasteRowsBefore$1,
  4762. pasteRowsAfter: pasteRowsAfter$1,
  4763. pasteCells: pasteCells$1,
  4764. makeCellsHeader: makeCellsHeader$1,
  4765. unmakeCellsHeader: unmakeCellsHeader$1,
  4766. makeColumnsHeader: makeColumnsHeader$1,
  4767. unmakeColumnsHeader: unmakeColumnsHeader$1,
  4768. makeRowsHeader: makeRowsHeader$1,
  4769. makeRowsBody: makeRowsBody$1,
  4770. makeRowsFooter: makeRowsFooter$1,
  4771. getTableRowType,
  4772. getTableCellType,
  4773. getTableColType
  4774. };
  4775. };
  4776. const constrainSpan = (element, property, value) => {
  4777. const currentColspan = getAttrValue(element, property, 1);
  4778. if (value === 1 || currentColspan <= 1) {
  4779. remove$7(element, property);
  4780. } else {
  4781. set$2(element, property, Math.min(value, currentColspan));
  4782. }
  4783. };
  4784. const isColInRange = (minColRange, maxColRange) => cell => {
  4785. const endCol = cell.column + cell.colspan - 1;
  4786. const startCol = cell.column;
  4787. return endCol >= minColRange && startCol < maxColRange;
  4788. };
  4789. const generateColGroup = (house, minColRange, maxColRange) => {
  4790. if (Warehouse.hasColumns(house)) {
  4791. const colsToCopy = filter$2(Warehouse.justColumns(house), isColInRange(minColRange, maxColRange));
  4792. const copiedCols = map$1(colsToCopy, c => {
  4793. const clonedCol = deep(c.element);
  4794. constrainSpan(clonedCol, 'span', maxColRange - minColRange);
  4795. return clonedCol;
  4796. });
  4797. const fakeColgroup = SugarElement.fromTag('colgroup');
  4798. append(fakeColgroup, copiedCols);
  4799. return [fakeColgroup];
  4800. } else {
  4801. return [];
  4802. }
  4803. };
  4804. const generateRows = (house, minColRange, maxColRange) => map$1(house.all, row => {
  4805. const cellsToCopy = filter$2(row.cells, isColInRange(minColRange, maxColRange));
  4806. const copiedCells = map$1(cellsToCopy, cell => {
  4807. const clonedCell = deep(cell.element);
  4808. constrainSpan(clonedCell, 'colspan', maxColRange - minColRange);
  4809. return clonedCell;
  4810. });
  4811. const fakeTR = SugarElement.fromTag('tr');
  4812. append(fakeTR, copiedCells);
  4813. return fakeTR;
  4814. });
  4815. const copyCols = (table, target) => {
  4816. const house = Warehouse.fromTable(table);
  4817. const details = onUnlockedCells(house, target);
  4818. return details.map(selectedCells => {
  4819. const lastSelectedCell = selectedCells[selectedCells.length - 1];
  4820. const minColRange = selectedCells[0].column;
  4821. const maxColRange = lastSelectedCell.column + lastSelectedCell.colspan;
  4822. const fakeColGroups = generateColGroup(house, minColRange, maxColRange);
  4823. const fakeRows = generateRows(house, minColRange, maxColRange);
  4824. return [
  4825. ...fakeColGroups,
  4826. ...fakeRows
  4827. ];
  4828. });
  4829. };
  4830. const copyRows = (table, target, generators) => {
  4831. const warehouse = Warehouse.fromTable(table);
  4832. const details = onCells(warehouse, target);
  4833. return details.bind(selectedCells => {
  4834. const grid = toGrid(warehouse, generators, false);
  4835. const rows = extractGridDetails(grid).rows;
  4836. const slicedGrid = rows.slice(selectedCells[0].row, selectedCells[selectedCells.length - 1].row + selectedCells[selectedCells.length - 1].rowspan);
  4837. const filteredGrid = bind$2(slicedGrid, row => {
  4838. const newCells = filter$2(row.cells, cell => !cell.isLocked);
  4839. return newCells.length > 0 ? [{
  4840. ...row,
  4841. cells: newCells
  4842. }] : [];
  4843. });
  4844. const slicedDetails = toDetailList(filteredGrid);
  4845. return someIf(slicedDetails.length > 0, slicedDetails);
  4846. }).map(slicedDetails => copy(slicedDetails));
  4847. };
  4848. const adt$5 = Adt.generate([
  4849. { invalid: ['raw'] },
  4850. { pixels: ['value'] },
  4851. { percent: ['value'] }
  4852. ]);
  4853. const validateFor = (suffix, type, value) => {
  4854. const rawAmount = value.substring(0, value.length - suffix.length);
  4855. const amount = parseFloat(rawAmount);
  4856. return rawAmount === amount.toString() ? type(amount) : adt$5.invalid(value);
  4857. };
  4858. const from = value => {
  4859. if (endsWith(value, '%')) {
  4860. return validateFor('%', adt$5.percent, value);
  4861. }
  4862. if (endsWith(value, 'px')) {
  4863. return validateFor('px', adt$5.pixels, value);
  4864. }
  4865. return adt$5.invalid(value);
  4866. };
  4867. const Size = {
  4868. ...adt$5,
  4869. from
  4870. };
  4871. const redistributeToPercent = (widths, totalWidth) => {
  4872. return map$1(widths, w => {
  4873. const colType = Size.from(w);
  4874. return colType.fold(() => {
  4875. return w;
  4876. }, px => {
  4877. const ratio = px / totalWidth * 100;
  4878. return ratio + '%';
  4879. }, pc => {
  4880. return pc + '%';
  4881. });
  4882. });
  4883. };
  4884. const redistributeToPx = (widths, totalWidth, newTotalWidth) => {
  4885. const scale = newTotalWidth / totalWidth;
  4886. return map$1(widths, w => {
  4887. const colType = Size.from(w);
  4888. return colType.fold(() => {
  4889. return w;
  4890. }, px => {
  4891. return px * scale + 'px';
  4892. }, pc => {
  4893. return pc / 100 * newTotalWidth + 'px';
  4894. });
  4895. });
  4896. };
  4897. const redistributeEmpty = (newWidthType, columns) => {
  4898. const f = newWidthType.fold(() => constant(''), pixels => {
  4899. const num = pixels / columns;
  4900. return constant(num + 'px');
  4901. }, () => {
  4902. const num = 100 / columns;
  4903. return constant(num + '%');
  4904. });
  4905. return range$1(columns, f);
  4906. };
  4907. const redistributeValues = (newWidthType, widths, totalWidth) => {
  4908. return newWidthType.fold(() => {
  4909. return widths;
  4910. }, px => {
  4911. return redistributeToPx(widths, totalWidth, px);
  4912. }, _pc => {
  4913. return redistributeToPercent(widths, totalWidth);
  4914. });
  4915. };
  4916. const redistribute$1 = (widths, totalWidth, newWidth) => {
  4917. const newType = Size.from(newWidth);
  4918. const floats = forall(widths, s => {
  4919. return s === '0px';
  4920. }) ? redistributeEmpty(newType, widths.length) : redistributeValues(newType, widths, totalWidth);
  4921. return normalize(floats);
  4922. };
  4923. const sum = (values, fallback) => {
  4924. if (values.length === 0) {
  4925. return fallback;
  4926. }
  4927. return foldr(values, (rest, v) => {
  4928. return Size.from(v).fold(constant(0), identity, identity) + rest;
  4929. }, 0);
  4930. };
  4931. const roundDown = (num, unit) => {
  4932. const floored = Math.floor(num);
  4933. return {
  4934. value: floored + unit,
  4935. remainder: num - floored
  4936. };
  4937. };
  4938. const add$3 = (value, amount) => {
  4939. return Size.from(value).fold(constant(value), px => {
  4940. return px + amount + 'px';
  4941. }, pc => {
  4942. return pc + amount + '%';
  4943. });
  4944. };
  4945. const normalize = values => {
  4946. if (values.length === 0) {
  4947. return values;
  4948. }
  4949. const scan = foldr(values, (rest, value) => {
  4950. const info = Size.from(value).fold(() => ({
  4951. value,
  4952. remainder: 0
  4953. }), num => roundDown(num, 'px'), num => ({
  4954. value: num + '%',
  4955. remainder: 0
  4956. }));
  4957. return {
  4958. output: [info.value].concat(rest.output),
  4959. remainder: rest.remainder + info.remainder
  4960. };
  4961. }, {
  4962. output: [],
  4963. remainder: 0
  4964. });
  4965. const r = scan.output;
  4966. return r.slice(0, r.length - 1).concat([add$3(r[r.length - 1], Math.round(scan.remainder))]);
  4967. };
  4968. const validate = Size.from;
  4969. const redistributeToW = (newWidths, cells, unit) => {
  4970. each$2(cells, cell => {
  4971. const widths = newWidths.slice(cell.column, cell.colspan + cell.column);
  4972. const w = sum(widths, minWidth());
  4973. set$1(cell.element, 'width', w + unit);
  4974. });
  4975. };
  4976. const redistributeToColumns = (newWidths, columns, unit) => {
  4977. each$2(columns, (column, index) => {
  4978. const width = sum([newWidths[index]], minWidth());
  4979. set$1(column.element, 'width', width + unit);
  4980. });
  4981. };
  4982. const redistributeToH = (newHeights, rows, cells, unit) => {
  4983. each$2(cells, cell => {
  4984. const heights = newHeights.slice(cell.row, cell.rowspan + cell.row);
  4985. const h = sum(heights, minHeight());
  4986. set$1(cell.element, 'height', h + unit);
  4987. });
  4988. each$2(rows, (row, i) => {
  4989. set$1(row.element, 'height', newHeights[i]);
  4990. });
  4991. };
  4992. const getUnit = newSize => {
  4993. return validate(newSize).fold(constant('px'), constant('px'), constant('%'));
  4994. };
  4995. const redistribute = (table, optWidth, optHeight) => {
  4996. const warehouse = Warehouse.fromTable(table);
  4997. const rows = warehouse.all;
  4998. const cells = Warehouse.justCells(warehouse);
  4999. const columns = Warehouse.justColumns(warehouse);
  5000. optWidth.each(newWidth => {
  5001. const widthUnit = getUnit(newWidth);
  5002. const totalWidth = get$9(table);
  5003. const oldWidths = getRawWidths(warehouse, table);
  5004. const nuWidths = redistribute$1(oldWidths, totalWidth, newWidth);
  5005. if (Warehouse.hasColumns(warehouse)) {
  5006. redistributeToColumns(nuWidths, columns, widthUnit);
  5007. } else {
  5008. redistributeToW(nuWidths, cells, widthUnit);
  5009. }
  5010. set$1(table, 'width', newWidth);
  5011. });
  5012. optHeight.each(newHeight => {
  5013. const hUnit = getUnit(newHeight);
  5014. const totalHeight = get$8(table);
  5015. const oldHeights = getRawHeights(warehouse, table, height);
  5016. const nuHeights = redistribute$1(oldHeights, totalHeight, newHeight);
  5017. redistributeToH(nuHeights, rows, cells, hUnit);
  5018. set$1(table, 'height', newHeight);
  5019. });
  5020. };
  5021. const isPercentSizing = isPercentSizing$1;
  5022. const isPixelSizing = isPixelSizing$1;
  5023. const isNoneSizing = isNoneSizing$1;
  5024. const cleanupLegacyAttributes = element => {
  5025. remove$7(element, 'width');
  5026. };
  5027. const convertToPercentSize = table => {
  5028. const newWidth = getPercentTableWidth(table);
  5029. redistribute(table, Optional.some(newWidth), Optional.none());
  5030. cleanupLegacyAttributes(table);
  5031. };
  5032. const convertToPixelSize = table => {
  5033. const newWidth = getPixelTableWidth(table);
  5034. redistribute(table, Optional.some(newWidth), Optional.none());
  5035. cleanupLegacyAttributes(table);
  5036. };
  5037. const convertToNoneSize = table => {
  5038. remove$5(table, 'width');
  5039. const columns = columns$1(table);
  5040. const rowElements = columns.length > 0 ? columns : cells$1(table);
  5041. each$2(rowElements, cell => {
  5042. remove$5(cell, 'width');
  5043. cleanupLegacyAttributes(cell);
  5044. });
  5045. cleanupLegacyAttributes(table);
  5046. };
  5047. const DefaultRenderOptions = {
  5048. styles: {
  5049. 'border-collapse': 'collapse',
  5050. 'width': '100%'
  5051. },
  5052. attributes: { border: '1' },
  5053. colGroups: false
  5054. };
  5055. const tableHeaderCell = () => SugarElement.fromTag('th');
  5056. const tableCell = () => SugarElement.fromTag('td');
  5057. const tableColumn = () => SugarElement.fromTag('col');
  5058. const createRow = (columns, rowHeaders, columnHeaders, rowIndex) => {
  5059. const tr = SugarElement.fromTag('tr');
  5060. for (let j = 0; j < columns; j++) {
  5061. const td = rowIndex < rowHeaders || j < columnHeaders ? tableHeaderCell() : tableCell();
  5062. if (j < columnHeaders) {
  5063. set$2(td, 'scope', 'row');
  5064. }
  5065. if (rowIndex < rowHeaders) {
  5066. set$2(td, 'scope', 'col');
  5067. }
  5068. append$1(td, SugarElement.fromTag('br'));
  5069. append$1(tr, td);
  5070. }
  5071. return tr;
  5072. };
  5073. const createGroupRow = columns => {
  5074. const columnGroup = SugarElement.fromTag('colgroup');
  5075. range$1(columns, () => append$1(columnGroup, tableColumn()));
  5076. return columnGroup;
  5077. };
  5078. const createRows = (rows, columns, rowHeaders, columnHeaders) => range$1(rows, r => createRow(columns, rowHeaders, columnHeaders, r));
  5079. const render = (rows, columns, rowHeaders, columnHeaders, headerType, renderOpts = DefaultRenderOptions) => {
  5080. const table = SugarElement.fromTag('table');
  5081. const rowHeadersGoInThead = headerType !== 'cells';
  5082. setAll(table, renderOpts.styles);
  5083. setAll$1(table, renderOpts.attributes);
  5084. if (renderOpts.colGroups) {
  5085. append$1(table, createGroupRow(columns));
  5086. }
  5087. const actualRowHeaders = Math.min(rows, rowHeaders);
  5088. if (rowHeadersGoInThead && rowHeaders > 0) {
  5089. const thead = SugarElement.fromTag('thead');
  5090. append$1(table, thead);
  5091. const theadRowHeaders = headerType === 'sectionCells' ? actualRowHeaders : 0;
  5092. const theadRows = createRows(rowHeaders, columns, theadRowHeaders, columnHeaders);
  5093. append(thead, theadRows);
  5094. }
  5095. const tbody = SugarElement.fromTag('tbody');
  5096. append$1(table, tbody);
  5097. const numRows = rowHeadersGoInThead ? rows - actualRowHeaders : rows;
  5098. const numRowHeaders = rowHeadersGoInThead ? 0 : rowHeaders;
  5099. const tbodyRows = createRows(numRows, columns, numRowHeaders, columnHeaders);
  5100. append(tbody, tbodyRows);
  5101. return table;
  5102. };
  5103. const get$4 = element => element.dom.innerHTML;
  5104. const getOuter = element => {
  5105. const container = SugarElement.fromTag('div');
  5106. const clone = SugarElement.fromDom(element.dom.cloneNode(true));
  5107. append$1(container, clone);
  5108. return get$4(container);
  5109. };
  5110. const placeCaretInCell = (editor, cell) => {
  5111. editor.selection.select(cell.dom, true);
  5112. editor.selection.collapse(true);
  5113. };
  5114. const selectFirstCellInTable = (editor, tableElm) => {
  5115. descendant(tableElm, 'td,th').each(curry(placeCaretInCell, editor));
  5116. };
  5117. const fireEvents = (editor, table) => {
  5118. each$2(descendants(table, 'tr'), row => {
  5119. fireNewRow(editor, row.dom);
  5120. each$2(descendants(row, 'th,td'), cell => {
  5121. fireNewCell(editor, cell.dom);
  5122. });
  5123. });
  5124. };
  5125. const isPercentage = width => isString(width) && width.indexOf('%') !== -1;
  5126. const insert = (editor, columns, rows, colHeaders, rowHeaders) => {
  5127. const defaultStyles = getTableDefaultStyles(editor);
  5128. const options = {
  5129. styles: defaultStyles,
  5130. attributes: getTableDefaultAttributes(editor),
  5131. colGroups: tableUseColumnGroup(editor)
  5132. };
  5133. editor.undoManager.ignore(() => {
  5134. const table = render(rows, columns, rowHeaders, colHeaders, getTableHeaderType(editor), options);
  5135. set$2(table, 'data-mce-id', '__mce');
  5136. const html = getOuter(table);
  5137. editor.insertContent(html);
  5138. editor.addVisual();
  5139. });
  5140. return descendant(getBody(editor), 'table[data-mce-id="__mce"]').map(table => {
  5141. if (isTablePixelsForced(editor)) {
  5142. convertToPixelSize(table);
  5143. } else if (isTableResponsiveForced(editor)) {
  5144. convertToNoneSize(table);
  5145. } else if (isTablePercentagesForced(editor) || isPercentage(defaultStyles.width)) {
  5146. convertToPercentSize(table);
  5147. }
  5148. removeDataStyle(table);
  5149. remove$7(table, 'data-mce-id');
  5150. fireEvents(editor, table);
  5151. selectFirstCellInTable(editor, table);
  5152. return table.dom;
  5153. }).getOrNull();
  5154. };
  5155. const insertTable = (editor, rows, columns, options = {}) => {
  5156. const checkInput = val => isNumber(val) && val > 0;
  5157. if (checkInput(rows) && checkInput(columns)) {
  5158. const headerRows = options.headerRows || 0;
  5159. const headerColumns = options.headerColumns || 0;
  5160. return insert(editor, columns, rows, headerColumns, headerRows);
  5161. } else {
  5162. console.error('Invalid values for mceInsertTable - rows and columns values are required to insert a table.');
  5163. return null;
  5164. }
  5165. };
  5166. var global = tinymce.util.Tools.resolve('tinymce.FakeClipboard');
  5167. const tableTypeBase = 'x-tinymce/dom-table-';
  5168. const tableTypeRow = tableTypeBase + 'rows';
  5169. const tableTypeColumn = tableTypeBase + 'columns';
  5170. const setData = items => {
  5171. const fakeClipboardItem = global.FakeClipboardItem(items);
  5172. global.write([fakeClipboardItem]);
  5173. };
  5174. const getData = type => {
  5175. var _a;
  5176. const items = (_a = global.read()) !== null && _a !== void 0 ? _a : [];
  5177. return findMap(items, item => Optional.from(item.getType(type)));
  5178. };
  5179. const clearData = type => {
  5180. if (getData(type).isSome()) {
  5181. global.clear();
  5182. }
  5183. };
  5184. const setRows = rowsOpt => {
  5185. rowsOpt.fold(clearRows, rows => setData({ [tableTypeRow]: rows }));
  5186. };
  5187. const getRows = () => getData(tableTypeRow);
  5188. const clearRows = () => clearData(tableTypeRow);
  5189. const setColumns = columnsOpt => {
  5190. columnsOpt.fold(clearColumns, columns => setData({ [tableTypeColumn]: columns }));
  5191. };
  5192. const getColumns = () => getData(tableTypeColumn);
  5193. const clearColumns = () => clearData(tableTypeColumn);
  5194. const getSelectionStartCellOrCaption = editor => getSelectionCellOrCaption(getSelectionStart(editor), getIsRoot(editor)).filter(isInEditableContext$1);
  5195. const getSelectionStartCell = editor => getSelectionCell(getSelectionStart(editor), getIsRoot(editor)).filter(isInEditableContext$1);
  5196. const registerCommands = (editor, actions) => {
  5197. const isRoot = getIsRoot(editor);
  5198. const eraseTable = () => getSelectionStartCellOrCaption(editor).each(cellOrCaption => {
  5199. table(cellOrCaption, isRoot).filter(not(isRoot)).each(table => {
  5200. const cursor = SugarElement.fromText('');
  5201. after$5(table, cursor);
  5202. remove$6(table);
  5203. if (editor.dom.isEmpty(editor.getBody())) {
  5204. editor.setContent('');
  5205. editor.selection.setCursorLocation();
  5206. } else {
  5207. const rng = editor.dom.createRng();
  5208. rng.setStart(cursor.dom, 0);
  5209. rng.setEnd(cursor.dom, 0);
  5210. editor.selection.setRng(rng);
  5211. editor.nodeChanged();
  5212. }
  5213. });
  5214. });
  5215. const setSizingMode = sizing => getSelectionStartCellOrCaption(editor).each(cellOrCaption => {
  5216. const isForcedSizing = isTableResponsiveForced(editor) || isTablePixelsForced(editor) || isTablePercentagesForced(editor);
  5217. if (!isForcedSizing) {
  5218. table(cellOrCaption, isRoot).each(table => {
  5219. if (sizing === 'relative' && !isPercentSizing(table)) {
  5220. convertToPercentSize(table);
  5221. } else if (sizing === 'fixed' && !isPixelSizing(table)) {
  5222. convertToPixelSize(table);
  5223. } else if (sizing === 'responsive' && !isNoneSizing(table)) {
  5224. convertToNoneSize(table);
  5225. }
  5226. removeDataStyle(table);
  5227. fireTableModified(editor, table.dom, structureModified);
  5228. });
  5229. }
  5230. });
  5231. const getTableFromCell = cell => table(cell, isRoot);
  5232. const performActionOnSelection = action => getSelectionStartCell(editor).bind(cell => getTableFromCell(cell).map(table => action(table, cell)));
  5233. const toggleTableClass = (_ui, clazz) => {
  5234. performActionOnSelection(table => {
  5235. editor.formatter.toggle('tableclass', { value: clazz }, table.dom);
  5236. fireTableModified(editor, table.dom, styleModified);
  5237. });
  5238. };
  5239. const toggleTableCellClass = (_ui, clazz) => {
  5240. performActionOnSelection(table => {
  5241. const selectedCells = getCellsFromSelection(editor);
  5242. const allHaveClass = forall(selectedCells, cell => editor.formatter.match('tablecellclass', { value: clazz }, cell.dom));
  5243. const formatterAction = allHaveClass ? editor.formatter.remove : editor.formatter.apply;
  5244. each$2(selectedCells, cell => formatterAction('tablecellclass', { value: clazz }, cell.dom));
  5245. fireTableModified(editor, table.dom, styleModified);
  5246. });
  5247. };
  5248. const toggleCaption = () => {
  5249. getSelectionStartCellOrCaption(editor).each(cellOrCaption => {
  5250. table(cellOrCaption, isRoot).each(table => {
  5251. child(table, 'caption').fold(() => {
  5252. const caption = SugarElement.fromTag('caption');
  5253. append$1(caption, SugarElement.fromText('Caption'));
  5254. appendAt(table, caption, 0);
  5255. editor.selection.setCursorLocation(caption.dom, 0);
  5256. }, caption => {
  5257. if (isTag('caption')(cellOrCaption)) {
  5258. one('td', table).each(td => editor.selection.setCursorLocation(td.dom, 0));
  5259. }
  5260. remove$6(caption);
  5261. });
  5262. fireTableModified(editor, table.dom, structureModified);
  5263. });
  5264. });
  5265. };
  5266. const postExecute = _data => {
  5267. editor.focus();
  5268. };
  5269. const actOnSelection = (execute, noEvents = false) => performActionOnSelection((table, startCell) => {
  5270. const targets = forMenu(getCellsFromSelection(editor), table, startCell);
  5271. execute(table, targets, noEvents).each(postExecute);
  5272. });
  5273. const copyRowSelection = () => performActionOnSelection((table, startCell) => {
  5274. const targets = forMenu(getCellsFromSelection(editor), table, startCell);
  5275. const generators = cellOperations(noop, SugarElement.fromDom(editor.getDoc()), Optional.none());
  5276. return copyRows(table, targets, generators);
  5277. });
  5278. const copyColSelection = () => performActionOnSelection((table, startCell) => {
  5279. const targets = forMenu(getCellsFromSelection(editor), table, startCell);
  5280. return copyCols(table, targets);
  5281. });
  5282. const pasteOnSelection = (execute, getRows) => getRows().each(rows => {
  5283. const clonedRows = map$1(rows, row => deep(row));
  5284. performActionOnSelection((table, startCell) => {
  5285. const generators = paste$1(SugarElement.fromDom(editor.getDoc()));
  5286. const targets = pasteRows(getCellsFromSelection(editor), startCell, clonedRows, generators);
  5287. execute(table, targets).each(postExecute);
  5288. });
  5289. });
  5290. const actOnType = getAction => (_ui, args) => get$c(args, 'type').each(type => {
  5291. actOnSelection(getAction(type), args.no_events);
  5292. });
  5293. each$1({
  5294. mceTableSplitCells: () => actOnSelection(actions.unmergeCells),
  5295. mceTableMergeCells: () => actOnSelection(actions.mergeCells),
  5296. mceTableInsertRowBefore: () => actOnSelection(actions.insertRowsBefore),
  5297. mceTableInsertRowAfter: () => actOnSelection(actions.insertRowsAfter),
  5298. mceTableInsertColBefore: () => actOnSelection(actions.insertColumnsBefore),
  5299. mceTableInsertColAfter: () => actOnSelection(actions.insertColumnsAfter),
  5300. mceTableDeleteCol: () => actOnSelection(actions.deleteColumn),
  5301. mceTableDeleteRow: () => actOnSelection(actions.deleteRow),
  5302. mceTableCutCol: () => copyColSelection().each(selection => {
  5303. setColumns(selection);
  5304. actOnSelection(actions.deleteColumn);
  5305. }),
  5306. mceTableCutRow: () => copyRowSelection().each(selection => {
  5307. setRows(selection);
  5308. actOnSelection(actions.deleteRow);
  5309. }),
  5310. mceTableCopyCol: () => copyColSelection().each(selection => setColumns(selection)),
  5311. mceTableCopyRow: () => copyRowSelection().each(selection => setRows(selection)),
  5312. mceTablePasteColBefore: () => pasteOnSelection(actions.pasteColsBefore, getColumns),
  5313. mceTablePasteColAfter: () => pasteOnSelection(actions.pasteColsAfter, getColumns),
  5314. mceTablePasteRowBefore: () => pasteOnSelection(actions.pasteRowsBefore, getRows),
  5315. mceTablePasteRowAfter: () => pasteOnSelection(actions.pasteRowsAfter, getRows),
  5316. mceTableDelete: eraseTable,
  5317. mceTableCellToggleClass: toggleTableCellClass,
  5318. mceTableToggleClass: toggleTableClass,
  5319. mceTableToggleCaption: toggleCaption,
  5320. mceTableSizingMode: (_ui, sizing) => setSizingMode(sizing),
  5321. mceTableCellType: actOnType(type => type === 'th' ? actions.makeCellsHeader : actions.unmakeCellsHeader),
  5322. mceTableColType: actOnType(type => type === 'th' ? actions.makeColumnsHeader : actions.unmakeColumnsHeader),
  5323. mceTableRowType: actOnType(type => {
  5324. switch (type) {
  5325. case 'header':
  5326. return actions.makeRowsHeader;
  5327. case 'footer':
  5328. return actions.makeRowsFooter;
  5329. default:
  5330. return actions.makeRowsBody;
  5331. }
  5332. })
  5333. }, (func, name) => editor.addCommand(name, func));
  5334. editor.addCommand('mceInsertTable', (_ui, args) => {
  5335. insertTable(editor, args.rows, args.columns, args.options);
  5336. });
  5337. editor.addCommand('mceTableApplyCellStyle', (_ui, args) => {
  5338. const getFormatName = style => 'tablecell' + style.toLowerCase().replace('-', '');
  5339. if (!isObject(args)) {
  5340. return;
  5341. }
  5342. const cells = filter$2(getCellsFromSelection(editor), isInEditableContext$1);
  5343. if (cells.length === 0) {
  5344. return;
  5345. }
  5346. const validArgs = filter$1(args, (value, style) => editor.formatter.has(getFormatName(style)) && isString(value));
  5347. if (isEmpty(validArgs)) {
  5348. return;
  5349. }
  5350. each$1(validArgs, (value, style) => {
  5351. const formatName = getFormatName(style);
  5352. each$2(cells, cell => {
  5353. if (value === '') {
  5354. editor.formatter.remove(formatName, { value: null }, cell.dom, true);
  5355. } else {
  5356. editor.formatter.apply(formatName, { value }, cell.dom);
  5357. }
  5358. });
  5359. });
  5360. getTableFromCell(cells[0]).each(table => fireTableModified(editor, table.dom, styleModified));
  5361. });
  5362. };
  5363. const registerQueryCommands = (editor, actions) => {
  5364. const isRoot = getIsRoot(editor);
  5365. const lookupOnSelection = action => getSelectionCell(getSelectionStart(editor)).bind(cell => table(cell, isRoot).map(table => {
  5366. const targets = forMenu(getCellsFromSelection(editor), table, cell);
  5367. return action(table, targets);
  5368. })).getOr('');
  5369. each$1({
  5370. mceTableRowType: () => lookupOnSelection(actions.getTableRowType),
  5371. mceTableCellType: () => lookupOnSelection(actions.getTableCellType),
  5372. mceTableColType: () => lookupOnSelection(actions.getTableColType)
  5373. }, (func, name) => editor.addQueryValueHandler(name, func));
  5374. };
  5375. const adt$4 = Adt.generate([
  5376. { before: ['element'] },
  5377. {
  5378. on: [
  5379. 'element',
  5380. 'offset'
  5381. ]
  5382. },
  5383. { after: ['element'] }
  5384. ]);
  5385. const cata$1 = (subject, onBefore, onOn, onAfter) => subject.fold(onBefore, onOn, onAfter);
  5386. const getStart$1 = situ => situ.fold(identity, identity, identity);
  5387. const before$2 = adt$4.before;
  5388. const on = adt$4.on;
  5389. const after$3 = adt$4.after;
  5390. const Situ = {
  5391. before: before$2,
  5392. on,
  5393. after: after$3,
  5394. cata: cata$1,
  5395. getStart: getStart$1
  5396. };
  5397. const create$4 = (selection, kill) => ({
  5398. selection,
  5399. kill
  5400. });
  5401. const Response = { create: create$4 };
  5402. const selectNode = (win, element) => {
  5403. const rng = win.document.createRange();
  5404. rng.selectNode(element.dom);
  5405. return rng;
  5406. };
  5407. const selectNodeContents = (win, element) => {
  5408. const rng = win.document.createRange();
  5409. selectNodeContentsUsing(rng, element);
  5410. return rng;
  5411. };
  5412. const selectNodeContentsUsing = (rng, element) => rng.selectNodeContents(element.dom);
  5413. const setStart = (rng, situ) => {
  5414. situ.fold(e => {
  5415. rng.setStartBefore(e.dom);
  5416. }, (e, o) => {
  5417. rng.setStart(e.dom, o);
  5418. }, e => {
  5419. rng.setStartAfter(e.dom);
  5420. });
  5421. };
  5422. const setFinish = (rng, situ) => {
  5423. situ.fold(e => {
  5424. rng.setEndBefore(e.dom);
  5425. }, (e, o) => {
  5426. rng.setEnd(e.dom, o);
  5427. }, e => {
  5428. rng.setEndAfter(e.dom);
  5429. });
  5430. };
  5431. const relativeToNative = (win, startSitu, finishSitu) => {
  5432. const range = win.document.createRange();
  5433. setStart(range, startSitu);
  5434. setFinish(range, finishSitu);
  5435. return range;
  5436. };
  5437. const exactToNative = (win, start, soffset, finish, foffset) => {
  5438. const rng = win.document.createRange();
  5439. rng.setStart(start.dom, soffset);
  5440. rng.setEnd(finish.dom, foffset);
  5441. return rng;
  5442. };
  5443. const toRect = rect => ({
  5444. left: rect.left,
  5445. top: rect.top,
  5446. right: rect.right,
  5447. bottom: rect.bottom,
  5448. width: rect.width,
  5449. height: rect.height
  5450. });
  5451. const getFirstRect$1 = rng => {
  5452. const rects = rng.getClientRects();
  5453. const rect = rects.length > 0 ? rects[0] : rng.getBoundingClientRect();
  5454. return rect.width > 0 || rect.height > 0 ? Optional.some(rect).map(toRect) : Optional.none();
  5455. };
  5456. const adt$3 = Adt.generate([
  5457. {
  5458. ltr: [
  5459. 'start',
  5460. 'soffset',
  5461. 'finish',
  5462. 'foffset'
  5463. ]
  5464. },
  5465. {
  5466. rtl: [
  5467. 'start',
  5468. 'soffset',
  5469. 'finish',
  5470. 'foffset'
  5471. ]
  5472. }
  5473. ]);
  5474. const fromRange = (win, type, range) => type(SugarElement.fromDom(range.startContainer), range.startOffset, SugarElement.fromDom(range.endContainer), range.endOffset);
  5475. const getRanges = (win, selection) => selection.match({
  5476. domRange: rng => {
  5477. return {
  5478. ltr: constant(rng),
  5479. rtl: Optional.none
  5480. };
  5481. },
  5482. relative: (startSitu, finishSitu) => {
  5483. return {
  5484. ltr: cached(() => relativeToNative(win, startSitu, finishSitu)),
  5485. rtl: cached(() => Optional.some(relativeToNative(win, finishSitu, startSitu)))
  5486. };
  5487. },
  5488. exact: (start, soffset, finish, foffset) => {
  5489. return {
  5490. ltr: cached(() => exactToNative(win, start, soffset, finish, foffset)),
  5491. rtl: cached(() => Optional.some(exactToNative(win, finish, foffset, start, soffset)))
  5492. };
  5493. }
  5494. });
  5495. const doDiagnose = (win, ranges) => {
  5496. const rng = ranges.ltr();
  5497. if (rng.collapsed) {
  5498. const reversed = ranges.rtl().filter(rev => rev.collapsed === false);
  5499. return reversed.map(rev => adt$3.rtl(SugarElement.fromDom(rev.endContainer), rev.endOffset, SugarElement.fromDom(rev.startContainer), rev.startOffset)).getOrThunk(() => fromRange(win, adt$3.ltr, rng));
  5500. } else {
  5501. return fromRange(win, adt$3.ltr, rng);
  5502. }
  5503. };
  5504. const diagnose = (win, selection) => {
  5505. const ranges = getRanges(win, selection);
  5506. return doDiagnose(win, ranges);
  5507. };
  5508. const asLtrRange = (win, selection) => {
  5509. const diagnosis = diagnose(win, selection);
  5510. return diagnosis.match({
  5511. ltr: (start, soffset, finish, foffset) => {
  5512. const rng = win.document.createRange();
  5513. rng.setStart(start.dom, soffset);
  5514. rng.setEnd(finish.dom, foffset);
  5515. return rng;
  5516. },
  5517. rtl: (start, soffset, finish, foffset) => {
  5518. const rng = win.document.createRange();
  5519. rng.setStart(finish.dom, foffset);
  5520. rng.setEnd(start.dom, soffset);
  5521. return rng;
  5522. }
  5523. });
  5524. };
  5525. adt$3.ltr;
  5526. adt$3.rtl;
  5527. const create$3 = (start, soffset, finish, foffset) => ({
  5528. start,
  5529. soffset,
  5530. finish,
  5531. foffset
  5532. });
  5533. const SimRange = { create: create$3 };
  5534. const create$2 = (start, soffset, finish, foffset) => {
  5535. return {
  5536. start: Situ.on(start, soffset),
  5537. finish: Situ.on(finish, foffset)
  5538. };
  5539. };
  5540. const Situs = { create: create$2 };
  5541. const convertToRange = (win, selection) => {
  5542. const rng = asLtrRange(win, selection);
  5543. return SimRange.create(SugarElement.fromDom(rng.startContainer), rng.startOffset, SugarElement.fromDom(rng.endContainer), rng.endOffset);
  5544. };
  5545. const makeSitus = Situs.create;
  5546. const sync = (container, isRoot, start, soffset, finish, foffset, selectRange) => {
  5547. if (!(eq$1(start, finish) && soffset === foffset)) {
  5548. return closest$1(start, 'td,th', isRoot).bind(s => {
  5549. return closest$1(finish, 'td,th', isRoot).bind(f => {
  5550. return detect(container, isRoot, s, f, selectRange);
  5551. });
  5552. });
  5553. } else {
  5554. return Optional.none();
  5555. }
  5556. };
  5557. const detect = (container, isRoot, start, finish, selectRange) => {
  5558. if (!eq$1(start, finish)) {
  5559. return identify(start, finish, isRoot).bind(cellSel => {
  5560. const boxes = cellSel.boxes.getOr([]);
  5561. if (boxes.length > 1) {
  5562. selectRange(container, boxes, cellSel.start, cellSel.finish);
  5563. return Optional.some(Response.create(Optional.some(makeSitus(start, 0, start, getEnd(start))), true));
  5564. } else {
  5565. return Optional.none();
  5566. }
  5567. });
  5568. } else {
  5569. return Optional.none();
  5570. }
  5571. };
  5572. const update = (rows, columns, container, selected, annotations) => {
  5573. const updateSelection = newSels => {
  5574. annotations.clearBeforeUpdate(container);
  5575. annotations.selectRange(container, newSels.boxes, newSels.start, newSels.finish);
  5576. return newSels.boxes;
  5577. };
  5578. return shiftSelection(selected, rows, columns, annotations.firstSelectedSelector, annotations.lastSelectedSelector).map(updateSelection);
  5579. };
  5580. const traverse = (item, mode) => ({
  5581. item,
  5582. mode
  5583. });
  5584. const backtrack = (universe, item, _direction, transition = sidestep) => {
  5585. return universe.property().parent(item).map(p => {
  5586. return traverse(p, transition);
  5587. });
  5588. };
  5589. const sidestep = (universe, item, direction, transition = advance) => {
  5590. return direction.sibling(universe, item).map(p => {
  5591. return traverse(p, transition);
  5592. });
  5593. };
  5594. const advance = (universe, item, direction, transition = advance) => {
  5595. const children = universe.property().children(item);
  5596. const result = direction.first(children);
  5597. return result.map(r => {
  5598. return traverse(r, transition);
  5599. });
  5600. };
  5601. const successors = [
  5602. {
  5603. current: backtrack,
  5604. next: sidestep,
  5605. fallback: Optional.none()
  5606. },
  5607. {
  5608. current: sidestep,
  5609. next: advance,
  5610. fallback: Optional.some(backtrack)
  5611. },
  5612. {
  5613. current: advance,
  5614. next: advance,
  5615. fallback: Optional.some(sidestep)
  5616. }
  5617. ];
  5618. const go = (universe, item, mode, direction, rules = successors) => {
  5619. const ruleOpt = find$1(rules, succ => {
  5620. return succ.current === mode;
  5621. });
  5622. return ruleOpt.bind(rule => {
  5623. return rule.current(universe, item, direction, rule.next).orThunk(() => {
  5624. return rule.fallback.bind(fb => {
  5625. return go(universe, item, fb, direction);
  5626. });
  5627. });
  5628. });
  5629. };
  5630. const left$1 = () => {
  5631. const sibling = (universe, item) => {
  5632. return universe.query().prevSibling(item);
  5633. };
  5634. const first = children => {
  5635. return children.length > 0 ? Optional.some(children[children.length - 1]) : Optional.none();
  5636. };
  5637. return {
  5638. sibling,
  5639. first
  5640. };
  5641. };
  5642. const right$1 = () => {
  5643. const sibling = (universe, item) => {
  5644. return universe.query().nextSibling(item);
  5645. };
  5646. const first = children => {
  5647. return children.length > 0 ? Optional.some(children[0]) : Optional.none();
  5648. };
  5649. return {
  5650. sibling,
  5651. first
  5652. };
  5653. };
  5654. const Walkers = {
  5655. left: left$1,
  5656. right: right$1
  5657. };
  5658. const hone = (universe, item, predicate, mode, direction, isRoot) => {
  5659. const next = go(universe, item, mode, direction);
  5660. return next.bind(n => {
  5661. if (isRoot(n.item)) {
  5662. return Optional.none();
  5663. } else {
  5664. return predicate(n.item) ? Optional.some(n.item) : hone(universe, n.item, predicate, n.mode, direction, isRoot);
  5665. }
  5666. });
  5667. };
  5668. const left = (universe, item, predicate, isRoot) => {
  5669. return hone(universe, item, predicate, sidestep, Walkers.left(), isRoot);
  5670. };
  5671. const right = (universe, item, predicate, isRoot) => {
  5672. return hone(universe, item, predicate, sidestep, Walkers.right(), isRoot);
  5673. };
  5674. const isLeaf = universe => element => universe.property().children(element).length === 0;
  5675. const before$1 = (universe, item, isRoot) => {
  5676. return seekLeft$1(universe, item, isLeaf(universe), isRoot);
  5677. };
  5678. const after$2 = (universe, item, isRoot) => {
  5679. return seekRight$1(universe, item, isLeaf(universe), isRoot);
  5680. };
  5681. const seekLeft$1 = left;
  5682. const seekRight$1 = right;
  5683. const universe = DomUniverse();
  5684. const before = (element, isRoot) => {
  5685. return before$1(universe, element, isRoot);
  5686. };
  5687. const after$1 = (element, isRoot) => {
  5688. return after$2(universe, element, isRoot);
  5689. };
  5690. const seekLeft = (element, predicate, isRoot) => {
  5691. return seekLeft$1(universe, element, predicate, isRoot);
  5692. };
  5693. const seekRight = (element, predicate, isRoot) => {
  5694. return seekRight$1(universe, element, predicate, isRoot);
  5695. };
  5696. const ancestor = (scope, predicate, isRoot) => ancestor$2(scope, predicate, isRoot).isSome();
  5697. const adt$2 = Adt.generate([
  5698. { none: ['message'] },
  5699. { success: [] },
  5700. { failedUp: ['cell'] },
  5701. { failedDown: ['cell'] }
  5702. ]);
  5703. const isOverlapping = (bridge, before, after) => {
  5704. const beforeBounds = bridge.getRect(before);
  5705. const afterBounds = bridge.getRect(after);
  5706. return afterBounds.right > beforeBounds.left && afterBounds.left < beforeBounds.right;
  5707. };
  5708. const isRow = elem => {
  5709. return closest$1(elem, 'tr');
  5710. };
  5711. const verify = (bridge, before, beforeOffset, after, afterOffset, failure, isRoot) => {
  5712. return closest$1(after, 'td,th', isRoot).bind(afterCell => {
  5713. return closest$1(before, 'td,th', isRoot).map(beforeCell => {
  5714. if (!eq$1(afterCell, beforeCell)) {
  5715. return sharedOne(isRow, [
  5716. afterCell,
  5717. beforeCell
  5718. ]).fold(() => {
  5719. return isOverlapping(bridge, beforeCell, afterCell) ? adt$2.success() : failure(beforeCell);
  5720. }, _sharedRow => {
  5721. return failure(beforeCell);
  5722. });
  5723. } else {
  5724. return eq$1(after, afterCell) && getEnd(afterCell) === afterOffset ? failure(beforeCell) : adt$2.none('in same cell');
  5725. }
  5726. });
  5727. }).getOr(adt$2.none('default'));
  5728. };
  5729. const cata = (subject, onNone, onSuccess, onFailedUp, onFailedDown) => {
  5730. return subject.fold(onNone, onSuccess, onFailedUp, onFailedDown);
  5731. };
  5732. const BeforeAfter = {
  5733. ...adt$2,
  5734. verify,
  5735. cata
  5736. };
  5737. const inParent = (parent, children, element, index) => ({
  5738. parent,
  5739. children,
  5740. element,
  5741. index
  5742. });
  5743. const indexInParent = element => parent(element).bind(parent => {
  5744. const children = children$2(parent);
  5745. return indexOf(children, element).map(index => inParent(parent, children, element, index));
  5746. });
  5747. const indexOf = (elements, element) => findIndex(elements, curry(eq$1, element));
  5748. const isBr = isTag('br');
  5749. const gatherer = (cand, gather, isRoot) => {
  5750. return gather(cand, isRoot).bind(target => {
  5751. return isText(target) && get$6(target).trim().length === 0 ? gatherer(target, gather, isRoot) : Optional.some(target);
  5752. });
  5753. };
  5754. const handleBr = (isRoot, element, direction) => {
  5755. return direction.traverse(element).orThunk(() => {
  5756. return gatherer(element, direction.gather, isRoot);
  5757. }).map(direction.relative);
  5758. };
  5759. const findBr = (element, offset) => {
  5760. return child$2(element, offset).filter(isBr).orThunk(() => {
  5761. return child$2(element, offset - 1).filter(isBr);
  5762. });
  5763. };
  5764. const handleParent = (isRoot, element, offset, direction) => {
  5765. return findBr(element, offset).bind(br => {
  5766. return direction.traverse(br).fold(() => {
  5767. return gatherer(br, direction.gather, isRoot).map(direction.relative);
  5768. }, adjacent => {
  5769. return indexInParent(adjacent).map(info => {
  5770. return Situ.on(info.parent, info.index);
  5771. });
  5772. });
  5773. });
  5774. };
  5775. const tryBr = (isRoot, element, offset, direction) => {
  5776. const target = isBr(element) ? handleBr(isRoot, element, direction) : handleParent(isRoot, element, offset, direction);
  5777. return target.map(tgt => {
  5778. return {
  5779. start: tgt,
  5780. finish: tgt
  5781. };
  5782. });
  5783. };
  5784. const process = analysis => {
  5785. return BeforeAfter.cata(analysis, _message => {
  5786. return Optional.none();
  5787. }, () => {
  5788. return Optional.none();
  5789. }, cell => {
  5790. return Optional.some(point(cell, 0));
  5791. }, cell => {
  5792. return Optional.some(point(cell, getEnd(cell)));
  5793. });
  5794. };
  5795. const moveDown = (caret, amount) => {
  5796. return {
  5797. left: caret.left,
  5798. top: caret.top + amount,
  5799. right: caret.right,
  5800. bottom: caret.bottom + amount
  5801. };
  5802. };
  5803. const moveUp = (caret, amount) => {
  5804. return {
  5805. left: caret.left,
  5806. top: caret.top - amount,
  5807. right: caret.right,
  5808. bottom: caret.bottom - amount
  5809. };
  5810. };
  5811. const translate = (caret, xDelta, yDelta) => {
  5812. return {
  5813. left: caret.left + xDelta,
  5814. top: caret.top + yDelta,
  5815. right: caret.right + xDelta,
  5816. bottom: caret.bottom + yDelta
  5817. };
  5818. };
  5819. const getTop = caret => {
  5820. return caret.top;
  5821. };
  5822. const getBottom = caret => {
  5823. return caret.bottom;
  5824. };
  5825. const getPartialBox = (bridge, element, offset) => {
  5826. if (offset >= 0 && offset < getEnd(element)) {
  5827. return bridge.getRangedRect(element, offset, element, offset + 1);
  5828. } else if (offset > 0) {
  5829. return bridge.getRangedRect(element, offset - 1, element, offset);
  5830. }
  5831. return Optional.none();
  5832. };
  5833. const toCaret = rect => ({
  5834. left: rect.left,
  5835. top: rect.top,
  5836. right: rect.right,
  5837. bottom: rect.bottom
  5838. });
  5839. const getElemBox = (bridge, element) => {
  5840. return Optional.some(bridge.getRect(element));
  5841. };
  5842. const getBoxAt = (bridge, element, offset) => {
  5843. if (isElement(element)) {
  5844. return getElemBox(bridge, element).map(toCaret);
  5845. } else if (isText(element)) {
  5846. return getPartialBox(bridge, element, offset).map(toCaret);
  5847. } else {
  5848. return Optional.none();
  5849. }
  5850. };
  5851. const getEntireBox = (bridge, element) => {
  5852. if (isElement(element)) {
  5853. return getElemBox(bridge, element).map(toCaret);
  5854. } else if (isText(element)) {
  5855. return bridge.getRangedRect(element, 0, element, getEnd(element)).map(toCaret);
  5856. } else {
  5857. return Optional.none();
  5858. }
  5859. };
  5860. const JUMP_SIZE = 5;
  5861. const NUM_RETRIES = 100;
  5862. const adt$1 = Adt.generate([
  5863. { none: [] },
  5864. { retry: ['caret'] }
  5865. ]);
  5866. const isOutside = (caret, box) => {
  5867. return caret.left < box.left || Math.abs(box.right - caret.left) < 1 || caret.left > box.right;
  5868. };
  5869. const inOutsideBlock = (bridge, element, caret) => {
  5870. return closest$2(element, isBlock).fold(never, cell => {
  5871. return getEntireBox(bridge, cell).exists(box => {
  5872. return isOutside(caret, box);
  5873. });
  5874. });
  5875. };
  5876. const adjustDown = (bridge, element, guessBox, original, caret) => {
  5877. const lowerCaret = moveDown(caret, JUMP_SIZE);
  5878. if (Math.abs(guessBox.bottom - original.bottom) < 1) {
  5879. return adt$1.retry(lowerCaret);
  5880. } else if (guessBox.top > caret.bottom) {
  5881. return adt$1.retry(lowerCaret);
  5882. } else if (guessBox.top === caret.bottom) {
  5883. return adt$1.retry(moveDown(caret, 1));
  5884. } else {
  5885. return inOutsideBlock(bridge, element, caret) ? adt$1.retry(translate(lowerCaret, JUMP_SIZE, 0)) : adt$1.none();
  5886. }
  5887. };
  5888. const adjustUp = (bridge, element, guessBox, original, caret) => {
  5889. const higherCaret = moveUp(caret, JUMP_SIZE);
  5890. if (Math.abs(guessBox.top - original.top) < 1) {
  5891. return adt$1.retry(higherCaret);
  5892. } else if (guessBox.bottom < caret.top) {
  5893. return adt$1.retry(higherCaret);
  5894. } else if (guessBox.bottom === caret.top) {
  5895. return adt$1.retry(moveUp(caret, 1));
  5896. } else {
  5897. return inOutsideBlock(bridge, element, caret) ? adt$1.retry(translate(higherCaret, JUMP_SIZE, 0)) : adt$1.none();
  5898. }
  5899. };
  5900. const upMovement = {
  5901. point: getTop,
  5902. adjuster: adjustUp,
  5903. move: moveUp,
  5904. gather: before
  5905. };
  5906. const downMovement = {
  5907. point: getBottom,
  5908. adjuster: adjustDown,
  5909. move: moveDown,
  5910. gather: after$1
  5911. };
  5912. const isAtTable = (bridge, x, y) => {
  5913. return bridge.elementFromPoint(x, y).filter(elm => {
  5914. return name(elm) === 'table';
  5915. }).isSome();
  5916. };
  5917. const adjustForTable = (bridge, movement, original, caret, numRetries) => {
  5918. return adjustTil(bridge, movement, original, movement.move(caret, JUMP_SIZE), numRetries);
  5919. };
  5920. const adjustTil = (bridge, movement, original, caret, numRetries) => {
  5921. if (numRetries === 0) {
  5922. return Optional.some(caret);
  5923. }
  5924. if (isAtTable(bridge, caret.left, movement.point(caret))) {
  5925. return adjustForTable(bridge, movement, original, caret, numRetries - 1);
  5926. }
  5927. return bridge.situsFromPoint(caret.left, movement.point(caret)).bind(guess => {
  5928. return guess.start.fold(Optional.none, element => {
  5929. return getEntireBox(bridge, element).bind(guessBox => {
  5930. return movement.adjuster(bridge, element, guessBox, original, caret).fold(Optional.none, newCaret => {
  5931. return adjustTil(bridge, movement, original, newCaret, numRetries - 1);
  5932. });
  5933. }).orThunk(() => {
  5934. return Optional.some(caret);
  5935. });
  5936. }, Optional.none);
  5937. });
  5938. };
  5939. const checkScroll = (movement, adjusted, bridge) => {
  5940. if (movement.point(adjusted) > bridge.getInnerHeight()) {
  5941. return Optional.some(movement.point(adjusted) - bridge.getInnerHeight());
  5942. } else if (movement.point(adjusted) < 0) {
  5943. return Optional.some(-movement.point(adjusted));
  5944. } else {
  5945. return Optional.none();
  5946. }
  5947. };
  5948. const retry = (movement, bridge, caret) => {
  5949. const moved = movement.move(caret, JUMP_SIZE);
  5950. const adjusted = adjustTil(bridge, movement, caret, moved, NUM_RETRIES).getOr(moved);
  5951. return checkScroll(movement, adjusted, bridge).fold(() => {
  5952. return bridge.situsFromPoint(adjusted.left, movement.point(adjusted));
  5953. }, delta => {
  5954. bridge.scrollBy(0, delta);
  5955. return bridge.situsFromPoint(adjusted.left, movement.point(adjusted) - delta);
  5956. });
  5957. };
  5958. const Retries = {
  5959. tryUp: curry(retry, upMovement),
  5960. tryDown: curry(retry, downMovement),
  5961. getJumpSize: constant(JUMP_SIZE)
  5962. };
  5963. const MAX_RETRIES = 20;
  5964. const findSpot = (bridge, isRoot, direction) => {
  5965. return bridge.getSelection().bind(sel => {
  5966. return tryBr(isRoot, sel.finish, sel.foffset, direction).fold(() => {
  5967. return Optional.some(point(sel.finish, sel.foffset));
  5968. }, brNeighbour => {
  5969. const range = bridge.fromSitus(brNeighbour);
  5970. const analysis = BeforeAfter.verify(bridge, sel.finish, sel.foffset, range.finish, range.foffset, direction.failure, isRoot);
  5971. return process(analysis);
  5972. });
  5973. });
  5974. };
  5975. const scan = (bridge, isRoot, element, offset, direction, numRetries) => {
  5976. if (numRetries === 0) {
  5977. return Optional.none();
  5978. }
  5979. return tryCursor(bridge, isRoot, element, offset, direction).bind(situs => {
  5980. const range = bridge.fromSitus(situs);
  5981. const analysis = BeforeAfter.verify(bridge, element, offset, range.finish, range.foffset, direction.failure, isRoot);
  5982. return BeforeAfter.cata(analysis, () => {
  5983. return Optional.none();
  5984. }, () => {
  5985. return Optional.some(situs);
  5986. }, cell => {
  5987. if (eq$1(element, cell) && offset === 0) {
  5988. return tryAgain(bridge, element, offset, moveUp, direction);
  5989. } else {
  5990. return scan(bridge, isRoot, cell, 0, direction, numRetries - 1);
  5991. }
  5992. }, cell => {
  5993. if (eq$1(element, cell) && offset === getEnd(cell)) {
  5994. return tryAgain(bridge, element, offset, moveDown, direction);
  5995. } else {
  5996. return scan(bridge, isRoot, cell, getEnd(cell), direction, numRetries - 1);
  5997. }
  5998. });
  5999. });
  6000. };
  6001. const tryAgain = (bridge, element, offset, move, direction) => {
  6002. return getBoxAt(bridge, element, offset).bind(box => {
  6003. return tryAt(bridge, direction, move(box, Retries.getJumpSize()));
  6004. });
  6005. };
  6006. const tryAt = (bridge, direction, box) => {
  6007. const browser = detect$2().browser;
  6008. if (browser.isChromium() || browser.isSafari() || browser.isFirefox()) {
  6009. return direction.retry(bridge, box);
  6010. } else {
  6011. return Optional.none();
  6012. }
  6013. };
  6014. const tryCursor = (bridge, isRoot, element, offset, direction) => {
  6015. return getBoxAt(bridge, element, offset).bind(box => {
  6016. return tryAt(bridge, direction, box);
  6017. });
  6018. };
  6019. const handle$1 = (bridge, isRoot, direction) => {
  6020. return findSpot(bridge, isRoot, direction).bind(spot => {
  6021. return scan(bridge, isRoot, spot.element, spot.offset, direction, MAX_RETRIES).map(bridge.fromSitus);
  6022. });
  6023. };
  6024. const inSameTable = (elem, table) => {
  6025. return ancestor(elem, e => {
  6026. return parent(e).exists(p => {
  6027. return eq$1(p, table);
  6028. });
  6029. });
  6030. };
  6031. const simulate = (bridge, isRoot, direction, initial, anchor) => {
  6032. return closest$1(initial, 'td,th', isRoot).bind(start => {
  6033. return closest$1(start, 'table', isRoot).bind(table => {
  6034. if (!inSameTable(anchor, table)) {
  6035. return Optional.none();
  6036. }
  6037. return handle$1(bridge, isRoot, direction).bind(range => {
  6038. return closest$1(range.finish, 'td,th', isRoot).map(finish => {
  6039. return {
  6040. start,
  6041. finish,
  6042. range
  6043. };
  6044. });
  6045. });
  6046. });
  6047. });
  6048. };
  6049. const navigate = (bridge, isRoot, direction, initial, anchor, precheck) => {
  6050. return precheck(initial, isRoot).orThunk(() => {
  6051. return simulate(bridge, isRoot, direction, initial, anchor).map(info => {
  6052. const range = info.range;
  6053. return Response.create(Optional.some(makeSitus(range.start, range.soffset, range.finish, range.foffset)), true);
  6054. });
  6055. });
  6056. };
  6057. const firstUpCheck = (initial, isRoot) => {
  6058. return closest$1(initial, 'tr', isRoot).bind(startRow => {
  6059. return closest$1(startRow, 'table', isRoot).bind(table => {
  6060. const rows = descendants(table, 'tr');
  6061. if (eq$1(startRow, rows[0])) {
  6062. return seekLeft(table, element => {
  6063. return last$1(element).isSome();
  6064. }, isRoot).map(last => {
  6065. const lastOffset = getEnd(last);
  6066. return Response.create(Optional.some(makeSitus(last, lastOffset, last, lastOffset)), true);
  6067. });
  6068. } else {
  6069. return Optional.none();
  6070. }
  6071. });
  6072. });
  6073. };
  6074. const lastDownCheck = (initial, isRoot) => {
  6075. return closest$1(initial, 'tr', isRoot).bind(startRow => {
  6076. return closest$1(startRow, 'table', isRoot).bind(table => {
  6077. const rows = descendants(table, 'tr');
  6078. if (eq$1(startRow, rows[rows.length - 1])) {
  6079. return seekRight(table, element => {
  6080. return first(element).isSome();
  6081. }, isRoot).map(first => {
  6082. return Response.create(Optional.some(makeSitus(first, 0, first, 0)), true);
  6083. });
  6084. } else {
  6085. return Optional.none();
  6086. }
  6087. });
  6088. });
  6089. };
  6090. const select = (bridge, container, isRoot, direction, initial, anchor, selectRange) => {
  6091. return simulate(bridge, isRoot, direction, initial, anchor).bind(info => {
  6092. return detect(container, isRoot, info.start, info.finish, selectRange);
  6093. });
  6094. };
  6095. const Cell = initial => {
  6096. let value = initial;
  6097. const get = () => {
  6098. return value;
  6099. };
  6100. const set = v => {
  6101. value = v;
  6102. };
  6103. return {
  6104. get,
  6105. set
  6106. };
  6107. };
  6108. const singleton = doRevoke => {
  6109. const subject = Cell(Optional.none());
  6110. const revoke = () => subject.get().each(doRevoke);
  6111. const clear = () => {
  6112. revoke();
  6113. subject.set(Optional.none());
  6114. };
  6115. const isSet = () => subject.get().isSome();
  6116. const get = () => subject.get();
  6117. const set = s => {
  6118. revoke();
  6119. subject.set(Optional.some(s));
  6120. };
  6121. return {
  6122. clear,
  6123. isSet,
  6124. get,
  6125. set
  6126. };
  6127. };
  6128. const value = () => {
  6129. const subject = singleton(noop);
  6130. const on = f => subject.get().each(f);
  6131. return {
  6132. ...subject,
  6133. on
  6134. };
  6135. };
  6136. const findCell = (target, isRoot) => closest$1(target, 'td,th', isRoot);
  6137. const isInEditableContext = cell => parentElement(cell).exists(isEditable$1);
  6138. const MouseSelection = (bridge, container, isRoot, annotations) => {
  6139. const cursor = value();
  6140. const clearstate = cursor.clear;
  6141. const applySelection = event => {
  6142. cursor.on(start => {
  6143. annotations.clearBeforeUpdate(container);
  6144. findCell(event.target, isRoot).each(finish => {
  6145. identify(start, finish, isRoot).each(cellSel => {
  6146. const boxes = cellSel.boxes.getOr([]);
  6147. if (boxes.length === 1) {
  6148. const singleCell = boxes[0];
  6149. const isNonEditableCell = getRaw(singleCell) === 'false';
  6150. const isCellClosestContentEditable = is(closest(event.target), singleCell, eq$1);
  6151. if (isNonEditableCell && isCellClosestContentEditable) {
  6152. annotations.selectRange(container, boxes, singleCell, singleCell);
  6153. bridge.selectContents(singleCell);
  6154. }
  6155. } else if (boxes.length > 1) {
  6156. annotations.selectRange(container, boxes, cellSel.start, cellSel.finish);
  6157. bridge.selectContents(finish);
  6158. }
  6159. });
  6160. });
  6161. });
  6162. };
  6163. const mousedown = event => {
  6164. annotations.clear(container);
  6165. findCell(event.target, isRoot).filter(isInEditableContext).each(cursor.set);
  6166. };
  6167. const mouseover = event => {
  6168. applySelection(event);
  6169. };
  6170. const mouseup = event => {
  6171. applySelection(event);
  6172. clearstate();
  6173. };
  6174. return {
  6175. clearstate,
  6176. mousedown,
  6177. mouseover,
  6178. mouseup
  6179. };
  6180. };
  6181. const down = {
  6182. traverse: nextSibling,
  6183. gather: after$1,
  6184. relative: Situ.before,
  6185. retry: Retries.tryDown,
  6186. failure: BeforeAfter.failedDown
  6187. };
  6188. const up = {
  6189. traverse: prevSibling,
  6190. gather: before,
  6191. relative: Situ.before,
  6192. retry: Retries.tryUp,
  6193. failure: BeforeAfter.failedUp
  6194. };
  6195. const isKey = key => {
  6196. return keycode => {
  6197. return keycode === key;
  6198. };
  6199. };
  6200. const isUp = isKey(38);
  6201. const isDown = isKey(40);
  6202. const isNavigation = keycode => {
  6203. return keycode >= 37 && keycode <= 40;
  6204. };
  6205. const ltr = {
  6206. isBackward: isKey(37),
  6207. isForward: isKey(39)
  6208. };
  6209. const rtl = {
  6210. isBackward: isKey(39),
  6211. isForward: isKey(37)
  6212. };
  6213. const get$3 = _DOC => {
  6214. const doc = _DOC !== undefined ? _DOC.dom : document;
  6215. const x = doc.body.scrollLeft || doc.documentElement.scrollLeft;
  6216. const y = doc.body.scrollTop || doc.documentElement.scrollTop;
  6217. return SugarPosition(x, y);
  6218. };
  6219. const by = (x, y, _DOC) => {
  6220. const doc = _DOC !== undefined ? _DOC.dom : document;
  6221. const win = doc.defaultView;
  6222. if (win) {
  6223. win.scrollBy(x, y);
  6224. }
  6225. };
  6226. const adt = Adt.generate([
  6227. { domRange: ['rng'] },
  6228. {
  6229. relative: [
  6230. 'startSitu',
  6231. 'finishSitu'
  6232. ]
  6233. },
  6234. {
  6235. exact: [
  6236. 'start',
  6237. 'soffset',
  6238. 'finish',
  6239. 'foffset'
  6240. ]
  6241. }
  6242. ]);
  6243. const exactFromRange = simRange => adt.exact(simRange.start, simRange.soffset, simRange.finish, simRange.foffset);
  6244. const getStart = selection => selection.match({
  6245. domRange: rng => SugarElement.fromDom(rng.startContainer),
  6246. relative: (startSitu, _finishSitu) => Situ.getStart(startSitu),
  6247. exact: (start, _soffset, _finish, _foffset) => start
  6248. });
  6249. const domRange = adt.domRange;
  6250. const relative = adt.relative;
  6251. const exact = adt.exact;
  6252. const getWin = selection => {
  6253. const start = getStart(selection);
  6254. return defaultView(start);
  6255. };
  6256. const range = SimRange.create;
  6257. const SimSelection = {
  6258. domRange,
  6259. relative,
  6260. exact,
  6261. exactFromRange,
  6262. getWin,
  6263. range
  6264. };
  6265. const caretPositionFromPoint = (doc, x, y) => {
  6266. var _a, _b;
  6267. return Optional.from((_b = (_a = doc.dom).caretPositionFromPoint) === null || _b === void 0 ? void 0 : _b.call(_a, x, y)).bind(pos => {
  6268. if (pos.offsetNode === null) {
  6269. return Optional.none();
  6270. }
  6271. const r = doc.dom.createRange();
  6272. r.setStart(pos.offsetNode, pos.offset);
  6273. r.collapse();
  6274. return Optional.some(r);
  6275. });
  6276. };
  6277. const caretRangeFromPoint = (doc, x, y) => {
  6278. var _a, _b;
  6279. return Optional.from((_b = (_a = doc.dom).caretRangeFromPoint) === null || _b === void 0 ? void 0 : _b.call(_a, x, y));
  6280. };
  6281. const availableSearch = (() => {
  6282. if (document.caretPositionFromPoint) {
  6283. return caretPositionFromPoint;
  6284. } else if (document.caretRangeFromPoint) {
  6285. return caretRangeFromPoint;
  6286. } else {
  6287. return Optional.none;
  6288. }
  6289. })();
  6290. const fromPoint = (win, x, y) => {
  6291. const doc = SugarElement.fromDom(win.document);
  6292. return availableSearch(doc, x, y).map(rng => SimRange.create(SugarElement.fromDom(rng.startContainer), rng.startOffset, SugarElement.fromDom(rng.endContainer), rng.endOffset));
  6293. };
  6294. const beforeSpecial = (element, offset) => {
  6295. const name$1 = name(element);
  6296. if ('input' === name$1) {
  6297. return Situ.after(element);
  6298. } else if (!contains$2([
  6299. 'br',
  6300. 'img'
  6301. ], name$1)) {
  6302. return Situ.on(element, offset);
  6303. } else {
  6304. return offset === 0 ? Situ.before(element) : Situ.after(element);
  6305. }
  6306. };
  6307. const preprocessRelative = (startSitu, finishSitu) => {
  6308. const start = startSitu.fold(Situ.before, beforeSpecial, Situ.after);
  6309. const finish = finishSitu.fold(Situ.before, beforeSpecial, Situ.after);
  6310. return SimSelection.relative(start, finish);
  6311. };
  6312. const preprocessExact = (start, soffset, finish, foffset) => {
  6313. const startSitu = beforeSpecial(start, soffset);
  6314. const finishSitu = beforeSpecial(finish, foffset);
  6315. return SimSelection.relative(startSitu, finishSitu);
  6316. };
  6317. const makeRange = (start, soffset, finish, foffset) => {
  6318. const doc = owner(start);
  6319. const rng = doc.dom.createRange();
  6320. rng.setStart(start.dom, soffset);
  6321. rng.setEnd(finish.dom, foffset);
  6322. return rng;
  6323. };
  6324. const after = (start, soffset, finish, foffset) => {
  6325. const r = makeRange(start, soffset, finish, foffset);
  6326. const same = eq$1(start, finish) && soffset === foffset;
  6327. return r.collapsed && !same;
  6328. };
  6329. const getNativeSelection = win => Optional.from(win.getSelection());
  6330. const doSetNativeRange = (win, rng) => {
  6331. getNativeSelection(win).each(selection => {
  6332. selection.removeAllRanges();
  6333. selection.addRange(rng);
  6334. });
  6335. };
  6336. const doSetRange = (win, start, soffset, finish, foffset) => {
  6337. const rng = exactToNative(win, start, soffset, finish, foffset);
  6338. doSetNativeRange(win, rng);
  6339. };
  6340. const setLegacyRtlRange = (win, selection, start, soffset, finish, foffset) => {
  6341. selection.collapse(start.dom, soffset);
  6342. selection.extend(finish.dom, foffset);
  6343. };
  6344. const setRangeFromRelative = (win, relative) => diagnose(win, relative).match({
  6345. ltr: (start, soffset, finish, foffset) => {
  6346. doSetRange(win, start, soffset, finish, foffset);
  6347. },
  6348. rtl: (start, soffset, finish, foffset) => {
  6349. getNativeSelection(win).each(selection => {
  6350. if (selection.setBaseAndExtent) {
  6351. selection.setBaseAndExtent(start.dom, soffset, finish.dom, foffset);
  6352. } else if (selection.extend) {
  6353. try {
  6354. setLegacyRtlRange(win, selection, start, soffset, finish, foffset);
  6355. } catch (e) {
  6356. doSetRange(win, finish, foffset, start, soffset);
  6357. }
  6358. } else {
  6359. doSetRange(win, finish, foffset, start, soffset);
  6360. }
  6361. });
  6362. }
  6363. });
  6364. const setExact = (win, start, soffset, finish, foffset) => {
  6365. const relative = preprocessExact(start, soffset, finish, foffset);
  6366. setRangeFromRelative(win, relative);
  6367. };
  6368. const setRelative = (win, startSitu, finishSitu) => {
  6369. const relative = preprocessRelative(startSitu, finishSitu);
  6370. setRangeFromRelative(win, relative);
  6371. };
  6372. const readRange = selection => {
  6373. if (selection.rangeCount > 0) {
  6374. const firstRng = selection.getRangeAt(0);
  6375. const lastRng = selection.getRangeAt(selection.rangeCount - 1);
  6376. return Optional.some(SimRange.create(SugarElement.fromDom(firstRng.startContainer), firstRng.startOffset, SugarElement.fromDom(lastRng.endContainer), lastRng.endOffset));
  6377. } else {
  6378. return Optional.none();
  6379. }
  6380. };
  6381. const doGetExact = selection => {
  6382. if (selection.anchorNode === null || selection.focusNode === null) {
  6383. return readRange(selection);
  6384. } else {
  6385. const anchor = SugarElement.fromDom(selection.anchorNode);
  6386. const focus = SugarElement.fromDom(selection.focusNode);
  6387. return after(anchor, selection.anchorOffset, focus, selection.focusOffset) ? Optional.some(SimRange.create(anchor, selection.anchorOffset, focus, selection.focusOffset)) : readRange(selection);
  6388. }
  6389. };
  6390. const setToElement = (win, element, selectNodeContents$1 = true) => {
  6391. const rngGetter = selectNodeContents$1 ? selectNodeContents : selectNode;
  6392. const rng = rngGetter(win, element);
  6393. doSetNativeRange(win, rng);
  6394. };
  6395. const getExact = win => getNativeSelection(win).filter(sel => sel.rangeCount > 0).bind(doGetExact);
  6396. const get$2 = win => getExact(win).map(range => SimSelection.exact(range.start, range.soffset, range.finish, range.foffset));
  6397. const getFirstRect = (win, selection) => {
  6398. const rng = asLtrRange(win, selection);
  6399. return getFirstRect$1(rng);
  6400. };
  6401. const getAtPoint = (win, x, y) => fromPoint(win, x, y);
  6402. const clear = win => {
  6403. getNativeSelection(win).each(selection => selection.removeAllRanges());
  6404. };
  6405. const WindowBridge = win => {
  6406. const elementFromPoint = (x, y) => {
  6407. return SugarElement.fromPoint(SugarElement.fromDom(win.document), x, y);
  6408. };
  6409. const getRect = element => {
  6410. return element.dom.getBoundingClientRect();
  6411. };
  6412. const getRangedRect = (start, soffset, finish, foffset) => {
  6413. const sel = SimSelection.exact(start, soffset, finish, foffset);
  6414. return getFirstRect(win, sel);
  6415. };
  6416. const getSelection = () => {
  6417. return get$2(win).map(exactAdt => {
  6418. return convertToRange(win, exactAdt);
  6419. });
  6420. };
  6421. const fromSitus = situs => {
  6422. const relative = SimSelection.relative(situs.start, situs.finish);
  6423. return convertToRange(win, relative);
  6424. };
  6425. const situsFromPoint = (x, y) => {
  6426. return getAtPoint(win, x, y).map(exact => {
  6427. return Situs.create(exact.start, exact.soffset, exact.finish, exact.foffset);
  6428. });
  6429. };
  6430. const clearSelection = () => {
  6431. clear(win);
  6432. };
  6433. const collapseSelection = (toStart = false) => {
  6434. get$2(win).each(sel => sel.fold(rng => rng.collapse(toStart), (startSitu, finishSitu) => {
  6435. const situ = toStart ? startSitu : finishSitu;
  6436. setRelative(win, situ, situ);
  6437. }, (start, soffset, finish, foffset) => {
  6438. const node = toStart ? start : finish;
  6439. const offset = toStart ? soffset : foffset;
  6440. setExact(win, node, offset, node, offset);
  6441. }));
  6442. };
  6443. const selectNode = element => {
  6444. setToElement(win, element, false);
  6445. };
  6446. const selectContents = element => {
  6447. setToElement(win, element);
  6448. };
  6449. const setSelection = sel => {
  6450. setExact(win, sel.start, sel.soffset, sel.finish, sel.foffset);
  6451. };
  6452. const setRelativeSelection = (start, finish) => {
  6453. setRelative(win, start, finish);
  6454. };
  6455. const getInnerHeight = () => {
  6456. return win.innerHeight;
  6457. };
  6458. const getScrollY = () => {
  6459. const pos = get$3(SugarElement.fromDom(win.document));
  6460. return pos.top;
  6461. };
  6462. const scrollBy = (x, y) => {
  6463. by(x, y, SugarElement.fromDom(win.document));
  6464. };
  6465. return {
  6466. elementFromPoint,
  6467. getRect,
  6468. getRangedRect,
  6469. getSelection,
  6470. fromSitus,
  6471. situsFromPoint,
  6472. clearSelection,
  6473. collapseSelection,
  6474. setSelection,
  6475. setRelativeSelection,
  6476. selectNode,
  6477. selectContents,
  6478. getInnerHeight,
  6479. getScrollY,
  6480. scrollBy
  6481. };
  6482. };
  6483. const rc = (rows, cols) => ({
  6484. rows,
  6485. cols
  6486. });
  6487. const mouse = (win, container, isRoot, annotations) => {
  6488. const bridge = WindowBridge(win);
  6489. const handlers = MouseSelection(bridge, container, isRoot, annotations);
  6490. return {
  6491. clearstate: handlers.clearstate,
  6492. mousedown: handlers.mousedown,
  6493. mouseover: handlers.mouseover,
  6494. mouseup: handlers.mouseup
  6495. };
  6496. };
  6497. const isEditableNode = node => closest$2(node, isHTMLElement).exists(isEditable$1);
  6498. const isEditableSelection = (start, finish) => isEditableNode(start) || isEditableNode(finish);
  6499. const keyboard = (win, container, isRoot, annotations) => {
  6500. const bridge = WindowBridge(win);
  6501. const clearToNavigate = () => {
  6502. annotations.clear(container);
  6503. return Optional.none();
  6504. };
  6505. const keydown = (event, start, soffset, finish, foffset, direction) => {
  6506. const realEvent = event.raw;
  6507. const keycode = realEvent.which;
  6508. const shiftKey = realEvent.shiftKey === true;
  6509. const handler = retrieve$1(container, annotations.selectedSelector).fold(() => {
  6510. if (isNavigation(keycode) && !shiftKey) {
  6511. annotations.clearBeforeUpdate(container);
  6512. }
  6513. if (isNavigation(keycode) && shiftKey && !isEditableSelection(start, finish)) {
  6514. return Optional.none;
  6515. } else if (isDown(keycode) && shiftKey) {
  6516. return curry(select, bridge, container, isRoot, down, finish, start, annotations.selectRange);
  6517. } else if (isUp(keycode) && shiftKey) {
  6518. return curry(select, bridge, container, isRoot, up, finish, start, annotations.selectRange);
  6519. } else if (isDown(keycode)) {
  6520. return curry(navigate, bridge, isRoot, down, finish, start, lastDownCheck);
  6521. } else if (isUp(keycode)) {
  6522. return curry(navigate, bridge, isRoot, up, finish, start, firstUpCheck);
  6523. } else {
  6524. return Optional.none;
  6525. }
  6526. }, selected => {
  6527. const update$1 = attempts => {
  6528. return () => {
  6529. const navigation = findMap(attempts, delta => {
  6530. return update(delta.rows, delta.cols, container, selected, annotations);
  6531. });
  6532. return navigation.fold(() => {
  6533. return getEdges(container, annotations.firstSelectedSelector, annotations.lastSelectedSelector).map(edges => {
  6534. const relative = isDown(keycode) || direction.isForward(keycode) ? Situ.after : Situ.before;
  6535. bridge.setRelativeSelection(Situ.on(edges.first, 0), relative(edges.table));
  6536. annotations.clear(container);
  6537. return Response.create(Optional.none(), true);
  6538. });
  6539. }, _ => {
  6540. return Optional.some(Response.create(Optional.none(), true));
  6541. });
  6542. };
  6543. };
  6544. if (isNavigation(keycode) && shiftKey && !isEditableSelection(start, finish)) {
  6545. return Optional.none;
  6546. } else if (isDown(keycode) && shiftKey) {
  6547. return update$1([rc(+1, 0)]);
  6548. } else if (isUp(keycode) && shiftKey) {
  6549. return update$1([rc(-1, 0)]);
  6550. } else if (direction.isBackward(keycode) && shiftKey) {
  6551. return update$1([
  6552. rc(0, -1),
  6553. rc(-1, 0)
  6554. ]);
  6555. } else if (direction.isForward(keycode) && shiftKey) {
  6556. return update$1([
  6557. rc(0, +1),
  6558. rc(+1, 0)
  6559. ]);
  6560. } else if (isNavigation(keycode) && !shiftKey) {
  6561. return clearToNavigate;
  6562. } else {
  6563. return Optional.none;
  6564. }
  6565. });
  6566. return handler();
  6567. };
  6568. const keyup = (event, start, soffset, finish, foffset) => {
  6569. return retrieve$1(container, annotations.selectedSelector).fold(() => {
  6570. const realEvent = event.raw;
  6571. const keycode = realEvent.which;
  6572. const shiftKey = realEvent.shiftKey === true;
  6573. if (!shiftKey) {
  6574. return Optional.none();
  6575. }
  6576. if (isNavigation(keycode) && isEditableSelection(start, finish)) {
  6577. return sync(container, isRoot, start, soffset, finish, foffset, annotations.selectRange);
  6578. } else {
  6579. return Optional.none();
  6580. }
  6581. }, Optional.none);
  6582. };
  6583. return {
  6584. keydown,
  6585. keyup
  6586. };
  6587. };
  6588. const external = (win, container, isRoot, annotations) => {
  6589. const bridge = WindowBridge(win);
  6590. return (start, finish) => {
  6591. annotations.clearBeforeUpdate(container);
  6592. identify(start, finish, isRoot).each(cellSel => {
  6593. const boxes = cellSel.boxes.getOr([]);
  6594. annotations.selectRange(container, boxes, cellSel.start, cellSel.finish);
  6595. bridge.selectContents(finish);
  6596. bridge.collapseSelection();
  6597. });
  6598. };
  6599. };
  6600. const read = (element, attr) => {
  6601. const value = get$b(element, attr);
  6602. return value === undefined || value === '' ? [] : value.split(' ');
  6603. };
  6604. const add$2 = (element, attr, id) => {
  6605. const old = read(element, attr);
  6606. const nu = old.concat([id]);
  6607. set$2(element, attr, nu.join(' '));
  6608. return true;
  6609. };
  6610. const remove$4 = (element, attr, id) => {
  6611. const nu = filter$2(read(element, attr), v => v !== id);
  6612. if (nu.length > 0) {
  6613. set$2(element, attr, nu.join(' '));
  6614. } else {
  6615. remove$7(element, attr);
  6616. }
  6617. return false;
  6618. };
  6619. const supports = element => element.dom.classList !== undefined;
  6620. const get$1 = element => read(element, 'class');
  6621. const add$1 = (element, clazz) => add$2(element, 'class', clazz);
  6622. const remove$3 = (element, clazz) => remove$4(element, 'class', clazz);
  6623. const add = (element, clazz) => {
  6624. if (supports(element)) {
  6625. element.dom.classList.add(clazz);
  6626. } else {
  6627. add$1(element, clazz);
  6628. }
  6629. };
  6630. const cleanClass = element => {
  6631. const classList = supports(element) ? element.dom.classList : get$1(element);
  6632. if (classList.length === 0) {
  6633. remove$7(element, 'class');
  6634. }
  6635. };
  6636. const remove$2 = (element, clazz) => {
  6637. if (supports(element)) {
  6638. const classList = element.dom.classList;
  6639. classList.remove(clazz);
  6640. } else {
  6641. remove$3(element, clazz);
  6642. }
  6643. cleanClass(element);
  6644. };
  6645. const has = (element, clazz) => supports(element) && element.dom.classList.contains(clazz);
  6646. const remove$1 = (element, classes) => {
  6647. each$2(classes, x => {
  6648. remove$2(element, x);
  6649. });
  6650. };
  6651. const addClass = clazz => element => {
  6652. add(element, clazz);
  6653. };
  6654. const removeClasses = classes => element => {
  6655. remove$1(element, classes);
  6656. };
  6657. const byClass = ephemera => {
  6658. const addSelectionClass = addClass(ephemera.selected);
  6659. const removeSelectionClasses = removeClasses([
  6660. ephemera.selected,
  6661. ephemera.lastSelected,
  6662. ephemera.firstSelected
  6663. ]);
  6664. const clear = container => {
  6665. const sels = descendants(container, ephemera.selectedSelector);
  6666. each$2(sels, removeSelectionClasses);
  6667. };
  6668. const selectRange = (container, cells, start, finish) => {
  6669. clear(container);
  6670. each$2(cells, addSelectionClass);
  6671. add(start, ephemera.firstSelected);
  6672. add(finish, ephemera.lastSelected);
  6673. };
  6674. return {
  6675. clearBeforeUpdate: clear,
  6676. clear,
  6677. selectRange,
  6678. selectedSelector: ephemera.selectedSelector,
  6679. firstSelectedSelector: ephemera.firstSelectedSelector,
  6680. lastSelectedSelector: ephemera.lastSelectedSelector
  6681. };
  6682. };
  6683. const byAttr = (ephemera, onSelection, onClear) => {
  6684. const removeSelectionAttributes = element => {
  6685. remove$7(element, ephemera.selected);
  6686. remove$7(element, ephemera.firstSelected);
  6687. remove$7(element, ephemera.lastSelected);
  6688. };
  6689. const addSelectionAttribute = element => {
  6690. set$2(element, ephemera.selected, '1');
  6691. };
  6692. const clear = container => {
  6693. clearBeforeUpdate(container);
  6694. onClear();
  6695. };
  6696. const clearBeforeUpdate = container => {
  6697. const sels = descendants(container, `${ ephemera.selectedSelector },${ ephemera.firstSelectedSelector },${ ephemera.lastSelectedSelector }`);
  6698. each$2(sels, removeSelectionAttributes);
  6699. };
  6700. const selectRange = (container, cells, start, finish) => {
  6701. clear(container);
  6702. each$2(cells, addSelectionAttribute);
  6703. set$2(start, ephemera.firstSelected, '1');
  6704. set$2(finish, ephemera.lastSelected, '1');
  6705. onSelection(cells, start, finish);
  6706. };
  6707. return {
  6708. clearBeforeUpdate,
  6709. clear,
  6710. selectRange,
  6711. selectedSelector: ephemera.selectedSelector,
  6712. firstSelectedSelector: ephemera.firstSelectedSelector,
  6713. lastSelectedSelector: ephemera.lastSelectedSelector
  6714. };
  6715. };
  6716. const SelectionAnnotation = {
  6717. byClass,
  6718. byAttr
  6719. };
  6720. const fold = (subject, onNone, onMultiple, onSingle) => {
  6721. switch (subject.tag) {
  6722. case 'none':
  6723. return onNone();
  6724. case 'single':
  6725. return onSingle(subject.element);
  6726. case 'multiple':
  6727. return onMultiple(subject.elements);
  6728. }
  6729. };
  6730. const none = () => ({ tag: 'none' });
  6731. const multiple = elements => ({
  6732. tag: 'multiple',
  6733. elements
  6734. });
  6735. const single = element => ({
  6736. tag: 'single',
  6737. element
  6738. });
  6739. const Selections = (lazyRoot, getStart, selectedSelector) => {
  6740. const get = () => retrieve(lazyRoot(), selectedSelector).fold(() => getStart().fold(none, single), multiple);
  6741. return { get };
  6742. };
  6743. const getUpOrLeftCells = (grid, selectedCells) => {
  6744. const upGrid = grid.slice(0, selectedCells[selectedCells.length - 1].row + 1);
  6745. const upDetails = toDetailList(upGrid);
  6746. return bind$2(upDetails, detail => {
  6747. const slicedCells = detail.cells.slice(0, selectedCells[selectedCells.length - 1].column + 1);
  6748. return map$1(slicedCells, cell => cell.element);
  6749. });
  6750. };
  6751. const getDownOrRightCells = (grid, selectedCells) => {
  6752. const downGrid = grid.slice(selectedCells[0].row + selectedCells[0].rowspan - 1, grid.length);
  6753. const downDetails = toDetailList(downGrid);
  6754. return bind$2(downDetails, detail => {
  6755. const slicedCells = detail.cells.slice(selectedCells[0].column + selectedCells[0].colspan - 1, detail.cells.length);
  6756. return map$1(slicedCells, cell => cell.element);
  6757. });
  6758. };
  6759. const getOtherCells = (table, target, generators) => {
  6760. const warehouse = Warehouse.fromTable(table);
  6761. const details = onCells(warehouse, target);
  6762. return details.map(selectedCells => {
  6763. const grid = toGrid(warehouse, generators, false);
  6764. const {rows} = extractGridDetails(grid);
  6765. const upOrLeftCells = getUpOrLeftCells(rows, selectedCells);
  6766. const downOrRightCells = getDownOrRightCells(rows, selectedCells);
  6767. return {
  6768. upOrLeftCells,
  6769. downOrRightCells
  6770. };
  6771. });
  6772. };
  6773. const mkEvent = (target, x, y, stop, prevent, kill, raw) => ({
  6774. target,
  6775. x,
  6776. y,
  6777. stop,
  6778. prevent,
  6779. kill,
  6780. raw
  6781. });
  6782. const fromRawEvent$1 = rawEvent => {
  6783. const target = SugarElement.fromDom(getOriginalEventTarget(rawEvent).getOr(rawEvent.target));
  6784. const stop = () => rawEvent.stopPropagation();
  6785. const prevent = () => rawEvent.preventDefault();
  6786. const kill = compose(prevent, stop);
  6787. return mkEvent(target, rawEvent.clientX, rawEvent.clientY, stop, prevent, kill, rawEvent);
  6788. };
  6789. const handle = (filter, handler) => rawEvent => {
  6790. if (filter(rawEvent)) {
  6791. handler(fromRawEvent$1(rawEvent));
  6792. }
  6793. };
  6794. const binder = (element, event, filter, handler, useCapture) => {
  6795. const wrapped = handle(filter, handler);
  6796. element.dom.addEventListener(event, wrapped, useCapture);
  6797. return { unbind: curry(unbind, element, event, wrapped, useCapture) };
  6798. };
  6799. const bind$1 = (element, event, filter, handler) => binder(element, event, filter, handler, false);
  6800. const unbind = (element, event, handler, useCapture) => {
  6801. element.dom.removeEventListener(event, handler, useCapture);
  6802. };
  6803. const filter = always;
  6804. const bind = (element, event, handler) => bind$1(element, event, filter, handler);
  6805. const fromRawEvent = fromRawEvent$1;
  6806. const hasInternalTarget = e => !has(SugarElement.fromDom(e.target), 'ephox-snooker-resizer-bar');
  6807. const TableCellSelectionHandler = (editor, resizeHandler) => {
  6808. const cellSelection = Selections(() => SugarElement.fromDom(editor.getBody()), () => getSelectionCell(getSelectionStart(editor), getIsRoot(editor)), ephemera.selectedSelector);
  6809. const onSelection = (cells, start, finish) => {
  6810. const tableOpt = table(start);
  6811. tableOpt.each(table => {
  6812. const cloneFormats = getTableCloneElements(editor);
  6813. const generators = cellOperations(noop, SugarElement.fromDom(editor.getDoc()), cloneFormats);
  6814. const selectedCells = getCellsFromSelection(editor);
  6815. const otherCells = getOtherCells(table, { selection: selectedCells }, generators);
  6816. fireTableSelectionChange(editor, cells, start, finish, otherCells);
  6817. });
  6818. };
  6819. const onClear = () => fireTableSelectionClear(editor);
  6820. const annotations = SelectionAnnotation.byAttr(ephemera, onSelection, onClear);
  6821. editor.on('init', _e => {
  6822. const win = editor.getWin();
  6823. const body = getBody(editor);
  6824. const isRoot = getIsRoot(editor);
  6825. const syncSelection = () => {
  6826. const sel = editor.selection;
  6827. const start = SugarElement.fromDom(sel.getStart());
  6828. const end = SugarElement.fromDom(sel.getEnd());
  6829. const shared = sharedOne(table, [
  6830. start,
  6831. end
  6832. ]);
  6833. shared.fold(() => annotations.clear(body), noop);
  6834. };
  6835. const mouseHandlers = mouse(win, body, isRoot, annotations);
  6836. const keyHandlers = keyboard(win, body, isRoot, annotations);
  6837. const external$1 = external(win, body, isRoot, annotations);
  6838. const hasShiftKey = event => event.raw.shiftKey === true;
  6839. editor.on('TableSelectorChange', e => external$1(e.start, e.finish));
  6840. const handleResponse = (event, response) => {
  6841. if (!hasShiftKey(event)) {
  6842. return;
  6843. }
  6844. if (response.kill) {
  6845. event.kill();
  6846. }
  6847. response.selection.each(ns => {
  6848. const relative = SimSelection.relative(ns.start, ns.finish);
  6849. const rng = asLtrRange(win, relative);
  6850. editor.selection.setRng(rng);
  6851. });
  6852. };
  6853. const keyup = event => {
  6854. const wrappedEvent = fromRawEvent(event);
  6855. if (wrappedEvent.raw.shiftKey && isNavigation(wrappedEvent.raw.which)) {
  6856. const rng = editor.selection.getRng();
  6857. const start = SugarElement.fromDom(rng.startContainer);
  6858. const end = SugarElement.fromDom(rng.endContainer);
  6859. keyHandlers.keyup(wrappedEvent, start, rng.startOffset, end, rng.endOffset).each(response => {
  6860. handleResponse(wrappedEvent, response);
  6861. });
  6862. }
  6863. };
  6864. const keydown = event => {
  6865. const wrappedEvent = fromRawEvent(event);
  6866. resizeHandler.hide();
  6867. const rng = editor.selection.getRng();
  6868. const start = SugarElement.fromDom(rng.startContainer);
  6869. const end = SugarElement.fromDom(rng.endContainer);
  6870. const direction = onDirection(ltr, rtl)(SugarElement.fromDom(editor.selection.getStart()));
  6871. keyHandlers.keydown(wrappedEvent, start, rng.startOffset, end, rng.endOffset, direction).each(response => {
  6872. handleResponse(wrappedEvent, response);
  6873. });
  6874. resizeHandler.show();
  6875. };
  6876. const isLeftMouse = raw => raw.button === 0;
  6877. const isLeftButtonPressed = raw => {
  6878. if (raw.buttons === undefined) {
  6879. return true;
  6880. }
  6881. return (raw.buttons & 1) !== 0;
  6882. };
  6883. const dragStart = _e => {
  6884. mouseHandlers.clearstate();
  6885. };
  6886. const mouseDown = e => {
  6887. if (isLeftMouse(e) && hasInternalTarget(e)) {
  6888. mouseHandlers.mousedown(fromRawEvent(e));
  6889. }
  6890. };
  6891. const mouseOver = e => {
  6892. if (isLeftButtonPressed(e) && hasInternalTarget(e)) {
  6893. mouseHandlers.mouseover(fromRawEvent(e));
  6894. }
  6895. };
  6896. const mouseUp = e => {
  6897. if (isLeftMouse(e) && hasInternalTarget(e)) {
  6898. mouseHandlers.mouseup(fromRawEvent(e));
  6899. }
  6900. };
  6901. const getDoubleTap = () => {
  6902. const lastTarget = Cell(SugarElement.fromDom(body));
  6903. const lastTimeStamp = Cell(0);
  6904. const touchEnd = t => {
  6905. const target = SugarElement.fromDom(t.target);
  6906. if (isTag('td')(target) || isTag('th')(target)) {
  6907. const lT = lastTarget.get();
  6908. const lTS = lastTimeStamp.get();
  6909. if (eq$1(lT, target) && t.timeStamp - lTS < 300) {
  6910. t.preventDefault();
  6911. external$1(target, target);
  6912. }
  6913. }
  6914. lastTarget.set(target);
  6915. lastTimeStamp.set(t.timeStamp);
  6916. };
  6917. return { touchEnd };
  6918. };
  6919. const doubleTap = getDoubleTap();
  6920. editor.on('dragstart', dragStart);
  6921. editor.on('mousedown', mouseDown);
  6922. editor.on('mouseover', mouseOver);
  6923. editor.on('mouseup', mouseUp);
  6924. editor.on('touchend', doubleTap.touchEnd);
  6925. editor.on('keyup', keyup);
  6926. editor.on('keydown', keydown);
  6927. editor.on('NodeChange', syncSelection);
  6928. });
  6929. editor.on('PreInit', () => {
  6930. editor.serializer.addTempAttr(ephemera.firstSelected);
  6931. editor.serializer.addTempAttr(ephemera.lastSelected);
  6932. });
  6933. const clearSelectedCells = container => annotations.clear(SugarElement.fromDom(container));
  6934. const getSelectedCells = () => fold(cellSelection.get(), constant([]), cells => {
  6935. return map$1(cells, cell => cell.dom);
  6936. }, cell => [cell.dom]);
  6937. return {
  6938. getSelectedCells,
  6939. clearSelectedCells
  6940. };
  6941. };
  6942. const Event = fields => {
  6943. let handlers = [];
  6944. const bind = handler => {
  6945. if (handler === undefined) {
  6946. throw new Error('Event bind error: undefined handler');
  6947. }
  6948. handlers.push(handler);
  6949. };
  6950. const unbind = handler => {
  6951. handlers = filter$2(handlers, h => {
  6952. return h !== handler;
  6953. });
  6954. };
  6955. const trigger = (...args) => {
  6956. const event = {};
  6957. each$2(fields, (name, i) => {
  6958. event[name] = args[i];
  6959. });
  6960. each$2(handlers, handler => {
  6961. handler(event);
  6962. });
  6963. };
  6964. return {
  6965. bind,
  6966. unbind,
  6967. trigger
  6968. };
  6969. };
  6970. const create$1 = typeDefs => {
  6971. const registry = map(typeDefs, event => {
  6972. return {
  6973. bind: event.bind,
  6974. unbind: event.unbind
  6975. };
  6976. });
  6977. const trigger = map(typeDefs, event => {
  6978. return event.trigger;
  6979. });
  6980. return {
  6981. registry,
  6982. trigger
  6983. };
  6984. };
  6985. const last = (fn, rate) => {
  6986. let timer = null;
  6987. const cancel = () => {
  6988. if (!isNull(timer)) {
  6989. clearTimeout(timer);
  6990. timer = null;
  6991. }
  6992. };
  6993. const throttle = (...args) => {
  6994. cancel();
  6995. timer = setTimeout(() => {
  6996. timer = null;
  6997. fn.apply(null, args);
  6998. }, rate);
  6999. };
  7000. return {
  7001. cancel,
  7002. throttle
  7003. };
  7004. };
  7005. const sort = arr => {
  7006. return arr.slice(0).sort();
  7007. };
  7008. const reqMessage = (required, keys) => {
  7009. throw new Error('All required keys (' + sort(required).join(', ') + ') were not specified. Specified keys were: ' + sort(keys).join(', ') + '.');
  7010. };
  7011. const unsuppMessage = unsupported => {
  7012. throw new Error('Unsupported keys for object: ' + sort(unsupported).join(', '));
  7013. };
  7014. const validateStrArr = (label, array) => {
  7015. if (!isArray(array)) {
  7016. throw new Error('The ' + label + ' fields must be an array. Was: ' + array + '.');
  7017. }
  7018. each$2(array, a => {
  7019. if (!isString(a)) {
  7020. throw new Error('The value ' + a + ' in the ' + label + ' fields was not a string.');
  7021. }
  7022. });
  7023. };
  7024. const invalidTypeMessage = (incorrect, type) => {
  7025. throw new Error('All values need to be of type: ' + type + '. Keys (' + sort(incorrect).join(', ') + ') were not.');
  7026. };
  7027. const checkDupes = everything => {
  7028. const sorted = sort(everything);
  7029. const dupe = find$1(sorted, (s, i) => {
  7030. return i < sorted.length - 1 && s === sorted[i + 1];
  7031. });
  7032. dupe.each(d => {
  7033. throw new Error('The field: ' + d + ' occurs more than once in the combined fields: [' + sorted.join(', ') + '].');
  7034. });
  7035. };
  7036. const base = (handleUnsupported, required) => {
  7037. return baseWith(handleUnsupported, required, {
  7038. validate: isFunction,
  7039. label: 'function'
  7040. });
  7041. };
  7042. const baseWith = (handleUnsupported, required, pred) => {
  7043. if (required.length === 0) {
  7044. throw new Error('You must specify at least one required field.');
  7045. }
  7046. validateStrArr('required', required);
  7047. checkDupes(required);
  7048. return obj => {
  7049. const keys$1 = keys(obj);
  7050. const allReqd = forall(required, req => {
  7051. return contains$2(keys$1, req);
  7052. });
  7053. if (!allReqd) {
  7054. reqMessage(required, keys$1);
  7055. }
  7056. handleUnsupported(required, keys$1);
  7057. const invalidKeys = filter$2(required, key => {
  7058. return !pred.validate(obj[key], key);
  7059. });
  7060. if (invalidKeys.length > 0) {
  7061. invalidTypeMessage(invalidKeys, pred.label);
  7062. }
  7063. return obj;
  7064. };
  7065. };
  7066. const handleExact = (required, keys) => {
  7067. const unsupported = filter$2(keys, key => {
  7068. return !contains$2(required, key);
  7069. });
  7070. if (unsupported.length > 0) {
  7071. unsuppMessage(unsupported);
  7072. }
  7073. };
  7074. const exactly = required => base(handleExact, required);
  7075. const DragMode = exactly([
  7076. 'compare',
  7077. 'extract',
  7078. 'mutate',
  7079. 'sink'
  7080. ]);
  7081. const DragSink = exactly([
  7082. 'element',
  7083. 'start',
  7084. 'stop',
  7085. 'destroy'
  7086. ]);
  7087. const DragApi = exactly([
  7088. 'forceDrop',
  7089. 'drop',
  7090. 'move',
  7091. 'delayDrop'
  7092. ]);
  7093. const InDrag = () => {
  7094. let previous = Optional.none();
  7095. const reset = () => {
  7096. previous = Optional.none();
  7097. };
  7098. const update = (mode, nu) => {
  7099. const result = previous.map(old => {
  7100. return mode.compare(old, nu);
  7101. });
  7102. previous = Optional.some(nu);
  7103. return result;
  7104. };
  7105. const onEvent = (event, mode) => {
  7106. const dataOption = mode.extract(event);
  7107. dataOption.each(data => {
  7108. const offset = update(mode, data);
  7109. offset.each(d => {
  7110. events.trigger.move(d);
  7111. });
  7112. });
  7113. };
  7114. const events = create$1({ move: Event(['info']) });
  7115. return {
  7116. onEvent,
  7117. reset,
  7118. events: events.registry
  7119. };
  7120. };
  7121. const NoDrag = () => {
  7122. const events = create$1({ move: Event(['info']) });
  7123. return {
  7124. onEvent: noop,
  7125. reset: noop,
  7126. events: events.registry
  7127. };
  7128. };
  7129. const Movement = () => {
  7130. const noDragState = NoDrag();
  7131. const inDragState = InDrag();
  7132. let dragState = noDragState;
  7133. const on = () => {
  7134. dragState.reset();
  7135. dragState = inDragState;
  7136. };
  7137. const off = () => {
  7138. dragState.reset();
  7139. dragState = noDragState;
  7140. };
  7141. const onEvent = (event, mode) => {
  7142. dragState.onEvent(event, mode);
  7143. };
  7144. const isOn = () => {
  7145. return dragState === inDragState;
  7146. };
  7147. return {
  7148. on,
  7149. off,
  7150. isOn,
  7151. onEvent,
  7152. events: inDragState.events
  7153. };
  7154. };
  7155. const setup = (mutation, mode, settings) => {
  7156. let active = false;
  7157. const events = create$1({
  7158. start: Event([]),
  7159. stop: Event([])
  7160. });
  7161. const movement = Movement();
  7162. const drop = () => {
  7163. sink.stop();
  7164. if (movement.isOn()) {
  7165. movement.off();
  7166. events.trigger.stop();
  7167. }
  7168. };
  7169. const throttledDrop = last(drop, 200);
  7170. const go = parent => {
  7171. sink.start(parent);
  7172. movement.on();
  7173. events.trigger.start();
  7174. };
  7175. const mousemove = event => {
  7176. throttledDrop.cancel();
  7177. movement.onEvent(event, mode);
  7178. };
  7179. movement.events.move.bind(event => {
  7180. mode.mutate(mutation, event.info);
  7181. });
  7182. const on = () => {
  7183. active = true;
  7184. };
  7185. const off = () => {
  7186. active = false;
  7187. };
  7188. const isActive = () => active;
  7189. const runIfActive = f => {
  7190. return (...args) => {
  7191. if (active) {
  7192. f.apply(null, args);
  7193. }
  7194. };
  7195. };
  7196. const sink = mode.sink(DragApi({
  7197. forceDrop: drop,
  7198. drop: runIfActive(drop),
  7199. move: runIfActive(mousemove),
  7200. delayDrop: runIfActive(throttledDrop.throttle)
  7201. }), settings);
  7202. const destroy = () => {
  7203. sink.destroy();
  7204. };
  7205. return {
  7206. element: sink.element,
  7207. go,
  7208. on,
  7209. off,
  7210. isActive,
  7211. destroy,
  7212. events: events.registry
  7213. };
  7214. };
  7215. const css = namespace => {
  7216. const dashNamespace = namespace.replace(/\./g, '-');
  7217. const resolve = str => {
  7218. return dashNamespace + '-' + str;
  7219. };
  7220. return { resolve };
  7221. };
  7222. const styles$1 = css('ephox-dragster');
  7223. const resolve$1 = styles$1.resolve;
  7224. const Blocker = options => {
  7225. const settings = {
  7226. layerClass: resolve$1('blocker'),
  7227. ...options
  7228. };
  7229. const div = SugarElement.fromTag('div');
  7230. set$2(div, 'role', 'presentation');
  7231. setAll(div, {
  7232. position: 'fixed',
  7233. left: '0px',
  7234. top: '0px',
  7235. width: '100%',
  7236. height: '100%'
  7237. });
  7238. add(div, resolve$1('blocker'));
  7239. add(div, settings.layerClass);
  7240. const element = constant(div);
  7241. const destroy = () => {
  7242. remove$6(div);
  7243. };
  7244. return {
  7245. element,
  7246. destroy
  7247. };
  7248. };
  7249. const compare = (old, nu) => {
  7250. return SugarPosition(nu.left - old.left, nu.top - old.top);
  7251. };
  7252. const extract = event => {
  7253. return Optional.some(SugarPosition(event.x, event.y));
  7254. };
  7255. const mutate = (mutation, info) => {
  7256. mutation.mutate(info.left, info.top);
  7257. };
  7258. const sink = (dragApi, settings) => {
  7259. const blocker = Blocker(settings);
  7260. const mdown = bind(blocker.element(), 'mousedown', dragApi.forceDrop);
  7261. const mup = bind(blocker.element(), 'mouseup', dragApi.drop);
  7262. const mmove = bind(blocker.element(), 'mousemove', dragApi.move);
  7263. const mout = bind(blocker.element(), 'mouseout', dragApi.delayDrop);
  7264. const destroy = () => {
  7265. blocker.destroy();
  7266. mup.unbind();
  7267. mmove.unbind();
  7268. mout.unbind();
  7269. mdown.unbind();
  7270. };
  7271. const start = parent => {
  7272. append$1(parent, blocker.element());
  7273. };
  7274. const stop = () => {
  7275. remove$6(blocker.element());
  7276. };
  7277. return DragSink({
  7278. element: blocker.element,
  7279. start,
  7280. stop,
  7281. destroy
  7282. });
  7283. };
  7284. var MouseDrag = DragMode({
  7285. compare,
  7286. extract,
  7287. sink,
  7288. mutate
  7289. });
  7290. const transform = (mutation, settings = {}) => {
  7291. var _a;
  7292. const mode = (_a = settings.mode) !== null && _a !== void 0 ? _a : MouseDrag;
  7293. return setup(mutation, mode, settings);
  7294. };
  7295. const styles = css('ephox-snooker');
  7296. const resolve = styles.resolve;
  7297. const Mutation = () => {
  7298. const events = create$1({
  7299. drag: Event([
  7300. 'xDelta',
  7301. 'yDelta'
  7302. ])
  7303. });
  7304. const mutate = (x, y) => {
  7305. events.trigger.drag(x, y);
  7306. };
  7307. return {
  7308. mutate,
  7309. events: events.registry
  7310. };
  7311. };
  7312. const BarMutation = () => {
  7313. const events = create$1({
  7314. drag: Event([
  7315. 'xDelta',
  7316. 'yDelta',
  7317. 'target'
  7318. ])
  7319. });
  7320. let target = Optional.none();
  7321. const delegate = Mutation();
  7322. delegate.events.drag.bind(event => {
  7323. target.each(t => {
  7324. events.trigger.drag(event.xDelta, event.yDelta, t);
  7325. });
  7326. });
  7327. const assign = t => {
  7328. target = Optional.some(t);
  7329. };
  7330. const get = () => {
  7331. return target;
  7332. };
  7333. return {
  7334. assign,
  7335. get,
  7336. mutate: delegate.mutate,
  7337. events: events.registry
  7338. };
  7339. };
  7340. const col = (column, x, y, w, h) => {
  7341. const bar = SugarElement.fromTag('div');
  7342. setAll(bar, {
  7343. position: 'absolute',
  7344. left: x - w / 2 + 'px',
  7345. top: y + 'px',
  7346. height: h + 'px',
  7347. width: w + 'px'
  7348. });
  7349. setAll$1(bar, {
  7350. 'data-column': column,
  7351. 'role': 'presentation'
  7352. });
  7353. return bar;
  7354. };
  7355. const row = (r, x, y, w, h) => {
  7356. const bar = SugarElement.fromTag('div');
  7357. setAll(bar, {
  7358. position: 'absolute',
  7359. left: x + 'px',
  7360. top: y - h / 2 + 'px',
  7361. height: h + 'px',
  7362. width: w + 'px'
  7363. });
  7364. setAll$1(bar, {
  7365. 'data-row': r,
  7366. 'role': 'presentation'
  7367. });
  7368. return bar;
  7369. };
  7370. const resizeBar = resolve('resizer-bar');
  7371. const resizeRowBar = resolve('resizer-rows');
  7372. const resizeColBar = resolve('resizer-cols');
  7373. const BAR_THICKNESS = 7;
  7374. const resizableRows = (warehouse, isResizable) => bind$2(warehouse.all, (row, i) => isResizable(row.element) ? [i] : []);
  7375. const resizableColumns = (warehouse, isResizable) => {
  7376. const resizableCols = [];
  7377. range$1(warehouse.grid.columns, index => {
  7378. const colElmOpt = Warehouse.getColumnAt(warehouse, index).map(col => col.element);
  7379. if (colElmOpt.forall(isResizable)) {
  7380. resizableCols.push(index);
  7381. }
  7382. });
  7383. return filter$2(resizableCols, colIndex => {
  7384. const columnCells = Warehouse.filterItems(warehouse, cell => cell.column === colIndex);
  7385. return forall(columnCells, cell => isResizable(cell.element));
  7386. });
  7387. };
  7388. const destroy = wire => {
  7389. const previous = descendants(wire.parent(), '.' + resizeBar);
  7390. each$2(previous, remove$6);
  7391. };
  7392. const drawBar = (wire, positions, create) => {
  7393. const origin = wire.origin();
  7394. each$2(positions, cpOption => {
  7395. cpOption.each(cp => {
  7396. const bar = create(origin, cp);
  7397. add(bar, resizeBar);
  7398. append$1(wire.parent(), bar);
  7399. });
  7400. });
  7401. };
  7402. const refreshCol = (wire, colPositions, position, tableHeight) => {
  7403. drawBar(wire, colPositions, (origin, cp) => {
  7404. const colBar = col(cp.col, cp.x - origin.left, position.top - origin.top, BAR_THICKNESS, tableHeight);
  7405. add(colBar, resizeColBar);
  7406. return colBar;
  7407. });
  7408. };
  7409. const refreshRow = (wire, rowPositions, position, tableWidth) => {
  7410. drawBar(wire, rowPositions, (origin, cp) => {
  7411. const rowBar = row(cp.row, position.left - origin.left, cp.y - origin.top, tableWidth, BAR_THICKNESS);
  7412. add(rowBar, resizeRowBar);
  7413. return rowBar;
  7414. });
  7415. };
  7416. const refreshGrid = (warhouse, wire, table, rows, cols) => {
  7417. const position = absolute(table);
  7418. const isResizable = wire.isResizable;
  7419. const rowPositions = rows.length > 0 ? height.positions(rows, table) : [];
  7420. const resizableRowBars = rowPositions.length > 0 ? resizableRows(warhouse, isResizable) : [];
  7421. const resizableRowPositions = filter$2(rowPositions, (_pos, i) => exists(resizableRowBars, barIndex => i === barIndex));
  7422. refreshRow(wire, resizableRowPositions, position, getOuter$2(table));
  7423. const colPositions = cols.length > 0 ? width.positions(cols, table) : [];
  7424. const resizableColBars = colPositions.length > 0 ? resizableColumns(warhouse, isResizable) : [];
  7425. const resizableColPositions = filter$2(colPositions, (_pos, i) => exists(resizableColBars, barIndex => i === barIndex));
  7426. refreshCol(wire, resizableColPositions, position, getOuter$1(table));
  7427. };
  7428. const refresh = (wire, table) => {
  7429. destroy(wire);
  7430. if (wire.isResizable(table)) {
  7431. const warehouse = Warehouse.fromTable(table);
  7432. const rows$1 = rows(warehouse);
  7433. const cols = columns(warehouse);
  7434. refreshGrid(warehouse, wire, table, rows$1, cols);
  7435. }
  7436. };
  7437. const each = (wire, f) => {
  7438. const bars = descendants(wire.parent(), '.' + resizeBar);
  7439. each$2(bars, f);
  7440. };
  7441. const hide = wire => {
  7442. each(wire, bar => {
  7443. set$1(bar, 'display', 'none');
  7444. });
  7445. };
  7446. const show = wire => {
  7447. each(wire, bar => {
  7448. set$1(bar, 'display', 'block');
  7449. });
  7450. };
  7451. const isRowBar = element => {
  7452. return has(element, resizeRowBar);
  7453. };
  7454. const isColBar = element => {
  7455. return has(element, resizeColBar);
  7456. };
  7457. const resizeBarDragging = resolve('resizer-bar-dragging');
  7458. const BarManager = wire => {
  7459. const mutation = BarMutation();
  7460. const resizing = transform(mutation, {});
  7461. let hoverTable = Optional.none();
  7462. const getResizer = (element, type) => {
  7463. return Optional.from(get$b(element, type));
  7464. };
  7465. mutation.events.drag.bind(event => {
  7466. getResizer(event.target, 'data-row').each(_dataRow => {
  7467. const currentRow = getCssValue(event.target, 'top');
  7468. set$1(event.target, 'top', currentRow + event.yDelta + 'px');
  7469. });
  7470. getResizer(event.target, 'data-column').each(_dataCol => {
  7471. const currentCol = getCssValue(event.target, 'left');
  7472. set$1(event.target, 'left', currentCol + event.xDelta + 'px');
  7473. });
  7474. });
  7475. const getDelta = (target, dir) => {
  7476. const newX = getCssValue(target, dir);
  7477. const oldX = getAttrValue(target, 'data-initial-' + dir, 0);
  7478. return newX - oldX;
  7479. };
  7480. resizing.events.stop.bind(() => {
  7481. mutation.get().each(target => {
  7482. hoverTable.each(table => {
  7483. getResizer(target, 'data-row').each(row => {
  7484. const delta = getDelta(target, 'top');
  7485. remove$7(target, 'data-initial-top');
  7486. events.trigger.adjustHeight(table, delta, parseInt(row, 10));
  7487. });
  7488. getResizer(target, 'data-column').each(column => {
  7489. const delta = getDelta(target, 'left');
  7490. remove$7(target, 'data-initial-left');
  7491. events.trigger.adjustWidth(table, delta, parseInt(column, 10));
  7492. });
  7493. refresh(wire, table);
  7494. });
  7495. });
  7496. });
  7497. const handler = (target, dir) => {
  7498. events.trigger.startAdjust();
  7499. mutation.assign(target);
  7500. set$2(target, 'data-initial-' + dir, getCssValue(target, dir));
  7501. add(target, resizeBarDragging);
  7502. set$1(target, 'opacity', '0.2');
  7503. resizing.go(wire.parent());
  7504. };
  7505. const mousedown = bind(wire.parent(), 'mousedown', event => {
  7506. if (isRowBar(event.target)) {
  7507. handler(event.target, 'top');
  7508. }
  7509. if (isColBar(event.target)) {
  7510. handler(event.target, 'left');
  7511. }
  7512. });
  7513. const isRoot = e => {
  7514. return eq$1(e, wire.view());
  7515. };
  7516. const findClosestEditableTable = target => closest$1(target, 'table', isRoot).filter(isEditable$1);
  7517. const mouseover = bind(wire.view(), 'mouseover', event => {
  7518. findClosestEditableTable(event.target).fold(() => {
  7519. if (inBody(event.target)) {
  7520. destroy(wire);
  7521. }
  7522. }, table => {
  7523. if (resizing.isActive()) {
  7524. hoverTable = Optional.some(table);
  7525. refresh(wire, table);
  7526. }
  7527. });
  7528. });
  7529. const destroy$1 = () => {
  7530. mousedown.unbind();
  7531. mouseover.unbind();
  7532. resizing.destroy();
  7533. destroy(wire);
  7534. };
  7535. const refresh$1 = tbl => {
  7536. refresh(wire, tbl);
  7537. };
  7538. const events = create$1({
  7539. adjustHeight: Event([
  7540. 'table',
  7541. 'delta',
  7542. 'row'
  7543. ]),
  7544. adjustWidth: Event([
  7545. 'table',
  7546. 'delta',
  7547. 'column'
  7548. ]),
  7549. startAdjust: Event([])
  7550. });
  7551. return {
  7552. destroy: destroy$1,
  7553. refresh: refresh$1,
  7554. on: resizing.on,
  7555. off: resizing.off,
  7556. hideBars: curry(hide, wire),
  7557. showBars: curry(show, wire),
  7558. events: events.registry
  7559. };
  7560. };
  7561. const create = (wire, resizing, lazySizing) => {
  7562. const hdirection = height;
  7563. const vdirection = width;
  7564. const manager = BarManager(wire);
  7565. const events = create$1({
  7566. beforeResize: Event([
  7567. 'table',
  7568. 'type'
  7569. ]),
  7570. afterResize: Event([
  7571. 'table',
  7572. 'type'
  7573. ]),
  7574. startDrag: Event([])
  7575. });
  7576. manager.events.adjustHeight.bind(event => {
  7577. const table = event.table;
  7578. events.trigger.beforeResize(table, 'row');
  7579. const delta = hdirection.delta(event.delta, table);
  7580. adjustHeight(table, delta, event.row, hdirection);
  7581. events.trigger.afterResize(table, 'row');
  7582. });
  7583. manager.events.startAdjust.bind(_event => {
  7584. events.trigger.startDrag();
  7585. });
  7586. manager.events.adjustWidth.bind(event => {
  7587. const table = event.table;
  7588. events.trigger.beforeResize(table, 'col');
  7589. const delta = vdirection.delta(event.delta, table);
  7590. const tableSize = lazySizing(table);
  7591. adjustWidth(table, delta, event.column, resizing, tableSize);
  7592. events.trigger.afterResize(table, 'col');
  7593. });
  7594. return {
  7595. on: manager.on,
  7596. off: manager.off,
  7597. refreshBars: manager.refresh,
  7598. hideBars: manager.hideBars,
  7599. showBars: manager.showBars,
  7600. destroy: manager.destroy,
  7601. events: events.registry
  7602. };
  7603. };
  7604. const TableResize = { create };
  7605. const only = (element, isResizable) => {
  7606. const parent = isDocument(element) ? documentElement(element) : element;
  7607. return {
  7608. parent: constant(parent),
  7609. view: constant(element),
  7610. origin: constant(SugarPosition(0, 0)),
  7611. isResizable
  7612. };
  7613. };
  7614. const detached = (editable, chrome, isResizable) => {
  7615. const origin = () => absolute(chrome);
  7616. return {
  7617. parent: constant(chrome),
  7618. view: constant(editable),
  7619. origin,
  7620. isResizable
  7621. };
  7622. };
  7623. const body = (editable, chrome, isResizable) => {
  7624. return {
  7625. parent: constant(chrome),
  7626. view: constant(editable),
  7627. origin: constant(SugarPosition(0, 0)),
  7628. isResizable
  7629. };
  7630. };
  7631. const ResizeWire = {
  7632. only,
  7633. detached,
  7634. body
  7635. };
  7636. const createContainer = () => {
  7637. const container = SugarElement.fromTag('div');
  7638. setAll(container, {
  7639. position: 'static',
  7640. height: '0',
  7641. width: '0',
  7642. padding: '0',
  7643. margin: '0',
  7644. border: '0'
  7645. });
  7646. append$1(body$1(), container);
  7647. return container;
  7648. };
  7649. const get = (editor, isResizable) => {
  7650. return editor.inline ? ResizeWire.body(SugarElement.fromDom(editor.getBody()), createContainer(), isResizable) : ResizeWire.only(SugarElement.fromDom(editor.getDoc()), isResizable);
  7651. };
  7652. const remove = (editor, wire) => {
  7653. if (editor.inline) {
  7654. remove$6(wire.parent());
  7655. }
  7656. };
  7657. const isTable = node => isNonNullable(node) && node.nodeName === 'TABLE';
  7658. const barResizerPrefix = 'bar-';
  7659. const isResizable = elm => get$b(elm, 'data-mce-resize') !== 'false';
  7660. const syncPixels = table => {
  7661. const warehouse = Warehouse.fromTable(table);
  7662. if (!Warehouse.hasColumns(warehouse)) {
  7663. each$2(cells$1(table), cell => {
  7664. const computedWidth = get$a(cell, 'width');
  7665. set$1(cell, 'width', computedWidth);
  7666. remove$7(cell, 'width');
  7667. });
  7668. }
  7669. };
  7670. const TableResizeHandler = editor => {
  7671. const selectionRng = value();
  7672. const tableResize = value();
  7673. const resizeWire = value();
  7674. let startW;
  7675. let startRawW;
  7676. const lazySizing = table => get$5(editor, table);
  7677. const lazyResizingBehaviour = () => isPreserveTableColumnResizing(editor) ? preserveTable() : resizeTable();
  7678. const getNumColumns = table => getGridSize(table).columns;
  7679. const afterCornerResize = (table, origin, width) => {
  7680. const isRightEdgeResize = endsWith(origin, 'e');
  7681. if (startRawW === '') {
  7682. convertToPercentSize(table);
  7683. }
  7684. if (width !== startW && startRawW !== '') {
  7685. set$1(table, 'width', startRawW);
  7686. const resizing = lazyResizingBehaviour();
  7687. const tableSize = lazySizing(table);
  7688. const col = isPreserveTableColumnResizing(editor) || isRightEdgeResize ? getNumColumns(table) - 1 : 0;
  7689. adjustWidth(table, width - startW, col, resizing, tableSize);
  7690. } else if (isPercentage$1(startRawW)) {
  7691. const percentW = parseFloat(startRawW.replace('%', ''));
  7692. const targetPercentW = width * percentW / startW;
  7693. set$1(table, 'width', targetPercentW + '%');
  7694. }
  7695. if (isPixel(startRawW)) {
  7696. syncPixels(table);
  7697. }
  7698. };
  7699. const destroy = () => {
  7700. tableResize.on(sz => {
  7701. sz.destroy();
  7702. });
  7703. resizeWire.on(w => {
  7704. remove(editor, w);
  7705. });
  7706. };
  7707. editor.on('init', () => {
  7708. const rawWire = get(editor, isResizable);
  7709. resizeWire.set(rawWire);
  7710. if (hasTableObjectResizing(editor) && hasTableResizeBars(editor)) {
  7711. const resizing = lazyResizingBehaviour();
  7712. const sz = TableResize.create(rawWire, resizing, lazySizing);
  7713. sz.on();
  7714. sz.events.startDrag.bind(_event => {
  7715. selectionRng.set(editor.selection.getRng());
  7716. });
  7717. sz.events.beforeResize.bind(event => {
  7718. const rawTable = event.table.dom;
  7719. fireObjectResizeStart(editor, rawTable, getPixelWidth(rawTable), getPixelHeight(rawTable), barResizerPrefix + event.type);
  7720. });
  7721. sz.events.afterResize.bind(event => {
  7722. const table = event.table;
  7723. const rawTable = table.dom;
  7724. removeDataStyle(table);
  7725. selectionRng.on(rng => {
  7726. editor.selection.setRng(rng);
  7727. editor.focus();
  7728. });
  7729. fireObjectResized(editor, rawTable, getPixelWidth(rawTable), getPixelHeight(rawTable), barResizerPrefix + event.type);
  7730. editor.undoManager.add();
  7731. });
  7732. tableResize.set(sz);
  7733. }
  7734. });
  7735. editor.on('ObjectResizeStart', e => {
  7736. const targetElm = e.target;
  7737. if (isTable(targetElm)) {
  7738. const table = SugarElement.fromDom(targetElm);
  7739. each$2(editor.dom.select('.mce-clonedresizable'), clone => {
  7740. editor.dom.addClass(clone, 'mce-' + getTableColumnResizingBehaviour(editor) + '-columns');
  7741. });
  7742. if (!isPixelSizing(table) && isTablePixelsForced(editor)) {
  7743. convertToPixelSize(table);
  7744. } else if (!isPercentSizing(table) && isTablePercentagesForced(editor)) {
  7745. convertToPercentSize(table);
  7746. }
  7747. if (isNoneSizing(table) && startsWith(e.origin, barResizerPrefix)) {
  7748. convertToPercentSize(table);
  7749. }
  7750. startW = e.width;
  7751. startRawW = isTableResponsiveForced(editor) ? '' : getRawWidth(editor, targetElm).getOr('');
  7752. }
  7753. });
  7754. editor.on('ObjectResized', e => {
  7755. const targetElm = e.target;
  7756. if (isTable(targetElm)) {
  7757. const table = SugarElement.fromDom(targetElm);
  7758. const origin = e.origin;
  7759. if (startsWith(origin, 'corner-')) {
  7760. afterCornerResize(table, origin, e.width);
  7761. }
  7762. removeDataStyle(table);
  7763. fireTableModified(editor, table.dom, styleModified);
  7764. }
  7765. });
  7766. editor.on('SwitchMode', () => {
  7767. tableResize.on(resize => {
  7768. if (editor.mode.isReadOnly()) {
  7769. resize.hideBars();
  7770. } else {
  7771. resize.showBars();
  7772. }
  7773. });
  7774. });
  7775. editor.on('dragstart dragend', e => {
  7776. tableResize.on(resize => {
  7777. if (e.type === 'dragstart') {
  7778. resize.hideBars();
  7779. resize.off();
  7780. } else {
  7781. resize.on();
  7782. resize.showBars();
  7783. }
  7784. });
  7785. });
  7786. editor.on('remove', () => {
  7787. destroy();
  7788. });
  7789. const refresh = table => {
  7790. tableResize.on(resize => resize.refreshBars(SugarElement.fromDom(table)));
  7791. };
  7792. const hide = () => {
  7793. tableResize.on(resize => resize.hideBars());
  7794. };
  7795. const show = () => {
  7796. tableResize.on(resize => resize.showBars());
  7797. };
  7798. return {
  7799. refresh,
  7800. hide,
  7801. show
  7802. };
  7803. };
  7804. const setupTable = editor => {
  7805. register(editor);
  7806. const resizeHandler = TableResizeHandler(editor);
  7807. const cellSelectionHandler = TableCellSelectionHandler(editor, resizeHandler);
  7808. const actions = TableActions(editor, resizeHandler, cellSelectionHandler);
  7809. registerCommands(editor, actions);
  7810. registerQueryCommands(editor, actions);
  7811. registerEvents(editor, actions);
  7812. return {
  7813. getSelectedCells: cellSelectionHandler.getSelectedCells,
  7814. clearSelectedCells: cellSelectionHandler.clearSelectedCells
  7815. };
  7816. };
  7817. const DomModel = editor => {
  7818. const table = setupTable(editor);
  7819. return { table };
  7820. };
  7821. var Model = () => {
  7822. global$1.add('dom', DomModel);
  7823. };
  7824. Model();
  7825. })();