model.js 285 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975
  1. /**
  2. * TinyMCE version 6.1.0 (2022-06-29)
  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. let offset = 0;
  3348. const substitute = substitution();
  3349. while (row.cells.length > index + offset && comparator(prevCell.element, row.cells[index + offset].element)) {
  3350. mutateCell(row, index + offset, elementnew(substitute, true, row.cells[index + offset].isLocked));
  3351. offset++;
  3352. }
  3353. });
  3354. }
  3355. return grid;
  3356. };
  3357. const splitRows = (grid, index, comparator, substitution) => {
  3358. const rows = extractGridDetails(grid).rows;
  3359. if (index > 0 && index < rows.length) {
  3360. const rowPrevCells = rows[index - 1].cells;
  3361. const cells = uniqueCells(rowPrevCells, comparator);
  3362. each$2(cells, cell => {
  3363. let replacement = Optional.none();
  3364. for (let i = index; i < rows.length; i++) {
  3365. for (let j = 0; j < cellLength(rows[0]); j++) {
  3366. const row = rows[i];
  3367. const current = getCell(row, j);
  3368. const isToReplace = comparator(current.element, cell.element);
  3369. if (isToReplace) {
  3370. if (replacement.isNone()) {
  3371. replacement = Optional.some(substitution());
  3372. }
  3373. replacement.each(sub => {
  3374. mutateCell(row, j, elementnew(sub, true, current.isLocked));
  3375. });
  3376. }
  3377. }
  3378. }
  3379. });
  3380. }
  3381. return grid;
  3382. };
  3383. const value$1 = value => {
  3384. const applyHelper = fn => fn(value);
  3385. const constHelper = constant(value);
  3386. const outputHelper = () => output;
  3387. const output = {
  3388. tag: true,
  3389. inner: value,
  3390. fold: (_onError, onValue) => onValue(value),
  3391. isValue: always,
  3392. isError: never,
  3393. map: mapper => Result.value(mapper(value)),
  3394. mapError: outputHelper,
  3395. bind: applyHelper,
  3396. exists: applyHelper,
  3397. forall: applyHelper,
  3398. getOr: constHelper,
  3399. or: outputHelper,
  3400. getOrThunk: constHelper,
  3401. orThunk: outputHelper,
  3402. getOrDie: constHelper,
  3403. each: fn => {
  3404. fn(value);
  3405. },
  3406. toOptional: () => Optional.some(value)
  3407. };
  3408. return output;
  3409. };
  3410. const error = error => {
  3411. const outputHelper = () => output;
  3412. const output = {
  3413. tag: false,
  3414. inner: error,
  3415. fold: (onError, _onValue) => onError(error),
  3416. isValue: never,
  3417. isError: always,
  3418. map: outputHelper,
  3419. mapError: mapper => Result.error(mapper(error)),
  3420. bind: outputHelper,
  3421. exists: never,
  3422. forall: always,
  3423. getOr: identity,
  3424. or: identity,
  3425. getOrThunk: apply,
  3426. orThunk: apply,
  3427. getOrDie: die(String(error)),
  3428. each: noop,
  3429. toOptional: Optional.none
  3430. };
  3431. return output;
  3432. };
  3433. const fromOption = (optional, err) => optional.fold(() => error(err), value$1);
  3434. const Result = {
  3435. value: value$1,
  3436. error,
  3437. fromOption
  3438. };
  3439. const measure = (startAddress, gridA, gridB) => {
  3440. if (startAddress.row >= gridA.length || startAddress.column > cellLength(gridA[0])) {
  3441. return Result.error('invalid start address out of table bounds, row: ' + startAddress.row + ', column: ' + startAddress.column);
  3442. }
  3443. const rowRemainder = gridA.slice(startAddress.row);
  3444. const colRemainder = rowRemainder[0].cells.slice(startAddress.column);
  3445. const colRequired = cellLength(gridB[0]);
  3446. const rowRequired = gridB.length;
  3447. return Result.value({
  3448. rowDelta: rowRemainder.length - rowRequired,
  3449. colDelta: colRemainder.length - colRequired
  3450. });
  3451. };
  3452. const measureWidth = (gridA, gridB) => {
  3453. const colLengthA = cellLength(gridA[0]);
  3454. const colLengthB = cellLength(gridB[0]);
  3455. return {
  3456. rowDelta: 0,
  3457. colDelta: colLengthA - colLengthB
  3458. };
  3459. };
  3460. const measureHeight = (gridA, gridB) => {
  3461. const rowLengthA = gridA.length;
  3462. const rowLengthB = gridB.length;
  3463. return {
  3464. rowDelta: rowLengthA - rowLengthB,
  3465. colDelta: 0
  3466. };
  3467. };
  3468. const generateElements = (amount, row, generators, isLocked) => {
  3469. const generator = row.section === 'colgroup' ? generators.col : generators.cell;
  3470. return range$1(amount, idx => elementnew(generator(), true, isLocked(idx)));
  3471. };
  3472. const rowFill = (grid, amount, generators, lockedColumns) => {
  3473. const exampleRow = grid[grid.length - 1];
  3474. return grid.concat(range$1(amount, () => {
  3475. const generator = exampleRow.section === 'colgroup' ? generators.colgroup : generators.row;
  3476. const row = clone(exampleRow, generator, identity);
  3477. const elements = generateElements(row.cells.length, row, generators, idx => has$1(lockedColumns, idx.toString()));
  3478. return setCells(row, elements);
  3479. }));
  3480. };
  3481. const colFill = (grid, amount, generators, startIndex) => map$1(grid, row => {
  3482. const newChildren = generateElements(amount, row, generators, never);
  3483. return addCells(row, startIndex, newChildren);
  3484. });
  3485. const lockedColFill = (grid, generators, lockedColumns) => map$1(grid, row => {
  3486. return foldl(lockedColumns, (acc, colNum) => {
  3487. const newChild = generateElements(1, row, generators, always)[0];
  3488. return addCell(acc, colNum, newChild);
  3489. }, row);
  3490. });
  3491. const tailor = (gridA, delta, generators) => {
  3492. const fillCols = delta.colDelta < 0 ? colFill : identity;
  3493. const fillRows = delta.rowDelta < 0 ? rowFill : identity;
  3494. const lockedColumns = getLockedColumnsFromGrid(gridA);
  3495. const gridWidth = cellLength(gridA[0]);
  3496. const isLastColLocked = exists(lockedColumns, locked => locked === gridWidth - 1);
  3497. const modifiedCols = fillCols(gridA, Math.abs(delta.colDelta), generators, isLastColLocked ? gridWidth - 1 : gridWidth);
  3498. const newLockedColumns = getLockedColumnsFromGrid(modifiedCols);
  3499. return fillRows(modifiedCols, Math.abs(delta.rowDelta), generators, mapToObject(newLockedColumns, always));
  3500. };
  3501. const isSpanning = (grid, row, col, comparator) => {
  3502. const candidate = getCell(grid[row], col);
  3503. const matching = curry(comparator, candidate.element);
  3504. const currentRow = grid[row];
  3505. 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)));
  3506. };
  3507. const mergeTables = (startAddress, gridA, gridBRows, generator, comparator, lockedColumns) => {
  3508. const startRow = startAddress.row;
  3509. const startCol = startAddress.column;
  3510. const mergeHeight = gridBRows.length;
  3511. const mergeWidth = cellLength(gridBRows[0]);
  3512. const endRow = startRow + mergeHeight;
  3513. const endCol = startCol + mergeWidth + lockedColumns.length;
  3514. const lockedColumnObj = mapToObject(lockedColumns, always);
  3515. for (let r = startRow; r < endRow; r++) {
  3516. let skippedCol = 0;
  3517. for (let c = startCol; c < endCol; c++) {
  3518. if (lockedColumnObj[c]) {
  3519. skippedCol++;
  3520. continue;
  3521. }
  3522. if (isSpanning(gridA, r, c, comparator)) {
  3523. unmerge(gridA, getCellElement(gridA[r], c), comparator, generator.cell);
  3524. }
  3525. const gridBColIndex = c - startCol - skippedCol;
  3526. const newCell = getCell(gridBRows[r - startRow], gridBColIndex);
  3527. const newCellElm = newCell.element;
  3528. const replacement = generator.replace(newCellElm);
  3529. mutateCell(gridA[r], c, elementnew(replacement, true, newCell.isLocked));
  3530. }
  3531. }
  3532. return gridA;
  3533. };
  3534. const getValidStartAddress = (currentStartAddress, grid, lockedColumns) => {
  3535. const gridColLength = cellLength(grid[0]);
  3536. const adjustedRowAddress = extractGridDetails(grid).cols.length + currentStartAddress.row;
  3537. const possibleColAddresses = range$1(gridColLength - currentStartAddress.column, num => num + currentStartAddress.column);
  3538. const validColAddress = find$1(possibleColAddresses, num => forall(lockedColumns, col => col !== num)).getOr(gridColLength - 1);
  3539. return {
  3540. row: adjustedRowAddress,
  3541. column: validColAddress
  3542. };
  3543. };
  3544. const getLockedColumnsWithinBounds = (startAddress, rows, lockedColumns) => filter$2(lockedColumns, colNum => colNum >= startAddress.column && colNum <= cellLength(rows[0]) + startAddress.column);
  3545. const merge$1 = (startAddress, gridA, gridB, generator, comparator) => {
  3546. const lockedColumns = getLockedColumnsFromGrid(gridA);
  3547. const validStartAddress = getValidStartAddress(startAddress, gridA, lockedColumns);
  3548. const gridBRows = extractGridDetails(gridB).rows;
  3549. const lockedColumnsWithinBounds = getLockedColumnsWithinBounds(validStartAddress, gridBRows, lockedColumns);
  3550. const result = measure(validStartAddress, gridA, gridBRows);
  3551. return result.map(diff => {
  3552. const delta = {
  3553. ...diff,
  3554. colDelta: diff.colDelta - lockedColumnsWithinBounds.length
  3555. };
  3556. const fittedGrid = tailor(gridA, delta, generator);
  3557. const newLockedColumns = getLockedColumnsFromGrid(fittedGrid);
  3558. const newLockedColumnsWithinBounds = getLockedColumnsWithinBounds(validStartAddress, gridBRows, newLockedColumns);
  3559. return mergeTables(validStartAddress, fittedGrid, gridBRows, generator, comparator, newLockedColumnsWithinBounds);
  3560. });
  3561. };
  3562. const insertCols = (index, gridA, gridB, generator, comparator) => {
  3563. splitCols(gridA, index, comparator, generator.cell);
  3564. const delta = measureHeight(gridB, gridA);
  3565. const fittedNewGrid = tailor(gridB, delta, generator);
  3566. const secondDelta = measureHeight(gridA, fittedNewGrid);
  3567. const fittedOldGrid = tailor(gridA, secondDelta, generator);
  3568. return map$1(fittedOldGrid, (gridRow, i) => {
  3569. return addCells(gridRow, index, fittedNewGrid[i].cells);
  3570. });
  3571. };
  3572. const insertRows = (index, gridA, gridB, generator, comparator) => {
  3573. splitRows(gridA, index, comparator, generator.cell);
  3574. const locked = getLockedColumnsFromGrid(gridA);
  3575. const diff = measureWidth(gridA, gridB);
  3576. const delta = {
  3577. ...diff,
  3578. colDelta: diff.colDelta - locked.length
  3579. };
  3580. const fittedOldGrid = tailor(gridA, delta, generator);
  3581. const {
  3582. cols: oldCols,
  3583. rows: oldRows
  3584. } = extractGridDetails(fittedOldGrid);
  3585. const newLocked = getLockedColumnsFromGrid(fittedOldGrid);
  3586. const secondDiff = measureWidth(gridB, gridA);
  3587. const secondDelta = {
  3588. ...secondDiff,
  3589. colDelta: secondDiff.colDelta + newLocked.length
  3590. };
  3591. const fittedGridB = lockedColFill(gridB, generator, newLocked);
  3592. const fittedNewGrid = tailor(fittedGridB, secondDelta, generator);
  3593. return [
  3594. ...oldCols,
  3595. ...oldRows.slice(0, index),
  3596. ...fittedNewGrid,
  3597. ...oldRows.slice(index, oldRows.length)
  3598. ];
  3599. };
  3600. const cloneRow = (row, cloneCell, comparator, substitution) => clone(row, elem => substitution(elem, comparator), cloneCell);
  3601. const insertRowAt = (grid, index, example, comparator, substitution) => {
  3602. const {rows, cols} = extractGridDetails(grid);
  3603. const before = rows.slice(0, index);
  3604. const after = rows.slice(index);
  3605. const newRow = cloneRow(rows[example], (ex, c) => {
  3606. const withinSpan = index > 0 && index < rows.length && comparator(getCellElement(rows[index - 1], c), getCellElement(rows[index], c));
  3607. const ret = withinSpan ? getCell(rows[index], c) : elementnew(substitution(ex.element, comparator), true, ex.isLocked);
  3608. return ret;
  3609. }, comparator, substitution);
  3610. return [
  3611. ...cols,
  3612. ...before,
  3613. newRow,
  3614. ...after
  3615. ];
  3616. };
  3617. const getElementFor = (row, column, section, withinSpan, example, comparator, substitution) => {
  3618. if (section === 'colgroup' || !withinSpan) {
  3619. const cell = getCell(row, example);
  3620. return elementnew(substitution(cell.element, comparator), true, false);
  3621. } else {
  3622. return getCell(row, column);
  3623. }
  3624. };
  3625. const insertColumnAt = (grid, index, example, comparator, substitution) => map$1(grid, row => {
  3626. const withinSpan = index > 0 && index < cellLength(row) && comparator(getCellElement(row, index - 1), getCellElement(row, index));
  3627. const sub = getElementFor(row, index, row.section, withinSpan, example, comparator, substitution);
  3628. return addCell(row, index, sub);
  3629. });
  3630. const deleteColumnsAt = (grid, columns) => bind$2(grid, row => {
  3631. const existingCells = row.cells;
  3632. const cells = foldr(columns, (acc, column) => column >= 0 && column < acc.length ? acc.slice(0, column).concat(acc.slice(column + 1)) : acc, existingCells);
  3633. return cells.length > 0 ? [rowcells(row.element, cells, row.section, row.isNew)] : [];
  3634. });
  3635. const deleteRowsAt = (grid, start, finish) => {
  3636. const {rows, cols} = extractGridDetails(grid);
  3637. return [
  3638. ...cols,
  3639. ...rows.slice(0, start),
  3640. ...rows.slice(finish + 1)
  3641. ];
  3642. };
  3643. const notInStartRow = (grid, rowIndex, colIndex, comparator) => getCellElement(grid[rowIndex], colIndex) !== undefined && (rowIndex > 0 && comparator(getCellElement(grid[rowIndex - 1], colIndex), getCellElement(grid[rowIndex], colIndex)));
  3644. const notInStartColumn = (row, index, comparator) => index > 0 && comparator(getCellElement(row, index - 1), getCellElement(row, index));
  3645. const isDuplicatedCell = (grid, rowIndex, colIndex, comparator) => notInStartRow(grid, rowIndex, colIndex, comparator) || notInStartColumn(grid[rowIndex], colIndex, comparator);
  3646. const rowReplacerPredicate = (targetRow, columnHeaders) => {
  3647. const entireTableIsHeader = forall(columnHeaders, identity) && isHeaderCells(targetRow.cells);
  3648. return entireTableIsHeader ? always : (cell, _rowIndex, colIndex) => {
  3649. const type = name(cell.element);
  3650. return !(type === 'th' && columnHeaders[colIndex]);
  3651. };
  3652. };
  3653. const columnReplacePredicate = (targetColumn, rowHeaders) => {
  3654. const entireTableIsHeader = forall(rowHeaders, identity) && isHeaderCells(targetColumn);
  3655. return entireTableIsHeader ? always : (cell, rowIndex, _colIndex) => {
  3656. const type = name(cell.element);
  3657. return !(type === 'th' && rowHeaders[rowIndex]);
  3658. };
  3659. };
  3660. const determineScope = (applyScope, cell, newScope, isInHeader) => {
  3661. const hasSpan = scope => scope === 'row' ? hasRowspan(cell) : hasColspan(cell);
  3662. const getScope = scope => hasSpan(scope) ? `${ scope }group` : scope;
  3663. if (applyScope) {
  3664. return isHeaderCell(cell) ? getScope(newScope) : null;
  3665. } else if (isInHeader && isHeaderCell(cell)) {
  3666. const oppositeScope = newScope === 'row' ? 'col' : 'row';
  3667. return getScope(oppositeScope);
  3668. } else {
  3669. return null;
  3670. }
  3671. };
  3672. const rowScopeGenerator = (applyScope, columnHeaders) => (cell, rowIndex, columnIndex) => Optional.some(determineScope(applyScope, cell.element, 'col', columnHeaders[columnIndex]));
  3673. const columnScopeGenerator = (applyScope, rowHeaders) => (cell, rowIndex) => Optional.some(determineScope(applyScope, cell.element, 'row', rowHeaders[rowIndex]));
  3674. const replace = (cell, comparator, substitute) => elementnew(substitute(cell.element, comparator), true, cell.isLocked);
  3675. const replaceIn = (grid, targets, comparator, substitute, replacer, genScope, shouldReplace) => {
  3676. const isTarget = cell => {
  3677. return exists(targets, target => {
  3678. return comparator(cell.element, target.element);
  3679. });
  3680. };
  3681. return map$1(grid, (row, rowIndex) => {
  3682. return mapCells(row, (cell, colIndex) => {
  3683. if (isTarget(cell)) {
  3684. const newCell = shouldReplace(cell, rowIndex, colIndex) ? replacer(cell, comparator, substitute) : cell;
  3685. genScope(newCell, rowIndex, colIndex).each(scope => {
  3686. setOptions(newCell.element, { scope: Optional.from(scope) });
  3687. });
  3688. return newCell;
  3689. } else {
  3690. return cell;
  3691. }
  3692. });
  3693. });
  3694. };
  3695. const getColumnCells = (rows, columnIndex, comparator) => bind$2(rows, (row, i) => {
  3696. return isDuplicatedCell(rows, i, columnIndex, comparator) ? [] : [getCell(row, columnIndex)];
  3697. });
  3698. const getRowCells = (rows, rowIndex, comparator) => {
  3699. const targetRow = rows[rowIndex];
  3700. return bind$2(targetRow.cells, (item, i) => {
  3701. return isDuplicatedCell(rows, rowIndex, i, comparator) ? [] : [item];
  3702. });
  3703. };
  3704. const replaceColumns = (grid, indexes, applyScope, comparator, substitution) => {
  3705. const rows = extractGridDetails(grid).rows;
  3706. const targets = bind$2(indexes, index => getColumnCells(rows, index, comparator));
  3707. const rowHeaders = map$1(rows, row => isHeaderCells(row.cells));
  3708. const shouldReplaceCell = columnReplacePredicate(targets, rowHeaders);
  3709. const scopeGenerator = columnScopeGenerator(applyScope, rowHeaders);
  3710. return replaceIn(grid, targets, comparator, substitution, replace, scopeGenerator, shouldReplaceCell);
  3711. };
  3712. const replaceRows = (grid, indexes, section, applyScope, comparator, substitution, tableSection) => {
  3713. const {cols, rows} = extractGridDetails(grid);
  3714. const targetRow = rows[indexes[0]];
  3715. const targets = bind$2(indexes, index => getRowCells(rows, index, comparator));
  3716. const columnHeaders = map$1(targetRow.cells, (_cell, index) => isHeaderCells(getColumnCells(rows, index, comparator)));
  3717. const newRows = [...rows];
  3718. each$2(indexes, index => {
  3719. newRows[index] = tableSection.transformRow(rows[index], section);
  3720. });
  3721. const newGrid = [
  3722. ...cols,
  3723. ...newRows
  3724. ];
  3725. const shouldReplaceCell = rowReplacerPredicate(targetRow, columnHeaders);
  3726. const scopeGenerator = rowScopeGenerator(applyScope, columnHeaders);
  3727. return replaceIn(newGrid, targets, comparator, substitution, tableSection.transformCell, scopeGenerator, shouldReplaceCell);
  3728. };
  3729. const replaceCells = (grid, details, comparator, substitution) => {
  3730. const rows = extractGridDetails(grid).rows;
  3731. const targetCells = map$1(details, detail => getCell(rows[detail.row], detail.column));
  3732. return replaceIn(grid, targetCells, comparator, substitution, replace, Optional.none, always);
  3733. };
  3734. const generate = cases => {
  3735. if (!isArray(cases)) {
  3736. throw new Error('cases must be an array');
  3737. }
  3738. if (cases.length === 0) {
  3739. throw new Error('there must be at least one case');
  3740. }
  3741. const constructors = [];
  3742. const adt = {};
  3743. each$2(cases, (acase, count) => {
  3744. const keys$1 = keys(acase);
  3745. if (keys$1.length !== 1) {
  3746. throw new Error('one and only one name per case');
  3747. }
  3748. const key = keys$1[0];
  3749. const value = acase[key];
  3750. if (adt[key] !== undefined) {
  3751. throw new Error('duplicate key detected:' + key);
  3752. } else if (key === 'cata') {
  3753. throw new Error('cannot have a case named cata (sorry)');
  3754. } else if (!isArray(value)) {
  3755. throw new Error('case arguments must be an array');
  3756. }
  3757. constructors.push(key);
  3758. adt[key] = (...args) => {
  3759. const argLength = args.length;
  3760. if (argLength !== value.length) {
  3761. throw new Error('Wrong number of arguments to case ' + key + '. Expected ' + value.length + ' (' + value + '), got ' + argLength);
  3762. }
  3763. const match = branches => {
  3764. const branchKeys = keys(branches);
  3765. if (constructors.length !== branchKeys.length) {
  3766. throw new Error('Wrong number of arguments to match. Expected: ' + constructors.join(',') + '\nActual: ' + branchKeys.join(','));
  3767. }
  3768. const allReqd = forall(constructors, reqKey => {
  3769. return contains$2(branchKeys, reqKey);
  3770. });
  3771. if (!allReqd) {
  3772. throw new Error('Not all branches were specified when using match. Specified: ' + branchKeys.join(', ') + '\nRequired: ' + constructors.join(', '));
  3773. }
  3774. return branches[key].apply(null, args);
  3775. };
  3776. return {
  3777. fold: (...foldArgs) => {
  3778. if (foldArgs.length !== cases.length) {
  3779. throw new Error('Wrong number of arguments to fold. Expected ' + cases.length + ', got ' + foldArgs.length);
  3780. }
  3781. const target = foldArgs[count];
  3782. return target.apply(null, args);
  3783. },
  3784. match,
  3785. log: label => {
  3786. console.log(label, {
  3787. constructors,
  3788. constructor: key,
  3789. params: args
  3790. });
  3791. }
  3792. };
  3793. };
  3794. });
  3795. return adt;
  3796. };
  3797. const Adt = { generate };
  3798. const adt$6 = Adt.generate([
  3799. { none: [] },
  3800. { only: ['index'] },
  3801. {
  3802. left: [
  3803. 'index',
  3804. 'next'
  3805. ]
  3806. },
  3807. {
  3808. middle: [
  3809. 'prev',
  3810. 'index',
  3811. 'next'
  3812. ]
  3813. },
  3814. {
  3815. right: [
  3816. 'prev',
  3817. 'index'
  3818. ]
  3819. }
  3820. ]);
  3821. const ColumnContext = { ...adt$6 };
  3822. const neighbours = (input, index) => {
  3823. if (input.length === 0) {
  3824. return ColumnContext.none();
  3825. }
  3826. if (input.length === 1) {
  3827. return ColumnContext.only(0);
  3828. }
  3829. if (index === 0) {
  3830. return ColumnContext.left(0, 1);
  3831. }
  3832. if (index === input.length - 1) {
  3833. return ColumnContext.right(index - 1, index);
  3834. }
  3835. if (index > 0 && index < input.length - 1) {
  3836. return ColumnContext.middle(index - 1, index, index + 1);
  3837. }
  3838. return ColumnContext.none();
  3839. };
  3840. const determine = (input, column, step, tableSize, resize) => {
  3841. const result = input.slice(0);
  3842. const context = neighbours(input, column);
  3843. const onNone = constant(map$1(result, constant(0)));
  3844. const onOnly = index => tableSize.singleColumnWidth(result[index], step);
  3845. const onLeft = (index, next) => resize.calcLeftEdgeDeltas(result, index, next, step, tableSize.minCellWidth(), tableSize.isRelative);
  3846. const onMiddle = (prev, index, next) => resize.calcMiddleDeltas(result, prev, index, next, step, tableSize.minCellWidth(), tableSize.isRelative);
  3847. const onRight = (prev, index) => resize.calcRightEdgeDeltas(result, prev, index, step, tableSize.minCellWidth(), tableSize.isRelative);
  3848. return context.fold(onNone, onOnly, onLeft, onMiddle, onRight);
  3849. };
  3850. const total = (start, end, measures) => {
  3851. let r = 0;
  3852. for (let i = start; i < end; i++) {
  3853. r += measures[i] !== undefined ? measures[i] : 0;
  3854. }
  3855. return r;
  3856. };
  3857. const recalculateWidthForCells = (warehouse, widths) => {
  3858. const all = Warehouse.justCells(warehouse);
  3859. return map$1(all, cell => {
  3860. const width = total(cell.column, cell.column + cell.colspan, widths);
  3861. return {
  3862. element: cell.element,
  3863. width,
  3864. colspan: cell.colspan
  3865. };
  3866. });
  3867. };
  3868. const recalculateWidthForColumns = (warehouse, widths) => {
  3869. const groups = Warehouse.justColumns(warehouse);
  3870. return map$1(groups, (column, index) => ({
  3871. element: column.element,
  3872. width: widths[index],
  3873. colspan: column.colspan
  3874. }));
  3875. };
  3876. const recalculateHeightForCells = (warehouse, heights) => {
  3877. const all = Warehouse.justCells(warehouse);
  3878. return map$1(all, cell => {
  3879. const height = total(cell.row, cell.row + cell.rowspan, heights);
  3880. return {
  3881. element: cell.element,
  3882. height,
  3883. rowspan: cell.rowspan
  3884. };
  3885. });
  3886. };
  3887. const matchRowHeight = (warehouse, heights) => {
  3888. return map$1(warehouse.all, (row, i) => {
  3889. return {
  3890. element: row.element,
  3891. height: heights[i]
  3892. };
  3893. });
  3894. };
  3895. const sumUp = newSize => foldr(newSize, (b, a) => b + a, 0);
  3896. const recalculate = (warehouse, widths) => {
  3897. if (Warehouse.hasColumns(warehouse)) {
  3898. return recalculateWidthForColumns(warehouse, widths);
  3899. } else {
  3900. return recalculateWidthForCells(warehouse, widths);
  3901. }
  3902. };
  3903. const recalculateAndApply = (warehouse, widths, tableSize) => {
  3904. const newSizes = recalculate(warehouse, widths);
  3905. each$2(newSizes, cell => {
  3906. tableSize.setElementWidth(cell.element, cell.width);
  3907. });
  3908. };
  3909. const adjustWidth = (table, delta, index, resizing, tableSize) => {
  3910. const warehouse = Warehouse.fromTable(table);
  3911. const step = tableSize.getCellDelta(delta);
  3912. const widths = tableSize.getWidths(warehouse, tableSize);
  3913. const isLastColumn = index === warehouse.grid.columns - 1;
  3914. const clampedStep = resizing.clampTableDelta(widths, index, step, tableSize.minCellWidth(), isLastColumn);
  3915. const deltas = determine(widths, index, clampedStep, tableSize, resizing);
  3916. const newWidths = map$1(deltas, (dx, i) => dx + widths[i]);
  3917. recalculateAndApply(warehouse, newWidths, tableSize);
  3918. resizing.resizeTable(tableSize.adjustTableWidth, clampedStep, isLastColumn);
  3919. };
  3920. const adjustHeight = (table, delta, index, direction) => {
  3921. const warehouse = Warehouse.fromTable(table);
  3922. const heights = getPixelHeights(warehouse, table, direction);
  3923. const newHeights = map$1(heights, (dy, i) => index === i ? Math.max(delta + dy, minHeight()) : dy);
  3924. const newCellSizes = recalculateHeightForCells(warehouse, newHeights);
  3925. const newRowSizes = matchRowHeight(warehouse, newHeights);
  3926. each$2(newRowSizes, row => {
  3927. setHeight(row.element, row.height);
  3928. });
  3929. each$2(newCellSizes, cell => {
  3930. setHeight(cell.element, cell.height);
  3931. });
  3932. const total = sumUp(newHeights);
  3933. setHeight(table, total);
  3934. };
  3935. const adjustAndRedistributeWidths$1 = (_table, list, details, tableSize, resizeBehaviour) => {
  3936. const warehouse = Warehouse.generate(list);
  3937. const sizes = tableSize.getWidths(warehouse, tableSize);
  3938. const tablePixelWidth = tableSize.pixelWidth();
  3939. const {newSizes, delta} = resizeBehaviour.calcRedestributedWidths(sizes, tablePixelWidth, details.pixelDelta, tableSize.isRelative);
  3940. recalculateAndApply(warehouse, newSizes, tableSize);
  3941. tableSize.adjustTableWidth(delta);
  3942. };
  3943. const adjustWidthTo = (_table, list, _info, tableSize) => {
  3944. const warehouse = Warehouse.generate(list);
  3945. const widths = tableSize.getWidths(warehouse, tableSize);
  3946. recalculateAndApply(warehouse, widths, tableSize);
  3947. };
  3948. const uniqueColumns = details => {
  3949. const uniqueCheck = (rest, detail) => {
  3950. const columnExists = exists(rest, currentDetail => currentDetail.column === detail.column);
  3951. return columnExists ? rest : rest.concat([detail]);
  3952. };
  3953. return foldl(details, uniqueCheck, []).sort((detailA, detailB) => detailA.column - detailB.column);
  3954. };
  3955. const isCol = isTag('col');
  3956. const isColgroup = isTag('colgroup');
  3957. const isRow$1 = element => name(element) === 'tr' || isColgroup(element);
  3958. const elementToData = element => {
  3959. const colspan = getAttrValue(element, 'colspan', 1);
  3960. const rowspan = getAttrValue(element, 'rowspan', 1);
  3961. return {
  3962. element,
  3963. colspan,
  3964. rowspan
  3965. };
  3966. };
  3967. const modification = (generators, toData = elementToData) => {
  3968. const nuCell = data => isCol(data.element) ? generators.col(data) : generators.cell(data);
  3969. const nuRow = data => isColgroup(data.element) ? generators.colgroup(data) : generators.row(data);
  3970. const add = element => {
  3971. if (isRow$1(element)) {
  3972. return nuRow({ element });
  3973. } else {
  3974. const cell = element;
  3975. const replacement = nuCell(toData(cell));
  3976. recent = Optional.some({
  3977. item: cell,
  3978. replacement
  3979. });
  3980. return replacement;
  3981. }
  3982. };
  3983. let recent = Optional.none();
  3984. const getOrInit = (element, comparator) => {
  3985. return recent.fold(() => {
  3986. return add(element);
  3987. }, p => {
  3988. return comparator(element, p.item) ? p.replacement : add(element);
  3989. });
  3990. };
  3991. return { getOrInit };
  3992. };
  3993. const transform$1 = tag => {
  3994. return generators => {
  3995. const list = [];
  3996. const find = (element, comparator) => {
  3997. return find$1(list, x => {
  3998. return comparator(x.item, element);
  3999. });
  4000. };
  4001. const makeNew = element => {
  4002. const attrs = tag === 'td' ? { scope: null } : {};
  4003. const cell = generators.replace(element, tag, attrs);
  4004. list.push({
  4005. item: element,
  4006. sub: cell
  4007. });
  4008. return cell;
  4009. };
  4010. const replaceOrInit = (element, comparator) => {
  4011. if (isRow$1(element) || isCol(element)) {
  4012. return element;
  4013. } else {
  4014. const cell = element;
  4015. return find(cell, comparator).fold(() => {
  4016. return makeNew(cell);
  4017. }, p => {
  4018. return comparator(element, p.item) ? p.sub : makeNew(cell);
  4019. });
  4020. }
  4021. };
  4022. return { replaceOrInit };
  4023. };
  4024. };
  4025. const getScopeAttribute = cell => getOpt(cell, 'scope').map(attribute => attribute.substr(0, 3));
  4026. const merging = generators => {
  4027. const unmerge = cell => {
  4028. const scope = getScopeAttribute(cell);
  4029. scope.each(attribute => set$2(cell, 'scope', attribute));
  4030. return () => {
  4031. const raw = generators.cell({
  4032. element: cell,
  4033. colspan: 1,
  4034. rowspan: 1
  4035. });
  4036. remove$5(raw, 'width');
  4037. remove$5(cell, 'width');
  4038. scope.each(attribute => set$2(raw, 'scope', attribute));
  4039. return raw;
  4040. };
  4041. };
  4042. const merge = cells => {
  4043. const getScopeProperty = () => {
  4044. const stringAttributes = cat(map$1(cells, getScopeAttribute));
  4045. if (stringAttributes.length === 0) {
  4046. return Optional.none();
  4047. } else {
  4048. const baseScope = stringAttributes[0];
  4049. const scopes = [
  4050. 'row',
  4051. 'col'
  4052. ];
  4053. const isMixed = exists(stringAttributes, attribute => {
  4054. return attribute !== baseScope && contains$2(scopes, attribute);
  4055. });
  4056. return isMixed ? Optional.none() : Optional.from(baseScope);
  4057. }
  4058. };
  4059. remove$5(cells[0], 'width');
  4060. getScopeProperty().fold(() => remove$7(cells[0], 'scope'), attribute => set$2(cells[0], 'scope', attribute + 'group'));
  4061. return constant(cells[0]);
  4062. };
  4063. return {
  4064. unmerge,
  4065. merge
  4066. };
  4067. };
  4068. const Generators = {
  4069. modification,
  4070. transform: transform$1,
  4071. merging
  4072. };
  4073. const blockList = [
  4074. 'body',
  4075. 'p',
  4076. 'div',
  4077. 'article',
  4078. 'aside',
  4079. 'figcaption',
  4080. 'figure',
  4081. 'footer',
  4082. 'header',
  4083. 'nav',
  4084. 'section',
  4085. 'ol',
  4086. 'ul',
  4087. 'table',
  4088. 'thead',
  4089. 'tfoot',
  4090. 'tbody',
  4091. 'caption',
  4092. 'tr',
  4093. 'td',
  4094. 'th',
  4095. 'h1',
  4096. 'h2',
  4097. 'h3',
  4098. 'h4',
  4099. 'h5',
  4100. 'h6',
  4101. 'blockquote',
  4102. 'pre',
  4103. 'address'
  4104. ];
  4105. const isList$1 = (universe, item) => {
  4106. const tagName = universe.property().name(item);
  4107. return contains$2([
  4108. 'ol',
  4109. 'ul'
  4110. ], tagName);
  4111. };
  4112. const isBlock$1 = (universe, item) => {
  4113. const tagName = universe.property().name(item);
  4114. return contains$2(blockList, tagName);
  4115. };
  4116. const isEmptyTag$1 = (universe, item) => {
  4117. return contains$2([
  4118. 'br',
  4119. 'img',
  4120. 'hr',
  4121. 'input'
  4122. ], universe.property().name(item));
  4123. };
  4124. const universe$1 = DomUniverse();
  4125. const isBlock = element => {
  4126. return isBlock$1(universe$1, element);
  4127. };
  4128. const isList = element => {
  4129. return isList$1(universe$1, element);
  4130. };
  4131. const isEmptyTag = element => {
  4132. return isEmptyTag$1(universe$1, element);
  4133. };
  4134. const merge = cells => {
  4135. const isBr = isTag('br');
  4136. const advancedBr = children => {
  4137. return forall(children, c => {
  4138. return isBr(c) || isText(c) && get$6(c).trim().length === 0;
  4139. });
  4140. };
  4141. const isListItem = el => {
  4142. return name(el) === 'li' || ancestor$2(el, isList).isSome();
  4143. };
  4144. const siblingIsBlock = el => {
  4145. return nextSibling(el).map(rightSibling => {
  4146. if (isBlock(rightSibling)) {
  4147. return true;
  4148. }
  4149. if (isEmptyTag(rightSibling)) {
  4150. return name(rightSibling) === 'img' ? false : true;
  4151. }
  4152. return false;
  4153. }).getOr(false);
  4154. };
  4155. const markCell = cell => {
  4156. return last$1(cell).bind(rightEdge => {
  4157. const rightSiblingIsBlock = siblingIsBlock(rightEdge);
  4158. return parent(rightEdge).map(parent => {
  4159. return rightSiblingIsBlock === true || isListItem(parent) || isBr(rightEdge) || isBlock(parent) && !eq$1(cell, parent) ? [] : [SugarElement.fromTag('br')];
  4160. });
  4161. }).getOr([]);
  4162. };
  4163. const markContent = () => {
  4164. const content = bind$2(cells, cell => {
  4165. const children = children$2(cell);
  4166. return advancedBr(children) ? [] : children.concat(markCell(cell));
  4167. });
  4168. return content.length === 0 ? [SugarElement.fromTag('br')] : content;
  4169. };
  4170. const contents = markContent();
  4171. empty(cells[0]);
  4172. append(cells[0], contents);
  4173. };
  4174. const isEditable = elem => isEditable$1(elem, true);
  4175. const prune = table => {
  4176. const cells = cells$1(table);
  4177. if (cells.length === 0) {
  4178. remove$6(table);
  4179. }
  4180. };
  4181. const outcome = (grid, cursor) => ({
  4182. grid,
  4183. cursor
  4184. });
  4185. const findEditableCursorPosition = rows => findMap(rows, row => findMap(row.cells, cell => {
  4186. const elem = cell.element;
  4187. return someIf(isEditable(elem), elem);
  4188. }));
  4189. const elementFromGrid = (grid, row, column) => {
  4190. var _a, _b;
  4191. const rows = extractGridDetails(grid).rows;
  4192. 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));
  4193. };
  4194. const bundle = (grid, row, column) => {
  4195. const cursorElement = elementFromGrid(grid, row, column);
  4196. return outcome(grid, cursorElement);
  4197. };
  4198. const uniqueRows = details => {
  4199. const rowCompilation = (rest, detail) => {
  4200. const rowExists = exists(rest, currentDetail => currentDetail.row === detail.row);
  4201. return rowExists ? rest : rest.concat([detail]);
  4202. };
  4203. return foldl(details, rowCompilation, []).sort((detailA, detailB) => detailA.row - detailB.row);
  4204. };
  4205. const opInsertRowsBefore = (grid, details, comparator, genWrappers) => {
  4206. const targetIndex = details[0].row;
  4207. const rows = uniqueRows(details);
  4208. const newGrid = foldr(rows, (acc, row) => {
  4209. const newG = insertRowAt(acc.grid, targetIndex, row.row + acc.delta, comparator, genWrappers.getOrInit);
  4210. return {
  4211. grid: newG,
  4212. delta: acc.delta + 1
  4213. };
  4214. }, {
  4215. grid,
  4216. delta: 0
  4217. }).grid;
  4218. return bundle(newGrid, targetIndex, details[0].column);
  4219. };
  4220. const opInsertRowsAfter = (grid, details, comparator, genWrappers) => {
  4221. const rows = uniqueRows(details);
  4222. const target = rows[rows.length - 1];
  4223. const targetIndex = target.row + target.rowspan;
  4224. const newGrid = foldr(rows, (newG, row) => {
  4225. return insertRowAt(newG, targetIndex, row.row, comparator, genWrappers.getOrInit);
  4226. }, grid);
  4227. return bundle(newGrid, targetIndex, details[0].column);
  4228. };
  4229. const opInsertColumnsBefore = (grid, extractDetail, comparator, genWrappers) => {
  4230. const details = extractDetail.details;
  4231. const columns = uniqueColumns(details);
  4232. const targetIndex = columns[0].column;
  4233. const newGrid = foldr(columns, (acc, col) => {
  4234. const newG = insertColumnAt(acc.grid, targetIndex, col.column + acc.delta, comparator, genWrappers.getOrInit);
  4235. return {
  4236. grid: newG,
  4237. delta: acc.delta + 1
  4238. };
  4239. }, {
  4240. grid,
  4241. delta: 0
  4242. }).grid;
  4243. return bundle(newGrid, details[0].row, targetIndex);
  4244. };
  4245. const opInsertColumnsAfter = (grid, extractDetail, comparator, genWrappers) => {
  4246. const details = extractDetail.details;
  4247. const target = details[details.length - 1];
  4248. const targetIndex = target.column + target.colspan;
  4249. const columns = uniqueColumns(details);
  4250. const newGrid = foldr(columns, (newG, col) => {
  4251. return insertColumnAt(newG, targetIndex, col.column, comparator, genWrappers.getOrInit);
  4252. }, grid);
  4253. return bundle(newGrid, details[0].row, targetIndex);
  4254. };
  4255. const opMakeColumnsHeader = (initialGrid, details, comparator, genWrappers) => {
  4256. const columns = uniqueColumns(details);
  4257. const columnIndexes = map$1(columns, detail => detail.column);
  4258. const newGrid = replaceColumns(initialGrid, columnIndexes, true, comparator, genWrappers.replaceOrInit);
  4259. return bundle(newGrid, details[0].row, details[0].column);
  4260. };
  4261. const opMakeCellsHeader = (initialGrid, details, comparator, genWrappers) => {
  4262. const newGrid = replaceCells(initialGrid, details, comparator, genWrappers.replaceOrInit);
  4263. return bundle(newGrid, details[0].row, details[0].column);
  4264. };
  4265. const opUnmakeColumnsHeader = (initialGrid, details, comparator, genWrappers) => {
  4266. const columns = uniqueColumns(details);
  4267. const columnIndexes = map$1(columns, detail => detail.column);
  4268. const newGrid = replaceColumns(initialGrid, columnIndexes, false, comparator, genWrappers.replaceOrInit);
  4269. return bundle(newGrid, details[0].row, details[0].column);
  4270. };
  4271. const opUnmakeCellsHeader = (initialGrid, details, comparator, genWrappers) => {
  4272. const newGrid = replaceCells(initialGrid, details, comparator, genWrappers.replaceOrInit);
  4273. return bundle(newGrid, details[0].row, details[0].column);
  4274. };
  4275. const makeRowsSection = (section, applyScope) => (initialGrid, details, comparator, genWrappers, tableSection) => {
  4276. const rows = uniqueRows(details);
  4277. const rowIndexes = map$1(rows, detail => detail.row);
  4278. const newGrid = replaceRows(initialGrid, rowIndexes, section, applyScope, comparator, genWrappers.replaceOrInit, tableSection);
  4279. return bundle(newGrid, details[0].row, details[0].column);
  4280. };
  4281. const opMakeRowsHeader = makeRowsSection('thead', true);
  4282. const opMakeRowsBody = makeRowsSection('tbody', false);
  4283. const opMakeRowsFooter = makeRowsSection('tfoot', false);
  4284. const opEraseColumns = (grid, extractDetail, _comparator, _genWrappers) => {
  4285. const columns = uniqueColumns(extractDetail.details);
  4286. const newGrid = deleteColumnsAt(grid, map$1(columns, column => column.column));
  4287. const maxColIndex = newGrid.length > 0 ? newGrid[0].cells.length - 1 : 0;
  4288. return bundle(newGrid, columns[0].row, Math.min(columns[0].column, maxColIndex));
  4289. };
  4290. const opEraseRows = (grid, details, _comparator, _genWrappers) => {
  4291. const rows = uniqueRows(details);
  4292. const newGrid = deleteRowsAt(grid, rows[0].row, rows[rows.length - 1].row);
  4293. const maxRowIndex = newGrid.length > 0 ? newGrid.length - 1 : 0;
  4294. return bundle(newGrid, Math.min(details[0].row, maxRowIndex), details[0].column);
  4295. };
  4296. const opMergeCells = (grid, mergable, comparator, genWrappers) => {
  4297. const cells = mergable.cells;
  4298. merge(cells);
  4299. const newGrid = merge$2(grid, mergable.bounds, comparator, genWrappers.merge(cells));
  4300. return outcome(newGrid, Optional.from(cells[0]));
  4301. };
  4302. const opUnmergeCells = (grid, unmergable, comparator, genWrappers) => {
  4303. const unmerge$1 = (b, cell) => unmerge(b, cell, comparator, genWrappers.unmerge(cell));
  4304. const newGrid = foldr(unmergable, unmerge$1, grid);
  4305. return outcome(newGrid, Optional.from(unmergable[0]));
  4306. };
  4307. const opPasteCells = (grid, pasteDetails, comparator, _genWrappers) => {
  4308. const gridify = (table, generators) => {
  4309. const wh = Warehouse.fromTable(table);
  4310. return toGrid(wh, generators, true);
  4311. };
  4312. const gridB = gridify(pasteDetails.clipboard, pasteDetails.generators);
  4313. const startAddress = address(pasteDetails.row, pasteDetails.column);
  4314. const mergedGrid = merge$1(startAddress, grid, gridB, pasteDetails.generators, comparator);
  4315. return mergedGrid.fold(() => outcome(grid, Optional.some(pasteDetails.element)), newGrid => {
  4316. return bundle(newGrid, pasteDetails.row, pasteDetails.column);
  4317. });
  4318. };
  4319. const gridifyRows = (rows, generators, context) => {
  4320. const pasteDetails = fromPastedRows(rows, context.section);
  4321. const wh = Warehouse.generate(pasteDetails);
  4322. return toGrid(wh, generators, true);
  4323. };
  4324. const opPasteColsBefore = (grid, pasteDetails, comparator, _genWrappers) => {
  4325. const rows = extractGridDetails(grid).rows;
  4326. const index = pasteDetails.cells[0].column;
  4327. const context = rows[pasteDetails.cells[0].row];
  4328. const gridB = gridifyRows(pasteDetails.clipboard, pasteDetails.generators, context);
  4329. const mergedGrid = insertCols(index, grid, gridB, pasteDetails.generators, comparator);
  4330. return bundle(mergedGrid, pasteDetails.cells[0].row, pasteDetails.cells[0].column);
  4331. };
  4332. const opPasteColsAfter = (grid, pasteDetails, comparator, _genWrappers) => {
  4333. const rows = extractGridDetails(grid).rows;
  4334. const index = pasteDetails.cells[pasteDetails.cells.length - 1].column + pasteDetails.cells[pasteDetails.cells.length - 1].colspan;
  4335. const context = rows[pasteDetails.cells[0].row];
  4336. const gridB = gridifyRows(pasteDetails.clipboard, pasteDetails.generators, context);
  4337. const mergedGrid = insertCols(index, grid, gridB, pasteDetails.generators, comparator);
  4338. return bundle(mergedGrid, pasteDetails.cells[0].row, pasteDetails.cells[0].column);
  4339. };
  4340. const opPasteRowsBefore = (grid, pasteDetails, comparator, _genWrappers) => {
  4341. const rows = extractGridDetails(grid).rows;
  4342. const index = pasteDetails.cells[0].row;
  4343. const context = rows[index];
  4344. const gridB = gridifyRows(pasteDetails.clipboard, pasteDetails.generators, context);
  4345. const mergedGrid = insertRows(index, grid, gridB, pasteDetails.generators, comparator);
  4346. return bundle(mergedGrid, pasteDetails.cells[0].row, pasteDetails.cells[0].column);
  4347. };
  4348. const opPasteRowsAfter = (grid, pasteDetails, comparator, _genWrappers) => {
  4349. const rows = extractGridDetails(grid).rows;
  4350. const index = pasteDetails.cells[pasteDetails.cells.length - 1].row + pasteDetails.cells[pasteDetails.cells.length - 1].rowspan;
  4351. const context = rows[pasteDetails.cells[0].row];
  4352. const gridB = gridifyRows(pasteDetails.clipboard, pasteDetails.generators, context);
  4353. const mergedGrid = insertRows(index, grid, gridB, pasteDetails.generators, comparator);
  4354. return bundle(mergedGrid, pasteDetails.cells[0].row, pasteDetails.cells[0].column);
  4355. };
  4356. const opGetColumnsType = (table, target) => {
  4357. const house = Warehouse.fromTable(table);
  4358. const details = onCells(house, target);
  4359. return details.bind(selectedCells => {
  4360. const lastSelectedCell = selectedCells[selectedCells.length - 1];
  4361. const minColRange = selectedCells[0].column;
  4362. const maxColRange = lastSelectedCell.column + lastSelectedCell.colspan;
  4363. const selectedColumnCells = flatten(map$1(house.all, row => filter$2(row.cells, cell => cell.column >= minColRange && cell.column < maxColRange)));
  4364. return findCommonCellType(selectedColumnCells);
  4365. }).getOr('');
  4366. };
  4367. const opGetCellsType = (table, target) => {
  4368. const house = Warehouse.fromTable(table);
  4369. const details = onCells(house, target);
  4370. return details.bind(findCommonCellType).getOr('');
  4371. };
  4372. const opGetRowsType = (table, target) => {
  4373. const house = Warehouse.fromTable(table);
  4374. const details = onCells(house, target);
  4375. return details.bind(selectedCells => {
  4376. const lastSelectedCell = selectedCells[selectedCells.length - 1];
  4377. const minRowRange = selectedCells[0].row;
  4378. const maxRowRange = lastSelectedCell.row + lastSelectedCell.rowspan;
  4379. const selectedRows = house.all.slice(minRowRange, maxRowRange);
  4380. return findCommonRowType(selectedRows);
  4381. }).getOr('');
  4382. };
  4383. const resize = (table, list, details, behaviours) => adjustWidthTo(table, list, details, behaviours.sizing);
  4384. const adjustAndRedistributeWidths = (table, list, details, behaviours) => adjustAndRedistributeWidths$1(table, list, details, behaviours.sizing, behaviours.resize);
  4385. const firstColumnIsLocked = (_warehouse, details) => exists(details, detail => detail.column === 0 && detail.isLocked);
  4386. const lastColumnIsLocked = (warehouse, details) => exists(details, detail => detail.column + detail.colspan >= warehouse.grid.columns && detail.isLocked);
  4387. const getColumnsWidth = (warehouse, details) => {
  4388. const columns$1 = columns(warehouse);
  4389. const uniqueCols = uniqueColumns(details);
  4390. return foldl(uniqueCols, (acc, detail) => {
  4391. const column = columns$1[detail.column];
  4392. const colWidth = column.map(getOuter$2).getOr(0);
  4393. return acc + colWidth;
  4394. }, 0);
  4395. };
  4396. const insertColumnsExtractor = before => (warehouse, target) => onCells(warehouse, target).filter(details => {
  4397. const checkLocked = before ? firstColumnIsLocked : lastColumnIsLocked;
  4398. return !checkLocked(warehouse, details);
  4399. }).map(details => ({
  4400. details,
  4401. pixelDelta: getColumnsWidth(warehouse, details)
  4402. }));
  4403. const eraseColumnsExtractor = (warehouse, target) => onUnlockedCells(warehouse, target).map(details => ({
  4404. details,
  4405. pixelDelta: -getColumnsWidth(warehouse, details)
  4406. }));
  4407. const pasteColumnsExtractor = before => (warehouse, target) => onPasteByEditor(warehouse, target).filter(details => {
  4408. const checkLocked = before ? firstColumnIsLocked : lastColumnIsLocked;
  4409. return !checkLocked(warehouse, details.cells);
  4410. });
  4411. const headerCellGenerator = Generators.transform('th');
  4412. const bodyCellGenerator = Generators.transform('td');
  4413. const insertRowsBefore = run(opInsertRowsBefore, onCells, noop, noop, Generators.modification);
  4414. const insertRowsAfter = run(opInsertRowsAfter, onCells, noop, noop, Generators.modification);
  4415. const insertColumnsBefore = run(opInsertColumnsBefore, insertColumnsExtractor(true), adjustAndRedistributeWidths, noop, Generators.modification);
  4416. const insertColumnsAfter = run(opInsertColumnsAfter, insertColumnsExtractor(false), adjustAndRedistributeWidths, noop, Generators.modification);
  4417. const eraseColumns = run(opEraseColumns, eraseColumnsExtractor, adjustAndRedistributeWidths, prune, Generators.modification);
  4418. const eraseRows = run(opEraseRows, onCells, noop, prune, Generators.modification);
  4419. const makeColumnsHeader = run(opMakeColumnsHeader, onUnlockedCells, noop, noop, headerCellGenerator);
  4420. const unmakeColumnsHeader = run(opUnmakeColumnsHeader, onUnlockedCells, noop, noop, bodyCellGenerator);
  4421. const makeRowsHeader = run(opMakeRowsHeader, onUnlockedCells, noop, noop, headerCellGenerator);
  4422. const makeRowsBody = run(opMakeRowsBody, onUnlockedCells, noop, noop, bodyCellGenerator);
  4423. const makeRowsFooter = run(opMakeRowsFooter, onUnlockedCells, noop, noop, bodyCellGenerator);
  4424. const makeCellsHeader = run(opMakeCellsHeader, onUnlockedCells, noop, noop, headerCellGenerator);
  4425. const unmakeCellsHeader = run(opUnmakeCellsHeader, onUnlockedCells, noop, noop, bodyCellGenerator);
  4426. const mergeCells = run(opMergeCells, onUnlockedMergable, resize, noop, Generators.merging);
  4427. const unmergeCells = run(opUnmergeCells, onUnlockedUnmergable, resize, noop, Generators.merging);
  4428. const pasteCells = run(opPasteCells, onPaste, resize, noop, Generators.modification);
  4429. const pasteColsBefore = run(opPasteColsBefore, pasteColumnsExtractor(true), noop, noop, Generators.modification);
  4430. const pasteColsAfter = run(opPasteColsAfter, pasteColumnsExtractor(false), noop, noop, Generators.modification);
  4431. const pasteRowsBefore = run(opPasteRowsBefore, onPasteByEditor, noop, noop, Generators.modification);
  4432. const pasteRowsAfter = run(opPasteRowsAfter, onPasteByEditor, noop, noop, Generators.modification);
  4433. const getColumnsType = opGetColumnsType;
  4434. const getCellsType = opGetCellsType;
  4435. const getRowsType = opGetRowsType;
  4436. const fireNewRow = (editor, row) => editor.dispatch('NewRow', { node: row });
  4437. const fireNewCell = (editor, cell) => editor.dispatch('NewCell', { node: cell });
  4438. const fireTableModified = (editor, table, data) => {
  4439. editor.dispatch('TableModified', {
  4440. ...data,
  4441. table
  4442. });
  4443. };
  4444. const fireTableSelectionChange = (editor, cells, start, finish, otherCells) => {
  4445. editor.dispatch('TableSelectionChange', {
  4446. cells,
  4447. start,
  4448. finish,
  4449. otherCells
  4450. });
  4451. };
  4452. const fireTableSelectionClear = editor => {
  4453. editor.dispatch('TableSelectionClear');
  4454. };
  4455. const fireObjectResizeStart = (editor, target, width, height, origin) => {
  4456. editor.dispatch('ObjectResizeStart', {
  4457. target,
  4458. width,
  4459. height,
  4460. origin
  4461. });
  4462. };
  4463. const fireObjectResized = (editor, target, width, height, origin) => {
  4464. editor.dispatch('ObjectResized', {
  4465. target,
  4466. width,
  4467. height,
  4468. origin
  4469. });
  4470. };
  4471. const styleModified = {
  4472. structure: false,
  4473. style: true
  4474. };
  4475. const structureModified = {
  4476. structure: true,
  4477. style: false
  4478. };
  4479. const styleAndStructureModified = {
  4480. structure: true,
  4481. style: true
  4482. };
  4483. const option = name => editor => editor.options.get(name);
  4484. const defaultWidth = '100%';
  4485. const getPixelForcedWidth = editor => {
  4486. var _a;
  4487. const dom = editor.dom;
  4488. const parentBlock = (_a = dom.getParent(editor.selection.getStart(), dom.isBlock)) !== null && _a !== void 0 ? _a : editor.getBody();
  4489. return getInner(SugarElement.fromDom(parentBlock)) + 'px';
  4490. };
  4491. const determineDefaultTableStyles = (editor, defaultStyles) => {
  4492. if (isTableResponsiveForced(editor) || !shouldStyleWithCss(editor)) {
  4493. return defaultStyles;
  4494. } else if (isTablePixelsForced(editor)) {
  4495. return {
  4496. ...defaultStyles,
  4497. width: getPixelForcedWidth(editor)
  4498. };
  4499. } else {
  4500. return {
  4501. ...defaultStyles,
  4502. width: defaultWidth
  4503. };
  4504. }
  4505. };
  4506. const determineDefaultTableAttributes = (editor, defaultAttributes) => {
  4507. if (isTableResponsiveForced(editor) || shouldStyleWithCss(editor)) {
  4508. return defaultAttributes;
  4509. } else if (isTablePixelsForced(editor)) {
  4510. return {
  4511. ...defaultAttributes,
  4512. width: getPixelForcedWidth(editor)
  4513. };
  4514. } else {
  4515. return {
  4516. ...defaultAttributes,
  4517. width: defaultWidth
  4518. };
  4519. }
  4520. };
  4521. const register = editor => {
  4522. const registerOption = editor.options.register;
  4523. registerOption('table_clone_elements', { processor: 'string[]' });
  4524. registerOption('table_use_colgroups', {
  4525. processor: 'boolean',
  4526. default: true
  4527. });
  4528. registerOption('table_header_type', {
  4529. processor: value => {
  4530. const valid = contains$2([
  4531. 'section',
  4532. 'cells',
  4533. 'sectionCells',
  4534. 'auto'
  4535. ], value);
  4536. return valid ? {
  4537. value,
  4538. valid
  4539. } : {
  4540. valid: false,
  4541. message: 'Must be one of: section, cells, sectionCells or auto.'
  4542. };
  4543. },
  4544. default: 'section'
  4545. });
  4546. registerOption('table_sizing_mode', {
  4547. processor: 'string',
  4548. default: 'auto'
  4549. });
  4550. registerOption('table_default_attributes', {
  4551. processor: 'object',
  4552. default: { border: '1' }
  4553. });
  4554. registerOption('table_default_styles', {
  4555. processor: 'object',
  4556. default: { 'border-collapse': 'collapse' }
  4557. });
  4558. registerOption('table_column_resizing', {
  4559. processor: value => {
  4560. const valid = contains$2([
  4561. 'preservetable',
  4562. 'resizetable'
  4563. ], value);
  4564. return valid ? {
  4565. value,
  4566. valid
  4567. } : {
  4568. valid: false,
  4569. message: 'Must be preservetable, or resizetable.'
  4570. };
  4571. },
  4572. default: 'preservetable'
  4573. });
  4574. registerOption('table_resize_bars', {
  4575. processor: 'boolean',
  4576. default: true
  4577. });
  4578. registerOption('table_style_by_css', {
  4579. processor: 'boolean',
  4580. default: true
  4581. });
  4582. };
  4583. const getTableCloneElements = editor => {
  4584. return Optional.from(editor.options.get('table_clone_elements'));
  4585. };
  4586. const hasTableObjectResizing = editor => {
  4587. const objectResizing = editor.options.get('object_resizing');
  4588. return contains$2(objectResizing.split(','), 'table');
  4589. };
  4590. const getTableHeaderType = option('table_header_type');
  4591. const getTableColumnResizingBehaviour = option('table_column_resizing');
  4592. const isPreserveTableColumnResizing = editor => getTableColumnResizingBehaviour(editor) === 'preservetable';
  4593. const isResizeTableColumnResizing = editor => getTableColumnResizingBehaviour(editor) === 'resizetable';
  4594. const getTableSizingMode = option('table_sizing_mode');
  4595. const isTablePercentagesForced = editor => getTableSizingMode(editor) === 'relative';
  4596. const isTablePixelsForced = editor => getTableSizingMode(editor) === 'fixed';
  4597. const isTableResponsiveForced = editor => getTableSizingMode(editor) === 'responsive';
  4598. const hasTableResizeBars = option('table_resize_bars');
  4599. const shouldStyleWithCss = option('table_style_by_css');
  4600. const getTableDefaultAttributes = editor => {
  4601. const options = editor.options;
  4602. const defaultAttributes = options.get('table_default_attributes');
  4603. return options.isSet('table_default_attributes') ? defaultAttributes : determineDefaultTableAttributes(editor, defaultAttributes);
  4604. };
  4605. const getTableDefaultStyles = editor => {
  4606. const options = editor.options;
  4607. const defaultStyles = options.get('table_default_styles');
  4608. return options.isSet('table_default_styles') ? defaultStyles : determineDefaultTableStyles(editor, defaultStyles);
  4609. };
  4610. const tableUseColumnGroup = option('table_use_colgroups');
  4611. const get$5 = (editor, table) => {
  4612. if (isTablePercentagesForced(editor)) {
  4613. return TableSize.percentageSize(table);
  4614. } else if (isTablePixelsForced(editor)) {
  4615. return TableSize.pixelSize(table);
  4616. } else {
  4617. return TableSize.getTableSize(table);
  4618. }
  4619. };
  4620. const TableActions = (editor, resizeHandler, cellSelectionHandler) => {
  4621. const isTableBody = editor => name(getBody(editor)) === 'table';
  4622. const lastRowGuard = table => isTableBody(editor) === false || getGridSize(table).rows > 1;
  4623. const lastColumnGuard = table => isTableBody(editor) === false || getGridSize(table).columns > 1;
  4624. const cloneFormats = getTableCloneElements(editor);
  4625. const colMutationOp = isResizeTableColumnResizing(editor) ? noop : halve;
  4626. const getTableSectionType = table => {
  4627. switch (getTableHeaderType(editor)) {
  4628. case 'section':
  4629. return TableSection.section();
  4630. case 'sectionCells':
  4631. return TableSection.sectionCells();
  4632. case 'cells':
  4633. return TableSection.cells();
  4634. default:
  4635. return TableSection.getTableSectionType(table, 'section');
  4636. }
  4637. };
  4638. const setSelectionFromAction = (table, result) => result.cursor.fold(() => {
  4639. const cells = cells$1(table);
  4640. return head(cells).filter(inBody).map(firstCell => {
  4641. cellSelectionHandler.clearSelectedCells(table.dom);
  4642. const rng = editor.dom.createRng();
  4643. rng.selectNode(firstCell.dom);
  4644. editor.selection.setRng(rng);
  4645. set$2(firstCell, 'data-mce-selected', '1');
  4646. return rng;
  4647. });
  4648. }, cell => {
  4649. const des = freefallRtl(cell);
  4650. const rng = editor.dom.createRng();
  4651. rng.setStart(des.element.dom, des.offset);
  4652. rng.setEnd(des.element.dom, des.offset);
  4653. editor.selection.setRng(rng);
  4654. cellSelectionHandler.clearSelectedCells(table.dom);
  4655. return Optional.some(rng);
  4656. });
  4657. const execute = (operation, guard, mutate, effect) => (table, target, noEvents = false) => {
  4658. removeDataStyle(table);
  4659. const doc = SugarElement.fromDom(editor.getDoc());
  4660. const generators = cellOperations(mutate, doc, cloneFormats);
  4661. const behaviours = {
  4662. sizing: get$5(editor, table),
  4663. resize: isResizeTableColumnResizing(editor) ? resizeTable() : preserveTable(),
  4664. section: getTableSectionType(table)
  4665. };
  4666. return guard(table) ? operation(table, target, generators, behaviours).bind(result => {
  4667. resizeHandler.refresh(table.dom);
  4668. each$2(result.newRows, row => {
  4669. fireNewRow(editor, row.dom);
  4670. });
  4671. each$2(result.newCells, cell => {
  4672. fireNewCell(editor, cell.dom);
  4673. });
  4674. const range = setSelectionFromAction(table, result);
  4675. if (inBody(table)) {
  4676. removeDataStyle(table);
  4677. if (!noEvents) {
  4678. fireTableModified(editor, table.dom, effect);
  4679. }
  4680. }
  4681. return range.map(rng => ({
  4682. rng,
  4683. effect
  4684. }));
  4685. }) : Optional.none();
  4686. };
  4687. const deleteRow = execute(eraseRows, lastRowGuard, noop, structureModified);
  4688. const deleteColumn = execute(eraseColumns, lastColumnGuard, noop, structureModified);
  4689. const insertRowsBefore$1 = execute(insertRowsBefore, always, noop, structureModified);
  4690. const insertRowsAfter$1 = execute(insertRowsAfter, always, noop, structureModified);
  4691. const insertColumnsBefore$1 = execute(insertColumnsBefore, always, colMutationOp, structureModified);
  4692. const insertColumnsAfter$1 = execute(insertColumnsAfter, always, colMutationOp, structureModified);
  4693. const mergeCells$1 = execute(mergeCells, always, noop, structureModified);
  4694. const unmergeCells$1 = execute(unmergeCells, always, noop, structureModified);
  4695. const pasteColsBefore$1 = execute(pasteColsBefore, always, noop, structureModified);
  4696. const pasteColsAfter$1 = execute(pasteColsAfter, always, noop, structureModified);
  4697. const pasteRowsBefore$1 = execute(pasteRowsBefore, always, noop, structureModified);
  4698. const pasteRowsAfter$1 = execute(pasteRowsAfter, always, noop, structureModified);
  4699. const pasteCells$1 = execute(pasteCells, always, noop, styleAndStructureModified);
  4700. const makeCellsHeader$1 = execute(makeCellsHeader, always, noop, structureModified);
  4701. const unmakeCellsHeader$1 = execute(unmakeCellsHeader, always, noop, structureModified);
  4702. const makeColumnsHeader$1 = execute(makeColumnsHeader, always, noop, structureModified);
  4703. const unmakeColumnsHeader$1 = execute(unmakeColumnsHeader, always, noop, structureModified);
  4704. const makeRowsHeader$1 = execute(makeRowsHeader, always, noop, structureModified);
  4705. const makeRowsBody$1 = execute(makeRowsBody, always, noop, structureModified);
  4706. const makeRowsFooter$1 = execute(makeRowsFooter, always, noop, structureModified);
  4707. const getTableCellType = getCellsType;
  4708. const getTableColType = getColumnsType;
  4709. const getTableRowType = getRowsType;
  4710. return {
  4711. deleteRow,
  4712. deleteColumn,
  4713. insertRowsBefore: insertRowsBefore$1,
  4714. insertRowsAfter: insertRowsAfter$1,
  4715. insertColumnsBefore: insertColumnsBefore$1,
  4716. insertColumnsAfter: insertColumnsAfter$1,
  4717. mergeCells: mergeCells$1,
  4718. unmergeCells: unmergeCells$1,
  4719. pasteColsBefore: pasteColsBefore$1,
  4720. pasteColsAfter: pasteColsAfter$1,
  4721. pasteRowsBefore: pasteRowsBefore$1,
  4722. pasteRowsAfter: pasteRowsAfter$1,
  4723. pasteCells: pasteCells$1,
  4724. makeCellsHeader: makeCellsHeader$1,
  4725. unmakeCellsHeader: unmakeCellsHeader$1,
  4726. makeColumnsHeader: makeColumnsHeader$1,
  4727. unmakeColumnsHeader: unmakeColumnsHeader$1,
  4728. makeRowsHeader: makeRowsHeader$1,
  4729. makeRowsBody: makeRowsBody$1,
  4730. makeRowsFooter: makeRowsFooter$1,
  4731. getTableRowType,
  4732. getTableCellType,
  4733. getTableColType
  4734. };
  4735. };
  4736. const constrainSpan = (element, property, value) => {
  4737. const currentColspan = getAttrValue(element, property, 1);
  4738. if (value === 1 || currentColspan <= 1) {
  4739. remove$7(element, property);
  4740. } else {
  4741. set$2(element, property, Math.min(value, currentColspan));
  4742. }
  4743. };
  4744. const isColInRange = (minColRange, maxColRange) => cell => {
  4745. const endCol = cell.column + cell.colspan - 1;
  4746. const startCol = cell.column;
  4747. return endCol >= minColRange && startCol < maxColRange;
  4748. };
  4749. const generateColGroup = (house, minColRange, maxColRange) => {
  4750. if (Warehouse.hasColumns(house)) {
  4751. const colsToCopy = filter$2(Warehouse.justColumns(house), isColInRange(minColRange, maxColRange));
  4752. const copiedCols = map$1(colsToCopy, c => {
  4753. const clonedCol = deep(c.element);
  4754. constrainSpan(clonedCol, 'span', maxColRange - minColRange);
  4755. return clonedCol;
  4756. });
  4757. const fakeColgroup = SugarElement.fromTag('colgroup');
  4758. append(fakeColgroup, copiedCols);
  4759. return [fakeColgroup];
  4760. } else {
  4761. return [];
  4762. }
  4763. };
  4764. const generateRows = (house, minColRange, maxColRange) => map$1(house.all, row => {
  4765. const cellsToCopy = filter$2(row.cells, isColInRange(minColRange, maxColRange));
  4766. const copiedCells = map$1(cellsToCopy, cell => {
  4767. const clonedCell = deep(cell.element);
  4768. constrainSpan(clonedCell, 'colspan', maxColRange - minColRange);
  4769. return clonedCell;
  4770. });
  4771. const fakeTR = SugarElement.fromTag('tr');
  4772. append(fakeTR, copiedCells);
  4773. return fakeTR;
  4774. });
  4775. const copyCols = (table, target) => {
  4776. const house = Warehouse.fromTable(table);
  4777. const details = onUnlockedCells(house, target);
  4778. return details.map(selectedCells => {
  4779. const lastSelectedCell = selectedCells[selectedCells.length - 1];
  4780. const minColRange = selectedCells[0].column;
  4781. const maxColRange = lastSelectedCell.column + lastSelectedCell.colspan;
  4782. const fakeColGroups = generateColGroup(house, minColRange, maxColRange);
  4783. const fakeRows = generateRows(house, minColRange, maxColRange);
  4784. return [
  4785. ...fakeColGroups,
  4786. ...fakeRows
  4787. ];
  4788. });
  4789. };
  4790. const copyRows = (table, target, generators) => {
  4791. const warehouse = Warehouse.fromTable(table);
  4792. const details = onCells(warehouse, target);
  4793. return details.bind(selectedCells => {
  4794. const grid = toGrid(warehouse, generators, false);
  4795. const rows = extractGridDetails(grid).rows;
  4796. const slicedGrid = rows.slice(selectedCells[0].row, selectedCells[selectedCells.length - 1].row + selectedCells[selectedCells.length - 1].rowspan);
  4797. const filteredGrid = bind$2(slicedGrid, row => {
  4798. const newCells = filter$2(row.cells, cell => !cell.isLocked);
  4799. return newCells.length > 0 ? [{
  4800. ...row,
  4801. cells: newCells
  4802. }] : [];
  4803. });
  4804. const slicedDetails = toDetailList(filteredGrid);
  4805. return someIf(slicedDetails.length > 0, slicedDetails);
  4806. }).map(slicedDetails => copy(slicedDetails));
  4807. };
  4808. const adt$5 = Adt.generate([
  4809. { invalid: ['raw'] },
  4810. { pixels: ['value'] },
  4811. { percent: ['value'] }
  4812. ]);
  4813. const validateFor = (suffix, type, value) => {
  4814. const rawAmount = value.substring(0, value.length - suffix.length);
  4815. const amount = parseFloat(rawAmount);
  4816. return rawAmount === amount.toString() ? type(amount) : adt$5.invalid(value);
  4817. };
  4818. const from = value => {
  4819. if (endsWith(value, '%')) {
  4820. return validateFor('%', adt$5.percent, value);
  4821. }
  4822. if (endsWith(value, 'px')) {
  4823. return validateFor('px', adt$5.pixels, value);
  4824. }
  4825. return adt$5.invalid(value);
  4826. };
  4827. const Size = {
  4828. ...adt$5,
  4829. from
  4830. };
  4831. const redistributeToPercent = (widths, totalWidth) => {
  4832. return map$1(widths, w => {
  4833. const colType = Size.from(w);
  4834. return colType.fold(() => {
  4835. return w;
  4836. }, px => {
  4837. const ratio = px / totalWidth * 100;
  4838. return ratio + '%';
  4839. }, pc => {
  4840. return pc + '%';
  4841. });
  4842. });
  4843. };
  4844. const redistributeToPx = (widths, totalWidth, newTotalWidth) => {
  4845. const scale = newTotalWidth / totalWidth;
  4846. return map$1(widths, w => {
  4847. const colType = Size.from(w);
  4848. return colType.fold(() => {
  4849. return w;
  4850. }, px => {
  4851. return px * scale + 'px';
  4852. }, pc => {
  4853. return pc / 100 * newTotalWidth + 'px';
  4854. });
  4855. });
  4856. };
  4857. const redistributeEmpty = (newWidthType, columns) => {
  4858. const f = newWidthType.fold(() => constant(''), pixels => {
  4859. const num = pixels / columns;
  4860. return constant(num + 'px');
  4861. }, () => {
  4862. const num = 100 / columns;
  4863. return constant(num + '%');
  4864. });
  4865. return range$1(columns, f);
  4866. };
  4867. const redistributeValues = (newWidthType, widths, totalWidth) => {
  4868. return newWidthType.fold(() => {
  4869. return widths;
  4870. }, px => {
  4871. return redistributeToPx(widths, totalWidth, px);
  4872. }, _pc => {
  4873. return redistributeToPercent(widths, totalWidth);
  4874. });
  4875. };
  4876. const redistribute$1 = (widths, totalWidth, newWidth) => {
  4877. const newType = Size.from(newWidth);
  4878. const floats = forall(widths, s => {
  4879. return s === '0px';
  4880. }) ? redistributeEmpty(newType, widths.length) : redistributeValues(newType, widths, totalWidth);
  4881. return normalize(floats);
  4882. };
  4883. const sum = (values, fallback) => {
  4884. if (values.length === 0) {
  4885. return fallback;
  4886. }
  4887. return foldr(values, (rest, v) => {
  4888. return Size.from(v).fold(constant(0), identity, identity) + rest;
  4889. }, 0);
  4890. };
  4891. const roundDown = (num, unit) => {
  4892. const floored = Math.floor(num);
  4893. return {
  4894. value: floored + unit,
  4895. remainder: num - floored
  4896. };
  4897. };
  4898. const add$3 = (value, amount) => {
  4899. return Size.from(value).fold(constant(value), px => {
  4900. return px + amount + 'px';
  4901. }, pc => {
  4902. return pc + amount + '%';
  4903. });
  4904. };
  4905. const normalize = values => {
  4906. if (values.length === 0) {
  4907. return values;
  4908. }
  4909. const scan = foldr(values, (rest, value) => {
  4910. const info = Size.from(value).fold(() => ({
  4911. value,
  4912. remainder: 0
  4913. }), num => roundDown(num, 'px'), num => ({
  4914. value: num + '%',
  4915. remainder: 0
  4916. }));
  4917. return {
  4918. output: [info.value].concat(rest.output),
  4919. remainder: rest.remainder + info.remainder
  4920. };
  4921. }, {
  4922. output: [],
  4923. remainder: 0
  4924. });
  4925. const r = scan.output;
  4926. return r.slice(0, r.length - 1).concat([add$3(r[r.length - 1], Math.round(scan.remainder))]);
  4927. };
  4928. const validate = Size.from;
  4929. const redistributeToW = (newWidths, cells, unit) => {
  4930. each$2(cells, cell => {
  4931. const widths = newWidths.slice(cell.column, cell.colspan + cell.column);
  4932. const w = sum(widths, minWidth());
  4933. set$1(cell.element, 'width', w + unit);
  4934. });
  4935. };
  4936. const redistributeToColumns = (newWidths, columns, unit) => {
  4937. each$2(columns, (column, index) => {
  4938. const width = sum([newWidths[index]], minWidth());
  4939. set$1(column.element, 'width', width + unit);
  4940. });
  4941. };
  4942. const redistributeToH = (newHeights, rows, cells, unit) => {
  4943. each$2(cells, cell => {
  4944. const heights = newHeights.slice(cell.row, cell.rowspan + cell.row);
  4945. const h = sum(heights, minHeight());
  4946. set$1(cell.element, 'height', h + unit);
  4947. });
  4948. each$2(rows, (row, i) => {
  4949. set$1(row.element, 'height', newHeights[i]);
  4950. });
  4951. };
  4952. const getUnit = newSize => {
  4953. return validate(newSize).fold(constant('px'), constant('px'), constant('%'));
  4954. };
  4955. const redistribute = (table, optWidth, optHeight) => {
  4956. const warehouse = Warehouse.fromTable(table);
  4957. const rows = warehouse.all;
  4958. const cells = Warehouse.justCells(warehouse);
  4959. const columns = Warehouse.justColumns(warehouse);
  4960. optWidth.each(newWidth => {
  4961. const widthUnit = getUnit(newWidth);
  4962. const totalWidth = get$9(table);
  4963. const oldWidths = getRawWidths(warehouse, table);
  4964. const nuWidths = redistribute$1(oldWidths, totalWidth, newWidth);
  4965. if (Warehouse.hasColumns(warehouse)) {
  4966. redistributeToColumns(nuWidths, columns, widthUnit);
  4967. } else {
  4968. redistributeToW(nuWidths, cells, widthUnit);
  4969. }
  4970. set$1(table, 'width', newWidth);
  4971. });
  4972. optHeight.each(newHeight => {
  4973. const hUnit = getUnit(newHeight);
  4974. const totalHeight = get$8(table);
  4975. const oldHeights = getRawHeights(warehouse, table, height);
  4976. const nuHeights = redistribute$1(oldHeights, totalHeight, newHeight);
  4977. redistributeToH(nuHeights, rows, cells, hUnit);
  4978. set$1(table, 'height', newHeight);
  4979. });
  4980. };
  4981. const isPercentSizing = isPercentSizing$1;
  4982. const isPixelSizing = isPixelSizing$1;
  4983. const isNoneSizing = isNoneSizing$1;
  4984. const cleanupLegacyAttributes = element => {
  4985. remove$7(element, 'width');
  4986. };
  4987. const convertToPercentSize = table => {
  4988. const newWidth = getPercentTableWidth(table);
  4989. redistribute(table, Optional.some(newWidth), Optional.none());
  4990. cleanupLegacyAttributes(table);
  4991. };
  4992. const convertToPixelSize = table => {
  4993. const newWidth = getPixelTableWidth(table);
  4994. redistribute(table, Optional.some(newWidth), Optional.none());
  4995. cleanupLegacyAttributes(table);
  4996. };
  4997. const convertToNoneSize = table => {
  4998. remove$5(table, 'width');
  4999. const columns = columns$1(table);
  5000. const rowElements = columns.length > 0 ? columns : cells$1(table);
  5001. each$2(rowElements, cell => {
  5002. remove$5(cell, 'width');
  5003. cleanupLegacyAttributes(cell);
  5004. });
  5005. cleanupLegacyAttributes(table);
  5006. };
  5007. const DefaultRenderOptions = {
  5008. styles: {
  5009. 'border-collapse': 'collapse',
  5010. 'width': '100%'
  5011. },
  5012. attributes: { border: '1' },
  5013. colGroups: false
  5014. };
  5015. const tableHeaderCell = () => SugarElement.fromTag('th');
  5016. const tableCell = () => SugarElement.fromTag('td');
  5017. const tableColumn = () => SugarElement.fromTag('col');
  5018. const createRow = (columns, rowHeaders, columnHeaders, rowIndex) => {
  5019. const tr = SugarElement.fromTag('tr');
  5020. for (let j = 0; j < columns; j++) {
  5021. const td = rowIndex < rowHeaders || j < columnHeaders ? tableHeaderCell() : tableCell();
  5022. if (j < columnHeaders) {
  5023. set$2(td, 'scope', 'row');
  5024. }
  5025. if (rowIndex < rowHeaders) {
  5026. set$2(td, 'scope', 'col');
  5027. }
  5028. append$1(td, SugarElement.fromTag('br'));
  5029. append$1(tr, td);
  5030. }
  5031. return tr;
  5032. };
  5033. const createGroupRow = columns => {
  5034. const columnGroup = SugarElement.fromTag('colgroup');
  5035. range$1(columns, () => append$1(columnGroup, tableColumn()));
  5036. return columnGroup;
  5037. };
  5038. const createRows = (rows, columns, rowHeaders, columnHeaders) => range$1(rows, r => createRow(columns, rowHeaders, columnHeaders, r));
  5039. const render = (rows, columns, rowHeaders, columnHeaders, headerType, renderOpts = DefaultRenderOptions) => {
  5040. const table = SugarElement.fromTag('table');
  5041. const rowHeadersGoInThead = headerType !== 'cells';
  5042. setAll(table, renderOpts.styles);
  5043. setAll$1(table, renderOpts.attributes);
  5044. if (renderOpts.colGroups) {
  5045. append$1(table, createGroupRow(columns));
  5046. }
  5047. const actualRowHeaders = Math.min(rows, rowHeaders);
  5048. if (rowHeadersGoInThead && rowHeaders > 0) {
  5049. const thead = SugarElement.fromTag('thead');
  5050. append$1(table, thead);
  5051. const theadRowHeaders = headerType === 'sectionCells' ? actualRowHeaders : 0;
  5052. const theadRows = createRows(rowHeaders, columns, theadRowHeaders, columnHeaders);
  5053. append(thead, theadRows);
  5054. }
  5055. const tbody = SugarElement.fromTag('tbody');
  5056. append$1(table, tbody);
  5057. const numRows = rowHeadersGoInThead ? rows - actualRowHeaders : rows;
  5058. const numRowHeaders = rowHeadersGoInThead ? 0 : rowHeaders;
  5059. const tbodyRows = createRows(numRows, columns, numRowHeaders, columnHeaders);
  5060. append(tbody, tbodyRows);
  5061. return table;
  5062. };
  5063. const get$4 = element => element.dom.innerHTML;
  5064. const getOuter = element => {
  5065. const container = SugarElement.fromTag('div');
  5066. const clone = SugarElement.fromDom(element.dom.cloneNode(true));
  5067. append$1(container, clone);
  5068. return get$4(container);
  5069. };
  5070. const placeCaretInCell = (editor, cell) => {
  5071. editor.selection.select(cell.dom, true);
  5072. editor.selection.collapse(true);
  5073. };
  5074. const selectFirstCellInTable = (editor, tableElm) => {
  5075. descendant(tableElm, 'td,th').each(curry(placeCaretInCell, editor));
  5076. };
  5077. const fireEvents = (editor, table) => {
  5078. each$2(descendants(table, 'tr'), row => {
  5079. fireNewRow(editor, row.dom);
  5080. each$2(descendants(row, 'th,td'), cell => {
  5081. fireNewCell(editor, cell.dom);
  5082. });
  5083. });
  5084. };
  5085. const isPercentage = width => isString(width) && width.indexOf('%') !== -1;
  5086. const insert = (editor, columns, rows, colHeaders, rowHeaders) => {
  5087. const defaultStyles = getTableDefaultStyles(editor);
  5088. const options = {
  5089. styles: defaultStyles,
  5090. attributes: getTableDefaultAttributes(editor),
  5091. colGroups: tableUseColumnGroup(editor)
  5092. };
  5093. editor.undoManager.ignore(() => {
  5094. const table = render(rows, columns, rowHeaders, colHeaders, getTableHeaderType(editor), options);
  5095. set$2(table, 'data-mce-id', '__mce');
  5096. const html = getOuter(table);
  5097. editor.insertContent(html);
  5098. editor.addVisual();
  5099. });
  5100. return descendant(getBody(editor), 'table[data-mce-id="__mce"]').map(table => {
  5101. if (isTablePixelsForced(editor)) {
  5102. convertToPixelSize(table);
  5103. } else if (isTableResponsiveForced(editor)) {
  5104. convertToNoneSize(table);
  5105. } else if (isTablePercentagesForced(editor) || isPercentage(defaultStyles.width)) {
  5106. convertToPercentSize(table);
  5107. }
  5108. removeDataStyle(table);
  5109. remove$7(table, 'data-mce-id');
  5110. fireEvents(editor, table);
  5111. selectFirstCellInTable(editor, table);
  5112. return table.dom;
  5113. }).getOr(null);
  5114. };
  5115. const insertTable = (editor, rows, columns, options = {}) => {
  5116. const checkInput = val => isNumber(val) && val > 0;
  5117. if (checkInput(rows) && checkInput(columns)) {
  5118. const headerRows = options.headerRows || 0;
  5119. const headerColumns = options.headerColumns || 0;
  5120. return insert(editor, columns, rows, headerColumns, headerRows);
  5121. } else {
  5122. console.error('Invalid values for mceInsertTable - rows and columns values are required to insert a table.');
  5123. return null;
  5124. }
  5125. };
  5126. var global = tinymce.util.Tools.resolve('tinymce.FakeClipboard');
  5127. const tableTypeBase = 'x-tinymce/dom-table-';
  5128. const tableTypeRow = tableTypeBase + 'rows';
  5129. const tableTypeColumn = tableTypeBase + 'columns';
  5130. const setData = items => {
  5131. const fakeClipboardItem = global.FakeClipboardItem(items);
  5132. global.write([fakeClipboardItem]);
  5133. };
  5134. const getData = type => {
  5135. var _a;
  5136. const items = (_a = global.read()) !== null && _a !== void 0 ? _a : [];
  5137. return findMap(items, item => Optional.from(item.getType(type)));
  5138. };
  5139. const clearData = type => {
  5140. if (getData(type).isSome()) {
  5141. global.clear();
  5142. }
  5143. };
  5144. const setRows = rowsOpt => {
  5145. rowsOpt.fold(clearRows, rows => setData({ [tableTypeRow]: rows }));
  5146. };
  5147. const getRows = () => getData(tableTypeRow);
  5148. const clearRows = () => clearData(tableTypeRow);
  5149. const setColumns = columnsOpt => {
  5150. columnsOpt.fold(clearColumns, columns => setData({ [tableTypeColumn]: columns }));
  5151. };
  5152. const getColumns = () => getData(tableTypeColumn);
  5153. const clearColumns = () => clearData(tableTypeColumn);
  5154. const getSelectionStartCellOrCaption = editor => getSelectionCellOrCaption(getSelectionStart(editor), getIsRoot(editor));
  5155. const getSelectionStartCell = editor => getSelectionCell(getSelectionStart(editor), getIsRoot(editor));
  5156. const registerCommands = (editor, actions) => {
  5157. const isRoot = getIsRoot(editor);
  5158. const eraseTable = () => getSelectionStartCellOrCaption(editor).each(cellOrCaption => {
  5159. table(cellOrCaption, isRoot).filter(not(isRoot)).each(table => {
  5160. const cursor = SugarElement.fromText('');
  5161. after$5(table, cursor);
  5162. remove$6(table);
  5163. if (editor.dom.isEmpty(editor.getBody())) {
  5164. editor.setContent('');
  5165. editor.selection.setCursorLocation();
  5166. } else {
  5167. const rng = editor.dom.createRng();
  5168. rng.setStart(cursor.dom, 0);
  5169. rng.setEnd(cursor.dom, 0);
  5170. editor.selection.setRng(rng);
  5171. editor.nodeChanged();
  5172. }
  5173. });
  5174. });
  5175. const setSizingMode = sizing => getSelectionStartCellOrCaption(editor).each(cellOrCaption => {
  5176. const isForcedSizing = isTableResponsiveForced(editor) || isTablePixelsForced(editor) || isTablePercentagesForced(editor);
  5177. if (!isForcedSizing) {
  5178. table(cellOrCaption, isRoot).each(table => {
  5179. if (sizing === 'relative' && !isPercentSizing(table)) {
  5180. convertToPercentSize(table);
  5181. } else if (sizing === 'fixed' && !isPixelSizing(table)) {
  5182. convertToPixelSize(table);
  5183. } else if (sizing === 'responsive' && !isNoneSizing(table)) {
  5184. convertToNoneSize(table);
  5185. }
  5186. removeDataStyle(table);
  5187. fireTableModified(editor, table.dom, structureModified);
  5188. });
  5189. }
  5190. });
  5191. const getTableFromCell = cell => table(cell, isRoot);
  5192. const performActionOnSelection = action => getSelectionStartCell(editor).bind(cell => getTableFromCell(cell).map(table => action(table, cell)));
  5193. const toggleTableClass = (_ui, clazz) => {
  5194. performActionOnSelection(table => {
  5195. editor.formatter.toggle('tableclass', { value: clazz }, table.dom);
  5196. fireTableModified(editor, table.dom, styleModified);
  5197. });
  5198. };
  5199. const toggleTableCellClass = (_ui, clazz) => {
  5200. performActionOnSelection(table => {
  5201. const selectedCells = getCellsFromSelection(editor);
  5202. const allHaveClass = forall(selectedCells, cell => editor.formatter.match('tablecellclass', { value: clazz }, cell.dom));
  5203. const formatterAction = allHaveClass ? editor.formatter.remove : editor.formatter.apply;
  5204. each$2(selectedCells, cell => formatterAction('tablecellclass', { value: clazz }, cell.dom));
  5205. fireTableModified(editor, table.dom, styleModified);
  5206. });
  5207. };
  5208. const toggleCaption = () => {
  5209. getSelectionStartCellOrCaption(editor).each(cellOrCaption => {
  5210. table(cellOrCaption, isRoot).each(table => {
  5211. child(table, 'caption').fold(() => {
  5212. const caption = SugarElement.fromTag('caption');
  5213. append$1(caption, SugarElement.fromText('Caption'));
  5214. appendAt(table, caption, 0);
  5215. editor.selection.setCursorLocation(caption.dom, 0);
  5216. }, caption => {
  5217. if (isTag('caption')(cellOrCaption)) {
  5218. one('td', table).each(td => editor.selection.setCursorLocation(td.dom, 0));
  5219. }
  5220. remove$6(caption);
  5221. });
  5222. fireTableModified(editor, table.dom, structureModified);
  5223. });
  5224. });
  5225. };
  5226. const postExecute = _data => {
  5227. editor.focus();
  5228. };
  5229. const actOnSelection = (execute, noEvents = false) => performActionOnSelection((table, startCell) => {
  5230. const targets = forMenu(getCellsFromSelection(editor), table, startCell);
  5231. execute(table, targets, noEvents).each(postExecute);
  5232. });
  5233. const copyRowSelection = () => performActionOnSelection((table, startCell) => {
  5234. const targets = forMenu(getCellsFromSelection(editor), table, startCell);
  5235. const generators = cellOperations(noop, SugarElement.fromDom(editor.getDoc()), Optional.none());
  5236. return copyRows(table, targets, generators);
  5237. });
  5238. const copyColSelection = () => performActionOnSelection((table, startCell) => {
  5239. const targets = forMenu(getCellsFromSelection(editor), table, startCell);
  5240. return copyCols(table, targets);
  5241. });
  5242. const pasteOnSelection = (execute, getRows) => getRows().each(rows => {
  5243. const clonedRows = map$1(rows, row => deep(row));
  5244. performActionOnSelection((table, startCell) => {
  5245. const generators = paste$1(SugarElement.fromDom(editor.getDoc()));
  5246. const targets = pasteRows(getCellsFromSelection(editor), startCell, clonedRows, generators);
  5247. execute(table, targets).each(postExecute);
  5248. });
  5249. });
  5250. const actOnType = getAction => (_ui, args) => get$c(args, 'type').each(type => {
  5251. actOnSelection(getAction(type), args.no_events);
  5252. });
  5253. each$1({
  5254. mceTableSplitCells: () => actOnSelection(actions.unmergeCells),
  5255. mceTableMergeCells: () => actOnSelection(actions.mergeCells),
  5256. mceTableInsertRowBefore: () => actOnSelection(actions.insertRowsBefore),
  5257. mceTableInsertRowAfter: () => actOnSelection(actions.insertRowsAfter),
  5258. mceTableInsertColBefore: () => actOnSelection(actions.insertColumnsBefore),
  5259. mceTableInsertColAfter: () => actOnSelection(actions.insertColumnsAfter),
  5260. mceTableDeleteCol: () => actOnSelection(actions.deleteColumn),
  5261. mceTableDeleteRow: () => actOnSelection(actions.deleteRow),
  5262. mceTableCutCol: () => copyColSelection().each(selection => {
  5263. setColumns(selection);
  5264. actOnSelection(actions.deleteColumn);
  5265. }),
  5266. mceTableCutRow: () => copyRowSelection().each(selection => {
  5267. setRows(selection);
  5268. actOnSelection(actions.deleteRow);
  5269. }),
  5270. mceTableCopyCol: () => copyColSelection().each(selection => setColumns(selection)),
  5271. mceTableCopyRow: () => copyRowSelection().each(selection => setRows(selection)),
  5272. mceTablePasteColBefore: () => pasteOnSelection(actions.pasteColsBefore, getColumns),
  5273. mceTablePasteColAfter: () => pasteOnSelection(actions.pasteColsAfter, getColumns),
  5274. mceTablePasteRowBefore: () => pasteOnSelection(actions.pasteRowsBefore, getRows),
  5275. mceTablePasteRowAfter: () => pasteOnSelection(actions.pasteRowsAfter, getRows),
  5276. mceTableDelete: eraseTable,
  5277. mceTableCellToggleClass: toggleTableCellClass,
  5278. mceTableToggleClass: toggleTableClass,
  5279. mceTableToggleCaption: toggleCaption,
  5280. mceTableSizingMode: (_ui, sizing) => setSizingMode(sizing),
  5281. mceTableCellType: actOnType(type => type === 'th' ? actions.makeCellsHeader : actions.unmakeCellsHeader),
  5282. mceTableColType: actOnType(type => type === 'th' ? actions.makeColumnsHeader : actions.unmakeColumnsHeader),
  5283. mceTableRowType: actOnType(type => {
  5284. switch (type) {
  5285. case 'header':
  5286. return actions.makeRowsHeader;
  5287. case 'footer':
  5288. return actions.makeRowsFooter;
  5289. default:
  5290. return actions.makeRowsBody;
  5291. }
  5292. })
  5293. }, (func, name) => editor.addCommand(name, func));
  5294. editor.addCommand('mceInsertTable', (_ui, args) => {
  5295. insertTable(editor, args.rows, args.columns, args.options);
  5296. });
  5297. editor.addCommand('mceTableApplyCellStyle', (_ui, args) => {
  5298. const getFormatName = style => 'tablecell' + style.toLowerCase().replace('-', '');
  5299. if (!isObject(args)) {
  5300. return;
  5301. }
  5302. const cells = getCellsFromSelection(editor);
  5303. if (cells.length === 0) {
  5304. return;
  5305. }
  5306. const validArgs = filter$1(args, (value, style) => editor.formatter.has(getFormatName(style)) && isString(value));
  5307. if (isEmpty(validArgs)) {
  5308. return;
  5309. }
  5310. each$1(validArgs, (value, style) => {
  5311. const formatName = getFormatName(style);
  5312. each$2(cells, cell => {
  5313. if (value === '') {
  5314. editor.formatter.remove(formatName, { value: null }, cell.dom, true);
  5315. } else {
  5316. editor.formatter.apply(formatName, { value }, cell.dom);
  5317. }
  5318. });
  5319. });
  5320. getTableFromCell(cells[0]).each(table => fireTableModified(editor, table.dom, styleModified));
  5321. });
  5322. };
  5323. const registerQueryCommands = (editor, actions) => {
  5324. const isRoot = getIsRoot(editor);
  5325. const lookupOnSelection = action => getSelectionCell(getSelectionStart(editor)).bind(cell => table(cell, isRoot).map(table => {
  5326. const targets = forMenu(getCellsFromSelection(editor), table, cell);
  5327. return action(table, targets);
  5328. })).getOr('');
  5329. each$1({
  5330. mceTableRowType: () => lookupOnSelection(actions.getTableRowType),
  5331. mceTableCellType: () => lookupOnSelection(actions.getTableCellType),
  5332. mceTableColType: () => lookupOnSelection(actions.getTableColType)
  5333. }, (func, name) => editor.addQueryValueHandler(name, func));
  5334. };
  5335. const adt$4 = Adt.generate([
  5336. { before: ['element'] },
  5337. {
  5338. on: [
  5339. 'element',
  5340. 'offset'
  5341. ]
  5342. },
  5343. { after: ['element'] }
  5344. ]);
  5345. const cata$1 = (subject, onBefore, onOn, onAfter) => subject.fold(onBefore, onOn, onAfter);
  5346. const getStart$1 = situ => situ.fold(identity, identity, identity);
  5347. const before$2 = adt$4.before;
  5348. const on = adt$4.on;
  5349. const after$3 = adt$4.after;
  5350. const Situ = {
  5351. before: before$2,
  5352. on,
  5353. after: after$3,
  5354. cata: cata$1,
  5355. getStart: getStart$1
  5356. };
  5357. const create$4 = (selection, kill) => ({
  5358. selection,
  5359. kill
  5360. });
  5361. const Response = { create: create$4 };
  5362. const selectNode = (win, element) => {
  5363. const rng = win.document.createRange();
  5364. rng.selectNode(element.dom);
  5365. return rng;
  5366. };
  5367. const selectNodeContents = (win, element) => {
  5368. const rng = win.document.createRange();
  5369. selectNodeContentsUsing(rng, element);
  5370. return rng;
  5371. };
  5372. const selectNodeContentsUsing = (rng, element) => rng.selectNodeContents(element.dom);
  5373. const setStart = (rng, situ) => {
  5374. situ.fold(e => {
  5375. rng.setStartBefore(e.dom);
  5376. }, (e, o) => {
  5377. rng.setStart(e.dom, o);
  5378. }, e => {
  5379. rng.setStartAfter(e.dom);
  5380. });
  5381. };
  5382. const setFinish = (rng, situ) => {
  5383. situ.fold(e => {
  5384. rng.setEndBefore(e.dom);
  5385. }, (e, o) => {
  5386. rng.setEnd(e.dom, o);
  5387. }, e => {
  5388. rng.setEndAfter(e.dom);
  5389. });
  5390. };
  5391. const relativeToNative = (win, startSitu, finishSitu) => {
  5392. const range = win.document.createRange();
  5393. setStart(range, startSitu);
  5394. setFinish(range, finishSitu);
  5395. return range;
  5396. };
  5397. const exactToNative = (win, start, soffset, finish, foffset) => {
  5398. const rng = win.document.createRange();
  5399. rng.setStart(start.dom, soffset);
  5400. rng.setEnd(finish.dom, foffset);
  5401. return rng;
  5402. };
  5403. const toRect = rect => ({
  5404. left: rect.left,
  5405. top: rect.top,
  5406. right: rect.right,
  5407. bottom: rect.bottom,
  5408. width: rect.width,
  5409. height: rect.height
  5410. });
  5411. const getFirstRect$1 = rng => {
  5412. const rects = rng.getClientRects();
  5413. const rect = rects.length > 0 ? rects[0] : rng.getBoundingClientRect();
  5414. return rect.width > 0 || rect.height > 0 ? Optional.some(rect).map(toRect) : Optional.none();
  5415. };
  5416. const adt$3 = Adt.generate([
  5417. {
  5418. ltr: [
  5419. 'start',
  5420. 'soffset',
  5421. 'finish',
  5422. 'foffset'
  5423. ]
  5424. },
  5425. {
  5426. rtl: [
  5427. 'start',
  5428. 'soffset',
  5429. 'finish',
  5430. 'foffset'
  5431. ]
  5432. }
  5433. ]);
  5434. const fromRange = (win, type, range) => type(SugarElement.fromDom(range.startContainer), range.startOffset, SugarElement.fromDom(range.endContainer), range.endOffset);
  5435. const getRanges = (win, selection) => selection.match({
  5436. domRange: rng => {
  5437. return {
  5438. ltr: constant(rng),
  5439. rtl: Optional.none
  5440. };
  5441. },
  5442. relative: (startSitu, finishSitu) => {
  5443. return {
  5444. ltr: cached(() => relativeToNative(win, startSitu, finishSitu)),
  5445. rtl: cached(() => Optional.some(relativeToNative(win, finishSitu, startSitu)))
  5446. };
  5447. },
  5448. exact: (start, soffset, finish, foffset) => {
  5449. return {
  5450. ltr: cached(() => exactToNative(win, start, soffset, finish, foffset)),
  5451. rtl: cached(() => Optional.some(exactToNative(win, finish, foffset, start, soffset)))
  5452. };
  5453. }
  5454. });
  5455. const doDiagnose = (win, ranges) => {
  5456. const rng = ranges.ltr();
  5457. if (rng.collapsed) {
  5458. const reversed = ranges.rtl().filter(rev => rev.collapsed === false);
  5459. 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));
  5460. } else {
  5461. return fromRange(win, adt$3.ltr, rng);
  5462. }
  5463. };
  5464. const diagnose = (win, selection) => {
  5465. const ranges = getRanges(win, selection);
  5466. return doDiagnose(win, ranges);
  5467. };
  5468. const asLtrRange = (win, selection) => {
  5469. const diagnosis = diagnose(win, selection);
  5470. return diagnosis.match({
  5471. ltr: (start, soffset, finish, foffset) => {
  5472. const rng = win.document.createRange();
  5473. rng.setStart(start.dom, soffset);
  5474. rng.setEnd(finish.dom, foffset);
  5475. return rng;
  5476. },
  5477. rtl: (start, soffset, finish, foffset) => {
  5478. const rng = win.document.createRange();
  5479. rng.setStart(finish.dom, foffset);
  5480. rng.setEnd(start.dom, soffset);
  5481. return rng;
  5482. }
  5483. });
  5484. };
  5485. adt$3.ltr;
  5486. adt$3.rtl;
  5487. const create$3 = (start, soffset, finish, foffset) => ({
  5488. start,
  5489. soffset,
  5490. finish,
  5491. foffset
  5492. });
  5493. const SimRange = { create: create$3 };
  5494. const create$2 = (start, soffset, finish, foffset) => {
  5495. return {
  5496. start: Situ.on(start, soffset),
  5497. finish: Situ.on(finish, foffset)
  5498. };
  5499. };
  5500. const Situs = { create: create$2 };
  5501. const convertToRange = (win, selection) => {
  5502. const rng = asLtrRange(win, selection);
  5503. return SimRange.create(SugarElement.fromDom(rng.startContainer), rng.startOffset, SugarElement.fromDom(rng.endContainer), rng.endOffset);
  5504. };
  5505. const makeSitus = Situs.create;
  5506. const sync = (container, isRoot, start, soffset, finish, foffset, selectRange) => {
  5507. if (!(eq$1(start, finish) && soffset === foffset)) {
  5508. return closest$1(start, 'td,th', isRoot).bind(s => {
  5509. return closest$1(finish, 'td,th', isRoot).bind(f => {
  5510. return detect(container, isRoot, s, f, selectRange);
  5511. });
  5512. });
  5513. } else {
  5514. return Optional.none();
  5515. }
  5516. };
  5517. const detect = (container, isRoot, start, finish, selectRange) => {
  5518. if (!eq$1(start, finish)) {
  5519. return identify(start, finish, isRoot).bind(cellSel => {
  5520. const boxes = cellSel.boxes.getOr([]);
  5521. if (boxes.length > 1) {
  5522. selectRange(container, boxes, cellSel.start, cellSel.finish);
  5523. return Optional.some(Response.create(Optional.some(makeSitus(start, 0, start, getEnd(start))), true));
  5524. } else {
  5525. return Optional.none();
  5526. }
  5527. });
  5528. } else {
  5529. return Optional.none();
  5530. }
  5531. };
  5532. const update = (rows, columns, container, selected, annotations) => {
  5533. const updateSelection = newSels => {
  5534. annotations.clearBeforeUpdate(container);
  5535. annotations.selectRange(container, newSels.boxes, newSels.start, newSels.finish);
  5536. return newSels.boxes;
  5537. };
  5538. return shiftSelection(selected, rows, columns, annotations.firstSelectedSelector, annotations.lastSelectedSelector).map(updateSelection);
  5539. };
  5540. const traverse = (item, mode) => ({
  5541. item,
  5542. mode
  5543. });
  5544. const backtrack = (universe, item, _direction, transition = sidestep) => {
  5545. return universe.property().parent(item).map(p => {
  5546. return traverse(p, transition);
  5547. });
  5548. };
  5549. const sidestep = (universe, item, direction, transition = advance) => {
  5550. return direction.sibling(universe, item).map(p => {
  5551. return traverse(p, transition);
  5552. });
  5553. };
  5554. const advance = (universe, item, direction, transition = advance) => {
  5555. const children = universe.property().children(item);
  5556. const result = direction.first(children);
  5557. return result.map(r => {
  5558. return traverse(r, transition);
  5559. });
  5560. };
  5561. const successors = [
  5562. {
  5563. current: backtrack,
  5564. next: sidestep,
  5565. fallback: Optional.none()
  5566. },
  5567. {
  5568. current: sidestep,
  5569. next: advance,
  5570. fallback: Optional.some(backtrack)
  5571. },
  5572. {
  5573. current: advance,
  5574. next: advance,
  5575. fallback: Optional.some(sidestep)
  5576. }
  5577. ];
  5578. const go = (universe, item, mode, direction, rules = successors) => {
  5579. const ruleOpt = find$1(rules, succ => {
  5580. return succ.current === mode;
  5581. });
  5582. return ruleOpt.bind(rule => {
  5583. return rule.current(universe, item, direction, rule.next).orThunk(() => {
  5584. return rule.fallback.bind(fb => {
  5585. return go(universe, item, fb, direction);
  5586. });
  5587. });
  5588. });
  5589. };
  5590. const left$1 = () => {
  5591. const sibling = (universe, item) => {
  5592. return universe.query().prevSibling(item);
  5593. };
  5594. const first = children => {
  5595. return children.length > 0 ? Optional.some(children[children.length - 1]) : Optional.none();
  5596. };
  5597. return {
  5598. sibling,
  5599. first
  5600. };
  5601. };
  5602. const right$1 = () => {
  5603. const sibling = (universe, item) => {
  5604. return universe.query().nextSibling(item);
  5605. };
  5606. const first = children => {
  5607. return children.length > 0 ? Optional.some(children[0]) : Optional.none();
  5608. };
  5609. return {
  5610. sibling,
  5611. first
  5612. };
  5613. };
  5614. const Walkers = {
  5615. left: left$1,
  5616. right: right$1
  5617. };
  5618. const hone = (universe, item, predicate, mode, direction, isRoot) => {
  5619. const next = go(universe, item, mode, direction);
  5620. return next.bind(n => {
  5621. if (isRoot(n.item)) {
  5622. return Optional.none();
  5623. } else {
  5624. return predicate(n.item) ? Optional.some(n.item) : hone(universe, n.item, predicate, n.mode, direction, isRoot);
  5625. }
  5626. });
  5627. };
  5628. const left = (universe, item, predicate, isRoot) => {
  5629. return hone(universe, item, predicate, sidestep, Walkers.left(), isRoot);
  5630. };
  5631. const right = (universe, item, predicate, isRoot) => {
  5632. return hone(universe, item, predicate, sidestep, Walkers.right(), isRoot);
  5633. };
  5634. const isLeaf = universe => element => universe.property().children(element).length === 0;
  5635. const before$1 = (universe, item, isRoot) => {
  5636. return seekLeft$1(universe, item, isLeaf(universe), isRoot);
  5637. };
  5638. const after$2 = (universe, item, isRoot) => {
  5639. return seekRight$1(universe, item, isLeaf(universe), isRoot);
  5640. };
  5641. const seekLeft$1 = left;
  5642. const seekRight$1 = right;
  5643. const universe = DomUniverse();
  5644. const before = (element, isRoot) => {
  5645. return before$1(universe, element, isRoot);
  5646. };
  5647. const after$1 = (element, isRoot) => {
  5648. return after$2(universe, element, isRoot);
  5649. };
  5650. const seekLeft = (element, predicate, isRoot) => {
  5651. return seekLeft$1(universe, element, predicate, isRoot);
  5652. };
  5653. const seekRight = (element, predicate, isRoot) => {
  5654. return seekRight$1(universe, element, predicate, isRoot);
  5655. };
  5656. const ancestor = (scope, predicate, isRoot) => ancestor$2(scope, predicate, isRoot).isSome();
  5657. const adt$2 = Adt.generate([
  5658. { none: ['message'] },
  5659. { success: [] },
  5660. { failedUp: ['cell'] },
  5661. { failedDown: ['cell'] }
  5662. ]);
  5663. const isOverlapping = (bridge, before, after) => {
  5664. const beforeBounds = bridge.getRect(before);
  5665. const afterBounds = bridge.getRect(after);
  5666. return afterBounds.right > beforeBounds.left && afterBounds.left < beforeBounds.right;
  5667. };
  5668. const isRow = elem => {
  5669. return closest$1(elem, 'tr');
  5670. };
  5671. const verify = (bridge, before, beforeOffset, after, afterOffset, failure, isRoot) => {
  5672. return closest$1(after, 'td,th', isRoot).bind(afterCell => {
  5673. return closest$1(before, 'td,th', isRoot).map(beforeCell => {
  5674. if (!eq$1(afterCell, beforeCell)) {
  5675. return sharedOne(isRow, [
  5676. afterCell,
  5677. beforeCell
  5678. ]).fold(() => {
  5679. return isOverlapping(bridge, beforeCell, afterCell) ? adt$2.success() : failure(beforeCell);
  5680. }, _sharedRow => {
  5681. return failure(beforeCell);
  5682. });
  5683. } else {
  5684. return eq$1(after, afterCell) && getEnd(afterCell) === afterOffset ? failure(beforeCell) : adt$2.none('in same cell');
  5685. }
  5686. });
  5687. }).getOr(adt$2.none('default'));
  5688. };
  5689. const cata = (subject, onNone, onSuccess, onFailedUp, onFailedDown) => {
  5690. return subject.fold(onNone, onSuccess, onFailedUp, onFailedDown);
  5691. };
  5692. const BeforeAfter = {
  5693. ...adt$2,
  5694. verify,
  5695. cata
  5696. };
  5697. const inParent = (parent, children, element, index) => ({
  5698. parent,
  5699. children,
  5700. element,
  5701. index
  5702. });
  5703. const indexInParent = element => parent(element).bind(parent => {
  5704. const children = children$2(parent);
  5705. return indexOf(children, element).map(index => inParent(parent, children, element, index));
  5706. });
  5707. const indexOf = (elements, element) => findIndex(elements, curry(eq$1, element));
  5708. const isBr = isTag('br');
  5709. const gatherer = (cand, gather, isRoot) => {
  5710. return gather(cand, isRoot).bind(target => {
  5711. return isText(target) && get$6(target).trim().length === 0 ? gatherer(target, gather, isRoot) : Optional.some(target);
  5712. });
  5713. };
  5714. const handleBr = (isRoot, element, direction) => {
  5715. return direction.traverse(element).orThunk(() => {
  5716. return gatherer(element, direction.gather, isRoot);
  5717. }).map(direction.relative);
  5718. };
  5719. const findBr = (element, offset) => {
  5720. return child$2(element, offset).filter(isBr).orThunk(() => {
  5721. return child$2(element, offset - 1).filter(isBr);
  5722. });
  5723. };
  5724. const handleParent = (isRoot, element, offset, direction) => {
  5725. return findBr(element, offset).bind(br => {
  5726. return direction.traverse(br).fold(() => {
  5727. return gatherer(br, direction.gather, isRoot).map(direction.relative);
  5728. }, adjacent => {
  5729. return indexInParent(adjacent).map(info => {
  5730. return Situ.on(info.parent, info.index);
  5731. });
  5732. });
  5733. });
  5734. };
  5735. const tryBr = (isRoot, element, offset, direction) => {
  5736. const target = isBr(element) ? handleBr(isRoot, element, direction) : handleParent(isRoot, element, offset, direction);
  5737. return target.map(tgt => {
  5738. return {
  5739. start: tgt,
  5740. finish: tgt
  5741. };
  5742. });
  5743. };
  5744. const process = analysis => {
  5745. return BeforeAfter.cata(analysis, _message => {
  5746. return Optional.none();
  5747. }, () => {
  5748. return Optional.none();
  5749. }, cell => {
  5750. return Optional.some(point(cell, 0));
  5751. }, cell => {
  5752. return Optional.some(point(cell, getEnd(cell)));
  5753. });
  5754. };
  5755. const moveDown = (caret, amount) => {
  5756. return {
  5757. left: caret.left,
  5758. top: caret.top + amount,
  5759. right: caret.right,
  5760. bottom: caret.bottom + amount
  5761. };
  5762. };
  5763. const moveUp = (caret, amount) => {
  5764. return {
  5765. left: caret.left,
  5766. top: caret.top - amount,
  5767. right: caret.right,
  5768. bottom: caret.bottom - amount
  5769. };
  5770. };
  5771. const translate = (caret, xDelta, yDelta) => {
  5772. return {
  5773. left: caret.left + xDelta,
  5774. top: caret.top + yDelta,
  5775. right: caret.right + xDelta,
  5776. bottom: caret.bottom + yDelta
  5777. };
  5778. };
  5779. const getTop = caret => {
  5780. return caret.top;
  5781. };
  5782. const getBottom = caret => {
  5783. return caret.bottom;
  5784. };
  5785. const getPartialBox = (bridge, element, offset) => {
  5786. if (offset >= 0 && offset < getEnd(element)) {
  5787. return bridge.getRangedRect(element, offset, element, offset + 1);
  5788. } else if (offset > 0) {
  5789. return bridge.getRangedRect(element, offset - 1, element, offset);
  5790. }
  5791. return Optional.none();
  5792. };
  5793. const toCaret = rect => ({
  5794. left: rect.left,
  5795. top: rect.top,
  5796. right: rect.right,
  5797. bottom: rect.bottom
  5798. });
  5799. const getElemBox = (bridge, element) => {
  5800. return Optional.some(bridge.getRect(element));
  5801. };
  5802. const getBoxAt = (bridge, element, offset) => {
  5803. if (isElement(element)) {
  5804. return getElemBox(bridge, element).map(toCaret);
  5805. } else if (isText(element)) {
  5806. return getPartialBox(bridge, element, offset).map(toCaret);
  5807. } else {
  5808. return Optional.none();
  5809. }
  5810. };
  5811. const getEntireBox = (bridge, element) => {
  5812. if (isElement(element)) {
  5813. return getElemBox(bridge, element).map(toCaret);
  5814. } else if (isText(element)) {
  5815. return bridge.getRangedRect(element, 0, element, getEnd(element)).map(toCaret);
  5816. } else {
  5817. return Optional.none();
  5818. }
  5819. };
  5820. const JUMP_SIZE = 5;
  5821. const NUM_RETRIES = 100;
  5822. const adt$1 = Adt.generate([
  5823. { none: [] },
  5824. { retry: ['caret'] }
  5825. ]);
  5826. const isOutside = (caret, box) => {
  5827. return caret.left < box.left || Math.abs(box.right - caret.left) < 1 || caret.left > box.right;
  5828. };
  5829. const inOutsideBlock = (bridge, element, caret) => {
  5830. return closest$2(element, isBlock).fold(never, cell => {
  5831. return getEntireBox(bridge, cell).exists(box => {
  5832. return isOutside(caret, box);
  5833. });
  5834. });
  5835. };
  5836. const adjustDown = (bridge, element, guessBox, original, caret) => {
  5837. const lowerCaret = moveDown(caret, JUMP_SIZE);
  5838. if (Math.abs(guessBox.bottom - original.bottom) < 1) {
  5839. return adt$1.retry(lowerCaret);
  5840. } else if (guessBox.top > caret.bottom) {
  5841. return adt$1.retry(lowerCaret);
  5842. } else if (guessBox.top === caret.bottom) {
  5843. return adt$1.retry(moveDown(caret, 1));
  5844. } else {
  5845. return inOutsideBlock(bridge, element, caret) ? adt$1.retry(translate(lowerCaret, JUMP_SIZE, 0)) : adt$1.none();
  5846. }
  5847. };
  5848. const adjustUp = (bridge, element, guessBox, original, caret) => {
  5849. const higherCaret = moveUp(caret, JUMP_SIZE);
  5850. if (Math.abs(guessBox.top - original.top) < 1) {
  5851. return adt$1.retry(higherCaret);
  5852. } else if (guessBox.bottom < caret.top) {
  5853. return adt$1.retry(higherCaret);
  5854. } else if (guessBox.bottom === caret.top) {
  5855. return adt$1.retry(moveUp(caret, 1));
  5856. } else {
  5857. return inOutsideBlock(bridge, element, caret) ? adt$1.retry(translate(higherCaret, JUMP_SIZE, 0)) : adt$1.none();
  5858. }
  5859. };
  5860. const upMovement = {
  5861. point: getTop,
  5862. adjuster: adjustUp,
  5863. move: moveUp,
  5864. gather: before
  5865. };
  5866. const downMovement = {
  5867. point: getBottom,
  5868. adjuster: adjustDown,
  5869. move: moveDown,
  5870. gather: after$1
  5871. };
  5872. const isAtTable = (bridge, x, y) => {
  5873. return bridge.elementFromPoint(x, y).filter(elm => {
  5874. return name(elm) === 'table';
  5875. }).isSome();
  5876. };
  5877. const adjustForTable = (bridge, movement, original, caret, numRetries) => {
  5878. return adjustTil(bridge, movement, original, movement.move(caret, JUMP_SIZE), numRetries);
  5879. };
  5880. const adjustTil = (bridge, movement, original, caret, numRetries) => {
  5881. if (numRetries === 0) {
  5882. return Optional.some(caret);
  5883. }
  5884. if (isAtTable(bridge, caret.left, movement.point(caret))) {
  5885. return adjustForTable(bridge, movement, original, caret, numRetries - 1);
  5886. }
  5887. return bridge.situsFromPoint(caret.left, movement.point(caret)).bind(guess => {
  5888. return guess.start.fold(Optional.none, element => {
  5889. return getEntireBox(bridge, element).bind(guessBox => {
  5890. return movement.adjuster(bridge, element, guessBox, original, caret).fold(Optional.none, newCaret => {
  5891. return adjustTil(bridge, movement, original, newCaret, numRetries - 1);
  5892. });
  5893. }).orThunk(() => {
  5894. return Optional.some(caret);
  5895. });
  5896. }, Optional.none);
  5897. });
  5898. };
  5899. const checkScroll = (movement, adjusted, bridge) => {
  5900. if (movement.point(adjusted) > bridge.getInnerHeight()) {
  5901. return Optional.some(movement.point(adjusted) - bridge.getInnerHeight());
  5902. } else if (movement.point(adjusted) < 0) {
  5903. return Optional.some(-movement.point(adjusted));
  5904. } else {
  5905. return Optional.none();
  5906. }
  5907. };
  5908. const retry = (movement, bridge, caret) => {
  5909. const moved = movement.move(caret, JUMP_SIZE);
  5910. const adjusted = adjustTil(bridge, movement, caret, moved, NUM_RETRIES).getOr(moved);
  5911. return checkScroll(movement, adjusted, bridge).fold(() => {
  5912. return bridge.situsFromPoint(adjusted.left, movement.point(adjusted));
  5913. }, delta => {
  5914. bridge.scrollBy(0, delta);
  5915. return bridge.situsFromPoint(adjusted.left, movement.point(adjusted) - delta);
  5916. });
  5917. };
  5918. const Retries = {
  5919. tryUp: curry(retry, upMovement),
  5920. tryDown: curry(retry, downMovement),
  5921. getJumpSize: constant(JUMP_SIZE)
  5922. };
  5923. const MAX_RETRIES = 20;
  5924. const findSpot = (bridge, isRoot, direction) => {
  5925. return bridge.getSelection().bind(sel => {
  5926. return tryBr(isRoot, sel.finish, sel.foffset, direction).fold(() => {
  5927. return Optional.some(point(sel.finish, sel.foffset));
  5928. }, brNeighbour => {
  5929. const range = bridge.fromSitus(brNeighbour);
  5930. const analysis = BeforeAfter.verify(bridge, sel.finish, sel.foffset, range.finish, range.foffset, direction.failure, isRoot);
  5931. return process(analysis);
  5932. });
  5933. });
  5934. };
  5935. const scan = (bridge, isRoot, element, offset, direction, numRetries) => {
  5936. if (numRetries === 0) {
  5937. return Optional.none();
  5938. }
  5939. return tryCursor(bridge, isRoot, element, offset, direction).bind(situs => {
  5940. const range = bridge.fromSitus(situs);
  5941. const analysis = BeforeAfter.verify(bridge, element, offset, range.finish, range.foffset, direction.failure, isRoot);
  5942. return BeforeAfter.cata(analysis, () => {
  5943. return Optional.none();
  5944. }, () => {
  5945. return Optional.some(situs);
  5946. }, cell => {
  5947. if (eq$1(element, cell) && offset === 0) {
  5948. return tryAgain(bridge, element, offset, moveUp, direction);
  5949. } else {
  5950. return scan(bridge, isRoot, cell, 0, direction, numRetries - 1);
  5951. }
  5952. }, cell => {
  5953. if (eq$1(element, cell) && offset === getEnd(cell)) {
  5954. return tryAgain(bridge, element, offset, moveDown, direction);
  5955. } else {
  5956. return scan(bridge, isRoot, cell, getEnd(cell), direction, numRetries - 1);
  5957. }
  5958. });
  5959. });
  5960. };
  5961. const tryAgain = (bridge, element, offset, move, direction) => {
  5962. return getBoxAt(bridge, element, offset).bind(box => {
  5963. return tryAt(bridge, direction, move(box, Retries.getJumpSize()));
  5964. });
  5965. };
  5966. const tryAt = (bridge, direction, box) => {
  5967. const browser = detect$2().browser;
  5968. if (browser.isChromium() || browser.isSafari() || browser.isFirefox()) {
  5969. return direction.retry(bridge, box);
  5970. } else {
  5971. return Optional.none();
  5972. }
  5973. };
  5974. const tryCursor = (bridge, isRoot, element, offset, direction) => {
  5975. return getBoxAt(bridge, element, offset).bind(box => {
  5976. return tryAt(bridge, direction, box);
  5977. });
  5978. };
  5979. const handle$1 = (bridge, isRoot, direction) => {
  5980. return findSpot(bridge, isRoot, direction).bind(spot => {
  5981. return scan(bridge, isRoot, spot.element, spot.offset, direction, MAX_RETRIES).map(bridge.fromSitus);
  5982. });
  5983. };
  5984. const inSameTable = (elem, table) => {
  5985. return ancestor(elem, e => {
  5986. return parent(e).exists(p => {
  5987. return eq$1(p, table);
  5988. });
  5989. });
  5990. };
  5991. const simulate = (bridge, isRoot, direction, initial, anchor) => {
  5992. return closest$1(initial, 'td,th', isRoot).bind(start => {
  5993. return closest$1(start, 'table', isRoot).bind(table => {
  5994. if (!inSameTable(anchor, table)) {
  5995. return Optional.none();
  5996. }
  5997. return handle$1(bridge, isRoot, direction).bind(range => {
  5998. return closest$1(range.finish, 'td,th', isRoot).map(finish => {
  5999. return {
  6000. start,
  6001. finish,
  6002. range
  6003. };
  6004. });
  6005. });
  6006. });
  6007. });
  6008. };
  6009. const navigate = (bridge, isRoot, direction, initial, anchor, precheck) => {
  6010. return precheck(initial, isRoot).orThunk(() => {
  6011. return simulate(bridge, isRoot, direction, initial, anchor).map(info => {
  6012. const range = info.range;
  6013. return Response.create(Optional.some(makeSitus(range.start, range.soffset, range.finish, range.foffset)), true);
  6014. });
  6015. });
  6016. };
  6017. const firstUpCheck = (initial, isRoot) => {
  6018. return closest$1(initial, 'tr', isRoot).bind(startRow => {
  6019. return closest$1(startRow, 'table', isRoot).bind(table => {
  6020. const rows = descendants(table, 'tr');
  6021. if (eq$1(startRow, rows[0])) {
  6022. return seekLeft(table, element => {
  6023. return last$1(element).isSome();
  6024. }, isRoot).map(last => {
  6025. const lastOffset = getEnd(last);
  6026. return Response.create(Optional.some(makeSitus(last, lastOffset, last, lastOffset)), true);
  6027. });
  6028. } else {
  6029. return Optional.none();
  6030. }
  6031. });
  6032. });
  6033. };
  6034. const lastDownCheck = (initial, isRoot) => {
  6035. return closest$1(initial, 'tr', isRoot).bind(startRow => {
  6036. return closest$1(startRow, 'table', isRoot).bind(table => {
  6037. const rows = descendants(table, 'tr');
  6038. if (eq$1(startRow, rows[rows.length - 1])) {
  6039. return seekRight(table, element => {
  6040. return first(element).isSome();
  6041. }, isRoot).map(first => {
  6042. return Response.create(Optional.some(makeSitus(first, 0, first, 0)), true);
  6043. });
  6044. } else {
  6045. return Optional.none();
  6046. }
  6047. });
  6048. });
  6049. };
  6050. const select = (bridge, container, isRoot, direction, initial, anchor, selectRange) => {
  6051. return simulate(bridge, isRoot, direction, initial, anchor).bind(info => {
  6052. return detect(container, isRoot, info.start, info.finish, selectRange);
  6053. });
  6054. };
  6055. const Cell = initial => {
  6056. let value = initial;
  6057. const get = () => {
  6058. return value;
  6059. };
  6060. const set = v => {
  6061. value = v;
  6062. };
  6063. return {
  6064. get,
  6065. set
  6066. };
  6067. };
  6068. const singleton = doRevoke => {
  6069. const subject = Cell(Optional.none());
  6070. const revoke = () => subject.get().each(doRevoke);
  6071. const clear = () => {
  6072. revoke();
  6073. subject.set(Optional.none());
  6074. };
  6075. const isSet = () => subject.get().isSome();
  6076. const get = () => subject.get();
  6077. const set = s => {
  6078. revoke();
  6079. subject.set(Optional.some(s));
  6080. };
  6081. return {
  6082. clear,
  6083. isSet,
  6084. get,
  6085. set
  6086. };
  6087. };
  6088. const value = () => {
  6089. const subject = singleton(noop);
  6090. const on = f => subject.get().each(f);
  6091. return {
  6092. ...subject,
  6093. on
  6094. };
  6095. };
  6096. const findCell = (target, isRoot) => closest$1(target, 'td,th', isRoot);
  6097. const MouseSelection = (bridge, container, isRoot, annotations) => {
  6098. const cursor = value();
  6099. const clearstate = cursor.clear;
  6100. const applySelection = event => {
  6101. cursor.on(start => {
  6102. annotations.clearBeforeUpdate(container);
  6103. findCell(event.target, isRoot).each(finish => {
  6104. identify(start, finish, isRoot).each(cellSel => {
  6105. const boxes = cellSel.boxes.getOr([]);
  6106. if (boxes.length === 1) {
  6107. const singleCell = boxes[0];
  6108. const isNonEditableCell = getRaw(singleCell) === 'false';
  6109. const isCellClosestContentEditable = is(closest(event.target), singleCell, eq$1);
  6110. if (isNonEditableCell && isCellClosestContentEditable) {
  6111. annotations.selectRange(container, boxes, singleCell, singleCell);
  6112. bridge.selectContents(singleCell);
  6113. }
  6114. } else if (boxes.length > 1) {
  6115. annotations.selectRange(container, boxes, cellSel.start, cellSel.finish);
  6116. bridge.selectContents(finish);
  6117. }
  6118. });
  6119. });
  6120. });
  6121. };
  6122. const mousedown = event => {
  6123. annotations.clear(container);
  6124. findCell(event.target, isRoot).each(cursor.set);
  6125. };
  6126. const mouseover = event => {
  6127. applySelection(event);
  6128. };
  6129. const mouseup = event => {
  6130. applySelection(event);
  6131. clearstate();
  6132. };
  6133. return {
  6134. clearstate,
  6135. mousedown,
  6136. mouseover,
  6137. mouseup
  6138. };
  6139. };
  6140. const down = {
  6141. traverse: nextSibling,
  6142. gather: after$1,
  6143. relative: Situ.before,
  6144. retry: Retries.tryDown,
  6145. failure: BeforeAfter.failedDown
  6146. };
  6147. const up = {
  6148. traverse: prevSibling,
  6149. gather: before,
  6150. relative: Situ.before,
  6151. retry: Retries.tryUp,
  6152. failure: BeforeAfter.failedUp
  6153. };
  6154. const isKey = key => {
  6155. return keycode => {
  6156. return keycode === key;
  6157. };
  6158. };
  6159. const isUp = isKey(38);
  6160. const isDown = isKey(40);
  6161. const isNavigation = keycode => {
  6162. return keycode >= 37 && keycode <= 40;
  6163. };
  6164. const ltr = {
  6165. isBackward: isKey(37),
  6166. isForward: isKey(39)
  6167. };
  6168. const rtl = {
  6169. isBackward: isKey(39),
  6170. isForward: isKey(37)
  6171. };
  6172. const get$3 = _DOC => {
  6173. const doc = _DOC !== undefined ? _DOC.dom : document;
  6174. const x = doc.body.scrollLeft || doc.documentElement.scrollLeft;
  6175. const y = doc.body.scrollTop || doc.documentElement.scrollTop;
  6176. return SugarPosition(x, y);
  6177. };
  6178. const by = (x, y, _DOC) => {
  6179. const doc = _DOC !== undefined ? _DOC.dom : document;
  6180. const win = doc.defaultView;
  6181. if (win) {
  6182. win.scrollBy(x, y);
  6183. }
  6184. };
  6185. const adt = Adt.generate([
  6186. { domRange: ['rng'] },
  6187. {
  6188. relative: [
  6189. 'startSitu',
  6190. 'finishSitu'
  6191. ]
  6192. },
  6193. {
  6194. exact: [
  6195. 'start',
  6196. 'soffset',
  6197. 'finish',
  6198. 'foffset'
  6199. ]
  6200. }
  6201. ]);
  6202. const exactFromRange = simRange => adt.exact(simRange.start, simRange.soffset, simRange.finish, simRange.foffset);
  6203. const getStart = selection => selection.match({
  6204. domRange: rng => SugarElement.fromDom(rng.startContainer),
  6205. relative: (startSitu, _finishSitu) => Situ.getStart(startSitu),
  6206. exact: (start, _soffset, _finish, _foffset) => start
  6207. });
  6208. const domRange = adt.domRange;
  6209. const relative = adt.relative;
  6210. const exact = adt.exact;
  6211. const getWin = selection => {
  6212. const start = getStart(selection);
  6213. return defaultView(start);
  6214. };
  6215. const range = SimRange.create;
  6216. const SimSelection = {
  6217. domRange,
  6218. relative,
  6219. exact,
  6220. exactFromRange,
  6221. getWin,
  6222. range
  6223. };
  6224. const caretPositionFromPoint = (doc, x, y) => {
  6225. var _a, _b;
  6226. return Optional.from((_b = (_a = doc.dom).caretPositionFromPoint) === null || _b === void 0 ? void 0 : _b.call(_a, x, y)).bind(pos => {
  6227. if (pos.offsetNode === null) {
  6228. return Optional.none();
  6229. }
  6230. const r = doc.dom.createRange();
  6231. r.setStart(pos.offsetNode, pos.offset);
  6232. r.collapse();
  6233. return Optional.some(r);
  6234. });
  6235. };
  6236. const caretRangeFromPoint = (doc, x, y) => {
  6237. var _a, _b;
  6238. return Optional.from((_b = (_a = doc.dom).caretRangeFromPoint) === null || _b === void 0 ? void 0 : _b.call(_a, x, y));
  6239. };
  6240. const availableSearch = (() => {
  6241. if (document.caretPositionFromPoint) {
  6242. return caretPositionFromPoint;
  6243. } else if (document.caretRangeFromPoint) {
  6244. return caretRangeFromPoint;
  6245. } else {
  6246. return Optional.none;
  6247. }
  6248. })();
  6249. const fromPoint = (win, x, y) => {
  6250. const doc = SugarElement.fromDom(win.document);
  6251. return availableSearch(doc, x, y).map(rng => SimRange.create(SugarElement.fromDom(rng.startContainer), rng.startOffset, SugarElement.fromDom(rng.endContainer), rng.endOffset));
  6252. };
  6253. const beforeSpecial = (element, offset) => {
  6254. const name$1 = name(element);
  6255. if ('input' === name$1) {
  6256. return Situ.after(element);
  6257. } else if (!contains$2([
  6258. 'br',
  6259. 'img'
  6260. ], name$1)) {
  6261. return Situ.on(element, offset);
  6262. } else {
  6263. return offset === 0 ? Situ.before(element) : Situ.after(element);
  6264. }
  6265. };
  6266. const preprocessRelative = (startSitu, finishSitu) => {
  6267. const start = startSitu.fold(Situ.before, beforeSpecial, Situ.after);
  6268. const finish = finishSitu.fold(Situ.before, beforeSpecial, Situ.after);
  6269. return SimSelection.relative(start, finish);
  6270. };
  6271. const preprocessExact = (start, soffset, finish, foffset) => {
  6272. const startSitu = beforeSpecial(start, soffset);
  6273. const finishSitu = beforeSpecial(finish, foffset);
  6274. return SimSelection.relative(startSitu, finishSitu);
  6275. };
  6276. const makeRange = (start, soffset, finish, foffset) => {
  6277. const doc = owner(start);
  6278. const rng = doc.dom.createRange();
  6279. rng.setStart(start.dom, soffset);
  6280. rng.setEnd(finish.dom, foffset);
  6281. return rng;
  6282. };
  6283. const after = (start, soffset, finish, foffset) => {
  6284. const r = makeRange(start, soffset, finish, foffset);
  6285. const same = eq$1(start, finish) && soffset === foffset;
  6286. return r.collapsed && !same;
  6287. };
  6288. const getNativeSelection = win => Optional.from(win.getSelection());
  6289. const doSetNativeRange = (win, rng) => {
  6290. getNativeSelection(win).each(selection => {
  6291. selection.removeAllRanges();
  6292. selection.addRange(rng);
  6293. });
  6294. };
  6295. const doSetRange = (win, start, soffset, finish, foffset) => {
  6296. const rng = exactToNative(win, start, soffset, finish, foffset);
  6297. doSetNativeRange(win, rng);
  6298. };
  6299. const setLegacyRtlRange = (win, selection, start, soffset, finish, foffset) => {
  6300. selection.collapse(start.dom, soffset);
  6301. selection.extend(finish.dom, foffset);
  6302. };
  6303. const setRangeFromRelative = (win, relative) => diagnose(win, relative).match({
  6304. ltr: (start, soffset, finish, foffset) => {
  6305. doSetRange(win, start, soffset, finish, foffset);
  6306. },
  6307. rtl: (start, soffset, finish, foffset) => {
  6308. getNativeSelection(win).each(selection => {
  6309. if (selection.setBaseAndExtent) {
  6310. selection.setBaseAndExtent(start.dom, soffset, finish.dom, foffset);
  6311. } else if (selection.extend) {
  6312. try {
  6313. setLegacyRtlRange(win, selection, start, soffset, finish, foffset);
  6314. } catch (e) {
  6315. doSetRange(win, finish, foffset, start, soffset);
  6316. }
  6317. } else {
  6318. doSetRange(win, finish, foffset, start, soffset);
  6319. }
  6320. });
  6321. }
  6322. });
  6323. const setExact = (win, start, soffset, finish, foffset) => {
  6324. const relative = preprocessExact(start, soffset, finish, foffset);
  6325. setRangeFromRelative(win, relative);
  6326. };
  6327. const setRelative = (win, startSitu, finishSitu) => {
  6328. const relative = preprocessRelative(startSitu, finishSitu);
  6329. setRangeFromRelative(win, relative);
  6330. };
  6331. const readRange = selection => {
  6332. if (selection.rangeCount > 0) {
  6333. const firstRng = selection.getRangeAt(0);
  6334. const lastRng = selection.getRangeAt(selection.rangeCount - 1);
  6335. return Optional.some(SimRange.create(SugarElement.fromDom(firstRng.startContainer), firstRng.startOffset, SugarElement.fromDom(lastRng.endContainer), lastRng.endOffset));
  6336. } else {
  6337. return Optional.none();
  6338. }
  6339. };
  6340. const doGetExact = selection => {
  6341. if (selection.anchorNode === null || selection.focusNode === null) {
  6342. return readRange(selection);
  6343. } else {
  6344. const anchor = SugarElement.fromDom(selection.anchorNode);
  6345. const focus = SugarElement.fromDom(selection.focusNode);
  6346. return after(anchor, selection.anchorOffset, focus, selection.focusOffset) ? Optional.some(SimRange.create(anchor, selection.anchorOffset, focus, selection.focusOffset)) : readRange(selection);
  6347. }
  6348. };
  6349. const setToElement = (win, element, selectNodeContents$1 = true) => {
  6350. const rngGetter = selectNodeContents$1 ? selectNodeContents : selectNode;
  6351. const rng = rngGetter(win, element);
  6352. doSetNativeRange(win, rng);
  6353. };
  6354. const getExact = win => getNativeSelection(win).filter(sel => sel.rangeCount > 0).bind(doGetExact);
  6355. const get$2 = win => getExact(win).map(range => SimSelection.exact(range.start, range.soffset, range.finish, range.foffset));
  6356. const getFirstRect = (win, selection) => {
  6357. const rng = asLtrRange(win, selection);
  6358. return getFirstRect$1(rng);
  6359. };
  6360. const getAtPoint = (win, x, y) => fromPoint(win, x, y);
  6361. const clear = win => {
  6362. getNativeSelection(win).each(selection => selection.removeAllRanges());
  6363. };
  6364. const WindowBridge = win => {
  6365. const elementFromPoint = (x, y) => {
  6366. return SugarElement.fromPoint(SugarElement.fromDom(win.document), x, y);
  6367. };
  6368. const getRect = element => {
  6369. return element.dom.getBoundingClientRect();
  6370. };
  6371. const getRangedRect = (start, soffset, finish, foffset) => {
  6372. const sel = SimSelection.exact(start, soffset, finish, foffset);
  6373. return getFirstRect(win, sel);
  6374. };
  6375. const getSelection = () => {
  6376. return get$2(win).map(exactAdt => {
  6377. return convertToRange(win, exactAdt);
  6378. });
  6379. };
  6380. const fromSitus = situs => {
  6381. const relative = SimSelection.relative(situs.start, situs.finish);
  6382. return convertToRange(win, relative);
  6383. };
  6384. const situsFromPoint = (x, y) => {
  6385. return getAtPoint(win, x, y).map(exact => {
  6386. return Situs.create(exact.start, exact.soffset, exact.finish, exact.foffset);
  6387. });
  6388. };
  6389. const clearSelection = () => {
  6390. clear(win);
  6391. };
  6392. const collapseSelection = (toStart = false) => {
  6393. get$2(win).each(sel => sel.fold(rng => rng.collapse(toStart), (startSitu, finishSitu) => {
  6394. const situ = toStart ? startSitu : finishSitu;
  6395. setRelative(win, situ, situ);
  6396. }, (start, soffset, finish, foffset) => {
  6397. const node = toStart ? start : finish;
  6398. const offset = toStart ? soffset : foffset;
  6399. setExact(win, node, offset, node, offset);
  6400. }));
  6401. };
  6402. const selectNode = element => {
  6403. setToElement(win, element, false);
  6404. };
  6405. const selectContents = element => {
  6406. setToElement(win, element);
  6407. };
  6408. const setSelection = sel => {
  6409. setExact(win, sel.start, sel.soffset, sel.finish, sel.foffset);
  6410. };
  6411. const setRelativeSelection = (start, finish) => {
  6412. setRelative(win, start, finish);
  6413. };
  6414. const getInnerHeight = () => {
  6415. return win.innerHeight;
  6416. };
  6417. const getScrollY = () => {
  6418. const pos = get$3(SugarElement.fromDom(win.document));
  6419. return pos.top;
  6420. };
  6421. const scrollBy = (x, y) => {
  6422. by(x, y, SugarElement.fromDom(win.document));
  6423. };
  6424. return {
  6425. elementFromPoint,
  6426. getRect,
  6427. getRangedRect,
  6428. getSelection,
  6429. fromSitus,
  6430. situsFromPoint,
  6431. clearSelection,
  6432. collapseSelection,
  6433. setSelection,
  6434. setRelativeSelection,
  6435. selectNode,
  6436. selectContents,
  6437. getInnerHeight,
  6438. getScrollY,
  6439. scrollBy
  6440. };
  6441. };
  6442. const rc = (rows, cols) => ({
  6443. rows,
  6444. cols
  6445. });
  6446. const mouse = (win, container, isRoot, annotations) => {
  6447. const bridge = WindowBridge(win);
  6448. const handlers = MouseSelection(bridge, container, isRoot, annotations);
  6449. return {
  6450. clearstate: handlers.clearstate,
  6451. mousedown: handlers.mousedown,
  6452. mouseover: handlers.mouseover,
  6453. mouseup: handlers.mouseup
  6454. };
  6455. };
  6456. const keyboard = (win, container, isRoot, annotations) => {
  6457. const bridge = WindowBridge(win);
  6458. const clearToNavigate = () => {
  6459. annotations.clear(container);
  6460. return Optional.none();
  6461. };
  6462. const keydown = (event, start, soffset, finish, foffset, direction) => {
  6463. const realEvent = event.raw;
  6464. const keycode = realEvent.which;
  6465. const shiftKey = realEvent.shiftKey === true;
  6466. const handler = retrieve$1(container, annotations.selectedSelector).fold(() => {
  6467. if (isNavigation(keycode) && !shiftKey) {
  6468. annotations.clearBeforeUpdate(container);
  6469. }
  6470. if (isDown(keycode) && shiftKey) {
  6471. return curry(select, bridge, container, isRoot, down, finish, start, annotations.selectRange);
  6472. } else if (isUp(keycode) && shiftKey) {
  6473. return curry(select, bridge, container, isRoot, up, finish, start, annotations.selectRange);
  6474. } else if (isDown(keycode)) {
  6475. return curry(navigate, bridge, isRoot, down, finish, start, lastDownCheck);
  6476. } else if (isUp(keycode)) {
  6477. return curry(navigate, bridge, isRoot, up, finish, start, firstUpCheck);
  6478. } else {
  6479. return Optional.none;
  6480. }
  6481. }, selected => {
  6482. const update$1 = attempts => {
  6483. return () => {
  6484. const navigation = findMap(attempts, delta => {
  6485. return update(delta.rows, delta.cols, container, selected, annotations);
  6486. });
  6487. return navigation.fold(() => {
  6488. return getEdges(container, annotations.firstSelectedSelector, annotations.lastSelectedSelector).map(edges => {
  6489. const relative = isDown(keycode) || direction.isForward(keycode) ? Situ.after : Situ.before;
  6490. bridge.setRelativeSelection(Situ.on(edges.first, 0), relative(edges.table));
  6491. annotations.clear(container);
  6492. return Response.create(Optional.none(), true);
  6493. });
  6494. }, _ => {
  6495. return Optional.some(Response.create(Optional.none(), true));
  6496. });
  6497. };
  6498. };
  6499. if (isDown(keycode) && shiftKey) {
  6500. return update$1([rc(+1, 0)]);
  6501. } else if (isUp(keycode) && shiftKey) {
  6502. return update$1([rc(-1, 0)]);
  6503. } else if (direction.isBackward(keycode) && shiftKey) {
  6504. return update$1([
  6505. rc(0, -1),
  6506. rc(-1, 0)
  6507. ]);
  6508. } else if (direction.isForward(keycode) && shiftKey) {
  6509. return update$1([
  6510. rc(0, +1),
  6511. rc(+1, 0)
  6512. ]);
  6513. } else if (isNavigation(keycode) && !shiftKey) {
  6514. return clearToNavigate;
  6515. } else {
  6516. return Optional.none;
  6517. }
  6518. });
  6519. return handler();
  6520. };
  6521. const keyup = (event, start, soffset, finish, foffset) => {
  6522. return retrieve$1(container, annotations.selectedSelector).fold(() => {
  6523. const realEvent = event.raw;
  6524. const keycode = realEvent.which;
  6525. const shiftKey = realEvent.shiftKey === true;
  6526. if (!shiftKey) {
  6527. return Optional.none();
  6528. }
  6529. if (isNavigation(keycode)) {
  6530. return sync(container, isRoot, start, soffset, finish, foffset, annotations.selectRange);
  6531. } else {
  6532. return Optional.none();
  6533. }
  6534. }, Optional.none);
  6535. };
  6536. return {
  6537. keydown,
  6538. keyup
  6539. };
  6540. };
  6541. const external = (win, container, isRoot, annotations) => {
  6542. const bridge = WindowBridge(win);
  6543. return (start, finish) => {
  6544. annotations.clearBeforeUpdate(container);
  6545. identify(start, finish, isRoot).each(cellSel => {
  6546. const boxes = cellSel.boxes.getOr([]);
  6547. annotations.selectRange(container, boxes, cellSel.start, cellSel.finish);
  6548. bridge.selectContents(finish);
  6549. bridge.collapseSelection();
  6550. });
  6551. };
  6552. };
  6553. const read = (element, attr) => {
  6554. const value = get$b(element, attr);
  6555. return value === undefined || value === '' ? [] : value.split(' ');
  6556. };
  6557. const add$2 = (element, attr, id) => {
  6558. const old = read(element, attr);
  6559. const nu = old.concat([id]);
  6560. set$2(element, attr, nu.join(' '));
  6561. return true;
  6562. };
  6563. const remove$4 = (element, attr, id) => {
  6564. const nu = filter$2(read(element, attr), v => v !== id);
  6565. if (nu.length > 0) {
  6566. set$2(element, attr, nu.join(' '));
  6567. } else {
  6568. remove$7(element, attr);
  6569. }
  6570. return false;
  6571. };
  6572. const supports = element => element.dom.classList !== undefined;
  6573. const get$1 = element => read(element, 'class');
  6574. const add$1 = (element, clazz) => add$2(element, 'class', clazz);
  6575. const remove$3 = (element, clazz) => remove$4(element, 'class', clazz);
  6576. const add = (element, clazz) => {
  6577. if (supports(element)) {
  6578. element.dom.classList.add(clazz);
  6579. } else {
  6580. add$1(element, clazz);
  6581. }
  6582. };
  6583. const cleanClass = element => {
  6584. const classList = supports(element) ? element.dom.classList : get$1(element);
  6585. if (classList.length === 0) {
  6586. remove$7(element, 'class');
  6587. }
  6588. };
  6589. const remove$2 = (element, clazz) => {
  6590. if (supports(element)) {
  6591. const classList = element.dom.classList;
  6592. classList.remove(clazz);
  6593. } else {
  6594. remove$3(element, clazz);
  6595. }
  6596. cleanClass(element);
  6597. };
  6598. const has = (element, clazz) => supports(element) && element.dom.classList.contains(clazz);
  6599. const remove$1 = (element, classes) => {
  6600. each$2(classes, x => {
  6601. remove$2(element, x);
  6602. });
  6603. };
  6604. const addClass = clazz => element => {
  6605. add(element, clazz);
  6606. };
  6607. const removeClasses = classes => element => {
  6608. remove$1(element, classes);
  6609. };
  6610. const byClass = ephemera => {
  6611. const addSelectionClass = addClass(ephemera.selected);
  6612. const removeSelectionClasses = removeClasses([
  6613. ephemera.selected,
  6614. ephemera.lastSelected,
  6615. ephemera.firstSelected
  6616. ]);
  6617. const clear = container => {
  6618. const sels = descendants(container, ephemera.selectedSelector);
  6619. each$2(sels, removeSelectionClasses);
  6620. };
  6621. const selectRange = (container, cells, start, finish) => {
  6622. clear(container);
  6623. each$2(cells, addSelectionClass);
  6624. add(start, ephemera.firstSelected);
  6625. add(finish, ephemera.lastSelected);
  6626. };
  6627. return {
  6628. clearBeforeUpdate: clear,
  6629. clear,
  6630. selectRange,
  6631. selectedSelector: ephemera.selectedSelector,
  6632. firstSelectedSelector: ephemera.firstSelectedSelector,
  6633. lastSelectedSelector: ephemera.lastSelectedSelector
  6634. };
  6635. };
  6636. const byAttr = (ephemera, onSelection, onClear) => {
  6637. const removeSelectionAttributes = element => {
  6638. remove$7(element, ephemera.selected);
  6639. remove$7(element, ephemera.firstSelected);
  6640. remove$7(element, ephemera.lastSelected);
  6641. };
  6642. const addSelectionAttribute = element => {
  6643. set$2(element, ephemera.selected, '1');
  6644. };
  6645. const clear = container => {
  6646. clearBeforeUpdate(container);
  6647. onClear();
  6648. };
  6649. const clearBeforeUpdate = container => {
  6650. const sels = descendants(container, `${ ephemera.selectedSelector },${ ephemera.firstSelectedSelector },${ ephemera.lastSelectedSelector }`);
  6651. each$2(sels, removeSelectionAttributes);
  6652. };
  6653. const selectRange = (container, cells, start, finish) => {
  6654. clear(container);
  6655. each$2(cells, addSelectionAttribute);
  6656. set$2(start, ephemera.firstSelected, '1');
  6657. set$2(finish, ephemera.lastSelected, '1');
  6658. onSelection(cells, start, finish);
  6659. };
  6660. return {
  6661. clearBeforeUpdate,
  6662. clear,
  6663. selectRange,
  6664. selectedSelector: ephemera.selectedSelector,
  6665. firstSelectedSelector: ephemera.firstSelectedSelector,
  6666. lastSelectedSelector: ephemera.lastSelectedSelector
  6667. };
  6668. };
  6669. const SelectionAnnotation = {
  6670. byClass,
  6671. byAttr
  6672. };
  6673. const fold = (subject, onNone, onMultiple, onSingle) => {
  6674. switch (subject.tag) {
  6675. case 'none':
  6676. return onNone();
  6677. case 'single':
  6678. return onSingle(subject.element);
  6679. case 'multiple':
  6680. return onMultiple(subject.elements);
  6681. }
  6682. };
  6683. const none = () => ({ tag: 'none' });
  6684. const multiple = elements => ({
  6685. tag: 'multiple',
  6686. elements
  6687. });
  6688. const single = element => ({
  6689. tag: 'single',
  6690. element
  6691. });
  6692. const Selections = (lazyRoot, getStart, selectedSelector) => {
  6693. const get = () => retrieve(lazyRoot(), selectedSelector).fold(() => getStart().fold(none, single), multiple);
  6694. return { get };
  6695. };
  6696. const getUpOrLeftCells = (grid, selectedCells) => {
  6697. const upGrid = grid.slice(0, selectedCells[selectedCells.length - 1].row + 1);
  6698. const upDetails = toDetailList(upGrid);
  6699. return bind$2(upDetails, detail => {
  6700. const slicedCells = detail.cells.slice(0, selectedCells[selectedCells.length - 1].column + 1);
  6701. return map$1(slicedCells, cell => cell.element);
  6702. });
  6703. };
  6704. const getDownOrRightCells = (grid, selectedCells) => {
  6705. const downGrid = grid.slice(selectedCells[0].row + selectedCells[0].rowspan - 1, grid.length);
  6706. const downDetails = toDetailList(downGrid);
  6707. return bind$2(downDetails, detail => {
  6708. const slicedCells = detail.cells.slice(selectedCells[0].column + selectedCells[0].colspan - 1, detail.cells.length);
  6709. return map$1(slicedCells, cell => cell.element);
  6710. });
  6711. };
  6712. const getOtherCells = (table, target, generators) => {
  6713. const warehouse = Warehouse.fromTable(table);
  6714. const details = onCells(warehouse, target);
  6715. return details.map(selectedCells => {
  6716. const grid = toGrid(warehouse, generators, false);
  6717. const {rows} = extractGridDetails(grid);
  6718. const upOrLeftCells = getUpOrLeftCells(rows, selectedCells);
  6719. const downOrRightCells = getDownOrRightCells(rows, selectedCells);
  6720. return {
  6721. upOrLeftCells,
  6722. downOrRightCells
  6723. };
  6724. });
  6725. };
  6726. const mkEvent = (target, x, y, stop, prevent, kill, raw) => ({
  6727. target,
  6728. x,
  6729. y,
  6730. stop,
  6731. prevent,
  6732. kill,
  6733. raw
  6734. });
  6735. const fromRawEvent$1 = rawEvent => {
  6736. const target = SugarElement.fromDom(getOriginalEventTarget(rawEvent).getOr(rawEvent.target));
  6737. const stop = () => rawEvent.stopPropagation();
  6738. const prevent = () => rawEvent.preventDefault();
  6739. const kill = compose(prevent, stop);
  6740. return mkEvent(target, rawEvent.clientX, rawEvent.clientY, stop, prevent, kill, rawEvent);
  6741. };
  6742. const handle = (filter, handler) => rawEvent => {
  6743. if (filter(rawEvent)) {
  6744. handler(fromRawEvent$1(rawEvent));
  6745. }
  6746. };
  6747. const binder = (element, event, filter, handler, useCapture) => {
  6748. const wrapped = handle(filter, handler);
  6749. element.dom.addEventListener(event, wrapped, useCapture);
  6750. return { unbind: curry(unbind, element, event, wrapped, useCapture) };
  6751. };
  6752. const bind$1 = (element, event, filter, handler) => binder(element, event, filter, handler, false);
  6753. const unbind = (element, event, handler, useCapture) => {
  6754. element.dom.removeEventListener(event, handler, useCapture);
  6755. };
  6756. const filter = always;
  6757. const bind = (element, event, handler) => bind$1(element, event, filter, handler);
  6758. const fromRawEvent = fromRawEvent$1;
  6759. const hasInternalTarget = e => has(SugarElement.fromDom(e.target), 'ephox-snooker-resizer-bar') === false;
  6760. const TableCellSelectionHandler = (editor, resizeHandler) => {
  6761. const cellSelection = Selections(() => SugarElement.fromDom(editor.getBody()), () => getSelectionCell(getSelectionStart(editor), getIsRoot(editor)), ephemera.selectedSelector);
  6762. const onSelection = (cells, start, finish) => {
  6763. const tableOpt = table(start);
  6764. tableOpt.each(table => {
  6765. const cloneFormats = getTableCloneElements(editor);
  6766. const generators = cellOperations(noop, SugarElement.fromDom(editor.getDoc()), cloneFormats);
  6767. const selectedCells = getCellsFromSelection(editor);
  6768. const otherCells = getOtherCells(table, { selection: selectedCells }, generators);
  6769. fireTableSelectionChange(editor, cells, start, finish, otherCells);
  6770. });
  6771. };
  6772. const onClear = () => fireTableSelectionClear(editor);
  6773. const annotations = SelectionAnnotation.byAttr(ephemera, onSelection, onClear);
  6774. editor.on('init', _e => {
  6775. const win = editor.getWin();
  6776. const body = getBody(editor);
  6777. const isRoot = getIsRoot(editor);
  6778. const syncSelection = () => {
  6779. const sel = editor.selection;
  6780. const start = SugarElement.fromDom(sel.getStart());
  6781. const end = SugarElement.fromDom(sel.getEnd());
  6782. const shared = sharedOne(table, [
  6783. start,
  6784. end
  6785. ]);
  6786. shared.fold(() => annotations.clear(body), noop);
  6787. };
  6788. const mouseHandlers = mouse(win, body, isRoot, annotations);
  6789. const keyHandlers = keyboard(win, body, isRoot, annotations);
  6790. const external$1 = external(win, body, isRoot, annotations);
  6791. const hasShiftKey = event => event.raw.shiftKey === true;
  6792. editor.on('TableSelectorChange', e => external$1(e.start, e.finish));
  6793. const handleResponse = (event, response) => {
  6794. if (!hasShiftKey(event)) {
  6795. return;
  6796. }
  6797. if (response.kill) {
  6798. event.kill();
  6799. }
  6800. response.selection.each(ns => {
  6801. const relative = SimSelection.relative(ns.start, ns.finish);
  6802. const rng = asLtrRange(win, relative);
  6803. editor.selection.setRng(rng);
  6804. });
  6805. };
  6806. const keyup = event => {
  6807. const wrappedEvent = fromRawEvent(event);
  6808. if (wrappedEvent.raw.shiftKey && isNavigation(wrappedEvent.raw.which)) {
  6809. const rng = editor.selection.getRng();
  6810. const start = SugarElement.fromDom(rng.startContainer);
  6811. const end = SugarElement.fromDom(rng.endContainer);
  6812. keyHandlers.keyup(wrappedEvent, start, rng.startOffset, end, rng.endOffset).each(response => {
  6813. handleResponse(wrappedEvent, response);
  6814. });
  6815. }
  6816. };
  6817. const keydown = event => {
  6818. const wrappedEvent = fromRawEvent(event);
  6819. resizeHandler.hide();
  6820. const rng = editor.selection.getRng();
  6821. const start = SugarElement.fromDom(rng.startContainer);
  6822. const end = SugarElement.fromDom(rng.endContainer);
  6823. const direction = onDirection(ltr, rtl)(SugarElement.fromDom(editor.selection.getStart()));
  6824. keyHandlers.keydown(wrappedEvent, start, rng.startOffset, end, rng.endOffset, direction).each(response => {
  6825. handleResponse(wrappedEvent, response);
  6826. });
  6827. resizeHandler.show();
  6828. };
  6829. const isLeftMouse = raw => raw.button === 0;
  6830. const isLeftButtonPressed = raw => {
  6831. if (raw.buttons === undefined) {
  6832. return true;
  6833. }
  6834. return (raw.buttons & 1) !== 0;
  6835. };
  6836. const dragStart = _e => {
  6837. mouseHandlers.clearstate();
  6838. };
  6839. const mouseDown = e => {
  6840. if (isLeftMouse(e) && hasInternalTarget(e)) {
  6841. mouseHandlers.mousedown(fromRawEvent(e));
  6842. }
  6843. };
  6844. const mouseOver = e => {
  6845. if (isLeftButtonPressed(e) && hasInternalTarget(e)) {
  6846. mouseHandlers.mouseover(fromRawEvent(e));
  6847. }
  6848. };
  6849. const mouseUp = e => {
  6850. if (isLeftMouse(e) && hasInternalTarget(e)) {
  6851. mouseHandlers.mouseup(fromRawEvent(e));
  6852. }
  6853. };
  6854. const getDoubleTap = () => {
  6855. const lastTarget = Cell(SugarElement.fromDom(body));
  6856. const lastTimeStamp = Cell(0);
  6857. const touchEnd = t => {
  6858. const target = SugarElement.fromDom(t.target);
  6859. if (isTag('td')(target) || isTag('th')(target)) {
  6860. const lT = lastTarget.get();
  6861. const lTS = lastTimeStamp.get();
  6862. if (eq$1(lT, target) && t.timeStamp - lTS < 300) {
  6863. t.preventDefault();
  6864. external$1(target, target);
  6865. }
  6866. }
  6867. lastTarget.set(target);
  6868. lastTimeStamp.set(t.timeStamp);
  6869. };
  6870. return { touchEnd };
  6871. };
  6872. const doubleTap = getDoubleTap();
  6873. editor.on('dragstart', dragStart);
  6874. editor.on('mousedown', mouseDown);
  6875. editor.on('mouseover', mouseOver);
  6876. editor.on('mouseup', mouseUp);
  6877. editor.on('touchend', doubleTap.touchEnd);
  6878. editor.on('keyup', keyup);
  6879. editor.on('keydown', keydown);
  6880. editor.on('NodeChange', syncSelection);
  6881. });
  6882. editor.on('PreInit', () => {
  6883. editor.serializer.addTempAttr(ephemera.firstSelected);
  6884. editor.serializer.addTempAttr(ephemera.lastSelected);
  6885. });
  6886. const clearSelectedCells = container => annotations.clear(SugarElement.fromDom(container));
  6887. const getSelectedCells = () => fold(cellSelection.get(), constant([]), cells => {
  6888. return map$1(cells, cell => cell.dom);
  6889. }, cell => [cell.dom]);
  6890. return {
  6891. getSelectedCells,
  6892. clearSelectedCells
  6893. };
  6894. };
  6895. const Event = fields => {
  6896. let handlers = [];
  6897. const bind = handler => {
  6898. if (handler === undefined) {
  6899. throw new Error('Event bind error: undefined handler');
  6900. }
  6901. handlers.push(handler);
  6902. };
  6903. const unbind = handler => {
  6904. handlers = filter$2(handlers, h => {
  6905. return h !== handler;
  6906. });
  6907. };
  6908. const trigger = (...args) => {
  6909. const event = {};
  6910. each$2(fields, (name, i) => {
  6911. event[name] = args[i];
  6912. });
  6913. each$2(handlers, handler => {
  6914. handler(event);
  6915. });
  6916. };
  6917. return {
  6918. bind,
  6919. unbind,
  6920. trigger
  6921. };
  6922. };
  6923. const create$1 = typeDefs => {
  6924. const registry = map(typeDefs, event => {
  6925. return {
  6926. bind: event.bind,
  6927. unbind: event.unbind
  6928. };
  6929. });
  6930. const trigger = map(typeDefs, event => {
  6931. return event.trigger;
  6932. });
  6933. return {
  6934. registry,
  6935. trigger
  6936. };
  6937. };
  6938. const last = (fn, rate) => {
  6939. let timer = null;
  6940. const cancel = () => {
  6941. if (!isNull(timer)) {
  6942. clearTimeout(timer);
  6943. timer = null;
  6944. }
  6945. };
  6946. const throttle = (...args) => {
  6947. cancel();
  6948. timer = setTimeout(() => {
  6949. timer = null;
  6950. fn.apply(null, args);
  6951. }, rate);
  6952. };
  6953. return {
  6954. cancel,
  6955. throttle
  6956. };
  6957. };
  6958. const sort = arr => {
  6959. return arr.slice(0).sort();
  6960. };
  6961. const reqMessage = (required, keys) => {
  6962. throw new Error('All required keys (' + sort(required).join(', ') + ') were not specified. Specified keys were: ' + sort(keys).join(', ') + '.');
  6963. };
  6964. const unsuppMessage = unsupported => {
  6965. throw new Error('Unsupported keys for object: ' + sort(unsupported).join(', '));
  6966. };
  6967. const validateStrArr = (label, array) => {
  6968. if (!isArray(array)) {
  6969. throw new Error('The ' + label + ' fields must be an array. Was: ' + array + '.');
  6970. }
  6971. each$2(array, a => {
  6972. if (!isString(a)) {
  6973. throw new Error('The value ' + a + ' in the ' + label + ' fields was not a string.');
  6974. }
  6975. });
  6976. };
  6977. const invalidTypeMessage = (incorrect, type) => {
  6978. throw new Error('All values need to be of type: ' + type + '. Keys (' + sort(incorrect).join(', ') + ') were not.');
  6979. };
  6980. const checkDupes = everything => {
  6981. const sorted = sort(everything);
  6982. const dupe = find$1(sorted, (s, i) => {
  6983. return i < sorted.length - 1 && s === sorted[i + 1];
  6984. });
  6985. dupe.each(d => {
  6986. throw new Error('The field: ' + d + ' occurs more than once in the combined fields: [' + sorted.join(', ') + '].');
  6987. });
  6988. };
  6989. const base = (handleUnsupported, required) => {
  6990. return baseWith(handleUnsupported, required, {
  6991. validate: isFunction,
  6992. label: 'function'
  6993. });
  6994. };
  6995. const baseWith = (handleUnsupported, required, pred) => {
  6996. if (required.length === 0) {
  6997. throw new Error('You must specify at least one required field.');
  6998. }
  6999. validateStrArr('required', required);
  7000. checkDupes(required);
  7001. return obj => {
  7002. const keys$1 = keys(obj);
  7003. const allReqd = forall(required, req => {
  7004. return contains$2(keys$1, req);
  7005. });
  7006. if (!allReqd) {
  7007. reqMessage(required, keys$1);
  7008. }
  7009. handleUnsupported(required, keys$1);
  7010. const invalidKeys = filter$2(required, key => {
  7011. return !pred.validate(obj[key], key);
  7012. });
  7013. if (invalidKeys.length > 0) {
  7014. invalidTypeMessage(invalidKeys, pred.label);
  7015. }
  7016. return obj;
  7017. };
  7018. };
  7019. const handleExact = (required, keys) => {
  7020. const unsupported = filter$2(keys, key => {
  7021. return !contains$2(required, key);
  7022. });
  7023. if (unsupported.length > 0) {
  7024. unsuppMessage(unsupported);
  7025. }
  7026. };
  7027. const exactly = required => base(handleExact, required);
  7028. const DragMode = exactly([
  7029. 'compare',
  7030. 'extract',
  7031. 'mutate',
  7032. 'sink'
  7033. ]);
  7034. const DragSink = exactly([
  7035. 'element',
  7036. 'start',
  7037. 'stop',
  7038. 'destroy'
  7039. ]);
  7040. const DragApi = exactly([
  7041. 'forceDrop',
  7042. 'drop',
  7043. 'move',
  7044. 'delayDrop'
  7045. ]);
  7046. const InDrag = () => {
  7047. let previous = Optional.none();
  7048. const reset = () => {
  7049. previous = Optional.none();
  7050. };
  7051. const update = (mode, nu) => {
  7052. const result = previous.map(old => {
  7053. return mode.compare(old, nu);
  7054. });
  7055. previous = Optional.some(nu);
  7056. return result;
  7057. };
  7058. const onEvent = (event, mode) => {
  7059. const dataOption = mode.extract(event);
  7060. dataOption.each(data => {
  7061. const offset = update(mode, data);
  7062. offset.each(d => {
  7063. events.trigger.move(d);
  7064. });
  7065. });
  7066. };
  7067. const events = create$1({ move: Event(['info']) });
  7068. return {
  7069. onEvent,
  7070. reset,
  7071. events: events.registry
  7072. };
  7073. };
  7074. const NoDrag = () => {
  7075. const events = create$1({ move: Event(['info']) });
  7076. return {
  7077. onEvent: noop,
  7078. reset: noop,
  7079. events: events.registry
  7080. };
  7081. };
  7082. const Movement = () => {
  7083. const noDragState = NoDrag();
  7084. const inDragState = InDrag();
  7085. let dragState = noDragState;
  7086. const on = () => {
  7087. dragState.reset();
  7088. dragState = inDragState;
  7089. };
  7090. const off = () => {
  7091. dragState.reset();
  7092. dragState = noDragState;
  7093. };
  7094. const onEvent = (event, mode) => {
  7095. dragState.onEvent(event, mode);
  7096. };
  7097. const isOn = () => {
  7098. return dragState === inDragState;
  7099. };
  7100. return {
  7101. on,
  7102. off,
  7103. isOn,
  7104. onEvent,
  7105. events: inDragState.events
  7106. };
  7107. };
  7108. const setup = (mutation, mode, settings) => {
  7109. let active = false;
  7110. const events = create$1({
  7111. start: Event([]),
  7112. stop: Event([])
  7113. });
  7114. const movement = Movement();
  7115. const drop = () => {
  7116. sink.stop();
  7117. if (movement.isOn()) {
  7118. movement.off();
  7119. events.trigger.stop();
  7120. }
  7121. };
  7122. const throttledDrop = last(drop, 200);
  7123. const go = parent => {
  7124. sink.start(parent);
  7125. movement.on();
  7126. events.trigger.start();
  7127. };
  7128. const mousemove = event => {
  7129. throttledDrop.cancel();
  7130. movement.onEvent(event, mode);
  7131. };
  7132. movement.events.move.bind(event => {
  7133. mode.mutate(mutation, event.info);
  7134. });
  7135. const on = () => {
  7136. active = true;
  7137. };
  7138. const off = () => {
  7139. active = false;
  7140. };
  7141. const runIfActive = f => {
  7142. return (...args) => {
  7143. if (active) {
  7144. f.apply(null, args);
  7145. }
  7146. };
  7147. };
  7148. const sink = mode.sink(DragApi({
  7149. forceDrop: drop,
  7150. drop: runIfActive(drop),
  7151. move: runIfActive(mousemove),
  7152. delayDrop: runIfActive(throttledDrop.throttle)
  7153. }), settings);
  7154. const destroy = () => {
  7155. sink.destroy();
  7156. };
  7157. return {
  7158. element: sink.element,
  7159. go,
  7160. on,
  7161. off,
  7162. destroy,
  7163. events: events.registry
  7164. };
  7165. };
  7166. const css = namespace => {
  7167. const dashNamespace = namespace.replace(/\./g, '-');
  7168. const resolve = str => {
  7169. return dashNamespace + '-' + str;
  7170. };
  7171. return { resolve };
  7172. };
  7173. const styles$1 = css('ephox-dragster');
  7174. const resolve$1 = styles$1.resolve;
  7175. const Blocker = options => {
  7176. const settings = {
  7177. layerClass: resolve$1('blocker'),
  7178. ...options
  7179. };
  7180. const div = SugarElement.fromTag('div');
  7181. set$2(div, 'role', 'presentation');
  7182. setAll(div, {
  7183. position: 'fixed',
  7184. left: '0px',
  7185. top: '0px',
  7186. width: '100%',
  7187. height: '100%'
  7188. });
  7189. add(div, resolve$1('blocker'));
  7190. add(div, settings.layerClass);
  7191. const element = constant(div);
  7192. const destroy = () => {
  7193. remove$6(div);
  7194. };
  7195. return {
  7196. element,
  7197. destroy
  7198. };
  7199. };
  7200. const compare = (old, nu) => {
  7201. return SugarPosition(nu.left - old.left, nu.top - old.top);
  7202. };
  7203. const extract = event => {
  7204. return Optional.some(SugarPosition(event.x, event.y));
  7205. };
  7206. const mutate = (mutation, info) => {
  7207. mutation.mutate(info.left, info.top);
  7208. };
  7209. const sink = (dragApi, settings) => {
  7210. const blocker = Blocker(settings);
  7211. const mdown = bind(blocker.element(), 'mousedown', dragApi.forceDrop);
  7212. const mup = bind(blocker.element(), 'mouseup', dragApi.drop);
  7213. const mmove = bind(blocker.element(), 'mousemove', dragApi.move);
  7214. const mout = bind(blocker.element(), 'mouseout', dragApi.delayDrop);
  7215. const destroy = () => {
  7216. blocker.destroy();
  7217. mup.unbind();
  7218. mmove.unbind();
  7219. mout.unbind();
  7220. mdown.unbind();
  7221. };
  7222. const start = parent => {
  7223. append$1(parent, blocker.element());
  7224. };
  7225. const stop = () => {
  7226. remove$6(blocker.element());
  7227. };
  7228. return DragSink({
  7229. element: blocker.element,
  7230. start,
  7231. stop,
  7232. destroy
  7233. });
  7234. };
  7235. var MouseDrag = DragMode({
  7236. compare,
  7237. extract,
  7238. sink,
  7239. mutate
  7240. });
  7241. const transform = (mutation, settings = {}) => {
  7242. var _a;
  7243. const mode = (_a = settings.mode) !== null && _a !== void 0 ? _a : MouseDrag;
  7244. return setup(mutation, mode, settings);
  7245. };
  7246. const styles = css('ephox-snooker');
  7247. const resolve = styles.resolve;
  7248. const Mutation = () => {
  7249. const events = create$1({
  7250. drag: Event([
  7251. 'xDelta',
  7252. 'yDelta'
  7253. ])
  7254. });
  7255. const mutate = (x, y) => {
  7256. events.trigger.drag(x, y);
  7257. };
  7258. return {
  7259. mutate,
  7260. events: events.registry
  7261. };
  7262. };
  7263. const BarMutation = () => {
  7264. const events = create$1({
  7265. drag: Event([
  7266. 'xDelta',
  7267. 'yDelta',
  7268. 'target'
  7269. ])
  7270. });
  7271. let target = Optional.none();
  7272. const delegate = Mutation();
  7273. delegate.events.drag.bind(event => {
  7274. target.each(t => {
  7275. events.trigger.drag(event.xDelta, event.yDelta, t);
  7276. });
  7277. });
  7278. const assign = t => {
  7279. target = Optional.some(t);
  7280. };
  7281. const get = () => {
  7282. return target;
  7283. };
  7284. return {
  7285. assign,
  7286. get,
  7287. mutate: delegate.mutate,
  7288. events: events.registry
  7289. };
  7290. };
  7291. const col = (column, x, y, w, h) => {
  7292. const bar = SugarElement.fromTag('div');
  7293. setAll(bar, {
  7294. position: 'absolute',
  7295. left: x - w / 2 + 'px',
  7296. top: y + 'px',
  7297. height: h + 'px',
  7298. width: w + 'px'
  7299. });
  7300. setAll$1(bar, {
  7301. 'data-column': column,
  7302. 'role': 'presentation'
  7303. });
  7304. return bar;
  7305. };
  7306. const row = (r, x, y, w, h) => {
  7307. const bar = SugarElement.fromTag('div');
  7308. setAll(bar, {
  7309. position: 'absolute',
  7310. left: x + 'px',
  7311. top: y - h / 2 + 'px',
  7312. height: h + 'px',
  7313. width: w + 'px'
  7314. });
  7315. setAll$1(bar, {
  7316. 'data-row': r,
  7317. 'role': 'presentation'
  7318. });
  7319. return bar;
  7320. };
  7321. const resizeBar = resolve('resizer-bar');
  7322. const resizeRowBar = resolve('resizer-rows');
  7323. const resizeColBar = resolve('resizer-cols');
  7324. const BAR_THICKNESS = 7;
  7325. const resizableRows = (warehouse, isResizable) => bind$2(warehouse.all, (row, i) => isResizable(row.element) ? [i] : []);
  7326. const resizableColumns = (warehouse, isResizable) => {
  7327. const resizableCols = [];
  7328. range$1(warehouse.grid.columns, index => {
  7329. const colElmOpt = Warehouse.getColumnAt(warehouse, index).map(col => col.element);
  7330. if (colElmOpt.forall(isResizable)) {
  7331. resizableCols.push(index);
  7332. }
  7333. });
  7334. return filter$2(resizableCols, colIndex => {
  7335. const columnCells = Warehouse.filterItems(warehouse, cell => cell.column === colIndex);
  7336. return forall(columnCells, cell => isResizable(cell.element));
  7337. });
  7338. };
  7339. const destroy = wire => {
  7340. const previous = descendants(wire.parent(), '.' + resizeBar);
  7341. each$2(previous, remove$6);
  7342. };
  7343. const drawBar = (wire, positions, create) => {
  7344. const origin = wire.origin();
  7345. each$2(positions, cpOption => {
  7346. cpOption.each(cp => {
  7347. const bar = create(origin, cp);
  7348. add(bar, resizeBar);
  7349. append$1(wire.parent(), bar);
  7350. });
  7351. });
  7352. };
  7353. const refreshCol = (wire, colPositions, position, tableHeight) => {
  7354. drawBar(wire, colPositions, (origin, cp) => {
  7355. const colBar = col(cp.col, cp.x - origin.left, position.top - origin.top, BAR_THICKNESS, tableHeight);
  7356. add(colBar, resizeColBar);
  7357. return colBar;
  7358. });
  7359. };
  7360. const refreshRow = (wire, rowPositions, position, tableWidth) => {
  7361. drawBar(wire, rowPositions, (origin, cp) => {
  7362. const rowBar = row(cp.row, position.left - origin.left, cp.y - origin.top, tableWidth, BAR_THICKNESS);
  7363. add(rowBar, resizeRowBar);
  7364. return rowBar;
  7365. });
  7366. };
  7367. const refreshGrid = (warhouse, wire, table, rows, cols) => {
  7368. const position = absolute(table);
  7369. const isResizable = wire.isResizable;
  7370. const rowPositions = rows.length > 0 ? height.positions(rows, table) : [];
  7371. const resizableRowBars = rowPositions.length > 0 ? resizableRows(warhouse, isResizable) : [];
  7372. const resizableRowPositions = filter$2(rowPositions, (_pos, i) => exists(resizableRowBars, barIndex => i === barIndex));
  7373. refreshRow(wire, resizableRowPositions, position, getOuter$2(table));
  7374. const colPositions = cols.length > 0 ? width.positions(cols, table) : [];
  7375. const resizableColBars = colPositions.length > 0 ? resizableColumns(warhouse, isResizable) : [];
  7376. const resizableColPositions = filter$2(colPositions, (_pos, i) => exists(resizableColBars, barIndex => i === barIndex));
  7377. refreshCol(wire, resizableColPositions, position, getOuter$1(table));
  7378. };
  7379. const refresh = (wire, table) => {
  7380. destroy(wire);
  7381. if (wire.isResizable(table)) {
  7382. const warehouse = Warehouse.fromTable(table);
  7383. const rows$1 = rows(warehouse);
  7384. const cols = columns(warehouse);
  7385. refreshGrid(warehouse, wire, table, rows$1, cols);
  7386. }
  7387. };
  7388. const each = (wire, f) => {
  7389. const bars = descendants(wire.parent(), '.' + resizeBar);
  7390. each$2(bars, f);
  7391. };
  7392. const hide = wire => {
  7393. each(wire, bar => {
  7394. set$1(bar, 'display', 'none');
  7395. });
  7396. };
  7397. const show = wire => {
  7398. each(wire, bar => {
  7399. set$1(bar, 'display', 'block');
  7400. });
  7401. };
  7402. const isRowBar = element => {
  7403. return has(element, resizeRowBar);
  7404. };
  7405. const isColBar = element => {
  7406. return has(element, resizeColBar);
  7407. };
  7408. const resizeBarDragging = resolve('resizer-bar-dragging');
  7409. const BarManager = wire => {
  7410. const mutation = BarMutation();
  7411. const resizing = transform(mutation, {});
  7412. let hoverTable = Optional.none();
  7413. const getResizer = (element, type) => {
  7414. return Optional.from(get$b(element, type));
  7415. };
  7416. mutation.events.drag.bind(event => {
  7417. getResizer(event.target, 'data-row').each(_dataRow => {
  7418. const currentRow = getCssValue(event.target, 'top');
  7419. set$1(event.target, 'top', currentRow + event.yDelta + 'px');
  7420. });
  7421. getResizer(event.target, 'data-column').each(_dataCol => {
  7422. const currentCol = getCssValue(event.target, 'left');
  7423. set$1(event.target, 'left', currentCol + event.xDelta + 'px');
  7424. });
  7425. });
  7426. const getDelta = (target, dir) => {
  7427. const newX = getCssValue(target, dir);
  7428. const oldX = getAttrValue(target, 'data-initial-' + dir, 0);
  7429. return newX - oldX;
  7430. };
  7431. resizing.events.stop.bind(() => {
  7432. mutation.get().each(target => {
  7433. hoverTable.each(table => {
  7434. getResizer(target, 'data-row').each(row => {
  7435. const delta = getDelta(target, 'top');
  7436. remove$7(target, 'data-initial-top');
  7437. events.trigger.adjustHeight(table, delta, parseInt(row, 10));
  7438. });
  7439. getResizer(target, 'data-column').each(column => {
  7440. const delta = getDelta(target, 'left');
  7441. remove$7(target, 'data-initial-left');
  7442. events.trigger.adjustWidth(table, delta, parseInt(column, 10));
  7443. });
  7444. refresh(wire, table);
  7445. });
  7446. });
  7447. });
  7448. const handler = (target, dir) => {
  7449. events.trigger.startAdjust();
  7450. mutation.assign(target);
  7451. set$2(target, 'data-initial-' + dir, getCssValue(target, dir));
  7452. add(target, resizeBarDragging);
  7453. set$1(target, 'opacity', '0.2');
  7454. resizing.go(wire.parent());
  7455. };
  7456. const mousedown = bind(wire.parent(), 'mousedown', event => {
  7457. if (isRowBar(event.target)) {
  7458. handler(event.target, 'top');
  7459. }
  7460. if (isColBar(event.target)) {
  7461. handler(event.target, 'left');
  7462. }
  7463. });
  7464. const isRoot = e => {
  7465. return eq$1(e, wire.view());
  7466. };
  7467. const findClosestEditableTable = target => closest$1(target, 'table', isRoot).filter(isEditable$1);
  7468. const mouseover = bind(wire.view(), 'mouseover', event => {
  7469. findClosestEditableTable(event.target).fold(() => {
  7470. if (inBody(event.target)) {
  7471. destroy(wire);
  7472. }
  7473. }, table => {
  7474. hoverTable = Optional.some(table);
  7475. refresh(wire, table);
  7476. });
  7477. });
  7478. const destroy$1 = () => {
  7479. mousedown.unbind();
  7480. mouseover.unbind();
  7481. resizing.destroy();
  7482. destroy(wire);
  7483. };
  7484. const refresh$1 = tbl => {
  7485. refresh(wire, tbl);
  7486. };
  7487. const events = create$1({
  7488. adjustHeight: Event([
  7489. 'table',
  7490. 'delta',
  7491. 'row'
  7492. ]),
  7493. adjustWidth: Event([
  7494. 'table',
  7495. 'delta',
  7496. 'column'
  7497. ]),
  7498. startAdjust: Event([])
  7499. });
  7500. return {
  7501. destroy: destroy$1,
  7502. refresh: refresh$1,
  7503. on: resizing.on,
  7504. off: resizing.off,
  7505. hideBars: curry(hide, wire),
  7506. showBars: curry(show, wire),
  7507. events: events.registry
  7508. };
  7509. };
  7510. const create = (wire, resizing, lazySizing) => {
  7511. const hdirection = height;
  7512. const vdirection = width;
  7513. const manager = BarManager(wire);
  7514. const events = create$1({
  7515. beforeResize: Event([
  7516. 'table',
  7517. 'type'
  7518. ]),
  7519. afterResize: Event([
  7520. 'table',
  7521. 'type'
  7522. ]),
  7523. startDrag: Event([])
  7524. });
  7525. manager.events.adjustHeight.bind(event => {
  7526. const table = event.table;
  7527. events.trigger.beforeResize(table, 'row');
  7528. const delta = hdirection.delta(event.delta, table);
  7529. adjustHeight(table, delta, event.row, hdirection);
  7530. events.trigger.afterResize(table, 'row');
  7531. });
  7532. manager.events.startAdjust.bind(_event => {
  7533. events.trigger.startDrag();
  7534. });
  7535. manager.events.adjustWidth.bind(event => {
  7536. const table = event.table;
  7537. events.trigger.beforeResize(table, 'col');
  7538. const delta = vdirection.delta(event.delta, table);
  7539. const tableSize = lazySizing(table);
  7540. adjustWidth(table, delta, event.column, resizing, tableSize);
  7541. events.trigger.afterResize(table, 'col');
  7542. });
  7543. return {
  7544. on: manager.on,
  7545. off: manager.off,
  7546. refreshBars: manager.refresh,
  7547. hideBars: manager.hideBars,
  7548. showBars: manager.showBars,
  7549. destroy: manager.destroy,
  7550. events: events.registry
  7551. };
  7552. };
  7553. const TableResize = { create };
  7554. const only = (element, isResizable) => {
  7555. const parent = isDocument(element) ? documentElement(element) : element;
  7556. return {
  7557. parent: constant(parent),
  7558. view: constant(element),
  7559. origin: constant(SugarPosition(0, 0)),
  7560. isResizable
  7561. };
  7562. };
  7563. const detached = (editable, chrome, isResizable) => {
  7564. const origin = () => absolute(chrome);
  7565. return {
  7566. parent: constant(chrome),
  7567. view: constant(editable),
  7568. origin,
  7569. isResizable
  7570. };
  7571. };
  7572. const body = (editable, chrome, isResizable) => {
  7573. return {
  7574. parent: constant(chrome),
  7575. view: constant(editable),
  7576. origin: constant(SugarPosition(0, 0)),
  7577. isResizable
  7578. };
  7579. };
  7580. const ResizeWire = {
  7581. only,
  7582. detached,
  7583. body
  7584. };
  7585. const createContainer = () => {
  7586. const container = SugarElement.fromTag('div');
  7587. setAll(container, {
  7588. position: 'static',
  7589. height: '0',
  7590. width: '0',
  7591. padding: '0',
  7592. margin: '0',
  7593. border: '0'
  7594. });
  7595. append$1(body$1(), container);
  7596. return container;
  7597. };
  7598. const get = (editor, isResizable) => {
  7599. return editor.inline ? ResizeWire.body(SugarElement.fromDom(editor.getBody()), createContainer(), isResizable) : ResizeWire.only(SugarElement.fromDom(editor.getDoc()), isResizable);
  7600. };
  7601. const remove = (editor, wire) => {
  7602. if (editor.inline) {
  7603. remove$6(wire.parent());
  7604. }
  7605. };
  7606. const isTable = node => isNonNullable(node) && node.tagName === 'TABLE';
  7607. const barResizerPrefix = 'bar-';
  7608. const isResizable = elm => get$b(elm, 'data-mce-resize') !== 'false';
  7609. const syncPixels = table => {
  7610. const warehouse = Warehouse.fromTable(table);
  7611. if (!Warehouse.hasColumns(warehouse)) {
  7612. each$2(cells$1(table), cell => {
  7613. const computedWidth = get$a(cell, 'width');
  7614. set$1(cell, 'width', computedWidth);
  7615. remove$7(cell, 'width');
  7616. });
  7617. }
  7618. };
  7619. const TableResizeHandler = editor => {
  7620. const selectionRng = value();
  7621. const tableResize = value();
  7622. const resizeWire = value();
  7623. let startW;
  7624. let startRawW;
  7625. const lazySizing = table => get$5(editor, table);
  7626. const lazyResizingBehaviour = () => isPreserveTableColumnResizing(editor) ? preserveTable() : resizeTable();
  7627. const getNumColumns = table => getGridSize(table).columns;
  7628. const afterCornerResize = (table, origin, width) => {
  7629. const isRightEdgeResize = endsWith(origin, 'e');
  7630. if (startRawW === '') {
  7631. convertToPercentSize(table);
  7632. }
  7633. if (width !== startW && startRawW !== '') {
  7634. set$1(table, 'width', startRawW);
  7635. const resizing = lazyResizingBehaviour();
  7636. const tableSize = lazySizing(table);
  7637. const col = isPreserveTableColumnResizing(editor) || isRightEdgeResize ? getNumColumns(table) - 1 : 0;
  7638. adjustWidth(table, width - startW, col, resizing, tableSize);
  7639. } else if (isPercentage$1(startRawW)) {
  7640. const percentW = parseFloat(startRawW.replace('%', ''));
  7641. const targetPercentW = width * percentW / startW;
  7642. set$1(table, 'width', targetPercentW + '%');
  7643. }
  7644. if (isPixel(startRawW)) {
  7645. syncPixels(table);
  7646. }
  7647. };
  7648. const destroy = () => {
  7649. tableResize.on(sz => {
  7650. sz.destroy();
  7651. });
  7652. resizeWire.on(w => {
  7653. remove(editor, w);
  7654. });
  7655. };
  7656. editor.on('init', () => {
  7657. const rawWire = get(editor, isResizable);
  7658. resizeWire.set(rawWire);
  7659. if (hasTableObjectResizing(editor) && hasTableResizeBars(editor)) {
  7660. const resizing = lazyResizingBehaviour();
  7661. const sz = TableResize.create(rawWire, resizing, lazySizing);
  7662. sz.on();
  7663. sz.events.startDrag.bind(_event => {
  7664. selectionRng.set(editor.selection.getRng());
  7665. });
  7666. sz.events.beforeResize.bind(event => {
  7667. const rawTable = event.table.dom;
  7668. fireObjectResizeStart(editor, rawTable, getPixelWidth(rawTable), getPixelHeight(rawTable), barResizerPrefix + event.type);
  7669. });
  7670. sz.events.afterResize.bind(event => {
  7671. const table = event.table;
  7672. const rawTable = table.dom;
  7673. removeDataStyle(table);
  7674. selectionRng.on(rng => {
  7675. editor.selection.setRng(rng);
  7676. editor.focus();
  7677. });
  7678. fireObjectResized(editor, rawTable, getPixelWidth(rawTable), getPixelHeight(rawTable), barResizerPrefix + event.type);
  7679. editor.undoManager.add();
  7680. });
  7681. tableResize.set(sz);
  7682. }
  7683. });
  7684. editor.on('ObjectResizeStart', e => {
  7685. const targetElm = e.target;
  7686. if (isTable(targetElm)) {
  7687. const table = SugarElement.fromDom(targetElm);
  7688. each$2(editor.dom.select('.mce-clonedresizable'), clone => {
  7689. editor.dom.addClass(clone, 'mce-' + getTableColumnResizingBehaviour(editor) + '-columns');
  7690. });
  7691. if (!isPixelSizing(table) && isTablePixelsForced(editor)) {
  7692. convertToPixelSize(table);
  7693. } else if (!isPercentSizing(table) && isTablePercentagesForced(editor)) {
  7694. convertToPercentSize(table);
  7695. }
  7696. if (isNoneSizing(table) && startsWith(e.origin, barResizerPrefix)) {
  7697. convertToPercentSize(table);
  7698. }
  7699. startW = e.width;
  7700. startRawW = isTableResponsiveForced(editor) ? '' : getRawWidth(editor, targetElm).getOr('');
  7701. }
  7702. });
  7703. editor.on('ObjectResized', e => {
  7704. const targetElm = e.target;
  7705. if (isTable(targetElm)) {
  7706. const table = SugarElement.fromDom(targetElm);
  7707. const origin = e.origin;
  7708. if (startsWith(origin, 'corner-')) {
  7709. afterCornerResize(table, origin, e.width);
  7710. }
  7711. removeDataStyle(table);
  7712. fireTableModified(editor, table.dom, styleModified);
  7713. }
  7714. });
  7715. editor.on('SwitchMode', () => {
  7716. tableResize.on(resize => {
  7717. if (editor.mode.isReadOnly()) {
  7718. resize.hideBars();
  7719. } else {
  7720. resize.showBars();
  7721. }
  7722. });
  7723. });
  7724. editor.on('remove', () => {
  7725. destroy();
  7726. });
  7727. const refresh = table => {
  7728. tableResize.on(resize => resize.refreshBars(SugarElement.fromDom(table)));
  7729. };
  7730. const hide = () => {
  7731. tableResize.on(resize => resize.hideBars());
  7732. };
  7733. const show = () => {
  7734. tableResize.on(resize => resize.showBars());
  7735. };
  7736. return {
  7737. refresh,
  7738. hide,
  7739. show
  7740. };
  7741. };
  7742. const setupTable = editor => {
  7743. register(editor);
  7744. const resizeHandler = TableResizeHandler(editor);
  7745. const cellSelectionHandler = TableCellSelectionHandler(editor, resizeHandler);
  7746. const actions = TableActions(editor, resizeHandler, cellSelectionHandler);
  7747. registerCommands(editor, actions);
  7748. registerQueryCommands(editor, actions);
  7749. registerEvents(editor, actions);
  7750. return {
  7751. getSelectedCells: cellSelectionHandler.getSelectedCells,
  7752. clearSelectedCells: cellSelectionHandler.clearSelectedCells
  7753. };
  7754. };
  7755. const DomModel = editor => {
  7756. const table = setupTable(editor);
  7757. return { table };
  7758. };
  7759. var Model = () => {
  7760. global$1.add('dom', DomModel);
  7761. };
  7762. Model();
  7763. })();