model.js 283 KB

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