123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811118121181311814118151181611817118181181911820118211182211823118241182511826118271182811829118301183111832118331183411835118361183711838118391184011841118421184311844118451184611847118481184911850118511185211853118541185511856118571185811859118601186111862118631186411865118661186711868118691187011871118721187311874118751187611877118781187911880118811188211883118841188511886118871188811889118901189111892118931189411895118961189711898118991190011901119021190311904119051190611907119081190911910119111191211913119141191511916119171191811919119201192111922119231192411925119261192711928119291193011931119321193311934119351193611937119381193911940119411194211943119441194511946119471194811949119501195111952119531195411955119561195711958119591196011961119621196311964119651196611967119681196911970119711197211973119741197511976119771197811979119801198111982119831198411985119861198711988119891199011991119921199311994119951199611997119981199912000120011200212003120041200512006120071200812009120101201112012120131201412015120161201712018120191202012021120221202312024120251202612027120281202912030120311203212033120341203512036120371203812039120401204112042120431204412045120461204712048120491205012051120521205312054120551205612057120581205912060120611206212063120641206512066120671206812069120701207112072120731207412075120761207712078120791208012081120821208312084120851208612087120881208912090120911209212093120941209512096120971209812099121001210112102121031210412105121061210712108121091211012111121121211312114121151211612117121181211912120121211212212123121241212512126121271212812129121301213112132121331213412135121361213712138121391214012141121421214312144121451214612147121481214912150121511215212153121541215512156121571215812159121601216112162121631216412165121661216712168121691217012171121721217312174121751217612177121781217912180121811218212183121841218512186121871218812189121901219112192121931219412195121961219712198121991220012201122021220312204122051220612207122081220912210122111221212213122141221512216122171221812219122201222112222122231222412225122261222712228122291223012231122321223312234122351223612237122381223912240122411224212243122441224512246122471224812249122501225112252122531225412255122561225712258122591226012261122621226312264122651226612267122681226912270122711227212273122741227512276122771227812279122801228112282122831228412285122861228712288122891229012291122921229312294122951229612297122981229912300123011230212303123041230512306123071230812309123101231112312123131231412315123161231712318123191232012321123221232312324123251232612327123281232912330123311233212333123341233512336123371233812339123401234112342123431234412345123461234712348123491235012351123521235312354123551235612357123581235912360123611236212363123641236512366123671236812369123701237112372123731237412375123761237712378123791238012381123821238312384123851238612387123881238912390123911239212393123941239512396123971239812399124001240112402124031240412405124061240712408124091241012411124121241312414124151241612417124181241912420124211242212423124241242512426124271242812429124301243112432124331243412435124361243712438124391244012441124421244312444124451244612447124481244912450124511245212453124541245512456124571245812459124601246112462124631246412465124661246712468124691247012471124721247312474124751247612477124781247912480124811248212483124841248512486124871248812489124901249112492124931249412495124961249712498124991250012501125021250312504125051250612507125081250912510125111251212513125141251512516125171251812519125201252112522125231252412525125261252712528125291253012531125321253312534125351253612537125381253912540125411254212543125441254512546125471254812549125501255112552125531255412555125561255712558125591256012561125621256312564125651256612567125681256912570125711257212573125741257512576125771257812579125801258112582125831258412585125861258712588125891259012591125921259312594125951259612597125981259912600126011260212603126041260512606126071260812609126101261112612126131261412615126161261712618126191262012621126221262312624126251262612627126281262912630126311263212633126341263512636126371263812639126401264112642126431264412645126461264712648126491265012651126521265312654126551265612657126581265912660126611266212663126641266512666126671266812669126701267112672126731267412675126761267712678126791268012681126821268312684126851268612687126881268912690126911269212693126941269512696126971269812699127001270112702127031270412705127061270712708127091271012711127121271312714127151271612717127181271912720127211272212723127241272512726127271272812729127301273112732127331273412735127361273712738127391274012741127421274312744127451274612747127481274912750127511275212753127541275512756127571275812759127601276112762127631276412765127661276712768127691277012771127721277312774127751277612777127781277912780127811278212783127841278512786127871278812789127901279112792127931279412795127961279712798127991280012801128021280312804128051280612807128081280912810128111281212813128141281512816128171281812819128201282112822128231282412825128261282712828128291283012831128321283312834128351283612837128381283912840128411284212843128441284512846128471284812849128501285112852128531285412855128561285712858128591286012861128621286312864128651286612867128681286912870128711287212873128741287512876128771287812879128801288112882128831288412885128861288712888128891289012891128921289312894128951289612897128981289912900129011290212903129041290512906129071290812909129101291112912129131291412915129161291712918129191292012921129221292312924129251292612927129281292912930129311293212933129341293512936129371293812939129401294112942129431294412945129461294712948129491295012951129521295312954129551295612957129581295912960129611296212963129641296512966129671296812969129701297112972129731297412975129761297712978129791298012981129821298312984129851298612987129881298912990129911299212993129941299512996129971299812999130001300113002130031300413005130061300713008130091301013011130121301313014130151301613017130181301913020130211302213023130241302513026130271302813029130301303113032130331303413035130361303713038130391304013041130421304313044130451304613047130481304913050130511305213053130541305513056130571305813059130601306113062130631306413065130661306713068130691307013071130721307313074130751307613077130781307913080130811308213083130841308513086130871308813089130901309113092130931309413095130961309713098130991310013101131021310313104131051310613107131081310913110131111311213113131141311513116131171311813119131201312113122131231312413125131261312713128131291313013131131321313313134131351313613137131381313913140131411314213143131441314513146131471314813149131501315113152131531315413155131561315713158131591316013161131621316313164131651316613167131681316913170131711317213173131741317513176131771317813179131801318113182131831318413185131861318713188131891319013191131921319313194131951319613197131981319913200132011320213203132041320513206132071320813209132101321113212132131321413215132161321713218132191322013221132221322313224132251322613227132281322913230132311323213233132341323513236132371323813239132401324113242132431324413245132461324713248132491325013251132521325313254132551325613257132581325913260132611326213263132641326513266132671326813269132701327113272132731327413275132761327713278132791328013281132821328313284132851328613287132881328913290132911329213293132941329513296132971329813299133001330113302133031330413305133061330713308133091331013311133121331313314133151331613317133181331913320133211332213323133241332513326133271332813329133301333113332133331333413335133361333713338133391334013341133421334313344133451334613347133481334913350133511335213353133541335513356133571335813359133601336113362133631336413365133661336713368133691337013371133721337313374133751337613377133781337913380133811338213383133841338513386133871338813389133901339113392133931339413395133961339713398133991340013401134021340313404134051340613407134081340913410134111341213413134141341513416134171341813419134201342113422134231342413425134261342713428134291343013431134321343313434134351343613437134381343913440134411344213443134441344513446134471344813449134501345113452134531345413455134561345713458134591346013461134621346313464134651346613467134681346913470134711347213473134741347513476134771347813479134801348113482134831348413485134861348713488134891349013491134921349313494134951349613497134981349913500135011350213503135041350513506135071350813509135101351113512135131351413515135161351713518135191352013521135221352313524135251352613527135281352913530135311353213533135341353513536135371353813539135401354113542135431354413545135461354713548135491355013551135521355313554135551355613557135581355913560135611356213563135641356513566135671356813569135701357113572135731357413575135761357713578135791358013581135821358313584135851358613587135881358913590135911359213593135941359513596135971359813599136001360113602136031360413605136061360713608136091361013611136121361313614136151361613617136181361913620136211362213623136241362513626136271362813629136301363113632136331363413635136361363713638136391364013641136421364313644136451364613647136481364913650136511365213653136541365513656136571365813659136601366113662136631366413665136661366713668136691367013671136721367313674136751367613677136781367913680136811368213683136841368513686136871368813689136901369113692136931369413695136961369713698136991370013701137021370313704137051370613707137081370913710137111371213713137141371513716137171371813719137201372113722137231372413725137261372713728137291373013731137321373313734137351373613737137381373913740137411374213743137441374513746137471374813749137501375113752137531375413755137561375713758137591376013761137621376313764137651376613767137681376913770137711377213773137741377513776137771377813779137801378113782137831378413785137861378713788137891379013791137921379313794137951379613797137981379913800138011380213803138041380513806138071380813809138101381113812138131381413815138161381713818138191382013821138221382313824138251382613827138281382913830138311383213833138341383513836138371383813839138401384113842138431384413845138461384713848138491385013851138521385313854138551385613857138581385913860138611386213863138641386513866138671386813869138701387113872138731387413875138761387713878138791388013881138821388313884138851388613887138881388913890138911389213893138941389513896138971389813899139001390113902139031390413905139061390713908139091391013911139121391313914139151391613917139181391913920139211392213923139241392513926139271392813929139301393113932139331393413935139361393713938139391394013941139421394313944139451394613947139481394913950139511395213953139541395513956139571395813959139601396113962139631396413965139661396713968139691397013971139721397313974139751397613977139781397913980139811398213983139841398513986139871398813989139901399113992139931399413995139961399713998139991400014001140021400314004140051400614007140081400914010140111401214013140141401514016140171401814019140201402114022140231402414025140261402714028140291403014031140321403314034140351403614037140381403914040140411404214043140441404514046140471404814049140501405114052140531405414055140561405714058140591406014061140621406314064140651406614067140681406914070140711407214073140741407514076140771407814079140801408114082140831408414085140861408714088140891409014091140921409314094140951409614097140981409914100141011410214103141041410514106141071410814109141101411114112141131411414115141161411714118141191412014121141221412314124141251412614127141281412914130141311413214133141341413514136141371413814139141401414114142141431414414145141461414714148141491415014151141521415314154141551415614157141581415914160141611416214163141641416514166141671416814169141701417114172141731417414175141761417714178141791418014181141821418314184141851418614187141881418914190141911419214193141941419514196141971419814199142001420114202142031420414205142061420714208142091421014211142121421314214142151421614217142181421914220142211422214223142241422514226142271422814229142301423114232142331423414235142361423714238142391424014241142421424314244142451424614247142481424914250142511425214253142541425514256142571425814259142601426114262142631426414265142661426714268142691427014271142721427314274142751427614277142781427914280142811428214283142841428514286142871428814289142901429114292142931429414295142961429714298142991430014301143021430314304143051430614307143081430914310143111431214313143141431514316143171431814319143201432114322143231432414325143261432714328143291433014331143321433314334143351433614337143381433914340143411434214343143441434514346143471434814349143501435114352143531435414355143561435714358143591436014361143621436314364143651436614367143681436914370143711437214373143741437514376143771437814379143801438114382143831438414385143861438714388143891439014391143921439314394143951439614397143981439914400144011440214403144041440514406144071440814409144101441114412144131441414415144161441714418144191442014421144221442314424144251442614427144281442914430144311443214433144341443514436144371443814439144401444114442144431444414445144461444714448144491445014451144521445314454144551445614457144581445914460144611446214463144641446514466144671446814469144701447114472144731447414475144761447714478144791448014481144821448314484144851448614487144881448914490144911449214493144941449514496144971449814499145001450114502145031450414505145061450714508145091451014511145121451314514145151451614517145181451914520145211452214523145241452514526145271452814529145301453114532145331453414535145361453714538145391454014541145421454314544145451454614547145481454914550145511455214553145541455514556145571455814559145601456114562145631456414565145661456714568145691457014571145721457314574145751457614577145781457914580145811458214583145841458514586145871458814589145901459114592145931459414595145961459714598145991460014601146021460314604146051460614607146081460914610146111461214613146141461514616146171461814619146201462114622146231462414625146261462714628146291463014631146321463314634146351463614637146381463914640146411464214643146441464514646146471464814649146501465114652146531465414655146561465714658146591466014661146621466314664146651466614667146681466914670146711467214673146741467514676146771467814679146801468114682146831468414685146861468714688146891469014691146921469314694146951469614697146981469914700147011470214703147041470514706147071470814709147101471114712147131471414715147161471714718147191472014721147221472314724147251472614727147281472914730147311473214733147341473514736147371473814739147401474114742147431474414745147461474714748147491475014751147521475314754147551475614757147581475914760147611476214763147641476514766147671476814769147701477114772147731477414775147761477714778147791478014781147821478314784147851478614787147881478914790147911479214793147941479514796147971479814799148001480114802148031480414805148061480714808148091481014811148121481314814148151481614817148181481914820148211482214823148241482514826148271482814829148301483114832148331483414835148361483714838148391484014841148421484314844148451484614847148481484914850148511485214853148541485514856148571485814859148601486114862148631486414865148661486714868148691487014871148721487314874148751487614877148781487914880148811488214883148841488514886148871488814889148901489114892148931489414895148961489714898148991490014901149021490314904149051490614907149081490914910149111491214913149141491514916149171491814919149201492114922149231492414925149261492714928149291493014931149321493314934149351493614937149381493914940149411494214943149441494514946149471494814949149501495114952149531495414955149561495714958149591496014961149621496314964149651496614967149681496914970149711497214973149741497514976149771497814979149801498114982149831498414985149861498714988149891499014991149921499314994149951499614997149981499915000150011500215003150041500515006150071500815009150101501115012150131501415015150161501715018150191502015021150221502315024150251502615027150281502915030150311503215033150341503515036150371503815039150401504115042150431504415045150461504715048150491505015051150521505315054150551505615057150581505915060150611506215063150641506515066150671506815069150701507115072150731507415075150761507715078150791508015081150821508315084150851508615087150881508915090150911509215093150941509515096150971509815099151001510115102151031510415105151061510715108151091511015111151121511315114151151511615117151181511915120151211512215123151241512515126151271512815129151301513115132151331513415135151361513715138151391514015141151421514315144151451514615147151481514915150151511515215153151541515515156151571515815159151601516115162151631516415165151661516715168151691517015171151721517315174151751517615177151781517915180151811518215183151841518515186151871518815189151901519115192151931519415195151961519715198151991520015201152021520315204152051520615207152081520915210152111521215213152141521515216152171521815219152201522115222152231522415225152261522715228152291523015231152321523315234152351523615237152381523915240152411524215243152441524515246152471524815249152501525115252152531525415255152561525715258152591526015261152621526315264152651526615267152681526915270152711527215273152741527515276152771527815279152801528115282152831528415285152861528715288152891529015291152921529315294152951529615297152981529915300153011530215303153041530515306153071530815309153101531115312153131531415315153161531715318153191532015321153221532315324153251532615327153281532915330153311533215333153341533515336153371533815339153401534115342153431534415345153461534715348153491535015351153521535315354153551535615357153581535915360153611536215363153641536515366153671536815369153701537115372153731537415375153761537715378153791538015381153821538315384153851538615387153881538915390153911539215393153941539515396153971539815399154001540115402154031540415405154061540715408154091541015411154121541315414154151541615417154181541915420154211542215423154241542515426154271542815429154301543115432154331543415435154361543715438154391544015441154421544315444154451544615447154481544915450154511545215453154541545515456154571545815459154601546115462154631546415465154661546715468154691547015471154721547315474154751547615477154781547915480154811548215483154841548515486154871548815489154901549115492154931549415495154961549715498154991550015501155021550315504155051550615507155081550915510155111551215513155141551515516155171551815519155201552115522155231552415525155261552715528155291553015531155321553315534155351553615537155381553915540155411554215543155441554515546155471554815549155501555115552155531555415555155561555715558155591556015561155621556315564155651556615567155681556915570155711557215573155741557515576155771557815579155801558115582155831558415585155861558715588155891559015591155921559315594155951559615597155981559915600156011560215603156041560515606156071560815609156101561115612156131561415615156161561715618156191562015621156221562315624156251562615627156281562915630156311563215633156341563515636156371563815639156401564115642156431564415645156461564715648156491565015651156521565315654156551565615657156581565915660156611566215663156641566515666156671566815669156701567115672156731567415675156761567715678156791568015681156821568315684156851568615687156881568915690156911569215693156941569515696156971569815699157001570115702157031570415705157061570715708157091571015711157121571315714157151571615717157181571915720157211572215723157241572515726157271572815729157301573115732157331573415735157361573715738157391574015741157421574315744157451574615747157481574915750157511575215753157541575515756157571575815759157601576115762157631576415765157661576715768157691577015771157721577315774157751577615777157781577915780157811578215783157841578515786157871578815789157901579115792157931579415795157961579715798157991580015801158021580315804158051580615807158081580915810158111581215813158141581515816158171581815819158201582115822158231582415825158261582715828158291583015831158321583315834158351583615837158381583915840158411584215843158441584515846158471584815849158501585115852158531585415855158561585715858158591586015861158621586315864158651586615867158681586915870158711587215873158741587515876158771587815879158801588115882158831588415885158861588715888158891589015891158921589315894158951589615897158981589915900159011590215903159041590515906159071590815909159101591115912159131591415915159161591715918159191592015921159221592315924159251592615927159281592915930159311593215933159341593515936159371593815939159401594115942159431594415945159461594715948159491595015951159521595315954159551595615957159581595915960159611596215963159641596515966159671596815969159701597115972159731597415975159761597715978159791598015981159821598315984159851598615987159881598915990159911599215993159941599515996159971599815999160001600116002160031600416005160061600716008160091601016011160121601316014160151601616017160181601916020160211602216023160241602516026160271602816029160301603116032160331603416035160361603716038160391604016041160421604316044160451604616047160481604916050160511605216053160541605516056160571605816059160601606116062160631606416065160661606716068160691607016071160721607316074160751607616077160781607916080160811608216083160841608516086160871608816089160901609116092160931609416095160961609716098160991610016101161021610316104161051610616107161081610916110161111611216113161141611516116161171611816119161201612116122161231612416125161261612716128161291613016131161321613316134161351613616137161381613916140161411614216143161441614516146161471614816149161501615116152161531615416155161561615716158161591616016161161621616316164161651616616167161681616916170161711617216173161741617516176161771617816179161801618116182161831618416185161861618716188161891619016191161921619316194161951619616197161981619916200162011620216203162041620516206162071620816209162101621116212162131621416215162161621716218162191622016221162221622316224162251622616227162281622916230162311623216233162341623516236162371623816239162401624116242162431624416245162461624716248162491625016251162521625316254162551625616257162581625916260162611626216263162641626516266162671626816269162701627116272162731627416275162761627716278162791628016281162821628316284162851628616287162881628916290162911629216293162941629516296162971629816299163001630116302163031630416305163061630716308163091631016311163121631316314163151631616317163181631916320163211632216323163241632516326163271632816329163301633116332163331633416335163361633716338163391634016341163421634316344163451634616347163481634916350163511635216353163541635516356163571635816359163601636116362163631636416365163661636716368163691637016371163721637316374163751637616377163781637916380163811638216383163841638516386163871638816389163901639116392163931639416395163961639716398163991640016401164021640316404164051640616407164081640916410164111641216413164141641516416164171641816419164201642116422164231642416425164261642716428164291643016431164321643316434164351643616437164381643916440164411644216443164441644516446164471644816449164501645116452164531645416455164561645716458164591646016461164621646316464164651646616467164681646916470164711647216473164741647516476164771647816479164801648116482164831648416485164861648716488164891649016491164921649316494164951649616497164981649916500165011650216503165041650516506165071650816509165101651116512165131651416515165161651716518165191652016521165221652316524165251652616527165281652916530165311653216533165341653516536165371653816539165401654116542165431654416545165461654716548165491655016551165521655316554165551655616557165581655916560165611656216563165641656516566165671656816569165701657116572165731657416575165761657716578165791658016581165821658316584165851658616587165881658916590165911659216593165941659516596165971659816599166001660116602166031660416605166061660716608166091661016611166121661316614166151661616617166181661916620166211662216623166241662516626166271662816629166301663116632166331663416635166361663716638166391664016641166421664316644166451664616647166481664916650166511665216653166541665516656166571665816659166601666116662166631666416665166661666716668166691667016671166721667316674166751667616677166781667916680166811668216683166841668516686166871668816689166901669116692166931669416695166961669716698166991670016701167021670316704167051670616707167081670916710167111671216713167141671516716167171671816719167201672116722167231672416725167261672716728167291673016731167321673316734167351673616737167381673916740167411674216743167441674516746167471674816749167501675116752167531675416755167561675716758167591676016761167621676316764167651676616767167681676916770167711677216773167741677516776167771677816779167801678116782167831678416785167861678716788167891679016791167921679316794167951679616797167981679916800168011680216803168041680516806168071680816809168101681116812168131681416815168161681716818168191682016821168221682316824168251682616827168281682916830168311683216833168341683516836168371683816839168401684116842168431684416845168461684716848168491685016851168521685316854168551685616857168581685916860168611686216863168641686516866168671686816869168701687116872168731687416875168761687716878168791688016881168821688316884168851688616887168881688916890168911689216893168941689516896168971689816899169001690116902169031690416905169061690716908169091691016911169121691316914169151691616917169181691916920169211692216923169241692516926169271692816929169301693116932169331693416935169361693716938169391694016941169421694316944169451694616947169481694916950169511695216953169541695516956169571695816959169601696116962169631696416965169661696716968169691697016971169721697316974169751697616977169781697916980169811698216983169841698516986169871698816989169901699116992169931699416995169961699716998169991700017001170021700317004170051700617007170081700917010170111701217013170141701517016170171701817019170201702117022170231702417025170261702717028170291703017031170321703317034170351703617037170381703917040170411704217043170441704517046170471704817049170501705117052170531705417055170561705717058170591706017061170621706317064170651706617067170681706917070170711707217073170741707517076170771707817079170801708117082170831708417085170861708717088170891709017091170921709317094170951709617097170981709917100171011710217103171041710517106171071710817109171101711117112171131711417115171161711717118171191712017121171221712317124171251712617127171281712917130171311713217133171341713517136171371713817139171401714117142171431714417145171461714717148171491715017151171521715317154171551715617157171581715917160171611716217163171641716517166171671716817169171701717117172171731717417175171761717717178171791718017181171821718317184171851718617187171881718917190171911719217193171941719517196171971719817199172001720117202172031720417205172061720717208172091721017211172121721317214172151721617217172181721917220172211722217223172241722517226172271722817229172301723117232172331723417235172361723717238172391724017241172421724317244172451724617247172481724917250172511725217253172541725517256172571725817259172601726117262172631726417265172661726717268172691727017271172721727317274172751727617277172781727917280172811728217283172841728517286172871728817289172901729117292172931729417295172961729717298172991730017301173021730317304173051730617307173081730917310173111731217313173141731517316173171731817319173201732117322173231732417325173261732717328173291733017331173321733317334173351733617337173381733917340173411734217343173441734517346173471734817349173501735117352173531735417355173561735717358173591736017361173621736317364173651736617367173681736917370173711737217373173741737517376173771737817379173801738117382173831738417385173861738717388173891739017391173921739317394173951739617397173981739917400174011740217403174041740517406174071740817409174101741117412174131741417415174161741717418174191742017421174221742317424174251742617427174281742917430174311743217433174341743517436174371743817439174401744117442174431744417445174461744717448174491745017451174521745317454174551745617457174581745917460174611746217463174641746517466174671746817469174701747117472174731747417475174761747717478174791748017481174821748317484174851748617487174881748917490174911749217493174941749517496174971749817499175001750117502175031750417505175061750717508175091751017511175121751317514175151751617517175181751917520175211752217523175241752517526175271752817529175301753117532175331753417535175361753717538175391754017541175421754317544175451754617547175481754917550175511755217553175541755517556175571755817559175601756117562175631756417565175661756717568175691757017571175721757317574175751757617577175781757917580175811758217583175841758517586175871758817589175901759117592175931759417595175961759717598175991760017601176021760317604176051760617607176081760917610176111761217613176141761517616176171761817619176201762117622176231762417625176261762717628176291763017631176321763317634176351763617637176381763917640176411764217643176441764517646176471764817649176501765117652176531765417655176561765717658176591766017661176621766317664176651766617667176681766917670176711767217673176741767517676176771767817679176801768117682176831768417685176861768717688176891769017691176921769317694176951769617697176981769917700177011770217703177041770517706177071770817709177101771117712177131771417715177161771717718177191772017721177221772317724177251772617727177281772917730177311773217733177341773517736177371773817739177401774117742177431774417745177461774717748177491775017751177521775317754177551775617757177581775917760177611776217763177641776517766177671776817769177701777117772177731777417775177761777717778177791778017781177821778317784177851778617787177881778917790177911779217793177941779517796177971779817799178001780117802178031780417805178061780717808178091781017811178121781317814178151781617817178181781917820178211782217823178241782517826178271782817829178301783117832178331783417835178361783717838178391784017841 |
- (function(factory) {
- if (typeof define === 'function' && define.amd) {
- define([ 'jquery', 'moment' ], factory);
- }
- else if (typeof exports === 'object') {
- module.exports = factory(require('jquery'), require('moment'));
- }
- else {
- factory(jQuery, moment);
- }
- })(function($, moment) {
- ;;
- var FC = $.fullCalendar = {
- version: "3.5.1",
-
-
-
- internalApiVersion: 10
- };
- var fcViews = FC.views = {};
- $.fn.fullCalendar = function(options) {
- var args = Array.prototype.slice.call(arguments, 1);
- var res = this;
- this.each(function(i, _element) {
- var element = $(_element);
- var calendar = element.data('fullCalendar');
- var singleRes;
-
- if (typeof options === 'string') {
- if (options === 'getCalendar') {
- if (!i) {
- res = calendar;
- }
- }
- else if (options === 'destroy') {
- if (calendar) {
- calendar.destroy();
- element.removeData('fullCalendar');
- }
- }
- else if (!calendar) {
- FC.warn("Attempting to call a FullCalendar method on an element with no calendar.");
- }
- else if ($.isFunction(calendar[options])) {
- singleRes = calendar[options].apply(calendar, args);
- if (!i) {
- res = singleRes;
- }
- if (options === 'destroy') {
- element.removeData('fullCalendar');
- }
- }
- else {
- FC.warn("'" + options + "' is an unknown FullCalendar method.");
- }
- }
-
- else if (!calendar) {
- calendar = new Calendar(element, options);
- element.data('fullCalendar', calendar);
- calendar.render();
- }
- });
- return res;
- };
- var complexOptions = [
- 'header',
- 'footer',
- 'buttonText',
- 'buttonIcons',
- 'themeButtonIcons'
- ];
- function mergeOptions(optionObjs) {
- return mergeProps(optionObjs, complexOptions);
- }
- ;;
- FC.applyAll = applyAll;
- FC.debounce = debounce;
- FC.isInt = isInt;
- FC.htmlEscape = htmlEscape;
- FC.cssToStr = cssToStr;
- FC.proxy = proxy;
- FC.capitaliseFirstLetter = capitaliseFirstLetter;
- function compensateScroll(rowEls, scrollbarWidths) {
- if (scrollbarWidths.left) {
- rowEls.css({
- 'border-left-width': 1,
- 'margin-left': scrollbarWidths.left - 1
- });
- }
- if (scrollbarWidths.right) {
- rowEls.css({
- 'border-right-width': 1,
- 'margin-right': scrollbarWidths.right - 1
- });
- }
- }
- function uncompensateScroll(rowEls) {
- rowEls.css({
- 'margin-left': '',
- 'margin-right': '',
- 'border-left-width': '',
- 'border-right-width': ''
- });
- }
- function disableCursor() {
- $('body').addClass('fc-not-allowed');
- }
- function enableCursor() {
- $('body').removeClass('fc-not-allowed');
- }
- function distributeHeight(els, availableHeight, shouldRedistribute) {
-
-
- var minOffset1 = Math.floor(availableHeight / els.length);
- var minOffset2 = Math.floor(availableHeight - minOffset1 * (els.length - 1));
- var flexEls = [];
- var flexOffsets = [];
- var flexHeights = [];
- var usedHeight = 0;
- undistributeHeight(els);
-
-
- els.each(function(i, el) {
- var minOffset = i === els.length - 1 ? minOffset2 : minOffset1;
- var naturalOffset = $(el).outerHeight(true);
- if (naturalOffset < minOffset) {
- flexEls.push(el);
- flexOffsets.push(naturalOffset);
- flexHeights.push($(el).height());
- }
- else {
-
- usedHeight += naturalOffset;
- }
- });
-
- if (shouldRedistribute) {
- availableHeight -= usedHeight;
- minOffset1 = Math.floor(availableHeight / flexEls.length);
- minOffset2 = Math.floor(availableHeight - minOffset1 * (flexEls.length - 1));
- }
-
- $(flexEls).each(function(i, el) {
- var minOffset = i === flexEls.length - 1 ? minOffset2 : minOffset1;
- var naturalOffset = flexOffsets[i];
- var naturalHeight = flexHeights[i];
- var newHeight = minOffset - (naturalOffset - naturalHeight);
- if (naturalOffset < minOffset) {
- $(el).height(newHeight);
- }
- });
- }
- function undistributeHeight(els) {
- els.height('');
- }
- function matchCellWidths(els) {
- var maxInnerWidth = 0;
- els.find('> *').each(function(i, innerEl) {
- var innerWidth = $(innerEl).outerWidth();
- if (innerWidth > maxInnerWidth) {
- maxInnerWidth = innerWidth;
- }
- });
- maxInnerWidth++;
- els.width(maxInnerWidth);
- return maxInnerWidth;
- }
- function subtractInnerElHeight(outerEl, innerEl) {
- var both = outerEl.add(innerEl);
- var diff;
-
- both.css({
- position: 'relative',
- left: -1
- });
- diff = outerEl.outerHeight() - innerEl.outerHeight();
- both.css({ position: '', left: '' });
- return diff;
- }
- FC.getOuterRect = getOuterRect;
- FC.getClientRect = getClientRect;
- FC.getContentRect = getContentRect;
- FC.getScrollbarWidths = getScrollbarWidths;
- function getScrollParent(el) {
- var position = el.css('position'),
- scrollParent = el.parents().filter(function() {
- var parent = $(this);
- return (/(auto|scroll)/).test(
- parent.css('overflow') + parent.css('overflow-y') + parent.css('overflow-x')
- );
- }).eq(0);
- return position === 'fixed' || !scrollParent.length ? $(el[0].ownerDocument || document) : scrollParent;
- }
- function getOuterRect(el, origin) {
- var offset = el.offset();
- var left = offset.left - (origin ? origin.left : 0);
- var top = offset.top - (origin ? origin.top : 0);
- return {
- left: left,
- right: left + el.outerWidth(),
- top: top,
- bottom: top + el.outerHeight()
- };
- }
- function getClientRect(el, origin) {
- var offset = el.offset();
- var scrollbarWidths = getScrollbarWidths(el);
- var left = offset.left + getCssFloat(el, 'border-left-width') + scrollbarWidths.left - (origin ? origin.left : 0);
- var top = offset.top + getCssFloat(el, 'border-top-width') + scrollbarWidths.top - (origin ? origin.top : 0);
- return {
- left: left,
- right: left + el[0].clientWidth,
- top: top,
- bottom: top + el[0].clientHeight
- };
- }
- function getContentRect(el, origin) {
- var offset = el.offset();
- var left = offset.left + getCssFloat(el, 'border-left-width') + getCssFloat(el, 'padding-left') -
- (origin ? origin.left : 0);
- var top = offset.top + getCssFloat(el, 'border-top-width') + getCssFloat(el, 'padding-top') -
- (origin ? origin.top : 0);
- return {
- left: left,
- right: left + el.width(),
- top: top,
- bottom: top + el.height()
- };
- }
- function getScrollbarWidths(el) {
- var leftRightWidth = el[0].offsetWidth - el[0].clientWidth;
- var bottomWidth = el[0].offsetHeight - el[0].clientHeight;
- var widths;
- leftRightWidth = sanitizeScrollbarWidth(leftRightWidth);
- bottomWidth = sanitizeScrollbarWidth(bottomWidth);
- widths = { left: 0, right: 0, top: 0, bottom: bottomWidth };
- if (getIsLeftRtlScrollbars() && el.css('direction') == 'rtl') {
- widths.left = leftRightWidth;
- }
- else {
- widths.right = leftRightWidth;
- }
- return widths;
- }
- function sanitizeScrollbarWidth(width) {
- width = Math.max(0, width);
- width = Math.round(width);
- return width;
- }
- var _isLeftRtlScrollbars = null;
- function getIsLeftRtlScrollbars() {
- if (_isLeftRtlScrollbars === null) {
- _isLeftRtlScrollbars = computeIsLeftRtlScrollbars();
- }
- return _isLeftRtlScrollbars;
- }
- function computeIsLeftRtlScrollbars() {
- var el = $('<div><div/></div>')
- .css({
- position: 'absolute',
- top: -1000,
- left: 0,
- border: 0,
- padding: 0,
- overflow: 'scroll',
- direction: 'rtl'
- })
- .appendTo('body');
- var innerEl = el.children();
- var res = innerEl.offset().left > el.offset().left;
- el.remove();
- return res;
- }
- function getCssFloat(el, prop) {
- return parseFloat(el.css(prop)) || 0;
- }
- FC.preventDefault = preventDefault;
- function isPrimaryMouseButton(ev) {
- return ev.which == 1 && !ev.ctrlKey;
- }
- function getEvX(ev) {
- var touches = ev.originalEvent.touches;
-
-
- if (touches && touches.length) {
- return touches[0].pageX;
- }
- return ev.pageX;
- }
- function getEvY(ev) {
- var touches = ev.originalEvent.touches;
-
-
- if (touches && touches.length) {
- return touches[0].pageY;
- }
- return ev.pageY;
- }
- function getEvIsTouch(ev) {
- return /^touch/.test(ev.type);
- }
- function preventSelection(el) {
- el.addClass('fc-unselectable')
- .on('selectstart', preventDefault);
- }
- function allowSelection(el) {
- el.removeClass('fc-unselectable')
- .off('selectstart', preventDefault);
- }
- function preventDefault(ev) {
- ev.preventDefault();
- }
- FC.intersectRects = intersectRects;
- function intersectRects(rect1, rect2) {
- var res = {
- left: Math.max(rect1.left, rect2.left),
- right: Math.min(rect1.right, rect2.right),
- top: Math.max(rect1.top, rect2.top),
- bottom: Math.min(rect1.bottom, rect2.bottom)
- };
- if (res.left < res.right && res.top < res.bottom) {
- return res;
- }
- return false;
- }
- function constrainPoint(point, rect) {
- return {
- left: Math.min(Math.max(point.left, rect.left), rect.right),
- top: Math.min(Math.max(point.top, rect.top), rect.bottom)
- };
- }
- function getRectCenter(rect) {
- return {
- left: (rect.left + rect.right) / 2,
- top: (rect.top + rect.bottom) / 2
- };
- }
- function diffPoints(point1, point2) {
- return {
- left: point1.left - point2.left,
- top: point1.top - point2.top
- };
- }
- FC.parseFieldSpecs = parseFieldSpecs;
- FC.compareByFieldSpecs = compareByFieldSpecs;
- FC.compareByFieldSpec = compareByFieldSpec;
- FC.flexibleCompare = flexibleCompare;
- function parseFieldSpecs(input) {
- var specs = [];
- var tokens = [];
- var i, token;
- if (typeof input === 'string') {
- tokens = input.split(/\s*,\s*/);
- }
- else if (typeof input === 'function') {
- tokens = [ input ];
- }
- else if ($.isArray(input)) {
- tokens = input;
- }
- for (i = 0; i < tokens.length; i++) {
- token = tokens[i];
- if (typeof token === 'string') {
- specs.push(
- token.charAt(0) == '-' ?
- { field: token.substring(1), order: -1 } :
- { field: token, order: 1 }
- );
- }
- else if (typeof token === 'function') {
- specs.push({ func: token });
- }
- }
- return specs;
- }
- function compareByFieldSpecs(obj1, obj2, fieldSpecs) {
- var i;
- var cmp;
- for (i = 0; i < fieldSpecs.length; i++) {
- cmp = compareByFieldSpec(obj1, obj2, fieldSpecs[i]);
- if (cmp) {
- return cmp;
- }
- }
- return 0;
- }
- function compareByFieldSpec(obj1, obj2, fieldSpec) {
- if (fieldSpec.func) {
- return fieldSpec.func(obj1, obj2);
- }
- return flexibleCompare(obj1[fieldSpec.field], obj2[fieldSpec.field]) *
- (fieldSpec.order || 1);
- }
- function flexibleCompare(a, b) {
- if (!a && !b) {
- return 0;
- }
- if (b == null) {
- return -1;
- }
- if (a == null) {
- return 1;
- }
- if ($.type(a) === 'string' || $.type(b) === 'string') {
- return String(a).localeCompare(String(b));
- }
- return a - b;
- }
- FC.computeGreatestUnit = computeGreatestUnit;
- FC.divideRangeByDuration = divideRangeByDuration;
- FC.divideDurationByDuration = divideDurationByDuration;
- FC.multiplyDuration = multiplyDuration;
- FC.durationHasTime = durationHasTime;
- var dayIDs = [ 'sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat' ];
- var unitsDesc = [ 'year', 'month', 'week', 'day', 'hour', 'minute', 'second', 'millisecond' ];
- function diffDayTime(a, b) {
- return moment.duration({
- days: a.clone().stripTime().diff(b.clone().stripTime(), 'days'),
- ms: a.time() - b.time()
- });
- }
- function diffDay(a, b) {
- return moment.duration({
- days: a.clone().stripTime().diff(b.clone().stripTime(), 'days')
- });
- }
- function diffByUnit(a, b, unit) {
- return moment.duration(
- Math.round(a.diff(b, unit, true)),
- unit
- );
- }
- function computeGreatestUnit(start, end) {
- var i, unit;
- var val;
- for (i = 0; i < unitsDesc.length; i++) {
- unit = unitsDesc[i];
- val = computeRangeAs(unit, start, end);
- if (val >= 1 && isInt(val)) {
- break;
- }
- }
- return unit;
- }
- function computeDurationGreatestUnit(duration, durationInput) {
- var unit = computeGreatestUnit(duration);
-
- if (unit === 'week' && typeof durationInput === 'object' && durationInput.days) {
- unit = 'day';
- }
- return unit;
- }
- function computeRangeAs(unit, start, end) {
- if (end != null) {
- return end.diff(start, unit, true);
- }
- else if (moment.isDuration(start)) {
- return start.as(unit);
- }
- else {
- return start.end.diff(start.start, unit, true);
- }
- }
- function divideRangeByDuration(start, end, dur) {
- var months;
- if (durationHasTime(dur)) {
- return (end - start) / dur;
- }
- months = dur.asMonths();
- if (Math.abs(months) >= 1 && isInt(months)) {
- return end.diff(start, 'months', true) / months;
- }
- return end.diff(start, 'days', true) / dur.asDays();
- }
- function divideDurationByDuration(dur1, dur2) {
- var months1, months2;
- if (durationHasTime(dur1) || durationHasTime(dur2)) {
- return dur1 / dur2;
- }
- months1 = dur1.asMonths();
- months2 = dur2.asMonths();
- if (
- Math.abs(months1) >= 1 && isInt(months1) &&
- Math.abs(months2) >= 1 && isInt(months2)
- ) {
- return months1 / months2;
- }
- return dur1.asDays() / dur2.asDays();
- }
- function multiplyDuration(dur, n) {
- var months;
- if (durationHasTime(dur)) {
- return moment.duration(dur * n);
- }
- months = dur.asMonths();
- if (Math.abs(months) >= 1 && isInt(months)) {
- return moment.duration({ months: months * n });
- }
- return moment.duration({ days: dur.asDays() * n });
- }
- function durationHasTime(dur) {
- return Boolean(dur.hours() || dur.minutes() || dur.seconds() || dur.milliseconds());
- }
- function isNativeDate(input) {
- return Object.prototype.toString.call(input) === '[object Date]' || input instanceof Date;
- }
- function isTimeString(str) {
- return typeof str === 'string' &&
- /^\d+\:\d+(?:\:\d+\.?(?:\d{3})?)?$/.test(str);
- }
- FC.log = function() {
- var console = window.console;
- if (console && console.log) {
- return console.log.apply(console, arguments);
- }
- };
- FC.warn = function() {
- var console = window.console;
- if (console && console.warn) {
- return console.warn.apply(console, arguments);
- }
- else {
- return FC.log.apply(FC, arguments);
- }
- };
- var hasOwnPropMethod = {}.hasOwnProperty;
- function mergeProps(propObjs, complexProps) {
- var dest = {};
- var i, name;
- var complexObjs;
- var j, val;
- var props;
- if (complexProps) {
- for (i = 0; i < complexProps.length; i++) {
- name = complexProps[i];
- complexObjs = [];
-
- for (j = propObjs.length - 1; j >= 0; j--) {
- val = propObjs[j][name];
- if (typeof val === 'object') {
- complexObjs.unshift(val);
- }
- else if (val !== undefined) {
- dest[name] = val;
- break;
- }
- }
-
- if (complexObjs.length) {
- dest[name] = mergeProps(complexObjs);
- }
- }
- }
-
- for (i = propObjs.length - 1; i >= 0; i--) {
- props = propObjs[i];
- for (name in props) {
- if (!(name in dest)) {
- dest[name] = props[name];
- }
- }
- }
- return dest;
- }
- function copyOwnProps(src, dest) {
- for (var name in src) {
- if (hasOwnProp(src, name)) {
- dest[name] = src[name];
- }
- }
- }
- function hasOwnProp(obj, name) {
- return hasOwnPropMethod.call(obj, name);
- }
- function applyAll(functions, thisObj, args) {
- if ($.isFunction(functions)) {
- functions = [ functions ];
- }
- if (functions) {
- var i;
- var ret;
- for (i=0; i<functions.length; i++) {
- ret = functions[i].apply(thisObj, args) || ret;
- }
- return ret;
- }
- }
- function removeMatching(array, testFunc) {
- var removeCnt = 0;
- var i = 0;
- while (i < array.length) {
- if (testFunc(array[i])) {
- array.splice(i, 1);
- removeCnt++;
- }
- else {
- i++;
- }
- }
- return removeCnt;
- }
- function removeExact(array, exactVal) {
- var removeCnt = 0;
- var i = 0;
- while (i < array.length) {
- if (array[i] === exactVal) {
- array.splice(i, 1);
- removeCnt++;
- }
- else {
- i++;
- }
- }
- return removeCnt;
- }
- FC.removeExact = removeExact;
- function firstDefined() {
- for (var i=0; i<arguments.length; i++) {
- if (arguments[i] !== undefined) {
- return arguments[i];
- }
- }
- }
- function htmlEscape(s) {
- return (s + '').replace(/&/g, '&')
- .replace(/</g, '<')
- .replace(/>/g, '>')
- .replace(/'/g, ''')
- .replace(/"/g, '"')
- .replace(/\n/g, '<br />');
- }
- function stripHtmlEntities(text) {
- return text.replace(/&.*?;/g, '');
- }
- function cssToStr(cssProps) {
- var statements = [];
- $.each(cssProps, function(name, val) {
- if (val != null) {
- statements.push(name + ':' + val);
- }
- });
- return statements.join(';');
- }
- function attrsToStr(attrs) {
- var parts = [];
- $.each(attrs, function(name, val) {
- if (val != null) {
- parts.push(name + '="' + htmlEscape(val) + '"');
- }
- });
- return parts.join(' ');
- }
- function capitaliseFirstLetter(str) {
- return str.charAt(0).toUpperCase() + str.slice(1);
- }
- function compareNumbers(a, b) {
- return a - b;
- }
- function isInt(n) {
- return n % 1 === 0;
- }
- function proxy(obj, methodName) {
- var method = obj[methodName];
- return function() {
- return method.apply(obj, arguments);
- };
- }
- function debounce(func, wait, immediate) {
- var timeout, args, context, timestamp, result;
- var later = function() {
- var last = +new Date() - timestamp;
- if (last < wait) {
- timeout = setTimeout(later, wait - last);
- }
- else {
- timeout = null;
- if (!immediate) {
- result = func.apply(context, args);
- context = args = null;
- }
- }
- };
- return function() {
- context = this;
- args = arguments;
- timestamp = +new Date();
- var callNow = immediate && !timeout;
- if (!timeout) {
- timeout = setTimeout(later, wait);
- }
- if (callNow) {
- result = func.apply(context, args);
- context = args = null;
- }
- return result;
- };
- }
- ;;
- var ambigDateOfMonthRegex = /^\s*\d{4}-\d\d$/;
- var ambigTimeOrZoneRegex =
- /^\s*\d{4}-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?)?$/;
- var newMomentProto = moment.fn;
- var oldMomentProto = $.extend({}, newMomentProto);
- var momentProperties = moment.momentProperties;
- momentProperties.push('_fullCalendar');
- momentProperties.push('_ambigTime');
- momentProperties.push('_ambigZone');
- FC.moment = function() {
- return makeMoment(arguments);
- };
- FC.moment.utc = function() {
- var mom = makeMoment(arguments, true);
-
-
- if (mom.hasTime()) {
- mom.utc();
- }
- return mom;
- };
- FC.moment.parseZone = function() {
- return makeMoment(arguments, true, true);
- };
- function makeMoment(args, parseAsUTC, parseZone) {
- var input = args[0];
- var isSingleString = args.length == 1 && typeof input === 'string';
- var isAmbigTime;
- var isAmbigZone;
- var ambigMatch;
- var mom;
- if (moment.isMoment(input) || isNativeDate(input) || input === undefined) {
- mom = moment.apply(null, args);
- }
- else {
- isAmbigTime = false;
- isAmbigZone = false;
- if (isSingleString) {
- if (ambigDateOfMonthRegex.test(input)) {
-
- input += '-01';
- args = [ input ];
- isAmbigTime = true;
- isAmbigZone = true;
- }
- else if ((ambigMatch = ambigTimeOrZoneRegex.exec(input))) {
- isAmbigTime = !ambigMatch[5];
- isAmbigZone = true;
- }
- }
- else if ($.isArray(input)) {
-
- isAmbigZone = true;
- }
-
- if (parseAsUTC || isAmbigTime) {
- mom = moment.utc.apply(moment, args);
- }
- else {
- mom = moment.apply(null, args);
- }
- if (isAmbigTime) {
- mom._ambigTime = true;
- mom._ambigZone = true;
- }
- else if (parseZone) {
- if (isAmbigZone) {
- mom._ambigZone = true;
- }
- else if (isSingleString) {
- mom.utcOffset(input);
- }
- }
- }
- mom._fullCalendar = true;
- return mom;
- }
- newMomentProto.week = newMomentProto.weeks = function(input) {
- var weekCalc = this._locale._fullCalendar_weekCalc;
- if (input == null && typeof weekCalc === 'function') {
- return weekCalc(this);
- }
- else if (weekCalc === 'ISO') {
- return oldMomentProto.isoWeek.apply(this, arguments);
- }
- return oldMomentProto.week.apply(this, arguments);
- };
- newMomentProto.time = function(time) {
-
-
- if (!this._fullCalendar) {
- return oldMomentProto.time.apply(this, arguments);
- }
- if (time == null) {
- return moment.duration({
- hours: this.hours(),
- minutes: this.minutes(),
- seconds: this.seconds(),
- milliseconds: this.milliseconds()
- });
- }
- else {
- this._ambigTime = false;
- if (!moment.isDuration(time) && !moment.isMoment(time)) {
- time = moment.duration(time);
- }
-
-
- var dayHours = 0;
- if (moment.isDuration(time)) {
- dayHours = Math.floor(time.asDays()) * 24;
- }
-
-
- return this.hours(dayHours + time.hours())
- .minutes(time.minutes())
- .seconds(time.seconds())
- .milliseconds(time.milliseconds());
- }
- };
- newMomentProto.stripTime = function() {
- if (!this._ambigTime) {
- this.utc(true);
-
- this.set({
- hours: 0,
- minutes: 0,
- seconds: 0,
- ms: 0
- });
-
-
- this._ambigTime = true;
- this._ambigZone = true;
- }
- return this;
- };
- newMomentProto.hasTime = function() {
- return !this._ambigTime;
- };
- newMomentProto.stripZone = function() {
- var wasAmbigTime;
- if (!this._ambigZone) {
- wasAmbigTime = this._ambigTime;
- this.utc(true);
-
- this._ambigTime = wasAmbigTime || false;
-
-
- this._ambigZone = true;
- }
- return this;
- };
- newMomentProto.hasZone = function() {
- return !this._ambigZone;
- };
- newMomentProto.local = function(keepLocalTime) {
-
-
- oldMomentProto.local.call(this, this._ambigZone || keepLocalTime);
-
-
- this._ambigTime = false;
- this._ambigZone = false;
- return this;
- };
- newMomentProto.utc = function(keepLocalTime) {
- oldMomentProto.utc.call(this, keepLocalTime);
-
-
- this._ambigTime = false;
- this._ambigZone = false;
- return this;
- };
- newMomentProto.utcOffset = function(tzo) {
- if (tzo != null) {
-
-
- this._ambigTime = false;
- this._ambigZone = false;
- }
- return oldMomentProto.utcOffset.apply(this, arguments);
- };
- newMomentProto.format = function() {
- if (this._fullCalendar && arguments[0]) {
- return formatDate(this, arguments[0]);
- }
- if (this._ambigTime) {
- return oldMomentFormat(englishMoment(this), 'YYYY-MM-DD');
- }
- if (this._ambigZone) {
- return oldMomentFormat(englishMoment(this), 'YYYY-MM-DD[T]HH:mm:ss');
- }
- if (this._fullCalendar) {
-
- return oldMomentFormat(englishMoment(this));
- }
- return oldMomentProto.format.apply(this, arguments);
- };
- newMomentProto.toISOString = function() {
- if (this._ambigTime) {
- return oldMomentFormat(englishMoment(this), 'YYYY-MM-DD');
- }
- if (this._ambigZone) {
- return oldMomentFormat(englishMoment(this), 'YYYY-MM-DD[T]HH:mm:ss');
- }
- if (this._fullCalendar) {
-
-
- return oldMomentProto.toISOString.apply(englishMoment(this), arguments);
- }
- return oldMomentProto.toISOString.apply(this, arguments);
- };
- function englishMoment(mom) {
- if (mom.locale() !== 'en') {
- return mom.clone().locale('en');
- }
- return mom;
- }
- ;;
- (function() {
- FC.formatDate = formatDate;
- FC.formatRange = formatRange;
- FC.oldMomentFormat = oldMomentFormat;
- FC.queryMostGranularFormatUnit = queryMostGranularFormatUnit;
- var PART_SEPARATOR = '\u000b';
- var SPECIAL_TOKEN_MARKER = '\u001f';
- var MAYBE_MARKER = '\u001e';
- var MAYBE_REGEXP = new RegExp(MAYBE_MARKER + '([^' + MAYBE_MARKER + ']*)' + MAYBE_MARKER, 'g');
- var specialTokens = {
- t: function(date) {
- return oldMomentFormat(date, 'a').charAt(0);
- },
- T: function(date) {
- return oldMomentFormat(date, 'A').charAt(0);
- }
- };
- var largeTokenMap = {
- Y: { value: 1, unit: 'year' },
- M: { value: 2, unit: 'month' },
- W: { value: 3, unit: 'week' },
- w: { value: 3, unit: 'week' },
- D: { value: 4, unit: 'day' },
- d: { value: 4, unit: 'day' }
- };
- function formatDate(date, formatStr) {
- return renderFakeFormatString(
- getParsedFormatString(formatStr).fakeFormatString,
- date
- );
- }
- function oldMomentFormat(mom, formatStr) {
- return oldMomentProto.format.call(mom, formatStr);
- }
- function formatRange(date1, date2, formatStr, separator, isRTL) {
- var localeData;
- date1 = FC.moment.parseZone(date1);
- date2 = FC.moment.parseZone(date2);
- localeData = date1.localeData();
-
-
-
- formatStr = localeData.longDateFormat(formatStr) || formatStr;
- return renderParsedFormat(
- getParsedFormatString(formatStr),
- date1,
- date2,
- separator || ' - ',
- isRTL
- );
- }
- function renderParsedFormat(parsedFormat, date1, date2, separator, isRTL) {
- var sameUnits = parsedFormat.sameUnits;
- var unzonedDate1 = date1.clone().stripZone();
- var unzonedDate2 = date2.clone().stripZone();
- var renderedParts1 = renderFakeFormatStringParts(parsedFormat.fakeFormatString, date1);
- var renderedParts2 = renderFakeFormatStringParts(parsedFormat.fakeFormatString, date2);
- var leftI;
- var leftStr = '';
- var rightI;
- var rightStr = '';
- var middleI;
- var middleStr1 = '';
- var middleStr2 = '';
- var middleStr = '';
-
-
- for (
- leftI = 0;
- leftI < sameUnits.length && (!sameUnits[leftI] || unzonedDate1.isSame(unzonedDate2, sameUnits[leftI]));
- leftI++
- ) {
- leftStr += renderedParts1[leftI];
- }
-
- for (
- rightI = sameUnits.length - 1;
- rightI > leftI && (!sameUnits[rightI] || unzonedDate1.isSame(unzonedDate2, sameUnits[rightI]));
- rightI--
- ) {
-
-
-
- if (rightI - 1 === leftI && renderedParts1[rightI] === '.') {
- break;
- }
- rightStr = renderedParts1[rightI] + rightStr;
- }
-
-
- for (middleI = leftI; middleI <= rightI; middleI++) {
- middleStr1 += renderedParts1[middleI];
- middleStr2 += renderedParts2[middleI];
- }
- if (middleStr1 || middleStr2) {
- if (isRTL) {
- middleStr = middleStr2 + separator + middleStr1;
- }
- else {
- middleStr = middleStr1 + separator + middleStr2;
- }
- }
- return processMaybeMarkers(
- leftStr + middleStr + rightStr
- );
- }
- var parsedFormatStrCache = {};
- function getParsedFormatString(formatStr) {
- return parsedFormatStrCache[formatStr] ||
- (parsedFormatStrCache[formatStr] = parseFormatString(formatStr));
- }
- function parseFormatString(formatStr) {
- var chunks = chunkFormatString(formatStr);
-
- return {
- fakeFormatString: buildFakeFormatString(chunks),
- sameUnits: buildSameUnits(chunks)
- };
- }
- function chunkFormatString(formatStr) {
- var chunks = [];
- var match;
-
-
- var chunker = /\[([^\]]*)\]|\(([^\)]*)\)|(LTS|LT|(\w)\4*o?)|([^\w\[\(]+)/g;
- while ((match = chunker.exec(formatStr))) {
- if (match[1]) {
- chunks.push.apply(chunks,
- splitStringLiteral(match[1])
- );
- }
- else if (match[2]) {
- chunks.push({ maybe: chunkFormatString(match[2]) });
- }
- else if (match[3]) {
- chunks.push({ token: match[3] });
- }
- else if (match[5]) {
- chunks.push.apply(chunks,
- splitStringLiteral(match[5])
- );
- }
- }
- return chunks;
- }
- function splitStringLiteral(s) {
- if (s === '. ') {
- return [ '.', ' ' ];
- }
- else {
- return [ s ];
- }
- }
- function buildFakeFormatString(chunks) {
- var parts = [];
- var i, chunk;
- for (i = 0; i < chunks.length; i++) {
- chunk = chunks[i];
- if (typeof chunk === 'string') {
- parts.push('[' + chunk + ']');
- }
- else if (chunk.token) {
- if (chunk.token in specialTokens) {
- parts.push(
- SPECIAL_TOKEN_MARKER +
- '[' + chunk.token + ']'
- );
- }
- else {
- parts.push(chunk.token);
- }
- }
- else if (chunk.maybe) {
- parts.push(
- MAYBE_MARKER +
- buildFakeFormatString(chunk.maybe) +
- MAYBE_MARKER
- );
- }
- }
- return parts.join(PART_SEPARATOR);
- }
- function buildSameUnits(chunks) {
- var units = [];
- var i, chunk;
- var tokenInfo;
- for (i = 0; i < chunks.length; i++) {
- chunk = chunks[i];
- if (chunk.token) {
- tokenInfo = largeTokenMap[chunk.token.charAt(0)];
- units.push(tokenInfo ? tokenInfo.unit : 'second');
- }
- else if (chunk.maybe) {
- units.push.apply(units,
- buildSameUnits(chunk.maybe)
- );
- }
- else {
- units.push(null);
- }
- }
- return units;
- }
- function renderFakeFormatString(fakeFormatString, date) {
- return processMaybeMarkers(
- renderFakeFormatStringParts(fakeFormatString, date).join('')
- );
- }
- function renderFakeFormatStringParts(fakeFormatString, date) {
- var parts = [];
- var fakeRender = oldMomentFormat(date, fakeFormatString);
- var fakeParts = fakeRender.split(PART_SEPARATOR);
- var i, fakePart;
- for (i = 0; i < fakeParts.length; i++) {
- fakePart = fakeParts[i];
- if (fakePart.charAt(0) === SPECIAL_TOKEN_MARKER) {
- parts.push(
-
-
- specialTokens[fakePart.substring(1)](date)
- );
- }
- else {
- parts.push(fakePart);
- }
- }
- return parts;
- }
- function processMaybeMarkers(s) {
- return s.replace(MAYBE_REGEXP, function(m0, m1) {
- if (m1.match(/[1-9]/)) {
- return m1;
- }
- else {
- return '';
- }
- });
- }
- function queryMostGranularFormatUnit(formatStr) {
- var chunks = chunkFormatString(formatStr);
- var i, chunk;
- var candidate;
- var best;
- for (i = 0; i < chunks.length; i++) {
- chunk = chunks[i];
- if (chunk.token) {
- candidate = largeTokenMap[chunk.token.charAt(0)];
- if (candidate) {
- if (!best || candidate.value > best.value) {
- best = candidate;
- }
- }
- }
- }
- if (best) {
- return best.unit;
- }
- return null;
- };
- })();
- var formatDate = FC.formatDate;
- var formatRange = FC.formatRange;
- var oldMomentFormat = FC.oldMomentFormat;
- ;;
- FC.Class = Class;
- function Class() { }
- Class.extend = function() {
- var members = {};
- var i;
- for (i = 0; i < arguments.length; i++) {
- copyOwnProps(arguments[i], members);
- }
- return extendClass(this, members);
- };
- Class.mixin = function(members) {
- copyOwnProps(members, this.prototype);
- };
- function extendClass(superClass, members) {
- var subClass;
-
- if (hasOwnProp(members, 'constructor')) {
- subClass = members.constructor;
- }
- if (typeof subClass !== 'function') {
- subClass = members.constructor = function() {
- superClass.apply(this, arguments);
- };
- }
-
- subClass.prototype = Object.create(superClass.prototype);
-
- copyOwnProps(members, subClass.prototype);
-
- copyOwnProps(superClass, subClass);
- return subClass;
- }
- ;;
- var EmitterMixin = FC.EmitterMixin = {
-
-
- on: function(types, handler) {
- $(this).on(types, this._prepareIntercept(handler));
- return this;
- },
- one: function(types, handler) {
- $(this).one(types, this._prepareIntercept(handler));
- return this;
- },
- _prepareIntercept: function(handler) {
-
-
-
- var intercept = function(ev, extra) {
- return handler.apply(
- extra.context || this,
- extra.args || []
- );
- };
-
-
-
-
- if (!handler.guid) {
- handler.guid = $.guid++;
- }
- intercept.guid = handler.guid;
- return intercept;
- },
- off: function(types, handler) {
- $(this).off(types, handler);
- return this;
- },
- trigger: function(types) {
- var args = Array.prototype.slice.call(arguments, 1);
-
- $(this).triggerHandler(types, { args: args });
- return this;
- },
- triggerWith: function(types, context, args) {
-
-
- $(this).triggerHandler(types, { context: context, args: args });
- return this;
- },
- hasHandlers: function(type) {
- var hash = $._data(this, 'events');
- return hash && hash[type] && hash[type].length > 0;
- }
- };
- ;;
- var ListenerMixin = FC.ListenerMixin = (function() {
- var guid = 0;
- var ListenerMixin = {
- listenerId: null,
-
- listenTo: function(other, arg, callback) {
- if (typeof arg === 'object') {
- for (var eventName in arg) {
- if (arg.hasOwnProperty(eventName)) {
- this.listenTo(other, eventName, arg[eventName]);
- }
- }
- }
- else if (typeof arg === 'string') {
- other.on(
- arg + '.' + this.getListenerNamespace(),
- $.proxy(callback, this)
-
-
- );
- }
- },
-
- stopListeningTo: function(other, eventName) {
- other.off((eventName || '') + '.' + this.getListenerNamespace());
- },
-
- getListenerNamespace: function() {
- if (this.listenerId == null) {
- this.listenerId = guid++;
- }
- return '_listener' + this.listenerId;
- }
- };
- return ListenerMixin;
- })();
- ;;
- var ParsableModelMixin = {
- standardPropMap: {},
-
- applyRawProps: function(rawProps) {
- var standardPropMap = this.standardPropMap;
- var manualProps = {};
- var otherProps = {};
- var propName;
- for (propName in rawProps) {
- if (standardPropMap[propName] === true) {
- this[propName] = rawProps[propName];
- }
- else if (standardPropMap[propName] === false) {
- manualProps[propName] = rawProps[propName];
- }
- else {
- otherProps[propName] = rawProps[propName];
- }
- }
- this.applyOtherRawProps(otherProps);
- return this.applyManualRawProps(manualProps);
- },
-
- applyManualRawProps: function(rawProps) {
- return true;
- },
- applyOtherRawProps: function(rawProps) {
-
- }
- };
- var ParsableModelMixin_allowRawProps = function(propDefs) {
- var proto = this.prototype;
- proto.standardPropMap = Object.create(proto.standardPropMap);
- copyOwnProps(propDefs, proto.standardPropMap);
- };
- var ParsableModelMixin_copyVerbatimStandardProps = function(src, dest) {
- var map = this.prototype.standardPropMap;
- var propName;
- for (propName in map) {
- if (
- src[propName] != null &&
- map[propName] === true
- ) {
- dest[propName] = src[propName];
- }
- }
- };
- ;;
- var Model = Class.extend(EmitterMixin, ListenerMixin, {
- _props: null,
- _watchers: null,
- _globalWatchArgs: null,
- constructor: function() {
- this._watchers = {};
- this._props = {};
- this.applyGlobalWatchers();
- },
- applyGlobalWatchers: function() {
- var argSets = this._globalWatchArgs || [];
- var i;
- for (i = 0; i < argSets.length; i++) {
- this.watch.apply(this, argSets[i]);
- }
- },
- has: function(name) {
- return name in this._props;
- },
- get: function(name) {
- if (name === undefined) {
- return this._props;
- }
- return this._props[name];
- },
- set: function(name, val) {
- var newProps;
- if (typeof name === 'string') {
- newProps = {};
- newProps[name] = val === undefined ? null : val;
- }
- else {
- newProps = name;
- }
- this.setProps(newProps);
- },
- reset: function(newProps) {
- var oldProps = this._props;
- var changeset = {};
- var name;
- for (name in oldProps) {
- changeset[name] = undefined;
- }
- for (name in newProps) {
- changeset[name] = newProps[name];
- }
- this.setProps(changeset);
- },
- unset: function(name) {
- var newProps = {};
- var names;
- var i;
- if (typeof name === 'string') {
- names = [ name ];
- }
- else {
- names = name;
- }
- for (i = 0; i < names.length; i++) {
- newProps[names[i]] = undefined;
- }
- this.setProps(newProps);
- },
- setProps: function(newProps) {
- var changedProps = {};
- var changedCnt = 0;
- var name, val;
- for (name in newProps) {
- val = newProps[name];
-
-
-
- if (
- typeof val === 'object' ||
- val !== this._props[name]
- ) {
- changedProps[name] = val;
- changedCnt++;
- }
- }
- if (changedCnt) {
- this.trigger('before:batchChange', changedProps);
- for (name in changedProps) {
- val = changedProps[name];
- this.trigger('before:change', name, val);
- this.trigger('before:change:' + name, val);
- }
- for (name in changedProps) {
- val = changedProps[name];
- if (val === undefined) {
- delete this._props[name];
- }
- else {
- this._props[name] = val;
- }
- this.trigger('change:' + name, val);
- this.trigger('change', name, val);
- }
- this.trigger('batchChange', changedProps);
- }
- },
- watch: function(name, depList, startFunc, stopFunc) {
- var _this = this;
- this.unwatch(name);
- this._watchers[name] = this._watchDeps(depList, function(deps) {
- var res = startFunc.call(_this, deps);
- if (res && res.then) {
- _this.unset(name);
- res.then(function(val) {
- _this.set(name, val);
- });
- }
- else {
- _this.set(name, res);
- }
- }, function() {
- _this.unset(name);
- if (stopFunc) {
- stopFunc.call(_this);
- }
- });
- },
- unwatch: function(name) {
- var watcher = this._watchers[name];
- if (watcher) {
- delete this._watchers[name];
- watcher.teardown();
- }
- },
- _watchDeps: function(depList, startFunc, stopFunc) {
- var _this = this;
- var queuedChangeCnt = 0;
- var depCnt = depList.length;
- var satisfyCnt = 0;
- var values = {};
- var bindTuples = [];
- var isCallingStop = false;
- function onBeforeDepChange(depName, val, isOptional) {
- queuedChangeCnt++;
- if (queuedChangeCnt === 1) {
- if (satisfyCnt === depCnt) {
- isCallingStop = true;
- stopFunc();
- isCallingStop = false;
- }
- }
- }
- function onDepChange(depName, val, isOptional) {
- if (val === undefined) {
-
- if (!isOptional && values[depName] !== undefined) {
- satisfyCnt--;
- }
- delete values[depName];
- }
- else {
-
- if (!isOptional && values[depName] === undefined) {
- satisfyCnt++;
- }
- values[depName] = val;
- }
- queuedChangeCnt--;
- if (!queuedChangeCnt) {
-
- if (satisfyCnt === depCnt) {
-
-
- if (!isCallingStop) {
- startFunc(values);
- }
- }
- }
- }
-
- function bind(eventName, handler) {
- _this.on(eventName, handler);
- bindTuples.push([ eventName, handler ]);
- }
-
- depList.forEach(function(depName) {
- var isOptional = false;
- if (depName.charAt(0) === '?') {
- depName = depName.substring(1);
- isOptional = true;
- }
- bind('before:change:' + depName, function(val) {
- onBeforeDepChange(depName, val, isOptional);
- });
- bind('change:' + depName, function(val) {
- onDepChange(depName, val, isOptional);
- });
- });
-
- depList.forEach(function(depName) {
- var isOptional = false;
- if (depName.charAt(0) === '?') {
- depName = depName.substring(1);
- isOptional = true;
- }
- if (_this.has(depName)) {
- values[depName] = _this.get(depName);
- satisfyCnt++;
- }
- else if (isOptional) {
- satisfyCnt++;
- }
- });
-
- if (satisfyCnt === depCnt) {
- startFunc(values);
- }
- return {
- teardown: function() {
-
- for (var i = 0; i < bindTuples.length; i++) {
- _this.off(bindTuples[i][0], bindTuples[i][1]);
- }
- bindTuples = null;
-
- if (satisfyCnt === depCnt) {
- stopFunc();
- }
- },
- flash: function() {
- if (satisfyCnt === depCnt) {
- stopFunc();
- startFunc(values);
- }
- }
- };
- },
- flash: function(name) {
- var watcher = this._watchers[name];
- if (watcher) {
- watcher.flash();
- }
- }
- });
- Model.watch = function(/* same arguments as this.watch() */) {
- var proto = this.prototype;
- if (!proto._globalWatchArgs) {
- proto._globalWatchArgs = [];
- }
- proto._globalWatchArgs.push(arguments);
- };
- FC.Model = Model;
- ;;
- var Promise = {
- construct: function(executor) {
- var deferred = $.Deferred();
- var promise = deferred.promise();
- if (typeof executor === 'function') {
- executor(
- function(val) {
- deferred.resolve(val);
- attachImmediatelyResolvingThen(promise, val);
- },
- function() {
- deferred.reject();
- attachImmediatelyRejectingThen(promise);
- }
- );
- }
- return promise;
- },
- resolve: function(val) {
- var deferred = $.Deferred().resolve(val);
- var promise = deferred.promise();
- attachImmediatelyResolvingThen(promise, val);
- return promise;
- },
- reject: function() {
- var deferred = $.Deferred().reject();
- var promise = deferred.promise();
- attachImmediatelyRejectingThen(promise);
- return promise;
- }
- };
- function attachImmediatelyResolvingThen(promise, val) {
- promise.then = function(onResolve) {
- if (typeof onResolve === 'function') {
- return Promise.resolve(onResolve(val));
- }
- return promise;
- };
- }
- function attachImmediatelyRejectingThen(promise) {
- promise.then = function(onResolve, onReject) {
- if (typeof onReject === 'function') {
- onReject();
- }
- return promise;
- };
- }
- FC.Promise = Promise;
- ;;
- var TaskQueue = Class.extend(EmitterMixin, {
- q: null,
- isPaused: false,
- isRunning: false,
- constructor: function() {
- this.q = [];
- },
- queue: function(/* taskFunc, taskFunc... */) {
- this.q.push.apply(this.q, arguments);
- this.tryStart();
- },
- pause: function() {
- this.isPaused = true;
- },
- resume: function() {
- this.isPaused = false;
- this.tryStart();
- },
- tryStart: function() {
- if (!this.isRunning && this.canRunNext()) {
- this.isRunning = true;
- this.trigger('start');
- this.runNext();
- }
- },
- canRunNext: function() {
- return !this.isPaused && this.q.length;
- },
- runNext: function() {
- this.runTask(this.q.shift());
- },
- runTask: function(task) {
- this.runTaskFunc(task);
- },
- runTaskFunc: function(taskFunc) {
- var _this = this;
- var res = taskFunc();
- if (res && res.then) {
- res.then(done);
- }
- else {
- done();
- }
- function done() {
- if (_this.canRunNext()) {
- _this.runNext();
- }
- else {
- _this.isRunning = false;
- _this.trigger('stop');
- }
- }
- }
- });
- FC.TaskQueue = TaskQueue;
- ;;
- var RenderQueue = TaskQueue.extend({
- waitsByNamespace: null,
- waitNamespace: null,
- waitId: null,
- constructor: function(waitsByNamespace) {
- TaskQueue.call(this);
- this.waitsByNamespace = waitsByNamespace || {};
- },
- queue: function(taskFunc, namespace, type) {
- var task = {
- func: taskFunc,
- namespace: namespace,
- type: type
- };
- var waitMs;
- if (namespace) {
- waitMs = this.waitsByNamespace[namespace];
- }
- if (this.waitNamespace) {
- if (namespace === this.waitNamespace && waitMs != null) {
- this.delayWait(waitMs);
- }
- else {
- this.clearWait();
- this.tryStart();
- }
- }
- if (this.compoundTask(task)) {
- if (!this.waitNamespace && waitMs != null) {
- this.startWait(namespace, waitMs);
- }
- else {
- this.tryStart();
- }
- }
- },
- startWait: function(namespace, waitMs) {
- this.waitNamespace = namespace;
- this.spawnWait(waitMs);
- },
- delayWait: function(waitMs) {
- clearTimeout(this.waitId);
- this.spawnWait(waitMs);
- },
- spawnWait: function(waitMs) {
- var _this = this;
- this.waitId = setTimeout(function() {
- _this.waitNamespace = null;
- _this.tryStart();
- }, waitMs);
- },
- clearWait: function() {
- if (this.waitNamespace) {
- clearTimeout(this.waitId);
- this.waitId = null;
- this.waitNamespace = null;
- }
- },
- canRunNext: function() {
- if (!TaskQueue.prototype.canRunNext.apply(this, arguments)) {
- return false;
- }
-
- if (this.waitNamespace) {
-
-
-
- for (var q = this.q, i = 0; i < q.length; i++) {
- if (q[i].namespace !== this.waitNamespace) {
- return true;
- }
- }
- return false;
- }
- return true;
- },
- runTask: function(task) {
- this.runTaskFunc(task.func);
- },
- compoundTask: function(newTask) {
- var q = this.q;
- var shouldAppend = true;
- var i, task;
- if (newTask.namespace) {
- if (newTask.type === 'destroy' || newTask.type === 'init') {
-
- for (i = q.length - 1; i >= 0; i--) {
- task = q[i];
- if (
- task.namespace === newTask.namespace &&
- (task.type === 'add' || task.type === 'remove')
- ) {
- q.splice(i, 1);
- }
- }
- if (newTask.type === 'destroy') {
-
- if (q.length) {
- task = q[q.length - 1];
- if (task.namespace === newTask.namespace) {
-
- if (task.type === 'init') {
- shouldAppend = false;
- q.pop();
- }
-
- else if (task.type === 'destroy') {
- shouldAppend = false;
- }
- }
- }
- }
- else if (newTask.type === 'init') {
-
- if (q.length) {
- task = q[q.length - 1];
- if (
- task.namespace === newTask.namespace &&
- task.type === 'init'
- ) {
-
- q.pop();
- }
- }
- }
- }
- }
- if (shouldAppend) {
- q.push(newTask);
- }
- return shouldAppend;
- }
- });
- FC.RenderQueue = RenderQueue;
- ;;
- var Popover = Class.extend(ListenerMixin, {
- isHidden: true,
- options: null,
- el: null,
- margin: 10,
- constructor: function(options) {
- this.options = options || {};
- },
-
- show: function() {
- if (this.isHidden) {
- if (!this.el) {
- this.render();
- }
- this.el.show();
- this.position();
- this.isHidden = false;
- this.trigger('show');
- }
- },
-
- hide: function() {
- if (!this.isHidden) {
- this.el.hide();
- this.isHidden = true;
- this.trigger('hide');
- }
- },
-
- render: function() {
- var _this = this;
- var options = this.options;
- this.el = $('<div class="fc-popover"/>')
- .addClass(options.className || '')
- .css({
-
- top: 0,
- left: 0
- })
- .append(options.content)
- .appendTo(options.parentEl);
-
- this.el.on('click', '.fc-close', function() {
- _this.hide();
- });
- if (options.autoHide) {
- this.listenTo($(document), 'mousedown', this.documentMousedown);
- }
- },
-
- documentMousedown: function(ev) {
-
- if (this.el && !$(ev.target).closest(this.el).length) {
- this.hide();
- }
- },
-
- removeElement: function() {
- this.hide();
- if (this.el) {
- this.el.remove();
- this.el = null;
- }
- this.stopListeningTo($(document), 'mousedown');
- },
-
- position: function() {
- var options = this.options;
- var origin = this.el.offsetParent().offset();
- var width = this.el.outerWidth();
- var height = this.el.outerHeight();
- var windowEl = $(window);
- var viewportEl = getScrollParent(this.el);
- var viewportTop;
- var viewportLeft;
- var viewportOffset;
- var top;
- var left;
-
- top = options.top || 0;
- if (options.left !== undefined) {
- left = options.left;
- }
- else if (options.right !== undefined) {
- left = options.right - width;
- }
- else {
- left = 0;
- }
- if (viewportEl.is(window) || viewportEl.is(document)) {
- viewportEl = windowEl;
- viewportTop = 0;
- viewportLeft = 0;
- }
- else {
- viewportOffset = viewportEl.offset();
- viewportTop = viewportOffset.top;
- viewportLeft = viewportOffset.left;
- }
-
- viewportTop += windowEl.scrollTop();
- viewportLeft += windowEl.scrollLeft();
-
- if (options.viewportConstrain !== false) {
- top = Math.min(top, viewportTop + viewportEl.outerHeight() - height - this.margin);
- top = Math.max(top, viewportTop + this.margin);
- left = Math.min(left, viewportLeft + viewportEl.outerWidth() - width - this.margin);
- left = Math.max(left, viewportLeft + this.margin);
- }
- this.el.css({
- top: top - origin.top,
- left: left - origin.left
- });
- },
-
-
-
- trigger: function(name) {
- if (this.options[name]) {
- this.options[name].apply(this, Array.prototype.slice.call(arguments, 1));
- }
- }
- });
- ;;
- var CoordCache = FC.CoordCache = Class.extend({
- els: null,
- forcedOffsetParentEl: null,
- origin: null,
- boundingRect: null,
- isHorizontal: false,
- isVertical: false,
-
- lefts: null,
- rights: null,
- tops: null,
- bottoms: null,
- constructor: function(options) {
- this.els = $(options.els);
- this.isHorizontal = options.isHorizontal;
- this.isVertical = options.isVertical;
- this.forcedOffsetParentEl = options.offsetParent ? $(options.offsetParent) : null;
- },
-
-
- build: function() {
- var offsetParentEl = this.forcedOffsetParentEl;
- if (!offsetParentEl && this.els.length > 0) {
- offsetParentEl = this.els.eq(0).offsetParent();
- }
- this.origin = offsetParentEl ?
- offsetParentEl.offset() :
- null;
- this.boundingRect = this.queryBoundingRect();
- if (this.isHorizontal) {
- this.buildElHorizontals();
- }
- if (this.isVertical) {
- this.buildElVerticals();
- }
- },
-
- clear: function() {
- this.origin = null;
- this.boundingRect = null;
- this.lefts = null;
- this.rights = null;
- this.tops = null;
- this.bottoms = null;
- },
-
- ensureBuilt: function() {
- if (!this.origin) {
- this.build();
- }
- },
-
- buildElHorizontals: function() {
- var lefts = [];
- var rights = [];
- this.els.each(function(i, node) {
- var el = $(node);
- var left = el.offset().left;
- var width = el.outerWidth();
- lefts.push(left);
- rights.push(left + width);
- });
- this.lefts = lefts;
- this.rights = rights;
- },
-
- buildElVerticals: function() {
- var tops = [];
- var bottoms = [];
- this.els.each(function(i, node) {
- var el = $(node);
- var top = el.offset().top;
- var height = el.outerHeight();
- tops.push(top);
- bottoms.push(top + height);
- });
- this.tops = tops;
- this.bottoms = bottoms;
- },
-
-
- getHorizontalIndex: function(leftOffset) {
- this.ensureBuilt();
- var lefts = this.lefts;
- var rights = this.rights;
- var len = lefts.length;
- var i;
- for (i = 0; i < len; i++) {
- if (leftOffset >= lefts[i] && leftOffset < rights[i]) {
- return i;
- }
- }
- },
-
-
- getVerticalIndex: function(topOffset) {
- this.ensureBuilt();
- var tops = this.tops;
- var bottoms = this.bottoms;
- var len = tops.length;
- var i;
- for (i = 0; i < len; i++) {
- if (topOffset >= tops[i] && topOffset < bottoms[i]) {
- return i;
- }
- }
- },
-
- getLeftOffset: function(leftIndex) {
- this.ensureBuilt();
- return this.lefts[leftIndex];
- },
-
- getLeftPosition: function(leftIndex) {
- this.ensureBuilt();
- return this.lefts[leftIndex] - this.origin.left;
- },
-
-
- getRightOffset: function(leftIndex) {
- this.ensureBuilt();
- return this.rights[leftIndex];
- },
-
-
- getRightPosition: function(leftIndex) {
- this.ensureBuilt();
- return this.rights[leftIndex] - this.origin.left;
- },
-
- getWidth: function(leftIndex) {
- this.ensureBuilt();
- return this.rights[leftIndex] - this.lefts[leftIndex];
- },
-
- getTopOffset: function(topIndex) {
- this.ensureBuilt();
- return this.tops[topIndex];
- },
-
- getTopPosition: function(topIndex) {
- this.ensureBuilt();
- return this.tops[topIndex] - this.origin.top;
- },
-
-
- getBottomOffset: function(topIndex) {
- this.ensureBuilt();
- return this.bottoms[topIndex];
- },
-
-
- getBottomPosition: function(topIndex) {
- this.ensureBuilt();
- return this.bottoms[topIndex] - this.origin.top;
- },
-
- getHeight: function(topIndex) {
- this.ensureBuilt();
- return this.bottoms[topIndex] - this.tops[topIndex];
- },
-
-
-
-
-
- queryBoundingRect: function() {
- var scrollParentEl;
- if (this.els.length > 0) {
- scrollParentEl = getScrollParent(this.els.eq(0));
- if (!scrollParentEl.is(document)) {
- return getClientRect(scrollParentEl);
- }
- }
- return null;
- },
- isPointInBounds: function(leftOffset, topOffset) {
- return this.isLeftInBounds(leftOffset) && this.isTopInBounds(topOffset);
- },
- isLeftInBounds: function(leftOffset) {
- return !this.boundingRect || (leftOffset >= this.boundingRect.left && leftOffset < this.boundingRect.right);
- },
- isTopInBounds: function(topOffset) {
- return !this.boundingRect || (topOffset >= this.boundingRect.top && topOffset < this.boundingRect.bottom);
- }
- });
- ;;
- var DragListener = FC.DragListener = Class.extend(ListenerMixin, {
- options: null,
- subjectEl: null,
-
- originX: null,
- originY: null,
-
-
- scrollEl: null,
- isInteracting: false,
- isDistanceSurpassed: false,
- isDelayEnded: false,
- isDragging: false,
- isTouch: false,
- isGeneric: false,
- delay: null,
- delayTimeoutId: null,
- minDistance: null,
- shouldCancelTouchScroll: true,
- scrollAlwaysKills: false,
- constructor: function(options) {
- this.options = options || {};
- },
-
-
- startInteraction: function(ev, extraOptions) {
- if (ev.type === 'mousedown') {
- if (GlobalEmitter.get().shouldIgnoreMouse()) {
- return;
- }
- else if (!isPrimaryMouseButton(ev)) {
- return;
- }
- else {
- ev.preventDefault();
- }
- }
- if (!this.isInteracting) {
-
- extraOptions = extraOptions || {};
- this.delay = firstDefined(extraOptions.delay, this.options.delay, 0);
- this.minDistance = firstDefined(extraOptions.distance, this.options.distance, 0);
- this.subjectEl = this.options.subjectEl;
- preventSelection($('body'));
- this.isInteracting = true;
- this.isTouch = getEvIsTouch(ev);
- this.isGeneric = ev.type === 'dragstart';
- this.isDelayEnded = false;
- this.isDistanceSurpassed = false;
- this.originX = getEvX(ev);
- this.originY = getEvY(ev);
- this.scrollEl = getScrollParent($(ev.target));
- this.bindHandlers();
- this.initAutoScroll();
- this.handleInteractionStart(ev);
- this.startDelay(ev);
- if (!this.minDistance) {
- this.handleDistanceSurpassed(ev);
- }
- }
- },
- handleInteractionStart: function(ev) {
- this.trigger('interactionStart', ev);
- },
- endInteraction: function(ev, isCancelled) {
- if (this.isInteracting) {
- this.endDrag(ev);
- if (this.delayTimeoutId) {
- clearTimeout(this.delayTimeoutId);
- this.delayTimeoutId = null;
- }
- this.destroyAutoScroll();
- this.unbindHandlers();
- this.isInteracting = false;
- this.handleInteractionEnd(ev, isCancelled);
- allowSelection($('body'));
- }
- },
- handleInteractionEnd: function(ev, isCancelled) {
- this.trigger('interactionEnd', ev, isCancelled || false);
- },
-
-
- bindHandlers: function() {
-
-
- var globalEmitter = GlobalEmitter.get();
- if (this.isGeneric) {
- this.listenTo($(document), {
- drag: this.handleMove,
- dragstop: this.endInteraction
- });
- }
- else if (this.isTouch) {
- this.listenTo(globalEmitter, {
- touchmove: this.handleTouchMove,
- touchend: this.endInteraction,
- scroll: this.handleTouchScroll
- });
- }
- else {
- this.listenTo(globalEmitter, {
- mousemove: this.handleMouseMove,
- mouseup: this.endInteraction
- });
- }
- this.listenTo(globalEmitter, {
- selectstart: preventDefault,
- contextmenu: preventDefault
- });
- },
- unbindHandlers: function() {
- this.stopListeningTo(GlobalEmitter.get());
- this.stopListeningTo($(document));
- },
-
-
-
- startDrag: function(ev, extraOptions) {
- this.startInteraction(ev, extraOptions);
- if (!this.isDragging) {
- this.isDragging = true;
- this.handleDragStart(ev);
- }
- },
- handleDragStart: function(ev) {
- this.trigger('dragStart', ev);
- },
- handleMove: function(ev) {
- var dx = getEvX(ev) - this.originX;
- var dy = getEvY(ev) - this.originY;
- var minDistance = this.minDistance;
- var distanceSq;
- if (!this.isDistanceSurpassed) {
- distanceSq = dx * dx + dy * dy;
- if (distanceSq >= minDistance * minDistance) {
- this.handleDistanceSurpassed(ev);
- }
- }
- if (this.isDragging) {
- this.handleDrag(dx, dy, ev);
- }
- },
-
- handleDrag: function(dx, dy, ev) {
- this.trigger('drag', dx, dy, ev);
- this.updateAutoScroll(ev);
- },
- endDrag: function(ev) {
- if (this.isDragging) {
- this.isDragging = false;
- this.handleDragEnd(ev);
- }
- },
- handleDragEnd: function(ev) {
- this.trigger('dragEnd', ev);
- },
-
-
- startDelay: function(initialEv) {
- var _this = this;
- if (this.delay) {
- this.delayTimeoutId = setTimeout(function() {
- _this.handleDelayEnd(initialEv);
- }, this.delay);
- }
- else {
- this.handleDelayEnd(initialEv);
- }
- },
- handleDelayEnd: function(initialEv) {
- this.isDelayEnded = true;
- if (this.isDistanceSurpassed) {
- this.startDrag(initialEv);
- }
- },
-
-
- handleDistanceSurpassed: function(ev) {
- this.isDistanceSurpassed = true;
- if (this.isDelayEnded) {
- this.startDrag(ev);
- }
- },
-
-
- handleTouchMove: function(ev) {
-
- if (this.isDragging && this.shouldCancelTouchScroll) {
- ev.preventDefault();
- }
- this.handleMove(ev);
- },
- handleMouseMove: function(ev) {
- this.handleMove(ev);
- },
-
-
- handleTouchScroll: function(ev) {
-
-
- if (!this.isDragging || this.scrollAlwaysKills) {
- this.endInteraction(ev, true);
- }
- },
-
-
-
-
- trigger: function(name) {
- if (this.options[name]) {
- this.options[name].apply(this, Array.prototype.slice.call(arguments, 1));
- }
-
- if (this['_' + name]) {
- this['_' + name].apply(this, Array.prototype.slice.call(arguments, 1));
- }
- }
- });
- ;;
- DragListener.mixin({
- isAutoScroll: false,
- scrollBounds: null,
- scrollTopVel: null,
- scrollLeftVel: null,
- scrollIntervalId: null,
-
- scrollSensitivity: 30,
- scrollSpeed: 200,
- scrollIntervalMs: 50,
- initAutoScroll: function() {
- var scrollEl = this.scrollEl;
- this.isAutoScroll =
- this.options.scroll &&
- scrollEl &&
- !scrollEl.is(window) &&
- !scrollEl.is(document);
- if (this.isAutoScroll) {
-
- this.listenTo(scrollEl, 'scroll', debounce(this.handleDebouncedScroll, 100));
- }
- },
- destroyAutoScroll: function() {
- this.endAutoScroll();
-
- if (this.isAutoScroll) {
- this.stopListeningTo(this.scrollEl, 'scroll');
- }
- },
-
- computeScrollBounds: function() {
- if (this.isAutoScroll) {
- this.scrollBounds = getOuterRect(this.scrollEl);
-
- }
- },
-
- updateAutoScroll: function(ev) {
- var sensitivity = this.scrollSensitivity;
- var bounds = this.scrollBounds;
- var topCloseness, bottomCloseness;
- var leftCloseness, rightCloseness;
- var topVel = 0;
- var leftVel = 0;
- if (bounds) {
-
- topCloseness = (sensitivity - (getEvY(ev) - bounds.top)) / sensitivity;
- bottomCloseness = (sensitivity - (bounds.bottom - getEvY(ev))) / sensitivity;
- leftCloseness = (sensitivity - (getEvX(ev) - bounds.left)) / sensitivity;
- rightCloseness = (sensitivity - (bounds.right - getEvX(ev))) / sensitivity;
-
-
- if (topCloseness >= 0 && topCloseness <= 1) {
- topVel = topCloseness * this.scrollSpeed * -1;
- }
- else if (bottomCloseness >= 0 && bottomCloseness <= 1) {
- topVel = bottomCloseness * this.scrollSpeed;
- }
-
- if (leftCloseness >= 0 && leftCloseness <= 1) {
- leftVel = leftCloseness * this.scrollSpeed * -1;
- }
- else if (rightCloseness >= 0 && rightCloseness <= 1) {
- leftVel = rightCloseness * this.scrollSpeed;
- }
- }
- this.setScrollVel(topVel, leftVel);
- },
-
- setScrollVel: function(topVel, leftVel) {
- this.scrollTopVel = topVel;
- this.scrollLeftVel = leftVel;
- this.constrainScrollVel();
-
- if ((this.scrollTopVel || this.scrollLeftVel) && !this.scrollIntervalId) {
- this.scrollIntervalId = setInterval(
- proxy(this, 'scrollIntervalFunc'),
- this.scrollIntervalMs
- );
- }
- },
-
- constrainScrollVel: function() {
- var el = this.scrollEl;
- if (this.scrollTopVel < 0) {
- if (el.scrollTop() <= 0) {
- this.scrollTopVel = 0;
- }
- }
- else if (this.scrollTopVel > 0) {
- if (el.scrollTop() + el[0].clientHeight >= el[0].scrollHeight) {
- this.scrollTopVel = 0;
- }
- }
- if (this.scrollLeftVel < 0) {
- if (el.scrollLeft() <= 0) {
- this.scrollLeftVel = 0;
- }
- }
- else if (this.scrollLeftVel > 0) {
- if (el.scrollLeft() + el[0].clientWidth >= el[0].scrollWidth) {
- this.scrollLeftVel = 0;
- }
- }
- },
-
- scrollIntervalFunc: function() {
- var el = this.scrollEl;
- var frac = this.scrollIntervalMs / 1000;
-
- if (this.scrollTopVel) {
- el.scrollTop(el.scrollTop() + this.scrollTopVel * frac);
- }
- if (this.scrollLeftVel) {
- el.scrollLeft(el.scrollLeft() + this.scrollLeftVel * frac);
- }
- this.constrainScrollVel();
-
- if (!this.scrollTopVel && !this.scrollLeftVel) {
- this.endAutoScroll();
- }
- },
-
- endAutoScroll: function() {
- if (this.scrollIntervalId) {
- clearInterval(this.scrollIntervalId);
- this.scrollIntervalId = null;
- this.handleScrollEnd();
- }
- },
-
- handleDebouncedScroll: function() {
-
- if (!this.scrollIntervalId) {
- this.handleScrollEnd();
- }
- },
-
- handleScrollEnd: function() {
- }
- });
- ;;
- var HitDragListener = DragListener.extend({
- component: null,
-
- origHit: null,
- hit: null,
- coordAdjust: null,
- constructor: function(component, options) {
- DragListener.call(this, options);
- this.component = component;
- },
-
-
- handleInteractionStart: function(ev) {
- var subjectEl = this.subjectEl;
- var subjectRect;
- var origPoint;
- var point;
- this.component.hitsNeeded();
- this.computeScrollBounds();
- if (ev) {
- origPoint = { left: getEvX(ev), top: getEvY(ev) };
- point = origPoint;
-
- if (subjectEl) {
- subjectRect = getOuterRect(subjectEl);
- point = constrainPoint(point, subjectRect);
- }
- this.origHit = this.queryHit(point.left, point.top);
-
- if (subjectEl && this.options.subjectCenter) {
-
-
- if (this.origHit) {
- subjectRect = intersectRects(this.origHit, subjectRect) ||
- subjectRect;
- }
- point = getRectCenter(subjectRect);
- }
- this.coordAdjust = diffPoints(point, origPoint);
- }
- else {
- this.origHit = null;
- this.coordAdjust = null;
- }
-
- DragListener.prototype.handleInteractionStart.apply(this, arguments);
- },
-
- handleDragStart: function(ev) {
- var hit;
- DragListener.prototype.handleDragStart.apply(this, arguments);
-
- hit = this.queryHit(getEvX(ev), getEvY(ev));
-
-
- if (hit) {
- this.handleHitOver(hit);
- }
- },
-
- handleDrag: function(dx, dy, ev) {
- var hit;
- DragListener.prototype.handleDrag.apply(this, arguments);
- hit = this.queryHit(getEvX(ev), getEvY(ev));
- if (!isHitsEqual(hit, this.hit)) {
- if (this.hit) {
- this.handleHitOut();
- }
- if (hit) {
- this.handleHitOver(hit);
- }
- }
- },
-
- handleDragEnd: function() {
- this.handleHitDone();
- DragListener.prototype.handleDragEnd.apply(this, arguments);
- },
-
- handleHitOver: function(hit) {
- var isOrig = isHitsEqual(hit, this.origHit);
- this.hit = hit;
- this.trigger('hitOver', this.hit, isOrig, this.origHit);
- },
-
- handleHitOut: function() {
- if (this.hit) {
- this.trigger('hitOut', this.hit);
- this.handleHitDone();
- this.hit = null;
- }
- },
-
- handleHitDone: function() {
- if (this.hit) {
- this.trigger('hitDone', this.hit);
- }
- },
-
- handleInteractionEnd: function() {
- DragListener.prototype.handleInteractionEnd.apply(this, arguments);
- this.origHit = null;
- this.hit = null;
- this.component.hitsNotNeeded();
- },
-
- handleScrollEnd: function() {
- DragListener.prototype.handleScrollEnd.apply(this, arguments);
-
-
- if (this.isDragging) {
- this.component.releaseHits();
- this.component.prepareHits();
- }
- },
-
- queryHit: function(left, top) {
- if (this.coordAdjust) {
- left += this.coordAdjust.left;
- top += this.coordAdjust.top;
- }
- return this.component.queryHit(left, top);
- }
- });
- function isHitsEqual(hit0, hit1) {
- if (!hit0 && !hit1) {
- return true;
- }
- if (hit0 && hit1) {
- return hit0.component === hit1.component &&
- isHitPropsWithin(hit0, hit1) &&
- isHitPropsWithin(hit1, hit0);
- }
- return false;
- }
- function isHitPropsWithin(subHit, superHit) {
- for (var propName in subHit) {
- if (!/^(component|left|right|top|bottom)$/.test(propName)) {
- if (subHit[propName] !== superHit[propName]) {
- return false;
- }
- }
- }
- return true;
- }
- ;;
- FC.touchMouseIgnoreWait = 500;
- var GlobalEmitter = Class.extend(ListenerMixin, EmitterMixin, {
- isTouching: false,
- mouseIgnoreDepth: 0,
- handleScrollProxy: null,
- bind: function() {
- var _this = this;
- this.listenTo($(document), {
- touchstart: this.handleTouchStart,
- touchcancel: this.handleTouchCancel,
- touchend: this.handleTouchEnd,
- mousedown: this.handleMouseDown,
- mousemove: this.handleMouseMove,
- mouseup: this.handleMouseUp,
- click: this.handleClick,
- selectstart: this.handleSelectStart,
- contextmenu: this.handleContextMenu
- });
-
-
-
- window.addEventListener(
- 'touchmove',
- this.handleTouchMoveProxy = function(ev) {
- _this.handleTouchMove($.Event(ev));
- },
- { passive: false }
- );
-
-
-
- window.addEventListener(
- 'scroll',
- this.handleScrollProxy = function(ev) {
- _this.handleScroll($.Event(ev));
- },
- true
- );
- },
- unbind: function() {
- this.stopListeningTo($(document));
- window.removeEventListener(
- 'touchmove',
- this.handleTouchMoveProxy
- );
- window.removeEventListener(
- 'scroll',
- this.handleScrollProxy,
- true
- );
- },
-
-
- handleTouchStart: function(ev) {
-
-
- this.stopTouch(ev, true);
- this.isTouching = true;
- this.trigger('touchstart', ev);
- },
- handleTouchMove: function(ev) {
- if (this.isTouching) {
- this.trigger('touchmove', ev);
- }
- },
- handleTouchCancel: function(ev) {
- if (this.isTouching) {
- this.trigger('touchcancel', ev);
-
-
- this.stopTouch(ev);
- }
- },
- handleTouchEnd: function(ev) {
- this.stopTouch(ev);
- },
-
-
- handleMouseDown: function(ev) {
- if (!this.shouldIgnoreMouse()) {
- this.trigger('mousedown', ev);
- }
- },
- handleMouseMove: function(ev) {
- if (!this.shouldIgnoreMouse()) {
- this.trigger('mousemove', ev);
- }
- },
- handleMouseUp: function(ev) {
- if (!this.shouldIgnoreMouse()) {
- this.trigger('mouseup', ev);
- }
- },
- handleClick: function(ev) {
- if (!this.shouldIgnoreMouse()) {
- this.trigger('click', ev);
- }
- },
-
-
- handleSelectStart: function(ev) {
- this.trigger('selectstart', ev);
- },
- handleContextMenu: function(ev) {
- this.trigger('contextmenu', ev);
- },
- handleScroll: function(ev) {
- this.trigger('scroll', ev);
- },
-
-
- stopTouch: function(ev, skipMouseIgnore) {
- if (this.isTouching) {
- this.isTouching = false;
- this.trigger('touchend', ev);
- if (!skipMouseIgnore) {
- this.startTouchMouseIgnore();
- }
- }
- },
- startTouchMouseIgnore: function() {
- var _this = this;
- var wait = FC.touchMouseIgnoreWait;
- if (wait) {
- this.mouseIgnoreDepth++;
- setTimeout(function() {
- _this.mouseIgnoreDepth--;
- }, wait);
- }
- },
- shouldIgnoreMouse: function() {
- return this.isTouching || Boolean(this.mouseIgnoreDepth);
- }
- });
- (function() {
- var globalEmitter = null;
- var neededCount = 0;
-
- GlobalEmitter.get = function() {
- if (!globalEmitter) {
- globalEmitter = new GlobalEmitter();
- globalEmitter.bind();
- }
- return globalEmitter;
- };
-
- GlobalEmitter.needed = function() {
- GlobalEmitter.get();
- neededCount++;
- };
-
- GlobalEmitter.unneeded = function() {
- neededCount--;
- if (!neededCount) {
- globalEmitter.unbind();
- globalEmitter = null;
- }
- };
- })();
- ;;
- var MouseFollower = Class.extend(ListenerMixin, {
- options: null,
- sourceEl: null,
- el: null,
- parentEl: null,
-
- top0: null,
- left0: null,
-
- y0: null,
- x0: null,
-
- topDelta: null,
- leftDelta: null,
- isFollowing: false,
- isHidden: false,
- isAnimating: false,
- constructor: function(sourceEl, options) {
- this.options = options = options || {};
- this.sourceEl = sourceEl;
- this.parentEl = options.parentEl ? $(options.parentEl) : sourceEl.parent();
- },
-
- start: function(ev) {
- if (!this.isFollowing) {
- this.isFollowing = true;
- this.y0 = getEvY(ev);
- this.x0 = getEvX(ev);
- this.topDelta = 0;
- this.leftDelta = 0;
- if (!this.isHidden) {
- this.updatePosition();
- }
- if (getEvIsTouch(ev)) {
- this.listenTo($(document), 'touchmove', this.handleMove);
- }
- else {
- this.listenTo($(document), 'mousemove', this.handleMove);
- }
- }
- },
-
-
- stop: function(shouldRevert, callback) {
- var _this = this;
- var revertDuration = this.options.revertDuration;
- function complete() {
- _this.isAnimating = false;
- _this.removeElement();
- _this.top0 = _this.left0 = null;
- if (callback) {
- callback();
- }
- }
- if (this.isFollowing && !this.isAnimating) {
- this.isFollowing = false;
- this.stopListeningTo($(document));
- if (shouldRevert && revertDuration && !this.isHidden) {
- this.isAnimating = true;
- this.el.animate({
- top: this.top0,
- left: this.left0
- }, {
- duration: revertDuration,
- complete: complete
- });
- }
- else {
- complete();
- }
- }
- },
-
- getEl: function() {
- var el = this.el;
- if (!el) {
- el = this.el = this.sourceEl.clone()
- .addClass(this.options.additionalClass || '')
- .css({
- position: 'absolute',
- visibility: '',
- display: this.isHidden ? 'none' : '',
- margin: 0,
- right: 'auto',
- bottom: 'auto',
- width: this.sourceEl.width(),
- height: this.sourceEl.height(),
- opacity: this.options.opacity || '',
- zIndex: this.options.zIndex
- });
-
-
- el.addClass('fc-unselectable');
- el.appendTo(this.parentEl);
- }
- return el;
- },
-
- removeElement: function() {
- if (this.el) {
- this.el.remove();
- this.el = null;
- }
- },
-
- updatePosition: function() {
- var sourceOffset;
- var origin;
- this.getEl();
-
- if (this.top0 === null) {
- sourceOffset = this.sourceEl.offset();
- origin = this.el.offsetParent().offset();
- this.top0 = sourceOffset.top - origin.top;
- this.left0 = sourceOffset.left - origin.left;
- }
- this.el.css({
- top: this.top0 + this.topDelta,
- left: this.left0 + this.leftDelta
- });
- },
-
- handleMove: function(ev) {
- this.topDelta = getEvY(ev) - this.y0;
- this.leftDelta = getEvX(ev) - this.x0;
- if (!this.isHidden) {
- this.updatePosition();
- }
- },
-
- hide: function() {
- if (!this.isHidden) {
- this.isHidden = true;
- if (this.el) {
- this.el.hide();
- }
- }
- },
-
- show: function() {
- if (this.isHidden) {
- this.isHidden = false;
- this.updatePosition();
- this.getEl().show();
- }
- }
- });
- ;;
- var ChronoComponent = Model.extend({
- children: null,
- el: null,
-
- isRTL: false,
- nextDayThreshold: null,
- constructor: function() {
- Model.call(this);
- this.children = [];
- this.nextDayThreshold = moment.duration(this.opt('nextDayThreshold'));
- this.isRTL = this.opt('isRTL');
- },
- addChild: function(chronoComponent) {
- this.children.push(chronoComponent);
- },
-
-
- opt: function(name) {
-
- },
- publiclyTrigger: function(/**/) {
- var calendar = this._getCalendar();
- return calendar.publiclyTrigger.apply(calendar, arguments);
- },
- hasPublicHandlers: function(/**/) {
- var calendar = this._getCalendar();
- return calendar.hasPublicHandlers.apply(calendar, arguments);
- },
-
-
-
-
- setElement: function(el) {
- this.el = el;
- this.bindGlobalHandlers();
- this.renderSkeleton();
- },
-
-
- removeElement: function() {
- this.unrenderSkeleton();
- this.unbindGlobalHandlers();
- this.el.remove();
-
-
-
- },
- bindGlobalHandlers: function() {
- },
- unbindGlobalHandlers: function() {
- },
-
-
-
- renderSkeleton: function() {
-
- },
-
- unrenderSkeleton: function() {
-
- },
-
-
-
- renderDates: function() {
-
- },
-
- unrenderDates: function() {
-
- },
-
-
-
-
- getNowIndicatorUnit: function() {
-
- },
-
- renderNowIndicator: function(date) {
- this.callChildren('renderNowIndicator', date);
- },
-
- unrenderNowIndicator: function() {
- this.callChildren('unrenderNowIndicator');
- },
-
-
-
- renderBusinessHours: function() {
- this.callChildren('renderBusinessHours');
- },
-
- unrenderBusinessHours: function() {
- this.callChildren('unrenderBusinessHours');
- },
-
-
-
-
- renderEventsPayload: function(eventsPayload) {
- this.callChildren('renderEventsPayload', eventsPayload);
- },
-
- unrenderEvents: function() {
- this.callChildren('unrenderEvents');
-
-
- },
-
- getEventSegs: function() {
- var children = this.children;
- var segs = [];
- var i;
- for (i = 0; i < children.length; i++) {
- segs.push.apply(
- segs,
- children[i].getEventSegs()
- );
- }
- return segs;
- },
-
-
-
-
-
- renderDrag: function(eventFootprints, seg) {
- var dragEls = null;
- var children = this.children;
- var i;
- var childDragEls;
- for (i = 0; i < children.length; i++) {
- childDragEls = children[i].renderDrag(eventFootprints, seg);
- if (childDragEls) {
- if (!dragEls) {
- dragEls = childDragEls;
- }
- else {
- dragEls = dragEls.add(childDragEls);
- }
- }
- }
- return dragEls;
- },
-
- unrenderDrag: function() {
- this.callChildren('unrenderDrag');
- },
-
-
-
-
- renderSelectionFootprint: function(componentFootprint) {
- this.callChildren('renderSelectionFootprint', componentFootprint);
- },
-
- unrenderSelection: function() {
- this.callChildren('unrenderSelection');
- },
-
-
- hitsNeeded: function() {
- this.callChildren('hitsNeeded');
- },
- hitsNotNeeded: function() {
- this.callChildren('hitsNotNeeded');
- },
-
- prepareHits: function() {
- this.callChildren('prepareHits');
- },
-
- releaseHits: function() {
- this.callChildren('releaseHits');
- },
-
-
-
-
- queryHit: function(leftOffset, topOffset) {
- var children = this.children;
- var i;
- var hit;
- for (i = 0; i < children.length; i++) {
- hit = children[i].queryHit(leftOffset, topOffset);
- if (hit) {
- break;
- }
- }
- return hit;
- },
-
-
-
- isEventDefDraggable: function(eventDef) {
- return this.isEventDefStartEditable(eventDef);
- },
- isEventDefStartEditable: function(eventDef) {
- var isEditable = eventDef.isStartExplicitlyEditable();
- if (isEditable == null) {
- isEditable = this.opt('eventStartEditable');
- if (isEditable == null) {
- isEditable = this.isEventDefGenerallyEditable(eventDef);
- }
- }
- return isEditable;
- },
- isEventDefGenerallyEditable: function(eventDef) {
- var isEditable = eventDef.isExplicitlyEditable();
- if (isEditable == null) {
- isEditable = this.opt('editable');
- }
- return isEditable;
- },
-
-
-
- isEventDefResizableFromStart: function(eventDef) {
- return this.opt('eventResizableFromStart') && this.isEventDefResizable(eventDef);
- },
-
- isEventDefResizableFromEnd: function(eventDef) {
- return this.isEventDefResizable(eventDef);
- },
-
- isEventDefResizable: function(eventDef) {
- var isResizable = eventDef.isDurationExplicitlyEditable();
- if (isResizable == null) {
- isResizable = this.opt('eventDurationEditable');
- if (isResizable == null) {
- isResizable = this.isEventDefGenerallyEditable(eventDef);
- }
- }
- return isResizable;
- },
-
-
-
- renderFgSegs: function(segs) {
-
- },
-
- unrenderFgSegs: function() {
-
- },
-
-
-
- renderFgSegEls: function(segs, disableResizing) {
- var _this = this;
- var hasEventRenderHandlers = this.hasPublicHandlers('eventRender');
- var html = '';
- var renderedSegs = [];
- var i;
- if (segs.length) {
-
- for (i = 0; i < segs.length; i++) {
- html += this.fgSegHtml(segs[i], disableResizing);
- }
-
-
- $(html).each(function(i, node) {
- var seg = segs[i];
- var el = $(node);
- if (hasEventRenderHandlers) {
- el = _this.filterEventRenderEl(seg.footprint, el);
- }
- if (el) {
- el.data('fc-seg', seg);
- seg.el = el;
- renderedSegs.push(seg);
- }
- });
- }
- return renderedSegs;
- },
-
- fgSegHtml: function(seg, disableResizing) {
-
- },
-
-
- filterEventRenderEl: function(eventFootprint, el) {
- var legacy = eventFootprint.getEventLegacy();
- var custom = this.publiclyTrigger('eventRender', {
- context: legacy,
- args: [ legacy, el, this._getView() ]
- });
- if (custom === false) {
- el = null;
- }
- else if (custom && custom !== true) {
- el = $(custom);
- }
- return el;
- },
-
-
-
-
-
-
-
-
- buildGotoAnchorHtml: function(gotoOptions, attrs, innerHtml) {
- var date, type, forceOff;
- var finalOptions;
- if ($.isPlainObject(gotoOptions)) {
- date = gotoOptions.date;
- type = gotoOptions.type;
- forceOff = gotoOptions.forceOff;
- }
- else {
- date = gotoOptions;
- }
- date = FC.moment(date);
- finalOptions = {
- date: date.format('YYYY-MM-DD'),
- type: type || 'day'
- };
- if (typeof attrs === 'string') {
- innerHtml = attrs;
- attrs = null;
- }
- attrs = attrs ? ' ' + attrsToStr(attrs) : '';
- innerHtml = innerHtml || '';
- if (!forceOff && this.opt('navLinks')) {
- return '<a' + attrs +
- ' data-goto="' + htmlEscape(JSON.stringify(finalOptions)) + '">' +
- innerHtml +
- '</a>';
- }
- else {
- return '<span' + attrs + '>' +
- innerHtml +
- '</span>';
- }
- },
-
-
-
-
-
- formatRange: function(range, isAllDay, formatStr, separator) {
- var end = range.end;
- if (isAllDay) {
- end = end.clone().subtract(1);
- }
- return formatRange(range.start, end, formatStr, separator, this.isRTL);
- },
- getAllDayHtml: function() {
- return this.opt('allDayHtml') || htmlEscape(this.opt('allDayText'));
- },
-
- getDayClasses: function(date, noThemeHighlight) {
- var view = this._getView();
- var classes = [];
- var today;
- if (!view.activeUnzonedRange.containsDate(date)) {
- classes.push('fc-disabled-day');
- }
- else {
- classes.push('fc-' + dayIDs[date.day()]);
- if (view.isDateInOtherMonth(date)) {
- classes.push('fc-other-month');
- }
- today = view.calendar.getNow();
- if (date.isSame(today, 'day')) {
- classes.push('fc-today');
- if (noThemeHighlight !== true) {
- classes.push(view.calendar.theme.getClass('today'));
- }
- }
- else if (date < today) {
- classes.push('fc-past');
- }
- else {
- classes.push('fc-future');
- }
- }
- return classes;
- },
-
-
-
-
- computeDayRange: function(unzonedRange) {
- var calendar = this._getCalendar();
- var startDay = calendar.msToUtcMoment(unzonedRange.startMs, true);
- var end = calendar.msToUtcMoment(unzonedRange.endMs);
- var endTimeMS = +end.time();
- var endDay = end.clone().stripTime();
-
-
-
- if (endTimeMS && endTimeMS >= this.nextDayThreshold) {
- endDay.add(1, 'days');
- }
-
- if (endDay <= startDay) {
- endDay = startDay.clone().add(1, 'days');
- }
- return { start: startDay, end: endDay };
- },
-
- isMultiDayRange: function(unzonedRange) {
- var dayRange = this.computeDayRange(unzonedRange);
- return dayRange.end.diff(dayRange.start, 'days') > 1;
- },
-
-
- callChildren: function(methodName) {
- var args = Array.prototype.slice.call(arguments, 1);
- var children = this.children;
- var i, child;
- for (i = 0; i < children.length; i++) {
- child = children[i];
- child[methodName].apply(child, args);
- }
- },
- _getCalendar: function() {
- return this.calendar || this.view.calendar;
- },
- _getView: function() {
- return this.view;
- }
- });
- ;;
- var Grid = FC.Grid = ChronoComponent.extend({
-
- hasDayInteractions: true,
- view: null,
- isRTL: null,
- unzonedRange: null,
- hitsNeededDepth: 0,
- dayClickListener: null,
- daySelectListener: null,
- segDragListener: null,
- segResizeListener: null,
- externalDragListener: null,
- constructor: function(view) {
- this.view = view;
- ChronoComponent.call(this);
- this.initFillInternals();
- this.dayClickListener = this.buildDayClickListener();
- this.daySelectListener = this.buildDaySelectListener();
- },
- opt: function(name) {
- return this.view.opt(name);
- },
-
-
-
- setRange: function(unzonedRange) {
- this.unzonedRange = unzonedRange;
- this.rangeUpdated();
- this.processRangeOptions();
- },
-
- rangeUpdated: function() {
- },
-
- processRangeOptions: function() {
- var displayEventTime;
- var displayEventEnd;
- this.eventTimeFormat =
- this.opt('eventTimeFormat') ||
- this.opt('timeFormat') ||
- this.computeEventTimeFormat();
- displayEventTime = this.opt('displayEventTime');
- if (displayEventTime == null) {
- displayEventTime = this.computeDisplayEventTime();
- }
- displayEventEnd = this.opt('displayEventEnd');
- if (displayEventEnd == null) {
- displayEventEnd = this.computeDisplayEventEnd();
- }
- this.displayEventTime = displayEventTime;
- this.displayEventEnd = displayEventEnd;
- },
-
- hitsNeeded: function() {
- if (!(this.hitsNeededDepth++)) {
- this.prepareHits();
- }
- },
- hitsNotNeeded: function() {
- if (this.hitsNeededDepth && !(--this.hitsNeededDepth)) {
- this.releaseHits();
- }
- },
- getSafeHitFootprint: function(hit) {
- var footprint = this.getHitFootprint(hit);
- if (!this.view.activeUnzonedRange.containsRange(footprint.unzonedRange)) {
- return null;
- }
- return footprint;
- },
- getHitFootprint: function(hit) {
- },
-
-
- getHitEl: function(hit) {
- },
-
-
-
- setElement: function(el) {
- ChronoComponent.prototype.setElement.apply(this, arguments);
- if (this.hasDayInteractions) {
- preventSelection(el);
- this.bindDayHandler('touchstart', this.dayTouchStart);
- this.bindDayHandler('mousedown', this.dayMousedown);
- }
-
-
- this.bindSegHandlers();
- },
- bindDayHandler: function(name, handler) {
- var _this = this;
-
-
- this.el.on(name, function(ev) {
- if (
- !$(ev.target).is(
- _this.segSelector + ',' +
- _this.segSelector + ' *,' +
- '.fc-more,' +
- 'a[data-goto]'
- )
- ) {
- return handler.call(_this, ev);
- }
- });
- },
-
-
- removeElement: function() {
- ChronoComponent.prototype.removeElement.apply(this, arguments);
- this.clearDragListeners();
- },
-
-
- bindGlobalHandlers: function() {
- ChronoComponent.prototype.bindGlobalHandlers.apply(this, arguments);
- this.listenTo($(document), {
- dragstart: this.externalDragStart,
- sortstart: this.externalDragStart
- });
- },
-
- unbindGlobalHandlers: function() {
- ChronoComponent.prototype.unbindGlobalHandlers.apply(this, arguments);
- this.stopListeningTo($(document));
- },
-
- dayMousedown: function(ev) {
-
-
- if (GlobalEmitter.get().shouldIgnoreMouse()) {
- return;
- }
- this.dayClickListener.startInteraction(ev);
- if (this.opt('selectable')) {
- this.daySelectListener.startInteraction(ev, {
- distance: this.opt('selectMinDistance')
- });
- }
- },
- dayTouchStart: function(ev) {
- var view = this.view;
- var selectLongPressDelay;
-
-
-
-
- if (view.isSelected || view.selectedEvent) {
- return;
- }
- selectLongPressDelay = this.opt('selectLongPressDelay');
- if (selectLongPressDelay == null) {
- selectLongPressDelay = this.opt('longPressDelay');
- }
- this.dayClickListener.startInteraction(ev);
- if (this.opt('selectable')) {
- this.daySelectListener.startInteraction(ev, {
- delay: selectLongPressDelay
- });
- }
- },
-
-
-
- clearDragListeners: function() {
- this.dayClickListener.endInteraction();
- this.daySelectListener.endInteraction();
- if (this.segDragListener) {
- this.segDragListener.endInteraction();
- }
- if (this.segResizeListener) {
- this.segResizeListener.endInteraction();
- }
- if (this.externalDragListener) {
- this.externalDragListener.endInteraction();
- }
- },
-
-
- renderHighlight: function(componentFootprint) {
- this.renderFill('highlight', this.componentFootprintToSegs(componentFootprint));
- },
-
- unrenderHighlight: function() {
- this.unrenderFill('highlight');
- },
-
- eventRangesToEventFootprints: function(eventRanges) {
- var eventFootprints = [];
- var i;
- for (i = 0; i < eventRanges.length; i++) {
- eventFootprints.push.apply(eventFootprints,
- this.eventRangeToEventFootprints(eventRanges[i])
- );
- }
- return eventFootprints;
- },
-
-
-
-
-
- eventRangeToEventFootprints: function(eventRange) {
- return [
- new EventFootprint(
- new ComponentFootprint(
- eventRange.unzonedRange,
- eventRange.eventDef.isAllDay()
- ),
- eventRange.eventDef,
- eventRange.eventInstance
- )
- ];
- },
-
- eventFootprintsToSegs: function(eventFootprints) {
- var segs = [];
- var i;
- for (i = 0; i < eventFootprints.length; i++) {
- segs.push.apply(segs,
- this.eventFootprintToSegs(eventFootprints[i])
- );
- }
- return segs;
- },
-
-
-
-
- eventFootprintToSegs: function(eventFootprint, constraintRange) {
- var unzonedRange = eventFootprint.componentFootprint.unzonedRange;
- var segs;
- var i, seg;
- if (constraintRange) {
- unzonedRange = unzonedRange.intersect(constraintRange);
- }
- segs = this.componentFootprintToSegs(eventFootprint.componentFootprint);
- for (i = 0; i < segs.length; i++) {
- seg = segs[i];
- if (!unzonedRange.isStart) {
- seg.isStart = false;
- }
- if (!unzonedRange.isEnd) {
- seg.isEnd = false;
- }
- seg.footprint = eventFootprint;
-
- }
- return segs;
- },
- componentFootprintToSegs: function(componentFootprint) {
-
- }
- });
- ;;
- Grid.mixin({
-
- buildDayClickListener: function() {
- var _this = this;
- var dayClickHit;
- var dragListener = new HitDragListener(this, {
- scroll: this.opt('dragScroll'),
- interactionStart: function() {
- dayClickHit = dragListener.origHit;
- },
- hitOver: function(hit, isOrig, origHit) {
-
- if (!isOrig) {
- dayClickHit = null;
- }
- },
- hitOut: function() {
- dayClickHit = null;
- },
- interactionEnd: function(ev, isCancelled) {
- var componentFootprint;
- if (!isCancelled && dayClickHit) {
- componentFootprint = _this.getSafeHitFootprint(dayClickHit);
- if (componentFootprint) {
- _this.view.triggerDayClick(componentFootprint, _this.getHitEl(dayClickHit), ev);
- }
- }
- }
- });
-
-
- dragListener.shouldCancelTouchScroll = false;
- dragListener.scrollAlwaysKills = true;
- return dragListener;
- }
- });
- ;;
- Grid.mixin({
-
- buildDaySelectListener: function() {
- var _this = this;
- var selectionFootprint;
- var dragListener = new HitDragListener(this, {
- scroll: this.opt('dragScroll'),
- interactionStart: function() {
- selectionFootprint = null;
- },
- dragStart: function() {
- _this.view.unselect();
- },
- hitOver: function(hit, isOrig, origHit) {
- var origHitFootprint;
- var hitFootprint;
- if (origHit) {
- origHitFootprint = _this.getSafeHitFootprint(origHit);
- hitFootprint = _this.getSafeHitFootprint(hit);
- if (origHitFootprint && hitFootprint) {
- selectionFootprint = _this.computeSelection(origHitFootprint, hitFootprint);
- }
- else {
- selectionFootprint = null;
- }
- if (selectionFootprint) {
- _this.renderSelectionFootprint(selectionFootprint);
- }
- else if (selectionFootprint === false) {
- disableCursor();
- }
- }
- },
- hitOut: function() {
- selectionFootprint = null;
- _this.unrenderSelection();
- },
- hitDone: function() {
- enableCursor();
- },
- interactionEnd: function(ev, isCancelled) {
- if (!isCancelled && selectionFootprint) {
-
- _this.view.reportSelection(selectionFootprint, ev);
- }
- }
- });
- return dragListener;
- },
-
-
- renderSelectionFootprint: function(componentFootprint) {
- this.renderHighlight(componentFootprint);
- },
-
- unrenderSelection: function() {
- this.unrenderHighlight();
- },
-
-
-
-
- computeSelection: function(footprint0, footprint1) {
- var wholeFootprint = this.computeSelectionFootprint(footprint0, footprint1);
- if (wholeFootprint && !this.isSelectionFootprintAllowed(wholeFootprint)) {
- return false;
- }
- return wholeFootprint;
- },
-
-
-
- computeSelectionFootprint: function(footprint0, footprint1) {
- var ms = [
- footprint0.unzonedRange.startMs,
- footprint0.unzonedRange.endMs,
- footprint1.unzonedRange.startMs,
- footprint1.unzonedRange.endMs
- ];
- ms.sort(compareNumbers);
- return new ComponentFootprint(
- new UnzonedRange(ms[0], ms[3]),
- footprint0.isAllDay
- );
- },
- isSelectionFootprintAllowed: function(componentFootprint) {
- return this.view.validUnzonedRange.containsRange(componentFootprint.unzonedRange) &&
- this.view.calendar.isSelectionFootprintAllowed(componentFootprint);
- }
- });
- ;;
- Grid.mixin({
-
-
- businessHoursSegClasses: function(seg) {
- return [ 'fc-nonbusiness', 'fc-bgevent' ];
- },
-
-
- buildBusinessHourSegs: function(wholeDay) {
- return this.eventFootprintsToSegs(
- this.buildBusinessHourEventFootprints(wholeDay)
- );
- },
-
-
-
- buildBusinessHourEventFootprints: function(wholeDay) {
- var calendar = this.view.calendar;
- return this._buildBusinessHourEventFootprints(wholeDay, calendar.opt('businessHours'));
- },
- _buildBusinessHourEventFootprints: function(wholeDay, businessHourDef) {
- var calendar = this.view.calendar;
- var eventInstanceGroup;
- var eventRanges;
- eventInstanceGroup = calendar.buildBusinessInstanceGroup(
- wholeDay,
- businessHourDef,
- this.unzonedRange
- );
- if (eventInstanceGroup) {
- eventRanges = eventInstanceGroup.sliceRenderRanges(
- this.unzonedRange,
- calendar
- );
- }
- else {
- eventRanges = [];
- }
- return this.eventRangesToEventFootprints(eventRanges);
- }
- });
- ;;
- Grid.mixin({
- segs: null,
-
-
- eventTimeFormat: null,
- displayEventTime: null,
- displayEventEnd: null,
-
- computeEventTimeFormat: function() {
- return this.opt('smallTimeFormat');
- },
-
-
- computeDisplayEventTime: function() {
- return true;
- },
-
- computeDisplayEventEnd: function() {
- return true;
- },
- renderEventsPayload: function(eventsPayload) {
- var id, eventInstanceGroup;
- var eventRenderRanges;
- var eventFootprints;
- var eventSegs;
- var bgSegs = [];
- var fgSegs = [];
- for (id in eventsPayload) {
- eventInstanceGroup = eventsPayload[id];
- eventRenderRanges = eventInstanceGroup.sliceRenderRanges(this.view.activeUnzonedRange);
- eventFootprints = this.eventRangesToEventFootprints(eventRenderRanges);
- eventSegs = this.eventFootprintsToSegs(eventFootprints);
- if (eventInstanceGroup.getEventDef().hasBgRendering()) {
- bgSegs.push.apply(bgSegs,
- eventSegs
- );
- }
- else {
- fgSegs.push.apply(fgSegs,
- eventSegs
- );
- }
- }
- this.segs = [].concat(
- this.renderBgSegs(bgSegs) || bgSegs,
- this.renderFgSegs(fgSegs) || fgSegs
- );
- },
-
- unrenderEvents: function() {
- this.handleSegMouseout();
- this.clearDragListeners();
- this.unrenderFgSegs();
- this.unrenderBgSegs();
- this.segs = null;
- },
-
- getEventSegs: function() {
- return this.segs || [];
- },
-
-
-
-
-
- renderBgSegs: function(segs) {
- return this.renderFill('bgEvent', segs);
- },
-
- unrenderBgSegs: function() {
- this.unrenderFill('bgEvent');
- },
-
- bgEventSegEl: function(seg, el) {
- return this.filterEventRenderEl(seg.footprint, el);
- },
-
-
- bgEventSegClasses: function(seg) {
- var eventDef = seg.footprint.eventDef;
- return [ 'fc-bgevent' ].concat(
- eventDef.className,
- eventDef.source.className
- );
- },
-
-
- bgEventSegCss: function(seg) {
- return {
- 'background-color': this.getSegSkinCss(seg)['background-color']
- };
- },
-
-
-
-
-
-
- getEventTimeText: function(eventFootprint, formatStr, displayEnd) {
- return this._getEventTimeText(
- eventFootprint.eventInstance.dateProfile.start,
- eventFootprint.eventInstance.dateProfile.end,
- eventFootprint.componentFootprint.isAllDay,
- formatStr,
- displayEnd
- );
- },
- _getEventTimeText: function(start, end, isAllDay, formatStr, displayEnd) {
- if (formatStr == null) {
- formatStr = this.eventTimeFormat;
- }
- if (displayEnd == null) {
- displayEnd = this.displayEventEnd;
- }
- if (this.displayEventTime && !isAllDay) {
- if (displayEnd && end) {
- return this.view.formatRange(
- { start: start, end: end },
- false,
- formatStr
- );
- }
- else {
- return start.format(formatStr);
- }
- }
- return '';
- },
-
- getSegClasses: function(seg, isDraggable, isResizable) {
- var view = this.view;
- var classes = [
- 'fc-event',
- seg.isStart ? 'fc-start' : 'fc-not-start',
- seg.isEnd ? 'fc-end' : 'fc-not-end'
- ].concat(this.getSegCustomClasses(seg));
- if (isDraggable) {
- classes.push('fc-draggable');
- }
- if (isResizable) {
- classes.push('fc-resizable');
- }
-
- if (view.isEventDefSelected(seg.footprint.eventDef)) {
- classes.push('fc-selected');
- }
- return classes;
- },
-
- getSegCustomClasses: function(seg) {
- var eventDef = seg.footprint.eventDef;
- return [].concat(
- eventDef.className,
- eventDef.source.className
- );
- },
-
- getSegSkinCss: function(seg) {
- return {
- 'background-color': this.getSegBackgroundColor(seg),
- 'border-color': this.getSegBorderColor(seg),
- color: this.getSegTextColor(seg)
- };
- },
-
- getSegBackgroundColor: function(seg) {
- var eventDef = seg.footprint.eventDef;
- return eventDef.backgroundColor ||
- eventDef.color ||
- this.getSegDefaultBackgroundColor(seg);
- },
- getSegDefaultBackgroundColor: function(seg) {
- var source = seg.footprint.eventDef.source;
- return source.backgroundColor ||
- source.color ||
- this.opt('eventBackgroundColor') ||
- this.opt('eventColor');
- },
-
- getSegBorderColor: function(seg) {
- var eventDef = seg.footprint.eventDef;
- return eventDef.borderColor ||
- eventDef.color ||
- this.getSegDefaultBorderColor(seg);
- },
- getSegDefaultBorderColor: function(seg) {
- var source = seg.footprint.eventDef.source;
- return source.borderColor ||
- source.color ||
- this.opt('eventBorderColor') ||
- this.opt('eventColor');
- },
-
- getSegTextColor: function(seg) {
- var eventDef = seg.footprint.eventDef;
- return eventDef.textColor ||
- this.getSegDefaultTextColor(seg);
- },
- getSegDefaultTextColor: function(seg) {
- var source = seg.footprint.eventDef.source;
- return source.textColor ||
- this.opt('eventTextColor');
- },
- sortEventSegs: function(segs) {
- segs.sort(proxy(this, 'compareEventSegs'));
- },
-
- compareEventSegs: function(seg1, seg2) {
- var f1 = seg1.footprint.componentFootprint;
- var r1 = f1.unzonedRange;
- var f2 = seg2.footprint.componentFootprint;
- var r2 = f2.unzonedRange;
- return r1.startMs - r2.startMs ||
- (r2.endMs - r2.startMs) - (r1.endMs - r1.startMs) ||
- f2.isAllDay - f1.isAllDay ||
- compareByFieldSpecs(
- seg1.footprint.eventDef,
- seg2.footprint.eventDef,
- this.view.eventOrderSpecs
- );
- }
- });
- ;;
- Grid.mixin({
-
- segSelector: '.fc-event-container > *',
- mousedOverSeg: null,
-
-
-
- largeUnit: null,
-
-
- diffDates: function(a, b) {
- if (this.largeUnit) {
- return diffByUnit(a, b, this.largeUnit);
- }
- else {
- return diffDayTime(a, b);
- }
- },
-
- bindSegHandlers: function() {
- this.bindSegHandlersToEl(this.el);
- },
-
- bindSegHandlersToEl: function(el) {
- this.bindSegHandlerToEl(el, 'touchstart', this.handleSegTouchStart);
- this.bindSegHandlerToEl(el, 'mouseenter', this.handleSegMouseover);
- this.bindSegHandlerToEl(el, 'mouseleave', this.handleSegMouseout);
- this.bindSegHandlerToEl(el, 'mousedown', this.handleSegMousedown);
- this.bindSegHandlerToEl(el, 'click', this.handleSegClick);
- },
-
-
- bindSegHandlerToEl: function(el, name, handler) {
- var _this = this;
- el.on(name, this.segSelector, function(ev) {
- var seg = $(this).data('fc-seg');
-
- if (seg && !_this.isDraggingSeg && !_this.isResizingSeg) {
- return handler.call(_this, seg, ev);
- }
- });
- },
- handleSegClick: function(seg, ev) {
- var res = this.publiclyTrigger('eventClick', {
- context: seg.el[0],
- args: [ seg.footprint.getEventLegacy(), ev, this.view ]
- });
- if (res === false) {
- ev.preventDefault();
- }
- },
-
- handleSegMouseover: function(seg, ev) {
- if (
- !GlobalEmitter.get().shouldIgnoreMouse() &&
- !this.mousedOverSeg
- ) {
- this.mousedOverSeg = seg;
- if (this.view.isEventDefResizable(seg.footprint.eventDef)) {
- seg.el.addClass('fc-allow-mouse-resize');
- }
- this.publiclyTrigger('eventMouseover', {
- context: seg.el[0],
- args: [ seg.footprint.getEventLegacy(), ev, this.view ]
- });
- }
- },
-
-
- handleSegMouseout: function(seg, ev) {
- ev = ev || {};
- if (this.mousedOverSeg) {
- seg = seg || this.mousedOverSeg;
- this.mousedOverSeg = null;
- if (this.view.isEventDefResizable(seg.footprint.eventDef)) {
- seg.el.removeClass('fc-allow-mouse-resize');
- }
- this.publiclyTrigger('eventMouseout', {
- context: seg.el[0],
- args: [ seg.footprint.getEventLegacy(), ev, this.view ]
- });
- }
- },
- handleSegMousedown: function(seg, ev) {
- var isResizing = this.startSegResize(seg, ev, { distance: 5 });
- if (!isResizing && this.view.isEventDefDraggable(seg.footprint.eventDef)) {
- this.buildSegDragListener(seg)
- .startInteraction(ev, {
- distance: 5
- });
- }
- },
- handleSegTouchStart: function(seg, ev) {
- var view = this.view;
- var eventDef = seg.footprint.eventDef;
- var isSelected = view.isEventDefSelected(eventDef);
- var isDraggable = view.isEventDefDraggable(eventDef);
- var isResizable = view.isEventDefResizable(eventDef);
- var isResizing = false;
- var dragListener;
- var eventLongPressDelay;
- if (isSelected && isResizable) {
-
- isResizing = this.startSegResize(seg, ev);
- }
- if (!isResizing && (isDraggable || isResizable)) {
- eventLongPressDelay = this.opt('eventLongPressDelay');
- if (eventLongPressDelay == null) {
- eventLongPressDelay = this.opt('longPressDelay');
- }
- dragListener = isDraggable ?
- this.buildSegDragListener(seg) :
- this.buildSegSelectListener(seg);
- dragListener.startInteraction(ev, {
- delay: isSelected ? 0 : eventLongPressDelay
- });
- }
- },
-
-
-
- buildSegSelectListener: function(seg) {
- var _this = this;
- var view = this.view;
- var eventDef = seg.footprint.eventDef;
- var eventInstance = seg.footprint.eventInstance;
- if (this.segDragListener) {
- return this.segDragListener;
- }
- var dragListener = this.segDragListener = new DragListener({
- dragStart: function(ev) {
- if (
- dragListener.isTouch &&
- !view.isEventDefSelected(eventDef) &&
- eventInstance
- ) {
-
- view.selectEventInstance(eventInstance);
- }
- },
- interactionEnd: function(ev) {
- _this.segDragListener = null;
- }
- });
- return dragListener;
- },
-
-
- isEventInstanceGroupAllowed: function(eventInstanceGroup) {
- var eventFootprints = this.eventRangesToEventFootprints(eventInstanceGroup.getAllEventRanges());
- var i;
- for (i = 0; i < eventFootprints.length; i++) {
-
- if (!this.view.validUnzonedRange.containsRange(eventFootprints[i].componentFootprint.unzonedRange)) {
- return false;
- }
- }
- return this.view.calendar.isEventInstanceGroupAllowed(eventInstanceGroup);
- },
-
-
- renderHelperEventFootprints: function(eventFootprints, sourceSeg) {
- return this.renderHelperEventFootprintEls(eventFootprints, sourceSeg)
- .addClass('fc-helper');
- },
- renderHelperEventFootprintEls: function(eventFootprints, sourceSeg) {
-
-
- },
-
-
- unrenderHelper: function() {
-
- },
- fabricateEventFootprint: function(componentFootprint) {
- var calendar = this.view.calendar;
- var eventDateProfile = calendar.footprintToDateProfile(componentFootprint);
- var dummyEvent = new SingleEventDef(new EventSource(calendar));
- var dummyInstance;
- dummyEvent.dateProfile = eventDateProfile;
- dummyInstance = dummyEvent.buildInstance();
- return new EventFootprint(componentFootprint, dummyEvent, dummyInstance);
- }
- });
- ;;
- Grid.mixin({
- isDraggingSeg: false,
-
-
-
- buildSegDragListener: function(seg) {
- var _this = this;
- var view = this.view;
- var calendar = view.calendar;
- var eventManager = calendar.eventManager;
- var el = seg.el;
- var eventDef = seg.footprint.eventDef;
- var eventInstance = seg.footprint.eventInstance;
- var isDragging;
- var mouseFollower;
- var eventDefMutation;
- if (this.segDragListener) {
- return this.segDragListener;
- }
-
-
- var dragListener = this.segDragListener = new HitDragListener(view, {
- scroll: this.opt('dragScroll'),
- subjectEl: el,
- subjectCenter: true,
- interactionStart: function(ev) {
- seg.component = _this;
- isDragging = false;
- mouseFollower = new MouseFollower(seg.el, {
- additionalClass: 'fc-dragging',
- parentEl: view.el,
- opacity: dragListener.isTouch ? null : _this.opt('dragOpacity'),
- revertDuration: _this.opt('dragRevertDuration'),
- zIndex: 2
- });
- mouseFollower.hide();
- mouseFollower.start(ev);
- },
- dragStart: function(ev) {
- if (
- dragListener.isTouch &&
- !view.isEventDefSelected(eventDef) &&
- eventInstance
- ) {
-
- view.selectEventInstance(eventInstance);
- }
- isDragging = true;
- _this.handleSegMouseout(seg, ev);
- _this.segDragStart(seg, ev);
- view.hideEventsWithId(eventDef.id);
- },
- hitOver: function(hit, isOrig, origHit) {
- var isAllowed = true;
- var origFootprint;
- var footprint;
- var mutatedEventInstanceGroup;
- var dragHelperEls;
-
- if (seg.hit) {
- origHit = seg.hit;
- }
-
- origFootprint = origHit.component.getSafeHitFootprint(origHit);
- footprint = hit.component.getSafeHitFootprint(hit);
- if (origFootprint && footprint) {
- eventDefMutation = _this.computeEventDropMutation(origFootprint, footprint, eventDef);
- if (eventDefMutation) {
- mutatedEventInstanceGroup = eventManager.buildMutatedEventInstanceGroup(
- eventDef.id,
- eventDefMutation
- );
- isAllowed = _this.isEventInstanceGroupAllowed(mutatedEventInstanceGroup);
- }
- else {
- isAllowed = false;
- }
- }
- else {
- isAllowed = false;
- }
- if (!isAllowed) {
- eventDefMutation = null;
- disableCursor();
- }
-
- if (
- eventDefMutation &&
- (dragHelperEls = view.renderDrag(
- _this.eventRangesToEventFootprints(
- mutatedEventInstanceGroup.sliceRenderRanges(_this.unzonedRange, calendar)
- ),
- seg
- ))
- ) {
- dragHelperEls.addClass('fc-dragging');
- if (!dragListener.isTouch) {
- _this.applyDragOpacity(dragHelperEls);
- }
- mouseFollower.hide();
- }
- else {
- mouseFollower.show();
- }
- if (isOrig) {
-
- eventDefMutation = null;
- }
- },
- hitOut: function() {
- view.unrenderDrag();
- mouseFollower.show();
- eventDefMutation = null;
- },
- hitDone: function() {
- enableCursor();
- },
- interactionEnd: function(ev) {
- delete seg.component;
-
- mouseFollower.stop(!eventDefMutation, function() {
- if (isDragging) {
- view.unrenderDrag();
- _this.segDragStop(seg, ev);
- }
- if (eventDefMutation) {
-
- view.reportEventDrop(eventInstance, eventDefMutation, el, ev);
- }
- else {
- view.showEventsWithId(eventDef.id);
- }
- });
- _this.segDragListener = null;
- }
- });
- return dragListener;
- },
-
- segDragStart: function(seg, ev) {
- this.isDraggingSeg = true;
- this.publiclyTrigger('eventDragStart', {
- context: seg.el[0],
- args: [
- seg.footprint.getEventLegacy(),
- ev,
- {},
- this.view
- ]
- });
- },
-
- segDragStop: function(seg, ev) {
- this.isDraggingSeg = false;
- this.publiclyTrigger('eventDragStop', {
- context: seg.el[0],
- args: [
- seg.footprint.getEventLegacy(),
- ev,
- {},
- this.view
- ]
- });
- },
-
- computeEventDropMutation: function(startFootprint, endFootprint, eventDef) {
- var date0 = startFootprint.unzonedRange.getStart();
- var date1 = endFootprint.unzonedRange.getStart();
- var clearEnd = false;
- var forceTimed = false;
- var forceAllDay = false;
- var dateDelta;
- var dateMutation;
- var eventDefMutation;
- if (startFootprint.isAllDay !== endFootprint.isAllDay) {
- clearEnd = true;
- if (endFootprint.isAllDay) {
- forceAllDay = true;
- date0.stripTime();
- }
- else {
- forceTimed = true;
- }
- }
- dateDelta = this.diffDates(date1, date0);
- dateMutation = new EventDefDateMutation();
- dateMutation.clearEnd = clearEnd;
- dateMutation.forceTimed = forceTimed;
- dateMutation.forceAllDay = forceAllDay;
- dateMutation.setDateDelta(dateDelta);
- eventDefMutation = new EventDefMutation();
- eventDefMutation.setDateMutation(dateMutation);
- return eventDefMutation;
- },
-
- applyDragOpacity: function(els) {
- var opacity = this.opt('dragOpacity');
- if (opacity != null) {
- els.css('opacity', opacity);
- }
- }
- });
- ;;
- Grid.mixin({
- isResizingSeg: false,
-
-
-
- startSegResize: function(seg, ev, dragOptions) {
- if ($(ev.target).is('.fc-resizer')) {
- this.buildSegResizeListener(seg, $(ev.target).is('.fc-start-resizer'))
- .startInteraction(ev, dragOptions);
- return true;
- }
- return false;
- },
-
-
- buildSegResizeListener: function(seg, isStart) {
- var _this = this;
- var view = this.view;
- var calendar = view.calendar;
- var eventManager = calendar.eventManager;
- var el = seg.el;
- var eventDef = seg.footprint.eventDef;
- var eventInstance = seg.footprint.eventInstance;
- var isDragging;
- var resizeMutation;
-
- var dragListener = this.segResizeListener = new HitDragListener(this, {
- scroll: this.opt('dragScroll'),
- subjectEl: el,
- interactionStart: function() {
- isDragging = false;
- },
- dragStart: function(ev) {
- isDragging = true;
- _this.handleSegMouseout(seg, ev);
- _this.segResizeStart(seg, ev);
- },
- hitOver: function(hit, isOrig, origHit) {
- var isAllowed = true;
- var origHitFootprint = _this.getSafeHitFootprint(origHit);
- var hitFootprint = _this.getSafeHitFootprint(hit);
- var mutatedEventInstanceGroup;
- if (origHitFootprint && hitFootprint) {
- resizeMutation = isStart ?
- _this.computeEventStartResizeMutation(origHitFootprint, hitFootprint, seg.footprint) :
- _this.computeEventEndResizeMutation(origHitFootprint, hitFootprint, seg.footprint);
- if (resizeMutation) {
- mutatedEventInstanceGroup = eventManager.buildMutatedEventInstanceGroup(
- eventDef.id,
- resizeMutation
- );
- isAllowed = _this.isEventInstanceGroupAllowed(mutatedEventInstanceGroup);
- }
- else {
- isAllowed = false;
- }
- }
- else {
- isAllowed = false;
- }
- if (!isAllowed) {
- resizeMutation = null;
- disableCursor();
- }
- else if (resizeMutation.isEmpty()) {
-
- resizeMutation = null;
- }
- if (resizeMutation) {
- view.hideEventsWithId(eventDef.id);
- _this.renderEventResize(
- _this.eventRangesToEventFootprints(
- mutatedEventInstanceGroup.sliceRenderRanges(_this.unzonedRange, calendar)
- ),
- seg
- );
- }
- },
- hitOut: function() {
- resizeMutation = null;
- view.showEventsWithId(eventDef.id);
- },
- hitDone: function() {
- _this.unrenderEventResize();
- enableCursor();
- },
- interactionEnd: function(ev) {
- if (isDragging) {
- _this.segResizeStop(seg, ev);
- }
- if (resizeMutation) {
-
- view.reportEventResize(eventInstance, resizeMutation, el, ev);
- }
- else {
- view.showEventsWithId(eventDef.id);
- }
- _this.segResizeListener = null;
- }
- });
- return dragListener;
- },
-
- segResizeStart: function(seg, ev) {
- this.isResizingSeg = true;
- this.publiclyTrigger('eventResizeStart', {
- context: seg.el[0],
- args: [
- seg.footprint.getEventLegacy(),
- ev,
- {},
- this.view
- ]
- });
- },
-
- segResizeStop: function(seg, ev) {
- this.isResizingSeg = false;
- this.publiclyTrigger('eventResizeStop', {
- context: seg.el[0],
- args: [
- seg.footprint.getEventLegacy(),
- ev,
- {},
- this.view
- ]
- });
- },
-
- computeEventStartResizeMutation: function(startFootprint, endFootprint, origEventFootprint) {
- var origRange = origEventFootprint.componentFootprint.unzonedRange;
- var startDelta = this.diffDates(
- endFootprint.unzonedRange.getStart(),
- startFootprint.unzonedRange.getStart()
- );
- var dateMutation;
- var eventDefMutation;
- if (origRange.getStart().add(startDelta) < origRange.getEnd()) {
- dateMutation = new EventDefDateMutation();
- dateMutation.setStartDelta(startDelta);
- eventDefMutation = new EventDefMutation();
- eventDefMutation.setDateMutation(dateMutation);
- return eventDefMutation;
- }
- return false;
- },
-
- computeEventEndResizeMutation: function(startFootprint, endFootprint, origEventFootprint) {
- var origRange = origEventFootprint.componentFootprint.unzonedRange;
- var endDelta = this.diffDates(
- endFootprint.unzonedRange.getEnd(),
- startFootprint.unzonedRange.getEnd()
- );
- var dateMutation;
- var eventDefMutation;
- if (origRange.getEnd().add(endDelta) > origRange.getStart()) {
- dateMutation = new EventDefDateMutation();
- dateMutation.setEndDelta(endDelta);
- eventDefMutation = new EventDefMutation();
- eventDefMutation.setDateMutation(dateMutation);
- return eventDefMutation;
- }
- return false;
- },
-
-
- renderEventResize: function(eventFootprints, seg) {
-
- },
-
- unrenderEventResize: function() {
-
- }
- });
- ;;
- Grid.mixin({
- isDraggingExternal: false,
-
- externalDragStart: function(ev, ui) {
- var el;
- var accept;
- if (this.opt('droppable')) {
- el = $((ui ? ui.item : null) || ev.target);
-
-
- accept = this.opt('dropAccept');
- if ($.isFunction(accept) ? accept.call(el[0], el) : el.is(accept)) {
- if (!this.isDraggingExternal) {
- this.listenToExternalDrag(el, ev, ui);
- }
- }
- }
- },
-
- listenToExternalDrag: function(el, ev, ui) {
- var _this = this;
- var view = this.view;
- var meta = getDraggedElMeta(el);
- var singleEventDef;
-
- var dragListener = _this.externalDragListener = new HitDragListener(this, {
- interactionStart: function() {
- _this.isDraggingExternal = true;
- },
- hitOver: function(hit) {
- var isAllowed = true;
- var hitFootprint = hit.component.getSafeHitFootprint(hit);
- var mutatedEventInstanceGroup;
- if (hitFootprint) {
- singleEventDef = _this.computeExternalDrop(hitFootprint, meta);
- if (singleEventDef) {
- mutatedEventInstanceGroup = new EventInstanceGroup(
- singleEventDef.buildInstances()
- );
- isAllowed = meta.eventProps ?
- _this.isEventInstanceGroupAllowed(mutatedEventInstanceGroup) :
- _this.isExternalInstanceGroupAllowed(mutatedEventInstanceGroup);
- }
- else {
- isAllowed = false;
- }
- }
- else {
- isAllowed = false;
- }
- if (!isAllowed) {
- singleEventDef = null;
- disableCursor();
- }
- if (singleEventDef) {
- _this.renderDrag(
- _this.eventRangesToEventFootprints(
- mutatedEventInstanceGroup.sliceRenderRanges(_this.unzonedRange, view.calendar)
- )
- );
- }
- },
- hitOut: function() {
- singleEventDef = null;
- },
- hitDone: function() {
- enableCursor();
- _this.unrenderDrag();
- },
- interactionEnd: function(ev) {
- if (singleEventDef) {
- view.reportExternalDrop(
- singleEventDef,
- Boolean(meta.eventProps),
- Boolean(meta.stick),
- el, ev, ui
- );
- }
- _this.isDraggingExternal = false;
- _this.externalDragListener = null;
- }
- });
- dragListener.startDrag(ev);
- },
-
-
-
-
-
- computeExternalDrop: function(componentFootprint, meta) {
- var calendar = this.view.calendar;
- var start = FC.moment.utc(componentFootprint.unzonedRange.startMs).stripZone();
- var end;
- var eventDef;
- if (componentFootprint.isAllDay) {
-
- if (meta.startTime) {
- start.time(meta.startTime);
- }
- else {
- start.stripTime();
- }
- }
- if (meta.duration) {
- end = start.clone().add(meta.duration);
- }
- start = calendar.applyTimezone(start);
- if (end) {
- end = calendar.applyTimezone(end);
- }
- eventDef = SingleEventDef.parse(
- $.extend({}, meta.eventProps, {
- start: start,
- end: end
- }),
- new EventSource(calendar)
- );
- return eventDef;
- },
-
-
- isExternalInstanceGroupAllowed: function(eventInstanceGroup) {
- var calendar = this.view.calendar;
- var eventFootprints = this.eventRangesToEventFootprints(eventInstanceGroup.getAllEventRanges());
- var i;
- for (i = 0; i < eventFootprints.length; i++) {
- if (!this.view.validUnzonedRange.containsRange(eventFootprints[i].componentFootprint.unzonedRange)) {
- return false;
- }
- }
- for (i = 0; i < eventFootprints.length; i++) {
-
-
-
-
- if (!calendar.isSelectionFootprintAllowed(eventFootprints[i].componentFootprint)) {
- return false;
- }
- }
- return true;
- }
- });
- FC.dataAttrPrefix = '';
- function getDraggedElMeta(el) {
- var prefix = FC.dataAttrPrefix;
- var eventProps;
- var startTime;
- var duration;
- var stick;
- if (prefix) { prefix += '-'; }
- eventProps = el.data(prefix + 'event') || null;
- if (eventProps) {
- if (typeof eventProps === 'object') {
- eventProps = $.extend({}, eventProps);
- }
- else {
- eventProps = {};
- }
-
- startTime = eventProps.start;
- if (startTime == null) { startTime = eventProps.time; }
- duration = eventProps.duration;
- stick = eventProps.stick;
- delete eventProps.start;
- delete eventProps.time;
- delete eventProps.duration;
- delete eventProps.stick;
- }
-
- if (startTime == null) { startTime = el.data(prefix + 'start'); }
- if (startTime == null) { startTime = el.data(prefix + 'time'); }
- if (duration == null) { duration = el.data(prefix + 'duration'); }
- if (stick == null) { stick = el.data(prefix + 'stick'); }
-
- startTime = startTime != null ? moment.duration(startTime) : null;
- duration = duration != null ? moment.duration(duration) : null;
- stick = Boolean(stick);
- return { eventProps: eventProps, startTime: startTime, duration: duration, stick: stick };
- }
- ;;
- Grid.mixin({
-
- elsByFill: null,
- initFillInternals: function() {
- this.elsByFill = {};
- },
-
-
-
- renderFill: function(type, segs) {
-
- },
-
- unrenderFill: function(type) {
- var el = this.elsByFill[type];
- if (el) {
- el.remove();
- delete this.elsByFill[type];
- }
- },
-
-
-
-
- renderFillSegEls: function(type, segs) {
- var _this = this;
- var segElMethod = this[type + 'SegEl'];
- var html = '';
- var renderedSegs = [];
- var i;
- if (segs.length) {
-
- for (i = 0; i < segs.length; i++) {
- html += this.fillSegHtml(type, segs[i]);
- }
-
-
- $(html).each(function(i, node) {
- var seg = segs[i];
- var el = $(node);
-
- if (segElMethod) {
- el = segElMethod.call(_this, seg, el);
- }
- if (el) {
- el = $(el);
-
- if (el.is(_this.fillSegTag)) {
- seg.el = el;
- renderedSegs.push(seg);
- }
- }
- });
- }
- return renderedSegs;
- },
- fillSegTag: 'div',
-
- fillSegHtml: function(type, seg) {
-
- var classesMethod = this[type + 'SegClasses'];
- var cssMethod = this[type + 'SegCss'];
- var classes = classesMethod ? classesMethod.call(this, seg) : [];
- var css = cssToStr(cssMethod ? cssMethod.call(this, seg) : {});
- return '<' + this.fillSegTag +
- (classes.length ? ' class="' + classes.join(' ') + '"' : '') +
- (css ? ' style="' + css + '"' : '') +
- ' />';
- },
-
- highlightSegClasses: function() {
- return [ 'fc-highlight' ];
- }
- });
- ;;
- var DayTableMixin = FC.DayTableMixin = {
- breakOnWeeks: false,
- dayDates: null,
- dayIndices: null,
- daysPerRow: null,
- rowCnt: null,
- colCnt: null,
- colHeadFormat: null,
-
- updateDayTable: function() {
- var view = this.view;
- var calendar = view.calendar;
- var date = calendar.msToUtcMoment(this.unzonedRange.startMs, true);
- var end = calendar.msToUtcMoment(this.unzonedRange.endMs, true);
- var dayIndex = -1;
- var dayIndices = [];
- var dayDates = [];
- var daysPerRow;
- var firstDay;
- var rowCnt;
- while (date.isBefore(end)) {
- if (view.isHiddenDay(date)) {
- dayIndices.push(dayIndex + 0.5);
- }
- else {
- dayIndex++;
- dayIndices.push(dayIndex);
- dayDates.push(date.clone());
- }
- date.add(1, 'days');
- }
- if (this.breakOnWeeks) {
-
- firstDay = dayDates[0].day();
- for (daysPerRow = 1; daysPerRow < dayDates.length; daysPerRow++) {
- if (dayDates[daysPerRow].day() == firstDay) {
- break;
- }
- }
- rowCnt = Math.ceil(dayDates.length / daysPerRow);
- }
- else {
- rowCnt = 1;
- daysPerRow = dayDates.length;
- }
- this.dayDates = dayDates;
- this.dayIndices = dayIndices;
- this.daysPerRow = daysPerRow;
- this.rowCnt = rowCnt;
- this.updateDayTableCols();
- },
-
- updateDayTableCols: function() {
- this.colCnt = this.computeColCnt();
- this.colHeadFormat = this.opt('columnFormat') || this.computeColHeadFormat();
- },
-
- computeColCnt: function() {
- return this.daysPerRow;
- },
-
- getCellDate: function(row, col) {
- return this.dayDates[
- this.getCellDayIndex(row, col)
- ].clone();
- },
-
- getCellRange: function(row, col) {
- var start = this.getCellDate(row, col);
- var end = start.clone().add(1, 'days');
- return { start: start, end: end };
- },
-
- getCellDayIndex: function(row, col) {
- return row * this.daysPerRow + this.getColDayIndex(col);
- },
-
- getColDayIndex: function(col) {
- if (this.isRTL) {
- return this.colCnt - 1 - col;
- }
- else {
- return col;
- }
- },
-
-
-
-
-
- getDateDayIndex: function(date) {
- var dayIndices = this.dayIndices;
- var dayOffset = date.diff(this.dayDates[0], 'days');
- if (dayOffset < 0) {
- return dayIndices[0] - 1;
- }
- else if (dayOffset >= dayIndices.length) {
- return dayIndices[dayIndices.length - 1] + 1;
- }
- else {
- return dayIndices[dayOffset];
- }
- },
-
-
- computeColHeadFormat: function() {
-
-
- if (this.rowCnt > 1 || this.colCnt > 10) {
- return 'ddd';
- }
-
- else if (this.colCnt > 1) {
- return this.opt('dayOfMonthFormat');
- }
-
- else {
- return 'dddd';
- }
- },
-
-
- sliceRangeByRow: function(unzonedRange) {
- var daysPerRow = this.daysPerRow;
- var normalRange = this.view.computeDayRange(unzonedRange);
- var rangeFirst = this.getDateDayIndex(normalRange.start);
- var rangeLast = this.getDateDayIndex(normalRange.end.clone().subtract(1, 'days'));
- var segs = [];
- var row;
- var rowFirst, rowLast;
- var segFirst, segLast;
- for (row = 0; row < this.rowCnt; row++) {
- rowFirst = row * daysPerRow;
- rowLast = rowFirst + daysPerRow - 1;
-
- segFirst = Math.max(rangeFirst, rowFirst);
- segLast = Math.min(rangeLast, rowLast);
-
- segFirst = Math.ceil(segFirst);
- segLast = Math.floor(segLast);
- if (segFirst <= segLast) {
- segs.push({
- row: row,
-
- firstRowDayIndex: segFirst - rowFirst,
- lastRowDayIndex: segLast - rowFirst,
-
- isStart: segFirst === rangeFirst,
- isEnd: segLast === rangeLast
- });
- }
- }
- return segs;
- },
-
-
- sliceRangeByDay: function(unzonedRange) {
- var daysPerRow = this.daysPerRow;
- var normalRange = this.view.computeDayRange(unzonedRange);
- var rangeFirst = this.getDateDayIndex(normalRange.start);
- var rangeLast = this.getDateDayIndex(normalRange.end.clone().subtract(1, 'days'));
- var segs = [];
- var row;
- var rowFirst, rowLast;
- var i;
- var segFirst, segLast;
- for (row = 0; row < this.rowCnt; row++) {
- rowFirst = row * daysPerRow;
- rowLast = rowFirst + daysPerRow - 1;
- for (i = rowFirst; i <= rowLast; i++) {
-
- segFirst = Math.max(rangeFirst, i);
- segLast = Math.min(rangeLast, i);
-
- segFirst = Math.ceil(segFirst);
- segLast = Math.floor(segLast);
- if (segFirst <= segLast) {
- segs.push({
- row: row,
-
- firstRowDayIndex: segFirst - rowFirst,
- lastRowDayIndex: segLast - rowFirst,
-
- isStart: segFirst === rangeFirst,
- isEnd: segLast === rangeLast
- });
- }
- }
- }
- return segs;
- },
-
- renderHeadHtml: function() {
- var theme = this.view.calendar.theme;
- return '' +
- '<div class="fc-row ' + theme.getClass('headerRow') + '">' +
- '<table class="' + theme.getClass('tableGrid') + '">' +
- '<thead>' +
- this.renderHeadTrHtml() +
- '</thead>' +
- '</table>' +
- '</div>';
- },
- renderHeadIntroHtml: function() {
- return this.renderIntroHtml();
- },
- renderHeadTrHtml: function() {
- return '' +
- '<tr>' +
- (this.isRTL ? '' : this.renderHeadIntroHtml()) +
- this.renderHeadDateCellsHtml() +
- (this.isRTL ? this.renderHeadIntroHtml() : '') +
- '</tr>';
- },
- renderHeadDateCellsHtml: function() {
- var htmls = [];
- var col, date;
- for (col = 0; col < this.colCnt; col++) {
- date = this.getCellDate(0, col);
- htmls.push(this.renderHeadDateCellHtml(date));
- }
- return htmls.join('');
- },
-
-
- renderHeadDateCellHtml: function(date, colspan, otherAttrs) {
- var view = this.view;
- var isDateValid = view.activeUnzonedRange.containsDate(date);
- var classNames = [
- 'fc-day-header',
- view.calendar.theme.getClass('widgetHeader')
- ];
- var innerHtml = htmlEscape(date.format(this.colHeadFormat));
-
- if (this.rowCnt === 1) {
- classNames = classNames.concat(
-
-
- this.getDayClasses(date, true)
- );
- }
- else {
- classNames.push('fc-' + dayIDs[date.day()]);
- }
- return '' +
- '<th class="' + classNames.join(' ') + '"' +
- ((isDateValid && this.rowCnt) === 1 ?
- ' data-date="' + date.format('YYYY-MM-DD') + '"' :
- '') +
- (colspan > 1 ?
- ' colspan="' + colspan + '"' :
- '') +
- (otherAttrs ?
- ' ' + otherAttrs :
- '') +
- '>' +
- (isDateValid ?
-
- view.buildGotoAnchorHtml(
- { date: date, forceOff: this.rowCnt > 1 || this.colCnt === 1 },
- innerHtml
- ) :
-
- innerHtml
- ) +
- '</th>';
- },
-
- renderBgTrHtml: function(row) {
- return '' +
- '<tr>' +
- (this.isRTL ? '' : this.renderBgIntroHtml(row)) +
- this.renderBgCellsHtml(row) +
- (this.isRTL ? this.renderBgIntroHtml(row) : '') +
- '</tr>';
- },
- renderBgIntroHtml: function(row) {
- return this.renderIntroHtml();
- },
- renderBgCellsHtml: function(row) {
- var htmls = [];
- var col, date;
- for (col = 0; col < this.colCnt; col++) {
- date = this.getCellDate(row, col);
- htmls.push(this.renderBgCellHtml(date));
- }
- return htmls.join('');
- },
- renderBgCellHtml: function(date, otherAttrs) {
- var view = this.view;
- var isDateValid = view.activeUnzonedRange.containsDate(date);
- var classes = this.getDayClasses(date);
- classes.unshift('fc-day', view.calendar.theme.getClass('widgetContent'));
- return '<td class="' + classes.join(' ') + '"' +
- (isDateValid ?
- ' data-date="' + date.format('YYYY-MM-DD') + '"' :
- '') +
- (otherAttrs ?
- ' ' + otherAttrs :
- '') +
- '></td>';
- },
-
-
- renderIntroHtml: function() {
- },
-
-
-
-
-
-
- bookendCells: function(trEl) {
- var introHtml = this.renderIntroHtml();
- if (introHtml) {
- if (this.isRTL) {
- trEl.append(introHtml);
- }
- else {
- trEl.prepend(introHtml);
- }
- }
- }
- };
- ;;
- var DayGrid = FC.DayGrid = Grid.extend(DayTableMixin, {
- numbersVisible: false,
- bottomCoordPadding: 0,
- rowEls: null,
- cellEls: null,
- helperEls: null,
- rowCoordCache: null,
- colCoordCache: null,
-
-
-
- renderDates: function(isRigid) {
- var view = this.view;
- var rowCnt = this.rowCnt;
- var colCnt = this.colCnt;
- var html = '';
- var row;
- var col;
- for (row = 0; row < rowCnt; row++) {
- html += this.renderDayRowHtml(row, isRigid);
- }
- this.el.html(html);
- this.rowEls = this.el.find('.fc-row');
- this.cellEls = this.el.find('.fc-day, .fc-disabled-day');
- this.rowCoordCache = new CoordCache({
- els: this.rowEls,
- isVertical: true
- });
- this.colCoordCache = new CoordCache({
- els: this.cellEls.slice(0, this.colCnt),
- isHorizontal: true
- });
-
- for (row = 0; row < rowCnt; row++) {
- for (col = 0; col < colCnt; col++) {
- this.publiclyTrigger('dayRender', {
- context: view,
- args: [
- this.getCellDate(row, col),
- this.getCellEl(row, col),
- view
- ]
- });
- }
- }
- },
- unrenderDates: function() {
- this.removeSegPopover();
- },
- renderBusinessHours: function() {
- var segs = this.buildBusinessHourSegs(true);
- this.renderFill('businessHours', segs, 'bgevent');
- },
- unrenderBusinessHours: function() {
- this.unrenderFill('businessHours');
- },
-
-
- renderDayRowHtml: function(row, isRigid) {
- var theme = this.view.calendar.theme;
- var classes = [ 'fc-row', 'fc-week', theme.getClass('dayRow') ];
- if (isRigid) {
- classes.push('fc-rigid');
- }
- return '' +
- '<div class="' + classes.join(' ') + '">' +
- '<div class="fc-bg">' +
- '<table class="' + theme.getClass('tableGrid') + '">' +
- this.renderBgTrHtml(row) +
- '</table>' +
- '</div>' +
- '<div class="fc-content-skeleton">' +
- '<table>' +
- (this.numbersVisible ?
- '<thead>' +
- this.renderNumberTrHtml(row) +
- '</thead>' :
- ''
- ) +
- '</table>' +
- '</div>' +
- '</div>';
- },
-
- renderNumberTrHtml: function(row) {
- return '' +
- '<tr>' +
- (this.isRTL ? '' : this.renderNumberIntroHtml(row)) +
- this.renderNumberCellsHtml(row) +
- (this.isRTL ? this.renderNumberIntroHtml(row) : '') +
- '</tr>';
- },
- renderNumberIntroHtml: function(row) {
- return this.renderIntroHtml();
- },
- renderNumberCellsHtml: function(row) {
- var htmls = [];
- var col, date;
- for (col = 0; col < this.colCnt; col++) {
- date = this.getCellDate(row, col);
- htmls.push(this.renderNumberCellHtml(date));
- }
- return htmls.join('');
- },
-
-
- renderNumberCellHtml: function(date) {
- var view = this.view;
- var html = '';
- var isDateValid = view.activeUnzonedRange.containsDate(date);
- var isDayNumberVisible = view.dayNumbersVisible && isDateValid;
- var classes;
- var weekCalcFirstDoW;
- if (!isDayNumberVisible && !view.cellWeekNumbersVisible) {
-
- return '<td/>';
- }
- classes = this.getDayClasses(date);
- classes.unshift('fc-day-top');
- if (view.cellWeekNumbersVisible) {
-
-
-
-
-
- if (date._locale._fullCalendar_weekCalc === 'ISO') {
- weekCalcFirstDoW = 1;
- }
- else {
- weekCalcFirstDoW = date._locale.firstDayOfWeek();
- }
- }
- html += '<td class="' + classes.join(' ') + '"' +
- (isDateValid ?
- ' data-date="' + date.format() + '"' :
- ''
- ) +
- '>';
- if (view.cellWeekNumbersVisible && (date.day() == weekCalcFirstDoW)) {
- html += view.buildGotoAnchorHtml(
- { date: date, type: 'week' },
- { 'class': 'fc-week-number' },
- date.format('w')
- );
- }
- if (isDayNumberVisible) {
- html += view.buildGotoAnchorHtml(
- date,
- { 'class': 'fc-day-number' },
- date.date()
- );
- }
- html += '</td>';
- return html;
- },
-
-
- computeEventTimeFormat: function() {
- return this.opt('extraSmallTimeFormat');
- },
-
- computeDisplayEventEnd: function() {
- return this.colCnt == 1;
- },
-
- rangeUpdated: function() {
- this.updateDayTable();
- },
-
- componentFootprintToSegs: function(componentFootprint) {
- var segs = this.sliceRangeByRow(componentFootprint.unzonedRange);
- var i, seg;
- for (i = 0; i < segs.length; i++) {
- seg = segs[i];
- if (this.isRTL) {
- seg.leftCol = this.daysPerRow - 1 - seg.lastRowDayIndex;
- seg.rightCol = this.daysPerRow - 1 - seg.firstRowDayIndex;
- }
- else {
- seg.leftCol = seg.firstRowDayIndex;
- seg.rightCol = seg.lastRowDayIndex;
- }
- }
- return segs;
- },
-
- prepareHits: function() {
- this.colCoordCache.build();
- this.rowCoordCache.build();
- this.rowCoordCache.bottoms[this.rowCnt - 1] += this.bottomCoordPadding;
- },
- releaseHits: function() {
- this.colCoordCache.clear();
- this.rowCoordCache.clear();
- },
- queryHit: function(leftOffset, topOffset) {
- if (this.colCoordCache.isLeftInBounds(leftOffset) && this.rowCoordCache.isTopInBounds(topOffset)) {
- var col = this.colCoordCache.getHorizontalIndex(leftOffset);
- var row = this.rowCoordCache.getVerticalIndex(topOffset);
- if (row != null && col != null) {
- return this.getCellHit(row, col);
- }
- }
- },
- getHitFootprint: function(hit) {
- var range = this.getCellRange(hit.row, hit.col);
- return new ComponentFootprint(
- new UnzonedRange(range.start, range.end),
- true
- );
- },
- getHitEl: function(hit) {
- return this.getCellEl(hit.row, hit.col);
- },
-
-
- getCellHit: function(row, col) {
- return {
- row: row,
- col: col,
- component: this,
- left: this.colCoordCache.getLeftOffset(col),
- right: this.colCoordCache.getRightOffset(col),
- top: this.rowCoordCache.getTopOffset(row),
- bottom: this.rowCoordCache.getBottomOffset(row)
- };
- },
- getCellEl: function(row, col) {
- return this.cellEls.eq(row * this.colCnt + col);
- },
-
-
-
-
- renderDrag: function(eventFootprints, seg) {
- var i;
- for (i = 0; i < eventFootprints.length; i++) {
- this.renderHighlight(eventFootprints[i].componentFootprint);
- }
-
- if (seg && seg.component !== this) {
- return this.renderHelperEventFootprints(eventFootprints, seg);
- }
- },
-
- unrenderDrag: function() {
- this.unrenderHighlight();
- this.unrenderHelper();
- },
-
-
- renderEventResize: function(eventFootprints, seg) {
- var i;
- for (i = 0; i < eventFootprints.length; i++) {
- this.renderHighlight(eventFootprints[i].componentFootprint);
- }
- return this.renderHelperEventFootprints(eventFootprints, seg);
- },
-
- unrenderEventResize: function() {
- this.unrenderHighlight();
- this.unrenderHelper();
- },
-
-
- renderHelperEventFootprintEls: function(eventFootprints, sourceSeg) {
- var helperNodes = [];
- var segs = this.eventFootprintsToSegs(eventFootprints);
- var rowStructs;
- segs = this.renderFgSegEls(segs);
- rowStructs = this.renderSegRows(segs);
-
- this.rowEls.each(function(row, rowNode) {
- var rowEl = $(rowNode);
- var skeletonEl = $('<div class="fc-helper-skeleton"><table/></div>');
- var skeletonTop;
-
- if (sourceSeg && sourceSeg.row === row) {
- skeletonTop = sourceSeg.el.position().top;
- }
- else {
- skeletonTop = rowEl.find('.fc-content-skeleton tbody').position().top;
- }
- skeletonEl.css('top', skeletonTop)
- .find('table')
- .append(rowStructs[row].tbodyEl);
- rowEl.append(skeletonEl);
- helperNodes.push(skeletonEl[0]);
- });
- return (
- this.helperEls = $(helperNodes)
- );
- },
-
- unrenderHelper: function() {
- if (this.helperEls) {
- this.helperEls.remove();
- this.helperEls = null;
- }
- },
-
- fillSegTag: 'td',
-
-
- renderFill: function(type, segs, className) {
- var nodes = [];
- var i, seg;
- var skeletonEl;
- segs = this.renderFillSegEls(type, segs);
- for (i = 0; i < segs.length; i++) {
- seg = segs[i];
- skeletonEl = this.renderFillRow(type, seg, className);
- this.rowEls.eq(seg.row).append(skeletonEl);
- nodes.push(skeletonEl[0]);
- }
- if (this.elsByFill[type]) {
- this.elsByFill[type] = this.elsByFill[type].add(nodes);
- }
- else {
- this.elsByFill[type] = $(nodes);
- }
- return segs;
- },
-
- renderFillRow: function(type, seg, className) {
- var colCnt = this.colCnt;
- var startCol = seg.leftCol;
- var endCol = seg.rightCol + 1;
- var skeletonEl;
- var trEl;
- className = className || type.toLowerCase();
- skeletonEl = $(
- '<div class="fc-' + className + '-skeleton">' +
- '<table><tr/></table>' +
- '</div>'
- );
- trEl = skeletonEl.find('tr');
- if (startCol > 0) {
- trEl.append('<td colspan="' + startCol + '"/>');
- }
- trEl.append(
- seg.el.attr('colspan', endCol - startCol)
- );
- if (endCol < colCnt) {
- trEl.append('<td colspan="' + (colCnt - endCol) + '"/>');
- }
- this.bookendCells(trEl);
- return skeletonEl;
- }
- });
- ;;
- DayGrid.mixin({
- rowStructs: null,
-
- unrenderEvents: function() {
- this.removeSegPopover();
- Grid.prototype.unrenderEvents.apply(this, arguments);
- },
-
- getEventSegs: function() {
- return Grid.prototype.getEventSegs.call(this)
- .concat(this.popoverSegs || []);
- },
-
- renderBgSegs: function(segs) {
-
- var allDaySegs = $.grep(segs, function(seg) {
- return seg.footprint.componentFootprint.isAllDay;
- });
- return Grid.prototype.renderBgSegs.call(this, allDaySegs);
- },
-
- renderFgSegs: function(segs) {
- var rowStructs;
-
-
- segs = this.renderFgSegEls(segs);
- rowStructs = this.rowStructs = this.renderSegRows(segs);
-
- this.rowEls.each(function(i, rowNode) {
- $(rowNode).find('.fc-content-skeleton > table').append(
- rowStructs[i].tbodyEl
- );
- });
- return segs;
- },
-
- unrenderFgSegs: function() {
- var rowStructs = this.rowStructs || [];
- var rowStruct;
- while ((rowStruct = rowStructs.pop())) {
- rowStruct.tbodyEl.remove();
- }
- this.rowStructs = null;
- },
-
-
-
- renderSegRows: function(segs) {
- var rowStructs = [];
- var segRows;
- var row;
- segRows = this.groupSegRows(segs);
-
- for (row = 0; row < segRows.length; row++) {
- rowStructs.push(
- this.renderSegRow(row, segRows[row])
- );
- }
- return rowStructs;
- },
-
- fgSegHtml: function(seg, disableResizing) {
- var view = this.view;
- var eventDef = seg.footprint.eventDef;
- var isAllDay = seg.footprint.componentFootprint.isAllDay;
- var isDraggable = view.isEventDefDraggable(eventDef);
- var isResizableFromStart = !disableResizing && isAllDay &&
- seg.isStart && view.isEventDefResizableFromStart(eventDef);
- var isResizableFromEnd = !disableResizing && isAllDay &&
- seg.isEnd && view.isEventDefResizableFromEnd(eventDef);
- var classes = this.getSegClasses(seg, isDraggable, isResizableFromStart || isResizableFromEnd);
- var skinCss = cssToStr(this.getSegSkinCss(seg));
- var timeHtml = '';
- var timeText;
- var titleHtml;
- classes.unshift('fc-day-grid-event', 'fc-h-event');
-
- if (seg.isStart) {
- timeText = this.getEventTimeText(seg.footprint);
- if (timeText) {
- timeHtml = '<span class="fc-time">' + htmlEscape(timeText) + '</span>';
- }
- }
- titleHtml =
- '<span class="fc-title">' +
- (htmlEscape(eventDef.title || '') || ' ') +
- '</span>';
-
- return '<a class="' + classes.join(' ') + '"' +
- (eventDef.url ?
- ' href="' + htmlEscape(eventDef.url) + '"' :
- ''
- ) +
- (skinCss ?
- ' style="' + skinCss + '"' :
- ''
- ) +
- '>' +
- '<div class="fc-content">' +
- (this.isRTL ?
- titleHtml + ' ' + timeHtml :
- timeHtml + ' ' + titleHtml
- ) +
- '</div>' +
- (isResizableFromStart ?
- '<div class="fc-resizer fc-start-resizer" />' :
- ''
- ) +
- (isResizableFromEnd ?
- '<div class="fc-resizer fc-end-resizer" />' :
- ''
- ) +
- '</a>';
- },
-
-
-
- renderSegRow: function(row, rowSegs) {
- var colCnt = this.colCnt;
- var segLevels = this.buildSegLevels(rowSegs);
- var levelCnt = Math.max(1, segLevels.length);
- var tbody = $('<tbody/>');
- var segMatrix = [];
- var cellMatrix = [];
- var loneCellMatrix = [];
- var i, levelSegs;
- var col;
- var tr;
- var j, seg;
- var td;
-
- function emptyCellsUntil(endCol) {
- while (col < endCol) {
-
- td = (loneCellMatrix[i - 1] || [])[col];
- if (td) {
- td.attr(
- 'rowspan',
- parseInt(td.attr('rowspan') || 1, 10) + 1
- );
- }
- else {
- td = $('<td/>');
- tr.append(td);
- }
- cellMatrix[i][col] = td;
- loneCellMatrix[i][col] = td;
- col++;
- }
- }
- for (i = 0; i < levelCnt; i++) {
- levelSegs = segLevels[i];
- col = 0;
- tr = $('<tr/>');
- segMatrix.push([]);
- cellMatrix.push([]);
- loneCellMatrix.push([]);
-
-
- if (levelSegs) {
- for (j = 0; j < levelSegs.length; j++) {
- seg = levelSegs[j];
- emptyCellsUntil(seg.leftCol);
-
- td = $('<td class="fc-event-container"/>').append(seg.el);
- if (seg.leftCol != seg.rightCol) {
- td.attr('colspan', seg.rightCol - seg.leftCol + 1);
- }
- else {
- loneCellMatrix[i][col] = td;
- }
- while (col <= seg.rightCol) {
- cellMatrix[i][col] = td;
- segMatrix[i][col] = seg;
- col++;
- }
- tr.append(td);
- }
- }
- emptyCellsUntil(colCnt);
- this.bookendCells(tr);
- tbody.append(tr);
- }
- return {
- row: row,
- tbodyEl: tbody,
- cellMatrix: cellMatrix,
- segMatrix: segMatrix,
- segLevels: segLevels,
- segs: rowSegs
- };
- },
-
-
- buildSegLevels: function(segs) {
- var levels = [];
- var i, seg;
- var j;
-
-
- this.sortEventSegs(segs);
-
- for (i = 0; i < segs.length; i++) {
- seg = segs[i];
-
- for (j = 0; j < levels.length; j++) {
- if (!isDaySegCollision(seg, levels[j])) {
- break;
- }
- }
-
- seg.level = j;
-
- (levels[j] || (levels[j] = [])).push(seg);
- }
-
- for (j = 0; j < levels.length; j++) {
- levels[j].sort(compareDaySegCols);
- }
- return levels;
- },
-
- groupSegRows: function(segs) {
- var segRows = [];
- var i;
- for (i = 0; i < this.rowCnt; i++) {
- segRows.push([]);
- }
- for (i = 0; i < segs.length; i++) {
- segRows[segs[i].row].push(segs[i]);
- }
- return segRows;
- }
- });
- function isDaySegCollision(seg, otherSegs) {
- var i, otherSeg;
- for (i = 0; i < otherSegs.length; i++) {
- otherSeg = otherSegs[i];
- if (
- otherSeg.leftCol <= seg.rightCol &&
- otherSeg.rightCol >= seg.leftCol
- ) {
- return true;
- }
- }
- return false;
- }
- function compareDaySegCols(a, b) {
- return a.leftCol - b.leftCol;
- }
- ;;
- DayGrid.mixin({
- segPopover: null,
- popoverSegs: null,
- removeSegPopover: function() {
- if (this.segPopover) {
- this.segPopover.hide();
- }
- },
-
-
- limitRows: function(levelLimit) {
- var rowStructs = this.rowStructs || [];
- var row;
- var rowLevelLimit;
- for (row = 0; row < rowStructs.length; row++) {
- this.unlimitRow(row);
- if (!levelLimit) {
- rowLevelLimit = false;
- }
- else if (typeof levelLimit === 'number') {
- rowLevelLimit = levelLimit;
- }
- else {
- rowLevelLimit = this.computeRowLevelLimit(row);
- }
- if (rowLevelLimit !== false) {
- this.limitRow(row, rowLevelLimit);
- }
- }
- },
-
-
-
- computeRowLevelLimit: function(row) {
- var rowEl = this.rowEls.eq(row);
- var rowHeight = rowEl.height();
- var trEls = this.rowStructs[row].tbodyEl.children();
- var i, trEl;
- var trHeight;
- function iterInnerHeights(i, childNode) {
- trHeight = Math.max(trHeight, $(childNode).outerHeight());
- }
-
- for (i = 0; i < trEls.length; i++) {
- trEl = trEls.eq(i).removeClass('fc-limited');
-
-
- trHeight = 0;
- trEl.find('> td > :first-child').each(iterInnerHeights);
- if (trEl.position().top + trHeight > rowHeight) {
- return i;
- }
- }
- return false;
- },
-
-
-
- limitRow: function(row, levelLimit) {
- var _this = this;
- var rowStruct = this.rowStructs[row];
- var moreNodes = [];
- var col = 0;
- var levelSegs;
- var cellMatrix;
- var limitedNodes;
- var i, seg;
- var segsBelow;
- var totalSegsBelow;
- var colSegsBelow;
- var td, rowspan;
- var segMoreNodes;
- var j;
- var moreTd, moreWrap, moreLink;
-
- function emptyCellsUntil(endCol) {
- while (col < endCol) {
- segsBelow = _this.getCellSegs(row, col, levelLimit);
- if (segsBelow.length) {
- td = cellMatrix[levelLimit - 1][col];
- moreLink = _this.renderMoreLink(row, col, segsBelow);
- moreWrap = $('<div/>').append(moreLink);
- td.append(moreWrap);
- moreNodes.push(moreWrap[0]);
- }
- col++;
- }
- }
- if (levelLimit && levelLimit < rowStruct.segLevels.length) {
- levelSegs = rowStruct.segLevels[levelLimit - 1];
- cellMatrix = rowStruct.cellMatrix;
- limitedNodes = rowStruct.tbodyEl.children().slice(levelLimit)
- .addClass('fc-limited').get();
-
- for (i = 0; i < levelSegs.length; i++) {
- seg = levelSegs[i];
- emptyCellsUntil(seg.leftCol);
-
- colSegsBelow = [];
- totalSegsBelow = 0;
- while (col <= seg.rightCol) {
- segsBelow = this.getCellSegs(row, col, levelLimit);
- colSegsBelow.push(segsBelow);
- totalSegsBelow += segsBelow.length;
- col++;
- }
- if (totalSegsBelow) {
- td = cellMatrix[levelLimit - 1][seg.leftCol];
- rowspan = td.attr('rowspan') || 1;
- segMoreNodes = [];
-
- for (j = 0; j < colSegsBelow.length; j++) {
- moreTd = $('<td class="fc-more-cell"/>').attr('rowspan', rowspan);
- segsBelow = colSegsBelow[j];
- moreLink = this.renderMoreLink(
- row,
- seg.leftCol + j,
- [ seg ].concat(segsBelow)
- );
- moreWrap = $('<div/>').append(moreLink);
- moreTd.append(moreWrap);
- segMoreNodes.push(moreTd[0]);
- moreNodes.push(moreTd[0]);
- }
- td.addClass('fc-limited').after($(segMoreNodes));
- limitedNodes.push(td[0]);
- }
- }
- emptyCellsUntil(this.colCnt);
- rowStruct.moreEls = $(moreNodes);
- rowStruct.limitedEls = $(limitedNodes);
- }
- },
-
-
- unlimitRow: function(row) {
- var rowStruct = this.rowStructs[row];
- if (rowStruct.moreEls) {
- rowStruct.moreEls.remove();
- rowStruct.moreEls = null;
- }
- if (rowStruct.limitedEls) {
- rowStruct.limitedEls.removeClass('fc-limited');
- rowStruct.limitedEls = null;
- }
- },
-
-
- renderMoreLink: function(row, col, hiddenSegs) {
- var _this = this;
- var view = this.view;
- return $('<a class="fc-more"/>')
- .text(
- this.getMoreLinkText(hiddenSegs.length)
- )
- .on('click', function(ev) {
- var clickOption = _this.opt('eventLimitClick');
- var date = _this.getCellDate(row, col);
- var moreEl = $(this);
- var dayEl = _this.getCellEl(row, col);
- var allSegs = _this.getCellSegs(row, col);
-
- var reslicedAllSegs = _this.resliceDaySegs(allSegs, date);
- var reslicedHiddenSegs = _this.resliceDaySegs(hiddenSegs, date);
- if (typeof clickOption === 'function') {
-
- clickOption = _this.publiclyTrigger('eventLimitClick', {
- context: view,
- args: [
- {
- date: date.clone(),
- dayEl: dayEl,
- moreEl: moreEl,
- segs: reslicedAllSegs,
- hiddenSegs: reslicedHiddenSegs
- },
- ev,
- view
- ]
- });
- }
- if (clickOption === 'popover') {
- _this.showSegPopover(row, col, moreEl, reslicedAllSegs);
- }
- else if (typeof clickOption === 'string') {
- view.calendar.zoomTo(date, clickOption);
- }
- });
- },
-
- showSegPopover: function(row, col, moreLink, segs) {
- var _this = this;
- var view = this.view;
- var moreWrap = moreLink.parent();
- var topEl;
- var options;
- if (this.rowCnt == 1) {
- topEl = view.el;
- }
- else {
- topEl = this.rowEls.eq(row);
- }
- options = {
- className: 'fc-more-popover ' + view.calendar.theme.getClass('popover'),
- content: this.renderSegPopoverContent(row, col, segs),
- parentEl: view.el,
- top: topEl.offset().top,
- autoHide: true,
- viewportConstrain: this.opt('popoverViewportConstrain'),
- hide: function() {
-
-
- if (_this.popoverSegs) {
- var seg;
- var legacy;
- var i;
- for (i = 0; i < _this.popoverSegs.length; ++i) {
- seg = _this.popoverSegs[i];
- legacy = seg.footprint.getEventLegacy();
- _this.publiclyTrigger('eventDestroy', {
- context: legacy,
- args: [ legacy, seg.el, view ]
- });
- }
- }
- _this.segPopover.removeElement();
- _this.segPopover = null;
- _this.popoverSegs = null;
- }
- };
-
-
- if (this.isRTL) {
- options.right = moreWrap.offset().left + moreWrap.outerWidth() + 1;
- }
- else {
- options.left = moreWrap.offset().left - 1;
- }
- this.segPopover = new Popover(options);
- this.segPopover.show();
-
-
- this.bindSegHandlersToEl(this.segPopover.el);
- },
-
- renderSegPopoverContent: function(row, col, segs) {
- var view = this.view;
- var theme = view.calendar.theme;
- var title = this.getCellDate(row, col).format(this.opt('dayPopoverFormat'));
- var content = $(
- '<div class="fc-header ' + theme.getClass('popoverHeader') + '">' +
- '<span class="fc-close ' + theme.getIconClass('close') + '"></span>' +
- '<span class="fc-title">' +
- htmlEscape(title) +
- '</span>' +
- '<div class="fc-clear"/>' +
- '</div>' +
- '<div class="fc-body ' + theme.getClass('popoverContent') + '">' +
- '<div class="fc-event-container"></div>' +
- '</div>'
- );
- var segContainer = content.find('.fc-event-container');
- var i;
-
- segs = this.renderFgSegEls(segs, true);
- this.popoverSegs = segs;
- for (i = 0; i < segs.length; i++) {
-
-
- this.hitsNeeded();
- segs[i].hit = this.getCellHit(row, col);
- this.hitsNotNeeded();
- segContainer.append(segs[i].el);
- }
- return content;
- },
-
- resliceDaySegs: function(segs, dayDate) {
- var dayStart = dayDate.clone();
- var dayEnd = dayStart.clone().add(1, 'days');
- var dayRange = new UnzonedRange(dayStart, dayEnd);
- var newSegs = [];
- var i;
- for (i = 0; i < segs.length; i++) {
- newSegs.push.apply(newSegs,
- this.eventFootprintToSegs(segs[i].footprint, dayRange)
- );
- }
-
-
- this.sortEventSegs(newSegs);
- return newSegs;
- },
-
- getMoreLinkText: function(num) {
- var opt = this.opt('eventLimitText');
- if (typeof opt === 'function') {
- return opt(num);
- }
- else {
- return '+' + num + ' ' + opt;
- }
- },
-
-
- getCellSegs: function(row, col, startLevel) {
- var segMatrix = this.rowStructs[row].segMatrix;
- var level = startLevel || 0;
- var segs = [];
- var seg;
- while (level < segMatrix.length) {
- seg = segMatrix[level][col];
- if (seg) {
- segs.push(seg);
- }
- level++;
- }
- return segs;
- }
- });
- ;;
- var TimeGrid = FC.TimeGrid = Grid.extend(DayTableMixin, {
- dayRanges: null,
- slotDuration: null,
- snapDuration: null,
- snapsPerSlot: null,
- labelFormat: null,
- labelInterval: null,
- colEls: null,
- slatContainerEl: null,
- slatEls: null,
- nowIndicatorEls: null,
- colCoordCache: null,
- slatCoordCache: null,
- constructor: function() {
- Grid.apply(this, arguments);
- this.processOptions();
- },
-
-
- renderDates: function() {
- this.el.html(this.renderHtml());
- this.colEls = this.el.find('.fc-day, .fc-disabled-day');
- this.slatContainerEl = this.el.find('.fc-slats');
- this.slatEls = this.slatContainerEl.find('tr');
- this.colCoordCache = new CoordCache({
- els: this.colEls,
- isHorizontal: true
- });
- this.slatCoordCache = new CoordCache({
- els: this.slatEls,
- isVertical: true
- });
- this.renderContentSkeleton();
- },
-
- renderHtml: function() {
- var theme = this.view.calendar.theme;
- return '' +
- '<div class="fc-bg">' +
- '<table class="' + theme.getClass('tableGrid') + '">' +
- this.renderBgTrHtml(0) +
- '</table>' +
- '</div>' +
- '<div class="fc-slats">' +
- '<table class="' + theme.getClass('tableGrid') + '">' +
- this.renderSlatRowHtml() +
- '</table>' +
- '</div>';
- },
-
- renderSlatRowHtml: function() {
- var view = this.view;
- var calendar = view.calendar;
- var theme = calendar.theme;
- var isRTL = this.isRTL;
- var html = '';
- var slotTime = moment.duration(+this.view.minTime);
- var slotIterator = moment.duration(0);
- var slotDate;
- var isLabeled;
- var axisHtml;
-
- while (slotTime < view.maxTime) {
- slotDate = calendar.msToUtcMoment(this.unzonedRange.startMs).time(slotTime);
- isLabeled = isInt(divideDurationByDuration(slotIterator, this.labelInterval));
- axisHtml =
- '<td class="fc-axis fc-time ' + theme.getClass('widgetContent') + '" ' + view.axisStyleAttr() + '>' +
- (isLabeled ?
- '<span>' +
- htmlEscape(slotDate.format(this.labelFormat)) +
- '</span>' :
- ''
- ) +
- '</td>';
- html +=
- '<tr data-time="' + slotDate.format('HH:mm:ss') + '"' +
- (isLabeled ? '' : ' class="fc-minor"') +
- '>' +
- (!isRTL ? axisHtml : '') +
- '<td class="' + theme.getClass('widgetContent') + '"/>' +
- (isRTL ? axisHtml : '') +
- "</tr>";
- slotTime.add(this.slotDuration);
- slotIterator.add(this.slotDuration);
- }
- return html;
- },
-
-
- processOptions: function() {
- var slotDuration = this.opt('slotDuration');
- var snapDuration = this.opt('snapDuration');
- var input;
- slotDuration = moment.duration(slotDuration);
- snapDuration = snapDuration ? moment.duration(snapDuration) : slotDuration;
- this.slotDuration = slotDuration;
- this.snapDuration = snapDuration;
- this.snapsPerSlot = slotDuration / snapDuration;
-
-
- input = this.opt('slotLabelFormat');
- if ($.isArray(input)) {
- input = input[input.length - 1];
- }
- this.labelFormat = input ||
- this.opt('smallTimeFormat');
- input = this.opt('slotLabelInterval');
- this.labelInterval = input ?
- moment.duration(input) :
- this.computeLabelInterval(slotDuration);
- },
-
- computeLabelInterval: function(slotDuration) {
- var i;
- var labelInterval;
- var slotsPerLabel;
-
- for (i = AGENDA_STOCK_SUB_DURATIONS.length - 1; i >= 0; i--) {
- labelInterval = moment.duration(AGENDA_STOCK_SUB_DURATIONS[i]);
- slotsPerLabel = divideDurationByDuration(labelInterval, slotDuration);
- if (isInt(slotsPerLabel) && slotsPerLabel > 1) {
- return labelInterval;
- }
- }
- return moment.duration(slotDuration);
- },
-
- computeEventTimeFormat: function() {
- return this.opt('noMeridiemTimeFormat');
- },
-
- computeDisplayEventEnd: function() {
- return true;
- },
-
- prepareHits: function() {
- this.colCoordCache.build();
- this.slatCoordCache.build();
- },
- releaseHits: function() {
- this.colCoordCache.clear();
-
- },
- queryHit: function(leftOffset, topOffset) {
- var snapsPerSlot = this.snapsPerSlot;
- var colCoordCache = this.colCoordCache;
- var slatCoordCache = this.slatCoordCache;
- if (colCoordCache.isLeftInBounds(leftOffset) && slatCoordCache.isTopInBounds(topOffset)) {
- var colIndex = colCoordCache.getHorizontalIndex(leftOffset);
- var slatIndex = slatCoordCache.getVerticalIndex(topOffset);
- if (colIndex != null && slatIndex != null) {
- var slatTop = slatCoordCache.getTopOffset(slatIndex);
- var slatHeight = slatCoordCache.getHeight(slatIndex);
- var partial = (topOffset - slatTop) / slatHeight;
- var localSnapIndex = Math.floor(partial * snapsPerSlot);
- var snapIndex = slatIndex * snapsPerSlot + localSnapIndex;
- var snapTop = slatTop + (localSnapIndex / snapsPerSlot) * slatHeight;
- var snapBottom = slatTop + ((localSnapIndex + 1) / snapsPerSlot) * slatHeight;
- return {
- col: colIndex,
- snap: snapIndex,
- component: this,
- left: colCoordCache.getLeftOffset(colIndex),
- right: colCoordCache.getRightOffset(colIndex),
- top: snapTop,
- bottom: snapBottom
- };
- }
- }
- },
- getHitFootprint: function(hit) {
- var start = this.getCellDate(0, hit.col);
- var time = this.computeSnapTime(hit.snap);
- var end;
- start.time(time);
- end = start.clone().add(this.snapDuration);
- return new ComponentFootprint(
- new UnzonedRange(start, end),
- false
- );
- },
- getHitEl: function(hit) {
- return this.colEls.eq(hit.col);
- },
-
- rangeUpdated: function() {
- var view = this.view;
- this.updateDayTable();
- this.dayRanges = this.dayDates.map(function(dayDate) {
- return new UnzonedRange(
- dayDate.clone().add(view.minTime),
- dayDate.clone().add(view.maxTime)
- );
- });
- },
-
- computeSnapTime: function(snapIndex) {
- return moment.duration(this.view.minTime + this.snapDuration * snapIndex);
- },
-
- componentFootprintToSegs: function(componentFootprint) {
- var segs = this.sliceRangeByTimes(componentFootprint.unzonedRange);
- var i;
- for (i = 0; i < segs.length; i++) {
- if (this.isRTL) {
- segs[i].col = this.daysPerRow - 1 - segs[i].dayIndex;
- }
- else {
- segs[i].col = segs[i].dayIndex;
- }
- }
- return segs;
- },
- sliceRangeByTimes: function(unzonedRange) {
- var segs = [];
- var segRange;
- var dayIndex;
- for (dayIndex = 0; dayIndex < this.daysPerRow; dayIndex++) {
- segRange = unzonedRange.intersect(this.dayRanges[dayIndex]);
- if (segRange) {
- segs.push({
- startMs: segRange.startMs,
- endMs: segRange.endMs,
- isStart: segRange.isStart,
- isEnd: segRange.isEnd,
- dayIndex: dayIndex
- });
- }
- }
- return segs;
- },
-
- updateSize: function(isResize) {
- this.slatCoordCache.build();
- if (isResize) {
- this.updateSegVerticals(
- [].concat(this.fgSegs || [], this.bgSegs || [], this.businessSegs || [])
- );
- }
- },
- getTotalSlatHeight: function() {
- return this.slatContainerEl.outerHeight();
- },
-
-
-
- computeDateTop: function(ms, startOfDayDate) {
- return this.computeTimeTop(
- moment.duration(
- ms - startOfDayDate.clone().stripTime()
- )
- );
- },
-
- computeTimeTop: function(time) {
- var len = this.slatEls.length;
- var slatCoverage = (time - this.view.minTime) / this.slotDuration;
- var slatIndex;
- var slatRemainder;
-
-
-
- slatCoverage = Math.max(0, slatCoverage);
- slatCoverage = Math.min(len, slatCoverage);
-
-
- slatIndex = Math.floor(slatCoverage);
- slatIndex = Math.min(slatIndex, len - 1);
-
-
- slatRemainder = slatCoverage - slatIndex;
- return this.slatCoordCache.getTopPosition(slatIndex) +
- this.slatCoordCache.getHeight(slatIndex) * slatRemainder;
- },
-
-
-
- renderDrag: function(eventFootprints, seg) {
- var i;
- if (seg) {
-
-
- return this.renderHelperEventFootprints(eventFootprints);
- }
- else {
- for (i = 0; i < eventFootprints.length; i++) {
- this.renderHighlight(eventFootprints[i].componentFootprint);
- }
- }
- },
-
- unrenderDrag: function() {
- this.unrenderHelper();
- this.unrenderHighlight();
- },
-
-
- renderEventResize: function(eventFootprints, seg) {
- return this.renderHelperEventFootprints(eventFootprints, seg);
- },
-
- unrenderEventResize: function() {
- this.unrenderHelper();
- },
-
-
- renderHelperEventFootprintEls: function(eventFootprints, sourceSeg) {
- var segs = this.eventFootprintsToSegs(eventFootprints);
- return this.renderHelperSegs(
- segs,
- sourceSeg
- );
- },
-
- unrenderHelper: function() {
- this.unrenderHelperSegs();
- },
-
- renderBusinessHours: function() {
- this.renderBusinessSegs(
- this.buildBusinessHourSegs()
- );
- },
- unrenderBusinessHours: function() {
- this.unrenderBusinessSegs();
- },
-
- getNowIndicatorUnit: function() {
- return 'minute';
- },
- renderNowIndicator: function(date) {
-
-
- var segs = this.componentFootprintToSegs(
- new ComponentFootprint(
- new UnzonedRange(date, date.valueOf() + 1),
- false
- )
- );
- var top = this.computeDateTop(date, date);
- var nodes = [];
- var i;
-
- for (i = 0; i < segs.length; i++) {
- nodes.push($('<div class="fc-now-indicator fc-now-indicator-line"></div>')
- .css('top', top)
- .appendTo(this.colContainerEls.eq(segs[i].col))[0]);
- }
-
- if (segs.length > 0) {
- nodes.push($('<div class="fc-now-indicator fc-now-indicator-arrow"></div>')
- .css('top', top)
- .appendTo(this.el.find('.fc-content-skeleton'))[0]);
- }
- this.nowIndicatorEls = $(nodes);
- },
- unrenderNowIndicator: function() {
- if (this.nowIndicatorEls) {
- this.nowIndicatorEls.remove();
- this.nowIndicatorEls = null;
- }
- },
-
-
- renderSelectionFootprint: function(componentFootprint) {
- if (this.opt('selectHelper')) {
- this.renderHelperEventFootprints([
- this.fabricateEventFootprint(componentFootprint)
- ]);
- }
- else {
- this.renderHighlight(componentFootprint);
- }
- },
-
- unrenderSelection: function() {
- this.unrenderHelper();
- this.unrenderHighlight();
- },
-
- renderHighlight: function(componentFootprint) {
- this.renderHighlightSegs(
- this.componentFootprintToSegs(componentFootprint)
- );
- },
- unrenderHighlight: function() {
- this.unrenderHighlightSegs();
- }
- });
- ;;
- TimeGrid.mixin({
- colContainerEls: null,
-
- fgContainerEls: null,
- bgContainerEls: null,
- helperContainerEls: null,
- highlightContainerEls: null,
- businessContainerEls: null,
-
- fgSegs: null,
- bgSegs: null,
- helperSegs: null,
- highlightSegs: null,
- businessSegs: null,
-
- renderContentSkeleton: function() {
- var cellHtml = '';
- var i;
- var skeletonEl;
- for (i = 0; i < this.colCnt; i++) {
- cellHtml +=
- '<td>' +
- '<div class="fc-content-col">' +
- '<div class="fc-event-container fc-helper-container"></div>' +
- '<div class="fc-event-container"></div>' +
- '<div class="fc-highlight-container"></div>' +
- '<div class="fc-bgevent-container"></div>' +
- '<div class="fc-business-container"></div>' +
- '</div>' +
- '</td>';
- }
- skeletonEl = $(
- '<div class="fc-content-skeleton">' +
- '<table>' +
- '<tr>' + cellHtml + '</tr>' +
- '</table>' +
- '</div>'
- );
- this.colContainerEls = skeletonEl.find('.fc-content-col');
- this.helperContainerEls = skeletonEl.find('.fc-helper-container');
- this.fgContainerEls = skeletonEl.find('.fc-event-container:not(.fc-helper-container)');
- this.bgContainerEls = skeletonEl.find('.fc-bgevent-container');
- this.highlightContainerEls = skeletonEl.find('.fc-highlight-container');
- this.businessContainerEls = skeletonEl.find('.fc-business-container');
- this.bookendCells(skeletonEl.find('tr'));
- this.el.append(skeletonEl);
- },
-
- renderFgSegs: function(segs) {
- segs = this.renderFgSegsIntoContainers(segs, this.fgContainerEls);
- this.fgSegs = segs;
- return segs;
- },
- unrenderFgSegs: function() {
- this.unrenderNamedSegs('fgSegs');
- },
-
- renderHelperSegs: function(segs, sourceSeg) {
- var helperEls = [];
- var i, seg;
- var sourceEl;
- segs = this.renderFgSegsIntoContainers(segs, this.helperContainerEls);
-
- for (i = 0; i < segs.length; i++) {
- seg = segs[i];
- if (sourceSeg && sourceSeg.col === seg.col) {
- sourceEl = sourceSeg.el;
- seg.el.css({
- left: sourceEl.css('left'),
- right: sourceEl.css('right'),
- 'margin-left': sourceEl.css('margin-left'),
- 'margin-right': sourceEl.css('margin-right')
- });
- }
- helperEls.push(seg.el[0]);
- }
- this.helperSegs = segs;
- return $(helperEls);
- },
- unrenderHelperSegs: function() {
- this.unrenderNamedSegs('helperSegs');
- },
-
- renderBgSegs: function(segs) {
- segs = this.renderFillSegEls('bgEvent', segs);
- this.updateSegVerticals(segs);
- this.attachSegsByCol(this.groupSegsByCol(segs), this.bgContainerEls);
- this.bgSegs = segs;
- return segs;
- },
- unrenderBgSegs: function() {
- this.unrenderNamedSegs('bgSegs');
- },
-
- renderHighlightSegs: function(segs) {
- segs = this.renderFillSegEls('highlight', segs);
- this.updateSegVerticals(segs);
- this.attachSegsByCol(this.groupSegsByCol(segs), this.highlightContainerEls);
- this.highlightSegs = segs;
- },
- unrenderHighlightSegs: function() {
- this.unrenderNamedSegs('highlightSegs');
- },
-
- renderBusinessSegs: function(segs) {
- segs = this.renderFillSegEls('businessHours', segs);
- this.updateSegVerticals(segs);
- this.attachSegsByCol(this.groupSegsByCol(segs), this.businessContainerEls);
- this.businessSegs = segs;
- },
- unrenderBusinessSegs: function() {
- this.unrenderNamedSegs('businessSegs');
- },
-
-
- groupSegsByCol: function(segs) {
- var segsByCol = [];
- var i;
- for (i = 0; i < this.colCnt; i++) {
- segsByCol.push([]);
- }
- for (i = 0; i < segs.length; i++) {
- segsByCol[segs[i].col].push(segs[i]);
- }
- return segsByCol;
- },
-
-
- attachSegsByCol: function(segsByCol, containerEls) {
- var col;
- var segs;
- var i;
- for (col = 0; col < this.colCnt; col++) {
- segs = segsByCol[col];
- for (i = 0; i < segs.length; i++) {
- containerEls.eq(col).append(segs[i].el);
- }
- }
- },
-
-
- unrenderNamedSegs: function(propName) {
- var segs = this[propName];
- var i;
- if (segs) {
- for (i = 0; i < segs.length; i++) {
- segs[i].el.remove();
- }
- this[propName] = null;
- }
- },
-
-
-
- renderFgSegsIntoContainers: function(segs, containerEls) {
- var segsByCol;
- var col;
- segs = this.renderFgSegEls(segs);
- segsByCol = this.groupSegsByCol(segs);
- for (col = 0; col < this.colCnt; col++) {
- this.updateFgSegCoords(segsByCol[col]);
- }
- this.attachSegsByCol(segsByCol, containerEls);
- return segs;
- },
-
- fgSegHtml: function(seg, disableResizing) {
- var view = this.view;
- var calendar = view.calendar;
- var componentFootprint = seg.footprint.componentFootprint;
- var isAllDay = componentFootprint.isAllDay;
- var eventDef = seg.footprint.eventDef;
- var isDraggable = view.isEventDefDraggable(eventDef);
- var isResizableFromStart = !disableResizing && seg.isStart && view.isEventDefResizableFromStart(eventDef);
- var isResizableFromEnd = !disableResizing && seg.isEnd && view.isEventDefResizableFromEnd(eventDef);
- var classes = this.getSegClasses(seg, isDraggable, isResizableFromStart || isResizableFromEnd);
- var skinCss = cssToStr(this.getSegSkinCss(seg));
- var timeText;
- var fullTimeText;
- var startTimeText;
- classes.unshift('fc-time-grid-event', 'fc-v-event');
-
- if (view.isMultiDayRange(componentFootprint.unzonedRange)) {
-
-
-
- if (seg.isStart || seg.isEnd) {
- var zonedStart = calendar.msToMoment(seg.startMs);
- var zonedEnd = calendar.msToMoment(seg.endMs);
- timeText = this._getEventTimeText(zonedStart, zonedEnd, isAllDay);
- fullTimeText = this._getEventTimeText(zonedStart, zonedEnd, isAllDay, 'LT');
- startTimeText = this._getEventTimeText(zonedStart, zonedEnd, isAllDay, null, false);
- }
- }
- else {
-
- timeText = this.getEventTimeText(seg.footprint);
- fullTimeText = this.getEventTimeText(seg.footprint, 'LT');
- startTimeText = this.getEventTimeText(seg.footprint, null, false);
- }
- return '<a class="' + classes.join(' ') + '"' +
- (eventDef.url ?
- ' href="' + htmlEscape(eventDef.url) + '"' :
- ''
- ) +
- (skinCss ?
- ' style="' + skinCss + '"' :
- ''
- ) +
- '>' +
- '<div class="fc-content">' +
- (timeText ?
- '<div class="fc-time"' +
- ' data-start="' + htmlEscape(startTimeText) + '"' +
- ' data-full="' + htmlEscape(fullTimeText) + '"' +
- '>' +
- '<span>' + htmlEscape(timeText) + '</span>' +
- '</div>' :
- ''
- ) +
- (eventDef.title ?
- '<div class="fc-title">' +
- htmlEscape(eventDef.title) +
- '</div>' :
- ''
- ) +
- '</div>' +
- '<div class="fc-bg"/>' +
-
- (isResizableFromEnd ?
- '<div class="fc-resizer fc-end-resizer" />' :
- ''
- ) +
- '</a>';
- },
-
-
-
- updateSegVerticals: function(segs) {
- this.computeSegVerticals(segs);
- this.assignSegVerticals(segs);
- },
-
- computeSegVerticals: function(segs) {
- var i, seg;
- var dayDate;
- for (i = 0; i < segs.length; i++) {
- seg = segs[i];
- dayDate = this.dayDates[seg.dayIndex];
- seg.top = this.computeDateTop(seg.startMs, dayDate);
- seg.bottom = this.computeDateTop(seg.endMs, dayDate);
- }
- },
-
-
- assignSegVerticals: function(segs) {
- var i, seg;
- for (i = 0; i < segs.length; i++) {
- seg = segs[i];
- seg.el.css(this.generateSegVerticalCss(seg));
- }
- },
-
- generateSegVerticalCss: function(seg) {
- return {
- top: seg.top,
- bottom: -seg.bottom
- };
- },
-
-
-
- updateFgSegCoords: function(segs) {
- this.computeSegVerticals(segs);
- this.computeFgSegHorizontals(segs);
- this.assignSegVerticals(segs);
- this.assignFgSegHorizontals(segs);
- },
-
-
- computeFgSegHorizontals: function(segs) {
- var levels;
- var level0;
- var i;
- this.sortEventSegs(segs);
- levels = buildSlotSegLevels(segs);
- computeForwardSlotSegs(levels);
- if ((level0 = levels[0])) {
- for (i = 0; i < level0.length; i++) {
- computeSlotSegPressures(level0[i]);
- }
- for (i = 0; i < level0.length; i++) {
- this.computeFgSegForwardBack(level0[i], 0, 0);
- }
- }
- },
-
-
-
-
-
-
-
-
- computeFgSegForwardBack: function(seg, seriesBackwardPressure, seriesBackwardCoord) {
- var forwardSegs = seg.forwardSegs;
- var i;
- if (seg.forwardCoord === undefined) {
- if (!forwardSegs.length) {
-
- seg.forwardCoord = 1;
- }
- else {
-
- this.sortForwardSegs(forwardSegs);
-
-
- this.computeFgSegForwardBack(forwardSegs[0], seriesBackwardPressure + 1, seriesBackwardCoord);
- seg.forwardCoord = forwardSegs[0].backwardCoord;
- }
-
- seg.backwardCoord = seg.forwardCoord -
- (seg.forwardCoord - seriesBackwardCoord) /
- (seriesBackwardPressure + 1);
-
-
- for (i=0; i<forwardSegs.length; i++) {
- this.computeFgSegForwardBack(forwardSegs[i], 0, seg.forwardCoord);
- }
- }
- },
- sortForwardSegs: function(forwardSegs) {
- forwardSegs.sort(proxy(this, 'compareForwardSegs'));
- },
-
- compareForwardSegs: function(seg1, seg2) {
-
- return seg2.forwardPressure - seg1.forwardPressure ||
-
- (seg1.backwardCoord || 0) - (seg2.backwardCoord || 0) ||
-
- this.compareEventSegs(seg1, seg2);
- },
-
-
- assignFgSegHorizontals: function(segs) {
- var i, seg;
- for (i = 0; i < segs.length; i++) {
- seg = segs[i];
- seg.el.css(this.generateFgSegHorizontalCss(seg));
-
- if (seg.bottom - seg.top < 30) {
- seg.el.addClass('fc-short');
- }
- }
- },
-
-
- generateFgSegHorizontalCss: function(seg) {
- var shouldOverlap = this.opt('slotEventOverlap');
- var backwardCoord = seg.backwardCoord;
- var forwardCoord = seg.forwardCoord;
- var props = this.generateSegVerticalCss(seg);
- var left;
- var right;
- if (shouldOverlap) {
-
- forwardCoord = Math.min(1, backwardCoord + (forwardCoord - backwardCoord) * 2);
- }
- if (this.isRTL) {
- left = 1 - forwardCoord;
- right = backwardCoord;
- }
- else {
- left = backwardCoord;
- right = 1 - forwardCoord;
- }
- props.zIndex = seg.level + 1;
- props.left = left * 100 + '%';
- props.right = right * 100 + '%';
- if (shouldOverlap && seg.forwardPressure) {
-
- props[this.isRTL ? 'marginLeft' : 'marginRight'] = 10 * 2;
- }
- return props;
- }
- });
- function buildSlotSegLevels(segs) {
- var levels = [];
- var i, seg;
- var j;
- for (i=0; i<segs.length; i++) {
- seg = segs[i];
-
- for (j=0; j<levels.length; j++) {
- if (!computeSlotSegCollisions(seg, levels[j]).length) {
- break;
- }
- }
- seg.level = j;
- (levels[j] || (levels[j] = [])).push(seg);
- }
- return levels;
- }
- function computeForwardSlotSegs(levels) {
- var i, level;
- var j, seg;
- var k;
- for (i=0; i<levels.length; i++) {
- level = levels[i];
- for (j=0; j<level.length; j++) {
- seg = level[j];
- seg.forwardSegs = [];
- for (k=i+1; k<levels.length; k++) {
- computeSlotSegCollisions(seg, levels[k], seg.forwardSegs);
- }
- }
- }
- }
- function computeSlotSegPressures(seg) {
- var forwardSegs = seg.forwardSegs;
- var forwardPressure = 0;
- var i, forwardSeg;
- if (seg.forwardPressure === undefined) {
- for (i=0; i<forwardSegs.length; i++) {
- forwardSeg = forwardSegs[i];
-
- computeSlotSegPressures(forwardSeg);
-
-
- forwardPressure = Math.max(
- forwardPressure,
- 1 + forwardSeg.forwardPressure
- );
- }
- seg.forwardPressure = forwardPressure;
- }
- }
- function computeSlotSegCollisions(seg, otherSegs, results) {
- results = results || [];
- for (var i=0; i<otherSegs.length; i++) {
- if (isSlotSegCollision(seg, otherSegs[i])) {
- results.push(otherSegs[i]);
- }
- }
- return results;
- }
- function isSlotSegCollision(seg1, seg2) {
- return seg1.bottom > seg2.top && seg1.top < seg2.bottom;
- }
- ;;
- var View = FC.View = ChronoComponent.extend({
- type: null,
- name: null,
- title: null,
- calendar: null,
- viewSpec: null,
- options: null,
- renderQueue: null,
- batchRenderDepth: 0,
- isDatesRendered: false,
- isEventsRendered: false,
- isBaseRendered: false,
- queuedScroll: null,
- isSelected: false,
- selectedEventInstance: null,
- eventOrderSpecs: null,
-
- isHiddenDayHash: null,
-
- isNowIndicatorRendered: null,
- initialNowDate: null,
- initialNowQueriedMs: null,
- nowIndicatorTimeoutID: null,
- nowIndicatorIntervalID: null,
- constructor: function(calendar, viewSpec) {
- this.calendar = calendar;
- this.viewSpec = viewSpec;
-
- this.type = viewSpec.type;
- this.options = viewSpec.options;
-
- this.name = this.type;
- ChronoComponent.call(this);
- this.initHiddenDays();
- this.eventOrderSpecs = parseFieldSpecs(this.opt('eventOrder'));
- this.renderQueue = this.buildRenderQueue();
- this.initAutoBatchRender();
- this.initialize();
- },
- buildRenderQueue: function() {
- var _this = this;
- var renderQueue = new RenderQueue({
- event: this.opt('eventRenderWait')
- });
- renderQueue.on('start', function() {
- _this.freezeHeight();
- _this.addScroll(_this.queryScroll());
- });
- renderQueue.on('stop', function() {
- _this.thawHeight();
- _this.popScroll();
- });
- return renderQueue;
- },
- initAutoBatchRender: function() {
- var _this = this;
- this.on('before:change', function() {
- _this.startBatchRender();
- });
- this.on('change', function() {
- _this.stopBatchRender();
- });
- },
- startBatchRender: function() {
- if (!(this.batchRenderDepth++)) {
- this.renderQueue.pause();
- }
- },
- stopBatchRender: function() {
- if (!(--this.batchRenderDepth)) {
- this.renderQueue.resume();
- }
- },
-
- initialize: function() {
-
- },
-
- opt: function(name) {
- return this.options[name];
- },
-
-
- computeTitle: function() {
- var unzonedRange;
-
- if (/^(year|month)$/.test(this.currentRangeUnit)) {
- unzonedRange = this.currentUnzonedRange;
- }
- else {
- unzonedRange = this.activeUnzonedRange;
- }
- return this.formatRange(
- {
- start: this.calendar.msToMoment(unzonedRange.startMs, this.isRangeAllDay),
- end: this.calendar.msToMoment(unzonedRange.endMs, this.isRangeAllDay)
- },
- this.isRangeAllDay,
- this.opt('titleFormat') || this.computeTitleFormat(),
- this.opt('titleRangeSeparator')
- );
- },
-
-
- computeTitleFormat: function() {
- if (this.currentRangeUnit == 'year') {
- return 'YYYY';
- }
- else if (this.currentRangeUnit == 'month') {
- return this.opt('monthYearFormat');
- }
- else if (this.currentRangeAs('days') > 1) {
- return 'll';
- }
- else {
- return 'LL';
- }
- },
-
-
- setElement: function(el) {
- ChronoComponent.prototype.setElement.apply(this, arguments);
- this.bindBaseRenderHandlers();
- },
- removeElement: function() {
- this.unsetDate();
- this.unbindBaseRenderHandlers();
- ChronoComponent.prototype.removeElement.apply(this, arguments);
- },
-
-
- setDate: function(date) {
- var currentDateProfile = this.get('dateProfile');
- var newDateProfile = this.buildDateProfile(date, null, true);
- if (
- !currentDateProfile ||
- !currentDateProfile.activeUnzonedRange.equals(newDateProfile.activeUnzonedRange)
- ) {
- this.set('dateProfile', newDateProfile);
- }
- return newDateProfile.date;
- },
- unsetDate: function() {
- this.unset('dateProfile');
- },
-
-
- requestDateRender: function(dateProfile) {
- var _this = this;
- this.renderQueue.queue(function() {
- _this.executeDateRender(dateProfile);
- }, 'date', 'init');
- },
- requestDateUnrender: function() {
- var _this = this;
- this.renderQueue.queue(function() {
- _this.executeDateUnrender();
- }, 'date', 'destroy');
- },
-
-
- fetchInitialEvents: function(dateProfile) {
- var calendar = this.calendar;
- var forceAllDay = dateProfile.isRangeAllDay && !this.usesMinMaxTime;
- return calendar.requestEvents(
- calendar.msToMoment(dateProfile.activeUnzonedRange.startMs, forceAllDay),
- calendar.msToMoment(dateProfile.activeUnzonedRange.endMs, forceAllDay)
- );
- },
- bindEventChanges: function() {
- this.listenTo(this.calendar, 'eventsReset', this.resetEvents);
- },
- unbindEventChanges: function() {
- this.stopListeningTo(this.calendar, 'eventsReset');
- },
- setEvents: function(eventsPayload) {
- this.set('currentEvents', eventsPayload);
- this.set('hasEvents', true);
- },
- unsetEvents: function() {
- this.unset('currentEvents');
- this.unset('hasEvents');
- },
- resetEvents: function(eventsPayload) {
- this.startBatchRender();
- this.unsetEvents();
- this.setEvents(eventsPayload);
- this.stopBatchRender();
- },
-
-
- requestEventsRender: function(eventsPayload) {
- var _this = this;
- this.renderQueue.queue(function() {
- _this.executeEventsRender(eventsPayload);
- }, 'event', 'init');
- },
- requestEventsUnrender: function() {
- var _this = this;
- this.renderQueue.queue(function() {
- _this.executeEventsUnrender();
- }, 'event', 'destroy');
- },
-
-
-
- executeDateRender: function(dateProfile, skipScroll) {
- this.setDateProfileForRendering(dateProfile);
- if (this.render) {
- this.render();
- }
- this.renderDates();
- this.updateSize();
- this.renderBusinessHours();
- this.startNowIndicator();
- if (!skipScroll) {
- this.addScroll(this.computeInitialDateScroll());
- }
- this.isDatesRendered = true;
- this.trigger('datesRendered');
- },
- executeDateUnrender: function() {
- this.unselect();
- this.stopNowIndicator();
- this.trigger('before:datesUnrendered');
- this.unrenderBusinessHours();
- this.unrenderDates();
- if (this.destroy) {
- this.destroy();
- }
- this.isDatesRendered = false;
- },
-
-
- bindBaseRenderHandlers: function() {
- var _this = this;
- this.on('datesRendered.baseHandler', function() {
- _this.onBaseRender();
- });
- this.on('before:datesUnrendered.baseHandler', function() {
- _this.onBeforeBaseUnrender();
- });
- },
- unbindBaseRenderHandlers: function() {
- this.off('.baseHandler');
- },
- onBaseRender: function() {
- this.applyScreenState();
- this.publiclyTrigger('viewRender', {
- context: this,
- args: [ this, this.el ]
- });
- },
- onBeforeBaseUnrender: function() {
- this.applyScreenState();
- this.publiclyTrigger('viewDestroy', {
- context: this,
- args: [ this, this.el ]
- });
- },
-
-
-
- bindGlobalHandlers: function() {
- this.listenTo(GlobalEmitter.get(), {
- touchstart: this.processUnselect,
- mousedown: this.handleDocumentMousedown
- });
- },
-
- unbindGlobalHandlers: function() {
- this.stopListeningTo(GlobalEmitter.get());
- },
-
-
-
-
- startNowIndicator: function() {
- var _this = this;
- var unit;
- var update;
- var delay;
- if (this.opt('nowIndicator')) {
- unit = this.getNowIndicatorUnit();
- if (unit) {
- update = proxy(this, 'updateNowIndicator');
- this.initialNowDate = this.calendar.getNow();
- this.initialNowQueriedMs = +new Date();
- this.renderNowIndicator(this.initialNowDate);
- this.isNowIndicatorRendered = true;
-
- delay = this.initialNowDate.clone().startOf(unit).add(1, unit) - this.initialNowDate;
- this.nowIndicatorTimeoutID = setTimeout(function() {
- _this.nowIndicatorTimeoutID = null;
- update();
- delay = +moment.duration(1, unit);
- delay = Math.max(100, delay);
- _this.nowIndicatorIntervalID = setInterval(update, delay);
- }, delay);
- }
- }
- },
-
-
- updateNowIndicator: function() {
- if (this.isNowIndicatorRendered) {
- this.unrenderNowIndicator();
- this.renderNowIndicator(
- this.initialNowDate.clone().add(new Date() - this.initialNowQueriedMs)
- );
- }
- },
-
-
- stopNowIndicator: function() {
- if (this.isNowIndicatorRendered) {
- if (this.nowIndicatorTimeoutID) {
- clearTimeout(this.nowIndicatorTimeoutID);
- this.nowIndicatorTimeoutID = null;
- }
- if (this.nowIndicatorIntervalID) {
- clearTimeout(this.nowIndicatorIntervalID);
- this.nowIndicatorIntervalID = null;
- }
- this.unrenderNowIndicator();
- this.isNowIndicatorRendered = false;
- }
- },
-
-
-
- updateSize: function(isResize) {
- var scroll;
- if (isResize) {
- scroll = this.queryScroll();
- }
- this.updateHeight(isResize);
- this.updateWidth(isResize);
- this.updateNowIndicator();
- if (isResize) {
- this.applyScroll(scroll);
- }
- },
-
- updateWidth: function(isResize) {
-
- },
-
- updateHeight: function(isResize) {
- var calendar = this.calendar;
- this.setHeight(
- calendar.getSuggestedViewHeight(),
- calendar.isHeightAuto()
- );
- },
-
-
- setHeight: function(height, isAuto) {
-
- },
-
- addForcedScroll: function(scroll) {
- this.addScroll(
- $.extend(scroll, { isForced: true })
- );
- },
- addScroll: function(scroll) {
- var queuedScroll = this.queuedScroll || (this.queuedScroll = {});
- if (!queuedScroll.isForced) {
- $.extend(queuedScroll, scroll);
- }
- },
- popScroll: function() {
- this.applyQueuedScroll();
- this.queuedScroll = null;
- },
- applyQueuedScroll: function() {
- if (this.queuedScroll) {
- this.applyScroll(this.queuedScroll);
- }
- },
- queryScroll: function() {
- var scroll = {};
- if (this.isDatesRendered) {
- $.extend(scroll, this.queryDateScroll());
- }
- return scroll;
- },
- applyScroll: function(scroll) {
- if (this.isDatesRendered) {
- this.applyDateScroll(scroll);
- }
- },
- computeInitialDateScroll: function() {
- return {};
- },
- queryDateScroll: function() {
- return {};
- },
- applyDateScroll: function(scroll) {
- ;
- },
-
- freezeHeight: function() {
- this.calendar.freezeContentHeight();
- },
- thawHeight: function() {
- this.calendar.thawContentHeight();
- },
-
-
- executeEventsRender: function(eventsPayload) {
- if (this.renderEvents) {
- this.renderEvents(convertEventsPayloadToLegacyArray(eventsPayload));
- }
- else {
- this.renderEventsPayload(eventsPayload);
- }
- this.isEventsRendered = true;
- this.onEventsRender();
- },
- executeEventsUnrender: function() {
- this.onBeforeEventsUnrender();
- if (this.destroyEvents) {
- this.destroyEvents();
- }
- this.unrenderEvents();
- this.isEventsRendered = false;
- },
-
-
-
- onEventsRender: function() {
- var _this = this;
- var hasSingleHandlers = this.hasPublicHandlers('eventAfterRender');
- if (hasSingleHandlers || this.hasPublicHandlers('eventAfterAllRender')) {
- this.applyScreenState();
- }
- if (hasSingleHandlers) {
- this.getEventSegs().forEach(function(seg) {
- var legacy;
- if (seg.el) {
- legacy = seg.footprint.getEventLegacy();
- _this.publiclyTrigger('eventAfterRender', {
- context: legacy,
- args: [ legacy, seg.el, _this ]
- });
- }
- });
- }
- this.publiclyTrigger('eventAfterAllRender', {
- context: this,
- args: [ this ]
- });
- },
-
- onBeforeEventsUnrender: function() {
- var _this = this;
- if (this.hasPublicHandlers('eventDestroy')) {
- this.applyScreenState();
- this.getEventSegs().forEach(function(seg) {
- var legacy;
- if (seg.el) {
- legacy = seg.footprint.getEventLegacy();
- _this.publiclyTrigger('eventDestroy', {
- context: legacy,
- args: [ legacy, seg.el, _this ]
- });
- }
- });
- }
- },
- applyScreenState: function() {
- this.thawHeight();
- this.freezeHeight();
- this.applyQueuedScroll();
- },
-
-
-
-
- showEventsWithId: function(eventDefId) {
- this.getEventSegs().forEach(function(seg) {
- if (
- seg.footprint.eventDef.id === eventDefId &&
- seg.el
- ) {
- seg.el.css('visibility', '');
- }
- });
- },
-
- hideEventsWithId: function(eventDefId) {
- this.getEventSegs().forEach(function(seg) {
- if (
- seg.footprint.eventDef.id === eventDefId &&
- seg.el
- ) {
- seg.el.css('visibility', 'hidden');
- }
- });
- },
-
- reportEventDrop: function(eventInstance, eventMutation, el, ev) {
- var eventManager = this.calendar.eventManager;
- var undoFunc = eventManager.mutateEventsWithId(
- eventInstance.def.id,
- eventMutation,
- this.calendar
- );
- var dateMutation = eventMutation.dateMutation;
-
- if (dateMutation) {
- eventInstance.dateProfile = dateMutation.buildNewDateProfile(
- eventInstance.dateProfile,
- this.calendar
- );
- }
- this.triggerEventDrop(
- eventInstance,
-
- (dateMutation && dateMutation.dateDelta) || moment.duration(),
- undoFunc,
- el, ev
- );
- },
-
- triggerEventDrop: function(eventInstance, dateDelta, undoFunc, el, ev) {
- this.publiclyTrigger('eventDrop', {
- context: el[0],
- args: [
- eventInstance.toLegacy(),
- dateDelta,
- undoFunc,
- ev,
- {},
- this
- ]
- });
- },
-
-
-
-
- reportExternalDrop: function(singleEventDef, isEvent, isSticky, el, ev, ui) {
- if (isEvent) {
- this.calendar.eventManager.addEventDef(singleEventDef, isSticky);
- }
- this.triggerExternalDrop(singleEventDef, isEvent, el, ev, ui);
- },
-
- triggerExternalDrop: function(singleEventDef, isEvent, el, ev, ui) {
-
- this.publiclyTrigger('drop', {
- context: el[0],
- args: [
- singleEventDef.dateProfile.start.clone(),
- ev,
- ui,
- this
- ]
- });
- if (isEvent) {
-
- this.publiclyTrigger('eventReceive', {
- context: this,
- args: [
- singleEventDef.buildInstance().toLegacy(),
- this
- ]
- });
- }
- },
-
-
- reportEventResize: function(eventInstance, eventMutation, el, ev) {
- var eventManager = this.calendar.eventManager;
- var undoFunc = eventManager.mutateEventsWithId(
- eventInstance.def.id,
- eventMutation,
- this.calendar
- );
-
- eventInstance.dateProfile = eventMutation.dateMutation.buildNewDateProfile(
- eventInstance.dateProfile,
- this.calendar
- );
- this.triggerEventResize(
- eventInstance,
- eventMutation.dateMutation.endDelta,
- undoFunc,
- el, ev
- );
- },
-
- triggerEventResize: function(eventInstance, durationDelta, undoFunc, el, ev) {
- this.publiclyTrigger('eventResize', {
- context: el[0],
- args: [
- eventInstance.toLegacy(),
- durationDelta,
- undoFunc,
- ev,
- {},
- this
- ]
- });
- },
-
-
-
- select: function(footprint, ev) {
- this.unselect(ev);
- this.renderSelectionFootprint(footprint);
- this.reportSelection(footprint, ev);
- },
- renderSelectionFootprint: function(footprint, ev) {
- if (this.renderSelection) {
- this.renderSelection(
- footprint.toLegacy(this.calendar)
- );
- }
- else {
- ChronoComponent.prototype.renderSelectionFootprint.apply(this, arguments);
- }
- },
-
- reportSelection: function(footprint, ev) {
- this.isSelected = true;
- this.triggerSelect(footprint, ev);
- },
-
- triggerSelect: function(footprint, ev) {
- var dateProfile = this.calendar.footprintToDateProfile(footprint);
- this.publiclyTrigger('select', {
- context: this,
- args: [
- dateProfile.start,
- dateProfile.end,
- ev,
- this
- ]
- });
- },
-
-
- unselect: function(ev) {
- if (this.isSelected) {
- this.isSelected = false;
- if (this.destroySelection) {
- this.destroySelection();
- }
- this.unrenderSelection();
- this.publiclyTrigger('unselect', {
- context: this,
- args: [ ev, this ]
- });
- }
- },
-
- selectEventInstance: function(eventInstance) {
- if (
- !this.selectedEventInstance ||
- this.selectedEventInstance !== eventInstance
- ) {
- this.unselectEventInstance();
- this.getEventSegs().forEach(function(seg) {
- if (
- seg.footprint.eventInstance === eventInstance &&
- seg.el
- ) {
- seg.el.addClass('fc-selected');
- }
- });
- this.selectedEventInstance = eventInstance;
- }
- },
- unselectEventInstance: function() {
- if (this.selectedEventInstance) {
- this.getEventSegs().forEach(function(seg) {
- if (seg.el) {
- seg.el.removeClass('fc-selected');
- }
- });
- this.selectedEventInstance = null;
- }
- },
- isEventDefSelected: function(eventDef) {
-
-
- return this.selectedEventInstance && this.selectedEventInstance.def.id === eventDef.id;
- },
-
-
-
- handleDocumentMousedown: function(ev) {
- if (isPrimaryMouseButton(ev)) {
- this.processUnselect(ev);
- }
- },
- processUnselect: function(ev) {
- this.processRangeUnselect(ev);
- this.processEventUnselect(ev);
- },
- processRangeUnselect: function(ev) {
- var ignore;
-
- if (this.isSelected && this.opt('unselectAuto')) {
-
- ignore = this.opt('unselectCancel');
- if (!ignore || !$(ev.target).closest(ignore).length) {
- this.unselect(ev);
- }
- }
- },
- processEventUnselect: function(ev) {
- if (this.selectedEventInstance) {
- if (!$(ev.target).closest('.fc-selected').length) {
- this.unselectEventInstance();
- }
- }
- },
-
-
-
- triggerDayClick: function(footprint, dayEl, ev) {
- var dateProfile = this.calendar.footprintToDateProfile(footprint);
- this.publiclyTrigger('dayClick', {
- context: dayEl,
- args: [ dateProfile.start, ev, this ]
- });
- }
- });
- View.watch('displayingDates', [ 'dateProfile' ], function(deps) {
- this.requestDateRender(deps.dateProfile);
- }, function() {
- this.requestDateUnrender();
- });
- View.watch('initialEvents', [ 'dateProfile' ], function(deps) {
- return this.fetchInitialEvents(deps.dateProfile);
- });
- View.watch('bindingEvents', [ 'initialEvents' ], function(deps) {
- this.setEvents(deps.initialEvents);
- this.bindEventChanges();
- }, function() {
- this.unbindEventChanges();
- this.unsetEvents();
- });
- View.watch('displayingEvents', [ 'displayingDates', 'hasEvents' ], function() {
- this.requestEventsRender(this.get('currentEvents'));
- }, function() {
- this.requestEventsUnrender();
- });
- function convertEventsPayloadToLegacyArray(eventsPayload) {
- var legacyEvents = [];
- var id;
- var eventInstances;
- var i;
- for (id in eventsPayload) {
- eventInstances = eventsPayload[id].eventInstances;
- for (i = 0; i < eventInstances.length; i++) {
- legacyEvents.push(
- eventInstances[i].toLegacy()
- );
- }
- }
- return legacyEvents;
- }
- ;;
- View.mixin({
-
-
- currentUnzonedRange: null,
- currentRangeUnit: null,
- isRangeAllDay: false,
-
-
- renderUnzonedRange: null,
-
- activeUnzonedRange: null,
-
-
- validUnzonedRange: null,
-
- dateIncrement: null,
- minTime: null,
- maxTime: null,
- usesMinMaxTime: false,
-
- start: null,
- end: null,
- intervalStart: null,
- intervalEnd: null,
-
- setDateProfileForRendering: function(dateProfile) {
- var calendar = this.calendar;
- this.currentUnzonedRange = dateProfile.currentUnzonedRange;
- this.currentRangeUnit = dateProfile.currentRangeUnit;
- this.isRangeAllDay = dateProfile.isRangeAllDay;
- this.renderUnzonedRange = dateProfile.renderUnzonedRange;
- this.activeUnzonedRange = dateProfile.activeUnzonedRange;
- this.validUnzonedRange = dateProfile.validUnzonedRange;
- this.dateIncrement = dateProfile.dateIncrement;
- this.minTime = dateProfile.minTime;
- this.maxTime = dateProfile.maxTime;
-
- this.start = calendar.msToMoment(dateProfile.activeUnzonedRange.startMs, this.isRangeAllDay);
- this.end = calendar.msToMoment(dateProfile.activeUnzonedRange.endMs, this.isRangeAllDay);
- this.intervalStart = calendar.msToMoment(dateProfile.currentUnzonedRange.startMs, this.isRangeAllDay);
- this.intervalEnd = calendar.msToMoment(dateProfile.currentUnzonedRange.endMs, this.isRangeAllDay);
- this.title = this.computeTitle();
- this.calendar.reportViewDatesChanged(this, dateProfile);
- },
-
- buildPrevDateProfile: function(date) {
- var prevDate = date.clone().startOf(this.currentRangeUnit).subtract(this.dateIncrement);
- return this.buildDateProfile(prevDate, -1);
- },
-
- buildNextDateProfile: function(date) {
- var nextDate = date.clone().startOf(this.currentRangeUnit).add(this.dateIncrement);
- return this.buildDateProfile(nextDate, 1);
- },
-
-
-
- buildDateProfile: function(date, direction, forceToValid) {
- var isDateAllDay = !date.hasTime();
- var validUnzonedRange = this.buildValidRange();
- var minTime = null;
- var maxTime = null;
- var currentInfo;
- var renderUnzonedRange;
- var activeUnzonedRange;
- var isValid;
- if (forceToValid) {
- date = this.calendar.msToUtcMoment(
- validUnzonedRange.constrainDate(date),
- isDateAllDay
- );
- }
- currentInfo = this.buildCurrentRangeInfo(date, direction);
- renderUnzonedRange = this.buildRenderRange(currentInfo.unzonedRange, currentInfo.unit);
- activeUnzonedRange = renderUnzonedRange.clone();
- if (!this.opt('showNonCurrentDates')) {
- activeUnzonedRange = activeUnzonedRange.intersect(currentInfo.unzonedRange);
- }
- minTime = moment.duration(this.opt('minTime'));
- maxTime = moment.duration(this.opt('maxTime'));
- activeUnzonedRange = this.adjustActiveRange(activeUnzonedRange, minTime, maxTime);
- activeUnzonedRange = activeUnzonedRange.intersect(validUnzonedRange);
- if (activeUnzonedRange) {
- date = this.calendar.msToUtcMoment(
- activeUnzonedRange.constrainDate(date),
- isDateAllDay
- );
- }
-
-
- isValid = currentInfo.unzonedRange.intersectsWith(validUnzonedRange);
- return {
- validUnzonedRange: validUnzonedRange,
- currentUnzonedRange: currentInfo.unzonedRange,
- currentRangeUnit: currentInfo.unit,
- isRangeAllDay: /^(year|month|week|day)$/.test(currentInfo.unit),
- activeUnzonedRange: activeUnzonedRange,
- renderUnzonedRange: renderUnzonedRange,
- minTime: minTime,
- maxTime: maxTime,
- isValid: isValid,
- date: date,
- dateIncrement: this.buildDateIncrement(currentInfo.duration)
-
- };
- },
-
-
- buildValidRange: function() {
- return this.getUnzonedRangeOption('validRange', this.calendar.getNow()) ||
- new UnzonedRange();
- },
-
-
-
-
-
- buildCurrentRangeInfo: function(date, direction) {
- var duration = null;
- var unit = null;
- var unzonedRange = null;
- var dayCount;
- if (this.viewSpec.duration) {
- duration = this.viewSpec.duration;
- unit = this.viewSpec.durationUnit;
- unzonedRange = this.buildRangeFromDuration(date, direction, duration, unit);
- }
- else if ((dayCount = this.opt('dayCount'))) {
- unit = 'day';
- unzonedRange = this.buildRangeFromDayCount(date, direction, dayCount);
- }
- else if ((unzonedRange = this.buildCustomVisibleRange(date))) {
- unit = computeGreatestUnit(unzonedRange.getStart(), unzonedRange.getEnd());
- }
- else {
- duration = this.getFallbackDuration();
- unit = computeGreatestUnit(duration);
- unzonedRange = this.buildRangeFromDuration(date, direction, duration, unit);
- }
- return { duration: duration, unit: unit, unzonedRange: unzonedRange };
- },
- getFallbackDuration: function() {
- return moment.duration({ days: 1 });
- },
-
-
- adjustActiveRange: function(unzonedRange, minTime, maxTime) {
- var start = unzonedRange.getStart();
- var end = unzonedRange.getEnd();
- if (this.usesMinMaxTime) {
- if (minTime < 0) {
- start.time(0).add(minTime);
- }
- if (maxTime > 24 * 60 * 60 * 1000) {
- end.time(maxTime - (24 * 60 * 60 * 1000));
- }
- }
- return new UnzonedRange(start, end);
- },
-
-
-
- buildRangeFromDuration: function(date, direction, duration, unit) {
- var alignment = this.opt('dateAlignment');
- var start = date.clone();
- var end;
- var dateIncrementInput;
- var dateIncrementDuration;
-
- if (duration.as('days') <= 1) {
- if (this.isHiddenDay(start)) {
- start = this.skipHiddenDays(start, direction);
- start.startOf('day');
- }
- }
-
- if (!alignment) {
- dateIncrementInput = this.opt('dateIncrement');
- if (dateIncrementInput) {
- dateIncrementDuration = moment.duration(dateIncrementInput);
-
- if (dateIncrementDuration < duration) {
- alignment = computeDurationGreatestUnit(dateIncrementDuration, dateIncrementInput);
- }
- else {
- alignment = unit;
- }
- }
- else {
- alignment = unit;
- }
- }
- start.startOf(alignment);
- end = start.clone().add(duration);
- return new UnzonedRange(start, end);
- },
-
-
- buildRangeFromDayCount: function(date, direction, dayCount) {
- var customAlignment = this.opt('dateAlignment');
- var runningCount = 0;
- var start = date.clone();
- var end;
- if (customAlignment) {
- start.startOf(customAlignment);
- }
- start.startOf('day');
- start = this.skipHiddenDays(start, direction);
- end = start.clone();
- do {
- end.add(1, 'day');
- if (!this.isHiddenDay(end)) {
- runningCount++;
- }
- } while (runningCount < dayCount);
- return new UnzonedRange(start, end);
- },
-
-
-
- buildCustomVisibleRange: function(date) {
- var visibleUnzonedRange = this.getUnzonedRangeOption(
- 'visibleRange',
- this.calendar.applyTimezone(date)
- );
- if (visibleUnzonedRange && (visibleUnzonedRange.startMs === null || visibleUnzonedRange.endMs === null)) {
- return null;
- }
- return visibleUnzonedRange;
- },
-
-
- buildRenderRange: function(currentUnzonedRange, currentRangeUnit) {
-
- return this.trimHiddenDays(currentUnzonedRange);
- },
-
-
- buildDateIncrement: function(fallback) {
- var dateIncrementInput = this.opt('dateIncrement');
- var customAlignment;
- if (dateIncrementInput) {
- return moment.duration(dateIncrementInput);
- }
- else if ((customAlignment = this.opt('dateAlignment'))) {
- return moment.duration(1, customAlignment);
- }
- else if (fallback) {
- return fallback;
- }
- else {
- return moment.duration({ days: 1 });
- }
- },
-
- trimHiddenDays: function(inputUnzonedRange) {
- var start = inputUnzonedRange.getStart();
- var end = inputUnzonedRange.getEnd();
- start = this.skipHiddenDays(start);
- end = this.skipHiddenDays(end, -1, true);
- return new UnzonedRange(start, end);
- },
-
-
- currentRangeAs: function(unit) {
- var currentUnzonedRange = this.currentUnzonedRange;
- return moment.utc(currentUnzonedRange.endMs).diff(
- moment.utc(currentUnzonedRange.startMs),
- unit,
- true
- );
- },
-
- isDateInOtherMonth: function(date) {
- return false;
- },
-
-
-
- getUnzonedRangeOption: function(name) {
- var val = this.opt(name);
- if (typeof val === 'function') {
- val = val.apply(
- null,
- Array.prototype.slice.call(arguments, 1)
- );
- }
- if (val) {
- return this.calendar.parseUnzonedRange(val);
- }
- },
-
-
- initHiddenDays: function() {
- var hiddenDays = this.opt('hiddenDays') || [];
- var isHiddenDayHash = [];
- var dayCnt = 0;
- var i;
- if (this.opt('weekends') === false) {
- hiddenDays.push(0, 6);
- }
- for (i = 0; i < 7; i++) {
- if (
- !(isHiddenDayHash[i] = $.inArray(i, hiddenDays) !== -1)
- ) {
- dayCnt++;
- }
- }
- if (!dayCnt) {
- throw 'invalid hiddenDays';
- }
- this.isHiddenDayHash = isHiddenDayHash;
- },
-
-
- isHiddenDay: function(day) {
- if (moment.isMoment(day)) {
- day = day.day();
- }
- return this.isHiddenDayHash[day];
- },
-
-
-
-
-
- skipHiddenDays: function(date, inc, isExclusive) {
- var out = date.clone();
- inc = inc || 1;
- while (
- this.isHiddenDayHash[(out.day() + (isExclusive ? inc : 0) + 7) % 7]
- ) {
- out.add(inc, 'days');
- }
- return out;
- }
- });
- ;;
- var Scroller = FC.Scroller = Class.extend({
- el: null,
- scrollEl: null,
- overflowX: null,
- overflowY: null,
- constructor: function(options) {
- options = options || {};
- this.overflowX = options.overflowX || options.overflow || 'auto';
- this.overflowY = options.overflowY || options.overflow || 'auto';
- },
- render: function() {
- this.el = this.renderEl();
- this.applyOverflow();
- },
- renderEl: function() {
- return (this.scrollEl = $('<div class="fc-scroller"></div>'));
- },
-
- clear: function() {
- this.setHeight('auto');
- this.applyOverflow();
- },
- destroy: function() {
- this.el.remove();
- },
-
-
- applyOverflow: function() {
- this.scrollEl.css({
- 'overflow-x': this.overflowX,
- 'overflow-y': this.overflowY
- });
- },
-
-
-
- lockOverflow: function(scrollbarWidths) {
- var overflowX = this.overflowX;
- var overflowY = this.overflowY;
- scrollbarWidths = scrollbarWidths || this.getScrollbarWidths();
- if (overflowX === 'auto') {
- overflowX = (
- scrollbarWidths.top || scrollbarWidths.bottom ||
-
- this.scrollEl[0].scrollWidth - 1 > this.scrollEl[0].clientWidth
-
- ) ? 'scroll' : 'hidden';
- }
- if (overflowY === 'auto') {
- overflowY = (
- scrollbarWidths.left || scrollbarWidths.right ||
-
- this.scrollEl[0].scrollHeight - 1 > this.scrollEl[0].clientHeight
-
- ) ? 'scroll' : 'hidden';
- }
- this.scrollEl.css({ 'overflow-x': overflowX, 'overflow-y': overflowY });
- },
-
-
- setHeight: function(height) {
- this.scrollEl.height(height);
- },
- getScrollTop: function() {
- return this.scrollEl.scrollTop();
- },
- setScrollTop: function(top) {
- this.scrollEl.scrollTop(top);
- },
- getClientWidth: function() {
- return this.scrollEl[0].clientWidth;
- },
- getClientHeight: function() {
- return this.scrollEl[0].clientHeight;
- },
- getScrollbarWidths: function() {
- return getScrollbarWidths(this.scrollEl);
- }
- });
- ;;
- function Iterator(items) {
- this.items = items || [];
- }
- Iterator.prototype.proxyCall = function(methodName) {
- var args = Array.prototype.slice.call(arguments, 1);
- var results = [];
- this.items.forEach(function(item) {
- results.push(item[methodName].apply(item, args));
- });
- return results;
- };
- ;;
- function Toolbar(calendar, toolbarOptions) {
- var t = this;
-
- t.setToolbarOptions = setToolbarOptions;
- t.render = render;
- t.removeElement = removeElement;
- t.updateTitle = updateTitle;
- t.activateButton = activateButton;
- t.deactivateButton = deactivateButton;
- t.disableButton = disableButton;
- t.enableButton = enableButton;
- t.getViewsWithButtons = getViewsWithButtons;
- t.el = null;
-
- var el;
- var viewsWithButtons = [];
-
- function setToolbarOptions(newToolbarOptions) {
- toolbarOptions = newToolbarOptions;
- }
-
- function render() {
- var sections = toolbarOptions.layout;
- if (sections) {
- if (!el) {
- el = this.el = $("<div class='fc-toolbar "+ toolbarOptions.extraClasses + "'/>");
- }
- else {
- el.empty();
- }
- el.append(renderSection('left'))
- .append(renderSection('right'))
- .append(renderSection('center'))
- .append('<div class="fc-clear"/>');
- }
- else {
- removeElement();
- }
- }
- function removeElement() {
- if (el) {
- el.remove();
- el = t.el = null;
- }
- }
- function renderSection(position) {
- var theme = calendar.theme;
- var sectionEl = $('<div class="fc-' + position + '"/>');
- var buttonStr = toolbarOptions.layout[position];
- var calendarCustomButtons = calendar.opt('customButtons') || {};
- var calendarButtonTextOverrides = calendar.overrides.buttonText || {};
- var calendarButtonText = calendar.opt('buttonText') || {};
- if (buttonStr) {
- $.each(buttonStr.split(' '), function(i) {
- var groupChildren = $();
- var isOnlyButtons = true;
- var groupEl;
- $.each(this.split(','), function(j, buttonName) {
- var customButtonProps;
- var viewSpec;
- var buttonClick;
- var buttonIcon;
- var buttonText;
- var buttonInnerHtml;
- var buttonClasses;
- var buttonEl;
- if (buttonName == 'title') {
- groupChildren = groupChildren.add($('<h2> </h2>'));
- isOnlyButtons = false;
- }
- else {
- if ((customButtonProps = calendarCustomButtons[buttonName])) {
- buttonClick = function(ev) {
- if (customButtonProps.click) {
- customButtonProps.click.call(buttonEl[0], ev);
- }
- };
- (buttonIcon = theme.getCustomButtonIconClass(customButtonProps)) ||
- (buttonIcon = theme.getIconClass(buttonName)) ||
- (buttonText = customButtonProps.text);
- }
- else if ((viewSpec = calendar.getViewSpec(buttonName))) {
- viewsWithButtons.push(buttonName);
- buttonClick = function() {
- calendar.changeView(buttonName);
- };
- (buttonText = viewSpec.buttonTextOverride) ||
- (buttonIcon = theme.getIconClass(buttonName)) ||
- (buttonText = viewSpec.buttonTextDefault);
- }
- else if (calendar[buttonName]) {
- buttonClick = function() {
- calendar[buttonName]();
- };
- (buttonText = calendarButtonTextOverrides[buttonName]) ||
- (buttonIcon = theme.getIconClass(buttonName)) ||
- (buttonText = calendarButtonText[buttonName]);
-
- }
- if (buttonClick) {
- buttonClasses = [
- 'fc-' + buttonName + '-button',
- theme.getClass('button'),
- theme.getClass('stateDefault')
- ];
- if (buttonText) {
- buttonInnerHtml = htmlEscape(buttonText);
- }
- else if (buttonIcon) {
- buttonInnerHtml = "<span class='" + buttonIcon + "'></span>";
- }
- buttonEl = $(
- '<button type="button" class="' + buttonClasses.join(' ') + '">' +
- buttonInnerHtml +
- '</button>'
- )
- .click(function(ev) {
-
- if (!buttonEl.hasClass(theme.getClass('stateDisabled'))) {
- buttonClick(ev);
-
-
- if (
- buttonEl.hasClass(theme.getClass('stateActive')) ||
- buttonEl.hasClass(theme.getClass('stateDisabled'))
- ) {
- buttonEl.removeClass(theme.getClass('stateHover'));
- }
- }
- })
- .mousedown(function() {
-
-
- buttonEl
- .not('.' + theme.getClass('stateActive'))
- .not('.' + theme.getClass('stateDisabled'))
- .addClass(theme.getClass('stateDown'));
- })
- .mouseup(function() {
-
- buttonEl.removeClass(theme.getClass('stateDown'));
- })
- .hover(
- function() {
-
-
- buttonEl
- .not('.' + theme.getClass('stateActive'))
- .not('.' + theme.getClass('stateDisabled'))
- .addClass(theme.getClass('stateHover'));
- },
- function() {
-
- buttonEl
- .removeClass(theme.getClass('stateHover'))
- .removeClass(theme.getClass('stateDown'));
- }
- );
- groupChildren = groupChildren.add(buttonEl);
- }
- }
- });
- if (isOnlyButtons) {
- groupChildren
- .first().addClass(theme.getClass('cornerLeft')).end()
- .last().addClass(theme.getClass('cornerRight')).end();
- }
- if (groupChildren.length > 1) {
- groupEl = $('<div/>');
- if (isOnlyButtons) {
- groupEl.addClass(theme.getClass('buttonGroup'));
- }
- groupEl.append(groupChildren);
- sectionEl.append(groupEl);
- }
- else {
- sectionEl.append(groupChildren);
- }
- });
- }
- return sectionEl;
- }
- function updateTitle(text) {
- if (el) {
- el.find('h2').text(text);
- }
- }
- function activateButton(buttonName) {
- if (el) {
- el.find('.fc-' + buttonName + '-button')
- .addClass(calendar.theme.getClass('stateActive'));
- }
- }
- function deactivateButton(buttonName) {
- if (el) {
- el.find('.fc-' + buttonName + '-button')
- .removeClass(calendar.theme.getClass('stateActive'));
- }
- }
- function disableButton(buttonName) {
- if (el) {
- el.find('.fc-' + buttonName + '-button')
- .prop('disabled', true)
- .addClass(calendar.theme.getClass('stateDisabled'));
- }
- }
- function enableButton(buttonName) {
- if (el) {
- el.find('.fc-' + buttonName + '-button')
- .prop('disabled', false)
- .removeClass(calendar.theme.getClass('stateDisabled'));
- }
- }
- function getViewsWithButtons() {
- return viewsWithButtons;
- }
- }
- ;;
- var Calendar = FC.Calendar = Class.extend(EmitterMixin, {
- view: null,
- viewsByType: null,
- currentDate: null,
- theme: null,
- loadingLevel: 0,
- constructor: function(el, overrides) {
-
-
- GlobalEmitter.needed();
- this.el = el;
- this.viewsByType = {};
- this.viewSpecCache = {};
- this.initOptionsInternals(overrides);
- this.initMomentInternals();
- this.initCurrentDate();
- this.initEventManager();
- EventManager.call(this);
- this.initialize();
- },
-
- initialize: function() {
- },
-
-
- getView: function() {
- return this.view;
- },
- publiclyTrigger: function(name, triggerInfo) {
- var optHandler = this.opt(name);
- var context;
- var args;
- if ($.isPlainObject(triggerInfo)) {
- context = triggerInfo.context;
- args = triggerInfo.args;
- }
- else if ($.isArray(triggerInfo)) {
- args = triggerInfo;
- }
- if (context == null) {
- context = this.el[0];
- }
- if (!args) {
- args = [];
- }
- this.triggerWith(name, context, args);
- if (optHandler) {
- return optHandler.apply(context, args);
- }
- },
- hasPublicHandlers: function(name) {
- return this.hasHandlers(name) ||
- this.opt(name);
- },
-
-
-
- instantiateView: function(viewType) {
- var spec = this.getViewSpec(viewType);
- return new spec['class'](this, spec);
- },
-
- isValidViewType: function(viewType) {
- return Boolean(this.getViewSpec(viewType));
- },
- changeView: function(viewName, dateOrRange) {
- if (dateOrRange) {
- if (dateOrRange.start && dateOrRange.end) {
- this.recordOptionOverrides({
- visibleRange: dateOrRange
- });
- }
- else {
- this.currentDate = this.moment(dateOrRange).stripZone();
- }
- }
- this.renderView(viewName);
- },
-
-
- zoomTo: function(newDate, viewType) {
- var spec;
- viewType = viewType || 'day';
- spec = this.getViewSpec(viewType) || this.getUnitViewSpec(viewType);
- this.currentDate = newDate.clone();
- this.renderView(spec ? spec.type : null);
- },
-
-
- initCurrentDate: function() {
- var defaultDateInput = this.opt('defaultDate');
-
- if (defaultDateInput != null) {
- this.currentDate = this.moment(defaultDateInput).stripZone();
- }
- else {
- this.currentDate = this.getNow();
- }
- },
- reportViewDatesChanged: function(view, dateProfile) {
- this.currentDate = dateProfile.date;
- this.setToolbarsTitle(view.title);
- this.updateToolbarButtons();
- },
- prev: function() {
- var prevInfo = this.view.buildPrevDateProfile(this.currentDate);
- if (prevInfo.isValid) {
- this.currentDate = prevInfo.date;
- this.renderView();
- }
- },
- next: function() {
- var nextInfo = this.view.buildNextDateProfile(this.currentDate);
- if (nextInfo.isValid) {
- this.currentDate = nextInfo.date;
- this.renderView();
- }
- },
- prevYear: function() {
- this.currentDate.add(-1, 'years');
- this.renderView();
- },
- nextYear: function() {
- this.currentDate.add(1, 'years');
- this.renderView();
- },
- today: function() {
- this.currentDate = this.getNow();
- this.renderView();
- },
- gotoDate: function(zonedDateInput) {
- this.currentDate = this.moment(zonedDateInput).stripZone();
- this.renderView();
- },
- incrementDate: function(delta) {
- this.currentDate.add(moment.duration(delta));
- this.renderView();
- },
-
- getDate: function() {
- return this.applyTimezone(this.currentDate);
- },
-
-
-
- pushLoading: function() {
- if (!(this.loadingLevel++)) {
- this.publiclyTrigger('loading', [ true, this.view ]);
- }
- },
-
- popLoading: function() {
- if (!(--this.loadingLevel)) {
- this.publiclyTrigger('loading', [ false, this.view ]);
- }
- },
-
-
-
- select: function(zonedStartInput, zonedEndInput) {
- this.view.select(
- this.buildSelectFootprint.apply(this, arguments)
- );
- },
- unselect: function() {
- if (this.view) {
- this.view.unselect();
- }
- },
-
- buildSelectFootprint: function(zonedStartInput, zonedEndInput) {
- var start = this.moment(zonedStartInput).stripZone();
- var end;
- if (zonedEndInput) {
- end = this.moment(zonedEndInput).stripZone();
- }
- else if (start.hasTime()) {
- end = start.clone().add(this.defaultTimedEventDuration);
- }
- else {
- end = start.clone().add(this.defaultAllDayEventDuration);
- }
- return new ComponentFootprint(
- new UnzonedRange(start, end),
- !start.hasTime()
- );
- },
-
-
-
- parseUnzonedRange: function(rangeInput) {
- var start = null;
- var end = null;
- if (rangeInput.start) {
- start = this.moment(rangeInput.start).stripZone();
- }
- if (rangeInput.end) {
- end = this.moment(rangeInput.end).stripZone();
- }
- if (!start && !end) {
- return null;
- }
- if (start && end && end.isBefore(start)) {
- return null;
- }
- return new UnzonedRange(start, end);
- },
- rerenderEvents: function() {
- if (this.elementVisible()) {
- this.view.flash('displayingEvents');
- }
- },
- initEventManager: function() {
- var _this = this;
- var eventManager = new EventManager(this);
- var rawSources = this.opt('eventSources') || [];
- var singleRawSource = this.opt('events');
- this.eventManager = eventManager;
- if (singleRawSource) {
- rawSources.unshift(singleRawSource);
- }
- eventManager.on('release', function(eventsPayload) {
- _this.trigger('eventsReset', eventsPayload);
- });
- eventManager.freeze();
- rawSources.forEach(function(rawSource) {
- var source = EventSourceParser.parse(rawSource, _this);
- if (source) {
- eventManager.addSource(source);
- }
- });
- eventManager.thaw();
- },
- requestEvents: function(start, end) {
- return this.eventManager.requestEvents(
- start,
- end,
- this.opt('timezone'),
- !this.opt('lazyFetching')
- );
- }
- });
- ;;
- Calendar.mixin({
- dirDefaults: null,
- localeDefaults: null,
- overrides: null,
- dynamicOverrides: null,
- optionsModel: null,
- initOptionsInternals: function(overrides) {
- this.overrides = $.extend({}, overrides);
- this.dynamicOverrides = {};
- this.optionsModel = new Model();
- this.populateOptionsHash();
- },
-
- option: function(name, value) {
- var newOptionHash;
- if (typeof name === 'string') {
- if (value === undefined) {
- return this.optionsModel.get(name);
- }
- else {
- newOptionHash = {};
- newOptionHash[name] = value;
- this.setOptions(newOptionHash);
- }
- }
- else if (typeof name === 'object') {
- this.setOptions(name);
- }
- },
-
- opt: function(name) {
- return this.optionsModel.get(name);
- },
- setOptions: function(newOptionHash) {
- var optionCnt = 0;
- var optionName;
- this.recordOptionOverrides(newOptionHash);
- for (optionName in newOptionHash) {
- optionCnt++;
- }
-
-
- if (optionCnt === 1) {
- if (optionName === 'height' || optionName === 'contentHeight' || optionName === 'aspectRatio') {
- this.updateSize(true);
- return;
- }
- else if (optionName === 'defaultDate') {
- return;
- }
- else if (optionName === 'businessHours') {
- if (this.view) {
- this.view.unrenderBusinessHours();
- this.view.renderBusinessHours();
- }
- return;
- }
- else if (optionName === 'timezone') {
- this.view.flash('initialEvents');
- return;
- }
- }
-
- this.renderHeader();
- this.renderFooter();
-
-
- this.viewsByType = {};
- this.reinitView();
- },
-
-
- populateOptionsHash: function() {
- var locale, localeDefaults;
- var isRTL, dirDefaults;
- var rawOptions;
- locale = firstDefined(
- this.dynamicOverrides.locale,
- this.overrides.locale
- );
- localeDefaults = localeOptionHash[locale];
- if (!localeDefaults) {
- locale = Calendar.defaults.locale;
- localeDefaults = localeOptionHash[locale] || {};
- }
- isRTL = firstDefined(
- this.dynamicOverrides.isRTL,
- this.overrides.isRTL,
- localeDefaults.isRTL,
- Calendar.defaults.isRTL
- );
- dirDefaults = isRTL ? Calendar.rtlDefaults : {};
- this.dirDefaults = dirDefaults;
- this.localeDefaults = localeDefaults;
- rawOptions = mergeOptions([
- Calendar.defaults,
- dirDefaults,
- localeDefaults,
- this.overrides,
- this.dynamicOverrides
- ]);
- populateInstanceComputableOptions(rawOptions);
- this.optionsModel.reset(rawOptions);
- },
-
- recordOptionOverrides: function(newOptionHash) {
- var optionName;
- for (optionName in newOptionHash) {
- this.dynamicOverrides[optionName] = newOptionHash[optionName];
- }
- this.viewSpecCache = {};
- this.populateOptionsHash();
- }
- });
- ;;
- Calendar.mixin({
- defaultAllDayEventDuration: null,
- defaultTimedEventDuration: null,
- localeData: null,
- initMomentInternals: function() {
- var _this = this;
- this.defaultAllDayEventDuration = moment.duration(this.opt('defaultAllDayEventDuration'));
- this.defaultTimedEventDuration = moment.duration(this.opt('defaultTimedEventDuration'));
-
-
- this.optionsModel.watch('buildingMomentLocale', [
- '?locale', '?monthNames', '?monthNamesShort', '?dayNames', '?dayNamesShort',
- '?firstDay', '?weekNumberCalculation'
- ], function(opts) {
- var weekNumberCalculation = opts.weekNumberCalculation;
- var firstDay = opts.firstDay;
- var _week;
-
- if (weekNumberCalculation === 'iso') {
- weekNumberCalculation = 'ISO';
- }
- var localeData = Object.create(
- getMomentLocaleData(opts.locale)
- );
- if (opts.monthNames) {
- localeData._months = opts.monthNames;
- }
- if (opts.monthNamesShort) {
- localeData._monthsShort = opts.monthNamesShort;
- }
- if (opts.dayNames) {
- localeData._weekdays = opts.dayNames;
- }
- if (opts.dayNamesShort) {
- localeData._weekdaysShort = opts.dayNamesShort;
- }
- if (firstDay == null && weekNumberCalculation === 'ISO') {
- firstDay = 1;
- }
- if (firstDay != null) {
- _week = Object.create(localeData._week);
- _week.dow = firstDay;
- localeData._week = _week;
- }
- if (
- weekNumberCalculation === 'ISO' ||
- weekNumberCalculation === 'local' ||
- typeof weekNumberCalculation === 'function'
- ) {
- localeData._fullCalendar_weekCalc = weekNumberCalculation;
- }
- _this.localeData = localeData;
-
-
- if (_this.currentDate) {
- _this.localizeMoment(_this.currentDate);
- }
- });
- },
-
-
- moment: function() {
- var mom;
- if (this.opt('timezone') === 'local') {
- mom = FC.moment.apply(null, arguments);
-
- if (mom.hasTime()) {
- mom.local();
- }
- }
- else if (this.opt('timezone') === 'UTC') {
- mom = FC.moment.utc.apply(null, arguments);
- }
- else {
- mom = FC.moment.parseZone.apply(null, arguments);
- }
- this.localizeMoment(mom);
- return mom;
- },
- msToMoment: function(ms, forceAllDay) {
- var mom = FC.moment.utc(ms);
- if (forceAllDay) {
- mom.stripTime();
- }
- else {
- mom = this.applyTimezone(mom);
- }
- this.localizeMoment(mom);
- return mom;
- },
- msToUtcMoment: function(ms, forceAllDay) {
- var mom = FC.moment.utc(ms);
- if (forceAllDay) {
- mom.stripTime();
- }
- this.localizeMoment(mom);
- return mom;
- },
-
- localizeMoment: function(mom) {
- mom._locale = this.localeData;
- },
-
-
- getIsAmbigTimezone: function() {
- return this.opt('timezone') !== 'local' && this.opt('timezone') !== 'UTC';
- },
-
- applyTimezone: function(date) {
- if (!date.hasTime()) {
- return date.clone();
- }
- var zonedDate = this.moment(date.toArray());
- var timeAdjust = date.time() - zonedDate.time();
- var adjustedZonedDate;
-
- if (timeAdjust) {
- adjustedZonedDate = zonedDate.clone().add(timeAdjust);
- if (date.time() - adjustedZonedDate.time() === 0) {
- zonedDate = adjustedZonedDate;
- }
- }
- return zonedDate;
- },
-
- footprintToDateProfile: function(componentFootprint, ignoreEnd) {
- var start = FC.moment.utc(componentFootprint.unzonedRange.startMs);
- var end;
- if (!ignoreEnd) {
- end = FC.moment.utc(componentFootprint.unzonedRange.endMs);
- }
- if (componentFootprint.isAllDay) {
- start.stripTime();
- if (end) {
- end.stripTime();
- }
- }
- else {
- start = this.applyTimezone(start);
- if (end) {
- end = this.applyTimezone(end);
- }
- }
- return new EventDateProfile(start, end, this);
- },
-
-
- getNow: function() {
- var now = this.opt('now');
- if (typeof now === 'function') {
- now = now();
- }
- return this.moment(now).stripZone();
- },
-
-
- humanizeDuration: function(duration) {
- return duration.locale(this.opt('locale')).humanize();
- },
-
-
-
- getEventEnd: function(event) {
- if (event.end) {
- return event.end.clone();
- }
- else {
- return this.getDefaultEventEnd(event.allDay, event.start);
- }
- },
-
-
- getDefaultEventEnd: function(allDay, zonedStart) {
- var end = zonedStart.clone();
- if (allDay) {
- end.stripTime().add(this.defaultAllDayEventDuration);
- }
- else {
- end.add(this.defaultTimedEventDuration);
- }
- if (this.getIsAmbigTimezone()) {
- end.stripZone();
- }
- return end;
- }
- });
- ;;
- Calendar.mixin({
- viewSpecCache: null,
-
- getViewSpec: function(viewType) {
- var cache = this.viewSpecCache;
- return cache[viewType] || (cache[viewType] = this.buildViewSpec(viewType));
- },
-
-
- getUnitViewSpec: function(unit) {
- var viewTypes;
- var i;
- var spec;
- if ($.inArray(unit, unitsDesc) != -1) {
-
- viewTypes = this.header.getViewsWithButtons();
- $.each(FC.views, function(viewType) {
- viewTypes.push(viewType);
- });
- for (i = 0; i < viewTypes.length; i++) {
- spec = this.getViewSpec(viewTypes[i]);
- if (spec) {
- if (spec.singleUnit == unit) {
- return spec;
- }
- }
- }
- }
- },
-
- buildViewSpec: function(requestedViewType) {
- var viewOverrides = this.overrides.views || {};
- var specChain = [];
- var defaultsChain = [];
- var overridesChain = [];
- var viewType = requestedViewType;
- var spec;
- var overrides;
- var durationInput;
- var duration;
- var unit;
-
- while (viewType) {
- spec = fcViews[viewType];
- overrides = viewOverrides[viewType];
- viewType = null;
- if (typeof spec === 'function') {
- spec = { 'class': spec };
- }
- if (spec) {
- specChain.unshift(spec);
- defaultsChain.unshift(spec.defaults || {});
- durationInput = durationInput || spec.duration;
- viewType = viewType || spec.type;
- }
- if (overrides) {
- overridesChain.unshift(overrides);
- durationInput = durationInput || overrides.duration;
- viewType = viewType || overrides.type;
- }
- }
- spec = mergeProps(specChain);
- spec.type = requestedViewType;
- if (!spec['class']) {
- return false;
- }
-
- durationInput = durationInput ||
- this.dynamicOverrides.duration ||
- this.overrides.duration;
- if (durationInput) {
- duration = moment.duration(durationInput);
- if (duration.valueOf()) {
- unit = computeDurationGreatestUnit(duration, durationInput);
- spec.duration = duration;
- spec.durationUnit = unit;
-
-
- if (duration.as(unit) === 1) {
- spec.singleUnit = unit;
- overridesChain.unshift(viewOverrides[unit] || {});
- }
- }
- }
- spec.defaults = mergeOptions(defaultsChain);
- spec.overrides = mergeOptions(overridesChain);
- this.buildViewSpecOptions(spec);
- this.buildViewSpecButtonText(spec, requestedViewType);
- return spec;
- },
-
- buildViewSpecOptions: function(spec) {
- spec.options = mergeOptions([
- Calendar.defaults,
- spec.defaults,
- this.dirDefaults,
- this.localeDefaults,
- this.overrides,
- spec.overrides,
- this.dynamicOverrides
- ]);
- populateInstanceComputableOptions(spec.options);
- },
-
- buildViewSpecButtonText: function(spec, requestedViewType) {
-
-
- function queryButtonText(options) {
- var buttonText = options.buttonText || {};
- return buttonText[requestedViewType] ||
-
- (spec.buttonTextKey ? buttonText[spec.buttonTextKey] : null) ||
-
- (spec.singleUnit ? buttonText[spec.singleUnit] : null);
- }
-
- spec.buttonTextOverride =
- queryButtonText(this.dynamicOverrides) ||
- queryButtonText(this.overrides) ||
- spec.overrides.buttonText;
-
- spec.buttonTextDefault =
- queryButtonText(this.localeDefaults) ||
- queryButtonText(this.dirDefaults) ||
- spec.defaults.buttonText ||
- queryButtonText(Calendar.defaults) ||
- (spec.duration ? this.humanizeDuration(spec.duration) : null) ||
- requestedViewType;
- }
- });
- ;;
- Calendar.mixin({
- el: null,
- contentEl: null,
- suggestedViewHeight: null,
- windowResizeProxy: null,
- ignoreWindowResize: 0,
- render: function() {
- if (!this.contentEl) {
- this.initialRender();
- }
- else if (this.elementVisible()) {
-
- this.calcSize();
- this.renderView();
- }
- },
- initialRender: function() {
- var _this = this;
- var el = this.el;
- el.addClass('fc');
-
- el.on('click.fc', 'a[data-goto]', function(ev) {
- var anchorEl = $(this);
- var gotoOptions = anchorEl.data('goto');
- var date = _this.moment(gotoOptions.date);
- var viewType = gotoOptions.type;
-
- var customAction = _this.view.opt('navLink' + capitaliseFirstLetter(viewType) + 'Click');
- if (typeof customAction === 'function') {
- customAction(date, ev);
- }
- else {
- if (typeof customAction === 'string') {
- viewType = customAction;
- }
- _this.zoomTo(date, viewType);
- }
- });
-
- this.optionsModel.watch('settingTheme', [ '?theme', '?themeSystem' ], function(opts) {
- var themeClass = ThemeRegistry.getThemeClass(opts.themeSystem || opts.theme);
- var theme = new themeClass(_this.optionsModel);
- var widgetClass = theme.getClass('widget');
- _this.theme = theme;
- if (widgetClass) {
- el.addClass(widgetClass);
- }
- }, function() {
- var widgetClass = _this.theme.getClass('widget');
- _this.theme = null;
- if (widgetClass) {
- el.removeClass(widgetClass);
- }
- });
-
-
- this.optionsModel.watch('applyingDirClasses', [ '?isRTL', '?locale' ], function(opts) {
- el.toggleClass('fc-ltr', !opts.isRTL);
- el.toggleClass('fc-rtl', opts.isRTL);
- });
- this.contentEl = $("<div class='fc-view-container'/>").prependTo(el);
- this.initToolbars();
- this.renderHeader();
- this.renderFooter();
- this.renderView(this.opt('defaultView'));
- if (this.opt('handleWindowResize')) {
- $(window).resize(
- this.windowResizeProxy = debounce(
- this.windowResize.bind(this),
- this.opt('windowResizeDelay')
- )
- );
- }
- },
- destroy: function() {
- if (this.view) {
- this.view.removeElement();
-
-
- }
- this.toolbarsManager.proxyCall('removeElement');
- this.contentEl.remove();
- this.el.removeClass('fc fc-ltr fc-rtl');
-
- this.optionsModel.unwatch('settingTheme');
- this.el.off('.fc');
- if (this.windowResizeProxy) {
- $(window).unbind('resize', this.windowResizeProxy);
- this.windowResizeProxy = null;
- }
- GlobalEmitter.unneeded();
- },
- elementVisible: function() {
- return this.el.is(':visible');
- },
-
-
-
-
-
- renderView: function(viewType, forcedScroll) {
- this.ignoreWindowResize++;
- var needsClearView = this.view && viewType && this.view.type !== viewType;
-
- if (needsClearView) {
- this.freezeContentHeight();
- this.clearView();
- }
-
- if (!this.view && viewType) {
- this.view =
- this.viewsByType[viewType] ||
- (this.viewsByType[viewType] = this.instantiateView(viewType));
- this.view.setElement(
- $("<div class='fc-view fc-" + viewType + "-view' />").appendTo(this.contentEl)
- );
- this.toolbarsManager.proxyCall('activateButton', viewType);
- }
- if (this.view) {
- if (forcedScroll) {
- this.view.addForcedScroll(forcedScroll);
- }
- if (this.elementVisible()) {
- this.view.setDate(this.currentDate);
- }
- }
- if (needsClearView) {
- this.thawContentHeight();
- }
- this.ignoreWindowResize--;
- },
-
-
- clearView: function() {
- this.toolbarsManager.proxyCall('deactivateButton', this.view.type);
- this.view.removeElement();
- this.view = null;
- },
-
-
-
- reinitView: function() {
- this.ignoreWindowResize++;
- this.freezeContentHeight();
- var viewType = this.view.type;
- var scrollState = this.view.queryScroll();
- this.clearView();
- this.calcSize();
- this.renderView(viewType, scrollState);
- this.thawContentHeight();
- this.ignoreWindowResize--;
- },
-
-
- getSuggestedViewHeight: function() {
- if (this.suggestedViewHeight === null) {
- this.calcSize();
- }
- return this.suggestedViewHeight;
- },
- isHeightAuto: function() {
- return this.opt('contentHeight') === 'auto' || this.opt('height') === 'auto';
- },
- updateSize: function(shouldRecalc) {
- if (this.elementVisible()) {
- if (shouldRecalc) {
- this._calcSize();
- }
- this.ignoreWindowResize++;
- this.view.updateSize(true);
- this.ignoreWindowResize--;
- return true;
- }
- },
- calcSize: function() {
- if (this.elementVisible()) {
- this._calcSize();
- }
- },
- _calcSize: function() {
- var contentHeightInput = this.opt('contentHeight');
- var heightInput = this.opt('height');
- if (typeof contentHeightInput === 'number') {
- this.suggestedViewHeight = contentHeightInput;
- }
- else if (typeof contentHeightInput === 'function') {
- this.suggestedViewHeight = contentHeightInput();
- }
- else if (typeof heightInput === 'number') {
- this.suggestedViewHeight = heightInput - this.queryToolbarsHeight();
- }
- else if (typeof heightInput === 'function') {
- this.suggestedViewHeight = heightInput() - this.queryToolbarsHeight();
- }
- else if (heightInput === 'parent') {
- this.suggestedViewHeight = this.el.parent().height() - this.queryToolbarsHeight();
- }
- else {
- this.suggestedViewHeight = Math.round(
- this.contentEl.width() /
- Math.max(this.opt('aspectRatio'), .5)
- );
- }
- },
- windowResize: function(ev) {
- if (
- !this.ignoreWindowResize &&
- ev.target === window &&
- this.view.renderUnzonedRange
- ) {
- if (this.updateSize(true)) {
- this.publiclyTrigger('windowResize', [ this.view ]);
- }
- }
- },
-
- freezeContentHeight: function() {
- this.contentEl.css({
- width: '100%',
- height: this.contentEl.height(),
- overflow: 'hidden'
- });
- },
- thawContentHeight: function() {
- this.contentEl.css({
- width: '',
- height: '',
- overflow: ''
- });
- }
- });
- ;;
- Calendar.mixin({
- header: null,
- footer: null,
- toolbarsManager: null,
- initToolbars: function() {
- this.header = new Toolbar(this, this.computeHeaderOptions());
- this.footer = new Toolbar(this, this.computeFooterOptions());
- this.toolbarsManager = new Iterator([ this.header, this.footer ]);
- },
- computeHeaderOptions: function() {
- return {
- extraClasses: 'fc-header-toolbar',
- layout: this.opt('header')
- };
- },
- computeFooterOptions: function() {
- return {
- extraClasses: 'fc-footer-toolbar',
- layout: this.opt('footer')
- };
- },
-
- renderHeader: function() {
- var header = this.header;
- header.setToolbarOptions(this.computeHeaderOptions());
- header.render();
- if (header.el) {
- this.el.prepend(header.el);
- }
- },
-
- renderFooter: function() {
- var footer = this.footer;
- footer.setToolbarOptions(this.computeFooterOptions());
- footer.render();
- if (footer.el) {
- this.el.append(footer.el);
- }
- },
- setToolbarsTitle: function(title) {
- this.toolbarsManager.proxyCall('updateTitle', title);
- },
- updateToolbarButtons: function() {
- var now = this.getNow();
- var view = this.view;
- var todayInfo = view.buildDateProfile(now);
- var prevInfo = view.buildPrevDateProfile(this.currentDate);
- var nextInfo = view.buildNextDateProfile(this.currentDate);
- this.toolbarsManager.proxyCall(
- (todayInfo.isValid && !view.currentUnzonedRange.containsDate(now)) ?
- 'enableButton' :
- 'disableButton',
- 'today'
- );
- this.toolbarsManager.proxyCall(
- prevInfo.isValid ?
- 'enableButton' :
- 'disableButton',
- 'prev'
- );
- this.toolbarsManager.proxyCall(
- nextInfo.isValid ?
- 'enableButton' :
- 'disableButton',
- 'next'
- );
- },
- queryToolbarsHeight: function() {
- return this.toolbarsManager.items.reduce(function(accumulator, toolbar) {
- var toolbarHeight = toolbar.el ? toolbar.el.outerHeight(true) : 0;
- return accumulator + toolbarHeight;
- }, 0);
- }
- });
- ;;
- var BUSINESS_HOUR_EVENT_DEFAULTS = {
- start: '09:00',
- end: '17:00',
- dow: [ 1, 2, 3, 4, 5 ],
- rendering: 'inverse-background'
-
- };
- Calendar.prototype.buildCurrentBusinessFootprints = function(wholeDay) {
- return this._buildCurrentBusinessFootprints(wholeDay, this.opt('businessHours'));
- };
- Calendar.prototype._buildCurrentBusinessFootprints = function(wholeDay, businessDefInput) {
- var eventPeriod = this.eventManager.currentPeriod;
- var businessInstanceGroup;
- if (eventPeriod) {
- businessInstanceGroup = this.buildBusinessInstanceGroup(
- wholeDay,
- businessDefInput,
- eventPeriod.unzonedRange
- );
- if (businessInstanceGroup) {
- return this.eventInstancesToFootprints(
- businessInstanceGroup.eventInstances
- );
- }
- }
- return [];
- };
- Calendar.prototype.buildBusinessInstanceGroup = function(wholeDay, rawComplexDef, unzonedRange) {
- var eventDefs = this.buildBusinessDefs(wholeDay, rawComplexDef);
- var eventInstanceGroup;
- if (eventDefs.length) {
- eventInstanceGroup = new EventInstanceGroup(
- eventDefsToEventInstances(eventDefs, unzonedRange)
- );
-
- eventInstanceGroup.explicitEventDef = eventDefs[0];
- return eventInstanceGroup;
- }
- };
- Calendar.prototype.buildBusinessDefs = function(wholeDay, rawComplexDef) {
- var rawDefs = [];
- var requireDow = false;
- var i;
- var defs = [];
- if (rawComplexDef === true) {
- rawDefs = [ {} ];
- }
- else if ($.isPlainObject(rawComplexDef)) {
- rawDefs = [ rawComplexDef ];
- }
- else if ($.isArray(rawComplexDef)) {
- rawDefs = rawComplexDef;
- requireDow = true;
- }
- for (i = 0; i < rawDefs.length; i++) {
- if (!requireDow || rawDefs[i].dow) {
- defs.push(
- this.buildBusinessDef(wholeDay, rawDefs[i])
- );
- }
- }
- return defs;
- };
- Calendar.prototype.buildBusinessDef = function(wholeDay, rawDef) {
- var fullRawDef = $.extend({}, BUSINESS_HOUR_EVENT_DEFAULTS, rawDef);
- if (wholeDay) {
- fullRawDef.start = null;
- fullRawDef.end = null;
- }
- return RecurringEventDef.parse(
- fullRawDef,
- new EventSource(this)
- );
- };
- ;;
- Calendar.prototype.isEventInstanceGroupAllowed = function(eventInstanceGroup) {
- var eventDef = eventInstanceGroup.getEventDef();
- var eventFootprints = this.eventRangesToEventFootprints(eventInstanceGroup.getAllEventRanges());
- var i;
- var peerEventInstances = this.getPeerEventInstances(eventDef);
- var peerEventRanges = eventInstancesToEventRanges(peerEventInstances);
- var peerEventFootprints = this.eventRangesToEventFootprints(peerEventRanges);
- var constraintVal = eventDef.getConstraint();
- var overlapVal = eventDef.getOverlap();
- var eventAllowFunc = this.opt('eventAllow');
- for (i = 0; i < eventFootprints.length; i++) {
- if (
- !this.isFootprintAllowed(
- eventFootprints[i].componentFootprint,
- peerEventFootprints,
- constraintVal,
- overlapVal,
- eventFootprints[i].eventInstance
- )
- ) {
- return false;
- }
- }
- if (eventAllowFunc) {
- for (i = 0; i < eventFootprints.length; i++) {
- if (
- eventAllowFunc(
- eventFootprints[i].componentFootprint.toLegacy(this),
- eventFootprints[i].getEventLegacy()
- ) === false
- ) {
- return false;
- }
- }
- }
- return true;
- };
- Calendar.prototype.getPeerEventInstances = function(eventDef) {
- return this.eventManager.getEventInstancesWithoutId(eventDef.id);
- };
- Calendar.prototype.isSelectionFootprintAllowed = function(componentFootprint) {
- var peerEventInstances = this.eventManager.getEventInstances();
- var peerEventRanges = eventInstancesToEventRanges(peerEventInstances);
- var peerEventFootprints = this.eventRangesToEventFootprints(peerEventRanges);
- var selectAllowFunc;
- if (
- this.isFootprintAllowed(
- componentFootprint,
- peerEventFootprints,
- this.opt('selectConstraint'),
- this.opt('selectOverlap')
- )
- ) {
- selectAllowFunc = this.opt('selectAllow');
- if (selectAllowFunc) {
- return selectAllowFunc(componentFootprint.toLegacy(this)) !== false;
- }
- else {
- return true;
- }
- }
- return false;
- };
- Calendar.prototype.isFootprintAllowed = function(
- componentFootprint,
- peerEventFootprints,
- constraintVal,
- overlapVal,
- subjectEventInstance // optional
- ) {
- var constraintFootprints;
- var overlapEventFootprints;
- if (constraintVal != null) {
- constraintFootprints = this.constraintValToFootprints(constraintVal, componentFootprint.isAllDay);
- if (!this.isFootprintWithinConstraints(componentFootprint, constraintFootprints)) {
- return false;
- }
- }
- overlapEventFootprints = this.collectOverlapEventFootprints(peerEventFootprints, componentFootprint);
- if (overlapVal === false) {
- if (overlapEventFootprints.length) {
- return false;
- }
- }
- else if (typeof overlapVal === 'function') {
- if (!isOverlapsAllowedByFunc(overlapEventFootprints, overlapVal, subjectEventInstance)) {
- return false;
- }
- }
- if (subjectEventInstance) {
- if (!isOverlapEventInstancesAllowed(overlapEventFootprints, subjectEventInstance)) {
- return false;
- }
- }
- return true;
- };
- Calendar.prototype.isFootprintWithinConstraints = function(componentFootprint, constraintFootprints) {
- var i;
- for (i = 0; i < constraintFootprints.length; i++) {
- if (this.footprintContainsFootprint(constraintFootprints[i], componentFootprint)) {
- return true;
- }
- }
- return false;
- };
- Calendar.prototype.constraintValToFootprints = function(constraintVal, isAllDay) {
- var eventInstances;
- if (constraintVal === 'businessHours') {
- return this.buildCurrentBusinessFootprints(isAllDay);
- }
- else if (typeof constraintVal === 'object') {
- eventInstances = this.parseEventDefToInstances(constraintVal);
- if (!eventInstances) {
- return this.parseFootprints(constraintVal);
- }
- else {
- return this.eventInstancesToFootprints(eventInstances);
- }
- }
- else if (constraintVal != null) {
- eventInstances = this.eventManager.getEventInstancesWithId(constraintVal);
- return this.eventInstancesToFootprints(eventInstances);
- }
- };
- Calendar.prototype.eventInstancesToFootprints = function(eventInstances) {
- return eventFootprintsToComponentFootprints(
- this.eventRangesToEventFootprints(
- eventInstancesToEventRanges(eventInstances)
- )
- );
- };
- Calendar.prototype.collectOverlapEventFootprints = function(peerEventFootprints, targetFootprint) {
- var overlapEventFootprints = [];
- var i;
- for (i = 0; i < peerEventFootprints.length; i++) {
- if (
- this.footprintsIntersect(
- targetFootprint,
- peerEventFootprints[i].componentFootprint
- )
- ) {
- overlapEventFootprints.push(peerEventFootprints[i]);
- }
- }
- return overlapEventFootprints;
- };
- function isOverlapsAllowedByFunc(overlapEventFootprints, overlapFunc, subjectEventInstance) {
- var i;
- for (i = 0; i < overlapEventFootprints.length; i++) {
- if (
- !overlapFunc(
- overlapEventFootprints[i].eventInstance.toLegacy(),
- subjectEventInstance ? subjectEventInstance.toLegacy() : null
- )
- ) {
- return false;
- }
- }
- return true;
- }
- function isOverlapEventInstancesAllowed(overlapEventFootprints, subjectEventInstance) {
- var subjectLegacyInstance = subjectEventInstance.toLegacy();
- var i;
- var overlapEventInstance;
- var overlapEventDef;
- var overlapVal;
- for (i = 0; i < overlapEventFootprints.length; i++) {
- overlapEventInstance = overlapEventFootprints[i].eventInstance;
- overlapEventDef = overlapEventInstance.def;
-
-
- overlapVal = overlapEventDef.getOverlap();
- if (overlapVal === false) {
- return false;
- }
- else if (typeof overlapVal === 'function') {
- if (
- !overlapVal(
- overlapEventInstance.toLegacy(),
- subjectLegacyInstance
- )
- ) {
- return false;
- }
- }
- }
- return true;
- }
- Calendar.prototype.parseEventDefToInstances = function(eventInput) {
- var eventPeriod = this.eventManager.currentPeriod;
- var eventDef = EventDefParser.parse(eventInput, new EventSource(this));
- if (!eventDef) {
- return false;
- }
- if (eventPeriod) {
- return eventDef.buildInstances(eventPeriod.unzonedRange);
- }
- else {
- return [];
- }
- };
- Calendar.prototype.eventRangesToEventFootprints = function(eventRanges) {
- var i;
- var eventFootprints = [];
- for (i = 0; i < eventRanges.length; i++) {
- eventFootprints.push.apply(eventFootprints,
- this.eventRangeToEventFootprints(eventRanges[i])
- );
- }
- return eventFootprints;
- };
- Calendar.prototype.eventRangeToEventFootprints = function(eventRange) {
- return [
- new EventFootprint(
- new ComponentFootprint(
- eventRange.unzonedRange,
- eventRange.eventDef.isAllDay()
- ),
- eventRange.eventDef,
- eventRange.eventInstance
- )
- ];
- };
- Calendar.prototype.parseFootprints = function(rawInput) {
- var start, end;
- if (rawInput.start) {
- start = this.moment(rawInput.start);
- if (!start.isValid()) {
- start = null;
- }
- }
- if (rawInput.end) {
- end = this.moment(rawInput.end);
- if (!end.isValid()) {
- end = null;
- }
- }
- return [
- new ComponentFootprint(
- new UnzonedRange(start, end),
- (start && !start.hasTime()) || (end && !end.hasTime())
- )
- ];
- };
- Calendar.prototype.footprintContainsFootprint = function(outerFootprint, innerFootprint) {
- return outerFootprint.unzonedRange.containsRange(innerFootprint.unzonedRange);
- };
- Calendar.prototype.footprintsIntersect = function(footprint0, footprint1) {
- return footprint0.unzonedRange.intersectsWith(footprint1.unzonedRange);
- };
- ;;
- Calendar.mixin({
-
-
- getEventSources: function() {
- return this.eventManager.otherSources.slice();
- },
- getEventSourceById: function(id) {
- return this.eventManager.getSourceById(
- EventSource.normalizeId(id)
- );
- },
- addEventSource: function(sourceInput) {
- var source = EventSourceParser.parse(sourceInput, this);
- if (source) {
- this.eventManager.addSource(source);
- }
- },
- removeEventSources: function(sourceMultiQuery) {
- var eventManager = this.eventManager;
- var sources;
- var i;
- if (sourceMultiQuery == null) {
- this.eventManager.removeAllSources();
- }
- else {
- sources = eventManager.multiQuerySources(sourceMultiQuery);
- eventManager.freeze();
- for (i = 0; i < sources.length; i++) {
- eventManager.removeSource(sources[i]);
- }
- eventManager.thaw();
- }
- },
- removeEventSource: function(sourceQuery) {
- var eventManager = this.eventManager;
- var sources = eventManager.querySources(sourceQuery);
- var i;
- eventManager.freeze();
- for (i = 0; i < sources.length; i++) {
- eventManager.removeSource(sources[i]);
- }
- eventManager.thaw();
- },
- refetchEventSources: function(sourceMultiQuery) {
- var eventManager = this.eventManager;
- var sources = eventManager.multiQuerySources(sourceMultiQuery);
- var i;
- eventManager.freeze();
- for (i = 0; i < sources.length; i++) {
- eventManager.refetchSource(sources[i]);
- }
- eventManager.thaw();
- },
-
-
- refetchEvents: function() {
- this.eventManager.refetchAllSources();
- },
- renderEvents: function(eventInputs, isSticky) {
- this.eventManager.freeze();
- for (var i = 0; i < eventInputs.length; i++) {
- this.renderEvent(eventInputs[i], isSticky);
- }
- this.eventManager.thaw();
- },
- renderEvent: function(eventInput, isSticky) {
- var eventManager = this.eventManager;
- var eventDef = EventDefParser.parse(
- eventInput,
- eventInput.source || eventManager.stickySource
- );
- if (eventDef) {
- eventManager.addEventDef(eventDef, isSticky);
- }
- },
-
- removeEvents: function(legacyQuery) {
- var eventManager = this.eventManager;
- var eventInstances = eventManager.getEventInstances();
- var legacyInstances;
- var idMap = {};
- var eventDef;
- var i;
- if (legacyQuery == null) {
- eventManager.removeAllEventDefs();
- }
- else {
- legacyInstances = eventInstances.map(function(eventInstance) {
- return eventInstance.toLegacy();
- });
- legacyInstances = filterLegacyEventInstances(legacyInstances, legacyQuery);
-
- for (i = 0; i < legacyInstances.length; i++) {
- eventDef = this.eventManager.getEventDefByUid(legacyInstances[i]._id);
- idMap[eventDef.id] = true;
- }
- eventManager.freeze();
- for (i in idMap) {
- eventManager.removeEventDefsById(i);
- }
- eventManager.thaw();
- }
- },
-
- clientEvents: function(legacyQuery) {
- var eventInstances = this.eventManager.getEventInstances();
- var legacyEventInstances = eventInstances.map(function(eventInstance) {
- return eventInstance.toLegacy();
- });
- return filterLegacyEventInstances(legacyEventInstances, legacyQuery);
- },
- updateEvents: function(eventPropsArray) {
- this.eventManager.freeze();
- for (var i = 0; i < eventPropsArray.length; i++) {
- this.updateEvent(eventPropsArray[i]);
- }
- this.eventManager.thaw();
- },
- updateEvent: function(eventProps) {
- var eventDef = this.eventManager.getEventDefByUid(eventProps._id);
- var eventInstance;
- var eventDefMutation;
- if (eventDef instanceof SingleEventDef) {
- eventInstance = eventDef.buildInstance();
- eventDefMutation = EventDefMutation.createFromRawProps(
- eventInstance,
- eventProps,
- null
- );
- this.eventManager.mutateEventsWithId(eventDef.id, eventDefMutation);
- }
- }
- });
- function filterLegacyEventInstances(legacyEventInstances, legacyQuery) {
- if (legacyQuery == null) {
- return legacyEventInstances;
- }
- else if ($.isFunction(legacyQuery)) {
- return legacyEventInstances.filter(legacyQuery);
- }
- else {
- legacyQuery += '';
- return legacyEventInstances.filter(function(legacyEventInstance) {
-
- return legacyEventInstance.id == legacyQuery;
- });
- }
- }
- ;;
- Calendar.defaults = {
- titleRangeSeparator: ' \u2013 ',
- monthYearFormat: 'MMMM YYYY',
- defaultTimedEventDuration: '02:00:00',
- defaultAllDayEventDuration: { days: 1 },
- forceEventDuration: false,
- nextDayThreshold: '09:00:00',
-
- defaultView: 'month',
- aspectRatio: 1.35,
- header: {
- left: 'title',
- center: '',
- right: 'today prev,next'
- },
- weekends: true,
- weekNumbers: false,
- weekNumberTitle: 'W',
- weekNumberCalculation: 'local',
-
-
-
- scrollTime: '06:00:00',
- minTime: '00:00:00',
- maxTime: '24:00:00',
- showNonCurrentDates: true,
-
-
- lazyFetching: true,
- startParam: 'start',
- endParam: 'end',
- timezoneParam: 'timezone',
- timezone: false,
-
-
- isRTL: false,
- buttonText: {
- prev: "prev",
- next: "next",
- prevYear: "prev year",
- nextYear: "next year",
- year: 'year',
- today: 'today',
- month: 'month',
- week: 'week',
- day: 'day'
- },
-
- allDayText: 'all-day',
-
-
- theme: false,
-
-
- dragOpacity: .75,
- dragRevertDuration: 500,
- dragScroll: true,
-
-
- unselectAuto: true,
-
-
- dropAccept: '*',
- eventOrder: 'title',
-
- eventLimit: false,
- eventLimitText: 'more',
- eventLimitClick: 'popover',
- dayPopoverFormat: 'LL',
-
- handleWindowResize: true,
- windowResizeDelay: 100,
- longPressDelay: 1000
-
- };
- Calendar.englishDefaults = {
- dayPopoverFormat: 'dddd, MMMM D'
- };
- Calendar.rtlDefaults = {
- header: {
- left: 'next,prev today',
- center: '',
- right: 'title'
- },
- buttonIcons: {
- prev: 'right-single-arrow',
- next: 'left-single-arrow',
- prevYear: 'right-double-arrow',
- nextYear: 'left-double-arrow'
- },
- themeButtonIcons: {
- prev: 'circle-triangle-e',
- next: 'circle-triangle-w',
- nextYear: 'seek-prev',
- prevYear: 'seek-next'
- }
- };
- ;;
- var localeOptionHash = FC.locales = {};
- FC.datepickerLocale = function(localeCode, dpLocaleCode, dpOptions) {
-
- var fcOptions = localeOptionHash[localeCode] || (localeOptionHash[localeCode] = {});
-
- fcOptions.isRTL = dpOptions.isRTL;
- fcOptions.weekNumberTitle = dpOptions.weekHeader;
-
- $.each(dpComputableOptions, function(name, func) {
- fcOptions[name] = func(dpOptions);
- });
-
- if ($.datepicker) {
-
-
-
-
- $.datepicker.regional[dpLocaleCode] =
- $.datepicker.regional[localeCode] =
- dpOptions;
-
- $.datepicker.regional.en = $.datepicker.regional[''];
-
- $.datepicker.setDefaults(dpOptions);
- }
- };
- FC.locale = function(localeCode, newFcOptions) {
- var fcOptions;
- var momOptions;
-
- fcOptions = localeOptionHash[localeCode] || (localeOptionHash[localeCode] = {});
-
- if (newFcOptions) {
- fcOptions = localeOptionHash[localeCode] = mergeOptions([ fcOptions, newFcOptions ]);
- }
-
-
-
- momOptions = getMomentLocaleData(localeCode);
- $.each(momComputableOptions, function(name, func) {
- if (fcOptions[name] == null) {
- fcOptions[name] = func(momOptions, fcOptions);
- }
- });
-
- Calendar.defaults.locale = localeCode;
- };
- var dpComputableOptions = {
- buttonText: function(dpOptions) {
- return {
-
- prev: stripHtmlEntities(dpOptions.prevText),
- next: stripHtmlEntities(dpOptions.nextText),
- today: stripHtmlEntities(dpOptions.currentText)
- };
- },
-
- monthYearFormat: function(dpOptions) {
- return dpOptions.showMonthAfterYear ?
- 'YYYY[' + dpOptions.yearSuffix + '] MMMM' :
- 'MMMM YYYY[' + dpOptions.yearSuffix + ']';
- }
- };
- var momComputableOptions = {
-
- dayOfMonthFormat: function(momOptions, fcOptions) {
- var format = momOptions.longDateFormat('l');
-
- format = format.replace(/^Y+[^\w\s]*|[^\w\s]*Y+$/g, '');
- if (fcOptions.isRTL) {
- format += ' ddd';
- }
- else {
- format = 'ddd ' + format;
- }
- return format;
- },
-
- mediumTimeFormat: function(momOptions) {
- return momOptions.longDateFormat('LT')
- .replace(/\s*a$/i, 'a');
- },
-
- smallTimeFormat: function(momOptions) {
- return momOptions.longDateFormat('LT')
- .replace(':mm', '(:mm)')
- .replace(/(\Wmm)$/, '($1)')
- .replace(/\s*a$/i, 'a');
- },
-
- extraSmallTimeFormat: function(momOptions) {
- return momOptions.longDateFormat('LT')
- .replace(':mm', '(:mm)')
- .replace(/(\Wmm)$/, '($1)')
- .replace(/\s*a$/i, 't');
- },
-
- hourFormat: function(momOptions) {
- return momOptions.longDateFormat('LT')
- .replace(':mm', '')
- .replace(/(\Wmm)$/, '')
- .replace(/\s*a$/i, 'a');
- },
-
- noMeridiemTimeFormat: function(momOptions) {
- return momOptions.longDateFormat('LT')
- .replace(/\s*a$/i, '');
- }
- };
- var instanceComputableOptions = {
-
- smallDayDateFormat: function(options) {
- return options.isRTL ?
- 'D dd' :
- 'dd D';
- },
-
- weekFormat: function(options) {
- return options.isRTL ?
- 'w[ ' + options.weekNumberTitle + ']' :
- '[' + options.weekNumberTitle + ' ]w';
- },
-
- smallWeekFormat: function(options) {
- return options.isRTL ?
- 'w[' + options.weekNumberTitle + ']' :
- '[' + options.weekNumberTitle + ']w';
- }
- };
- function populateInstanceComputableOptions(options) {
- $.each(instanceComputableOptions, function(name, func) {
- if (options[name] == null) {
- options[name] = func(options);
- }
- });
- }
- function getMomentLocaleData(localeCode) {
- return moment.localeData(localeCode) || moment.localeData('en');
- }
- FC.locale('en', Calendar.englishDefaults);
- ;;
- var UnzonedRange = FC.UnzonedRange = Class.extend({
- startMs: null,
- endMs: null,
-
-
- isStart: true,
- isEnd: true,
- constructor: function(startInput, endInput) {
- if (moment.isMoment(startInput)) {
- startInput = startInput.clone().stripZone();
- }
- if (moment.isMoment(endInput)) {
- endInput = endInput.clone().stripZone();
- }
- if (startInput) {
- this.startMs = startInput.valueOf();
- }
- if (endInput) {
- this.endMs = endInput.valueOf();
- }
- },
- intersect: function(otherRange) {
- var startMs = this.startMs;
- var endMs = this.endMs;
- var newRange = null;
- if (otherRange.startMs !== null) {
- if (startMs === null) {
- startMs = otherRange.startMs;
- }
- else {
- startMs = Math.max(startMs, otherRange.startMs);
- }
- }
- if (otherRange.endMs !== null) {
- if (endMs === null) {
- endMs = otherRange.endMs;
- }
- else {
- endMs = Math.min(endMs, otherRange.endMs);
- }
- }
- if (startMs === null || endMs === null || startMs < endMs) {
- newRange = new UnzonedRange(startMs, endMs);
- newRange.isStart = this.isStart && startMs === this.startMs;
- newRange.isEnd = this.isEnd && endMs === this.endMs;
- }
- return newRange;
- },
- intersectsWith: function(otherRange) {
- return (this.endMs === null || otherRange.startMs === null || this.endMs > otherRange.startMs) &&
- (this.startMs === null || otherRange.endMs === null || this.startMs < otherRange.endMs);
- },
- containsRange: function(innerRange) {
- return (this.startMs === null || (innerRange.startMs !== null && innerRange.startMs >= this.startMs)) &&
- (this.endMs === null || (innerRange.endMs !== null && innerRange.endMs <= this.endMs));
- },
-
- containsDate: function(date) {
- var ms = date.valueOf();
- return (this.startMs === null || ms >= this.startMs) &&
- (this.endMs === null || ms < this.endMs);
- },
-
-
-
-
- constrainDate: function(date) {
- var ms = date.valueOf();
- if (this.startMs !== null && ms < this.startMs) {
- ms = this.startMs;
- }
- if (this.endMs !== null && ms >= this.endMs) {
- ms = this.endMs - 1;
- }
- return ms;
- },
- equals: function(otherRange) {
- return this.startMs === otherRange.startMs && this.endMs === otherRange.endMs;
- },
- clone: function() {
- var range = new UnzonedRange(this.startMs, this.endMs);
- range.isStart = this.isStart;
- range.isEnd = this.isEnd;
- return range;
- },
-
-
-
- getStart: function() {
- if (this.startMs !== null) {
- return FC.moment.utc(this.startMs).stripZone();
- }
- },
-
-
-
- getEnd: function() {
- if (this.endMs !== null) {
- return FC.moment.utc(this.endMs).stripZone();
- }
- }
- });
- function invertUnzonedRanges(ranges, constraintRange) {
- var invertedRanges = [];
- var startMs = constraintRange.startMs;
- var i;
- var dateRange;
-
- ranges.sort(compareUnzonedRanges);
- for (i = 0; i < ranges.length; i++) {
- dateRange = ranges[i];
-
- if (dateRange.startMs > startMs) {
- invertedRanges.push(
- new UnzonedRange(startMs, dateRange.startMs)
- );
- }
- if (dateRange.endMs > startMs) {
- startMs = dateRange.endMs;
- }
- }
-
- if (startMs < constraintRange.endMs) {
- invertedRanges.push(
- new UnzonedRange(startMs, constraintRange.endMs)
- );
- }
- return invertedRanges;
- }
- function compareUnzonedRanges(range1, range2) {
- return range1.startMs - range2.startMs;
- }
- ;;
- var ComponentFootprint = FC.ComponentFootprint = Class.extend({
- unzonedRange: null,
- isAllDay: false,
- constructor: function(unzonedRange, isAllDay) {
- this.unzonedRange = unzonedRange;
- this.isAllDay = isAllDay;
- },
-
- toLegacy: function(calendar) {
- return {
- start: calendar.msToMoment(this.unzonedRange.startMs, this.isAllDay),
- end: calendar.msToMoment(this.unzonedRange.endMs, this.isAllDay)
- };
- }
- });
- ;;
- var EventManager = Class.extend(EmitterMixin, ListenerMixin, {
- currentPeriod: null,
- calendar: null,
- stickySource: null,
- otherSources: null,
- constructor: function(calendar) {
- this.calendar = calendar;
- this.stickySource = new ArrayEventSource(calendar);
- this.otherSources = [];
- },
- requestEvents: function(start, end, timezone, force) {
- if (
- force ||
- !this.currentPeriod ||
- !this.currentPeriod.isWithinRange(start, end) ||
- timezone !== this.currentPeriod.timezone
- ) {
- this.setPeriod(
- new EventPeriod(start, end, timezone)
- );
- }
- return this.currentPeriod.whenReleased();
- },
-
-
- addSource: function(eventSource) {
- this.otherSources.push(eventSource);
- if (this.currentPeriod) {
- this.currentPeriod.requestSource(eventSource);
- }
- },
- removeSource: function(doomedSource) {
- removeExact(this.otherSources, doomedSource);
- if (this.currentPeriod) {
- this.currentPeriod.purgeSource(doomedSource);
- }
- },
- removeAllSources: function() {
- this.otherSources = [];
- if (this.currentPeriod) {
- this.currentPeriod.purgeAllSources();
- }
- },
-
-
- refetchSource: function(eventSource) {
- var currentPeriod = this.currentPeriod;
- if (currentPeriod) {
- currentPeriod.freeze();
- currentPeriod.purgeSource(eventSource);
- currentPeriod.requestSource(eventSource);
- currentPeriod.thaw();
- }
- },
- refetchAllSources: function() {
- var currentPeriod = this.currentPeriod;
- if (currentPeriod) {
- currentPeriod.freeze();
- currentPeriod.purgeAllSources();
- currentPeriod.requestSources(this.getSources());
- currentPeriod.thaw();
- }
- },
-
-
- getSources: function() {
- return [ this.stickySource ].concat(this.otherSources);
- },
-
- multiQuerySources: function(matchInputs) {
-
- if (!matchInputs) {
- matchInputs = [];
- }
- else if (!$.isArray(matchInputs)) {
- matchInputs = [ matchInputs ];
- }
- var matchingSources = [];
- var i;
-
- for (i = 0; i < matchInputs.length; i++) {
- matchingSources.push.apply(
- matchingSources,
- this.querySources(matchInputs[i])
- );
- }
- return matchingSources;
- },
-
-
- querySources: function(matchInput) {
- var sources = this.otherSources;
- var i, source;
-
- for (i = 0; i < sources.length; i++) {
- source = sources[i];
- if (source === matchInput) {
- return [ source ];
- }
- }
-
- source = this.getSourceById(EventSource.normalizeId(matchInput));
- if (source) {
- return [ source ];
- }
-
- matchInput = EventSourceParser.parse(matchInput, this.calendar);
- if (matchInput) {
- return $.grep(sources, function(source) {
- return isSourcesEquivalent(matchInput, source);
- });
- }
- },
-
- getSourceById: function(id) {
- return $.grep(this.otherSources, function(source) {
- return source.id && source.id === id;
- })[0];
- },
-
-
- setPeriod: function(eventPeriod) {
- if (this.currentPeriod) {
- this.unbindPeriod(this.currentPeriod);
- this.currentPeriod = null;
- }
- this.currentPeriod = eventPeriod;
- this.bindPeriod(eventPeriod);
- eventPeriod.requestSources(this.getSources());
- },
- bindPeriod: function(eventPeriod) {
- this.listenTo(eventPeriod, 'release', function(eventsPayload) {
- this.trigger('release', eventsPayload);
- });
- },
- unbindPeriod: function(eventPeriod) {
- this.stopListeningTo(eventPeriod);
- },
-
-
- getEventDefByUid: function(uid) {
- if (this.currentPeriod) {
- return this.currentPeriod.getEventDefByUid(uid);
- }
- },
- addEventDef: function(eventDef, isSticky) {
- if (isSticky) {
- this.stickySource.addEventDef(eventDef);
- }
- if (this.currentPeriod) {
- this.currentPeriod.addEventDef(eventDef);
- }
- },
- removeEventDefsById: function(eventId) {
- this.getSources().forEach(function(eventSource) {
- eventSource.removeEventDefsById(eventId);
- });
- if (this.currentPeriod) {
- this.currentPeriod.removeEventDefsById(eventId);
- }
- },
- removeAllEventDefs: function() {
- this.getSources().forEach(function(eventSource) {
- eventSource.removeAllEventDefs();
- });
- if (this.currentPeriod) {
- this.currentPeriod.removeAllEventDefs();
- }
- },
-
-
-
- mutateEventsWithId: function(eventDefId, eventDefMutation) {
- var currentPeriod = this.currentPeriod;
- var eventDefs;
- var undoFuncs = [];
- if (currentPeriod) {
- currentPeriod.freeze();
- eventDefs = currentPeriod.getEventDefsById(eventDefId);
- eventDefs.forEach(function(eventDef) {
-
- currentPeriod.removeEventDef(eventDef);
- undoFuncs.push(eventDefMutation.mutateSingle(eventDef));
- currentPeriod.addEventDef(eventDef);
- });
- currentPeriod.thaw();
- return function() {
- currentPeriod.freeze();
- for (var i = 0; i < eventDefs.length; i++) {
- currentPeriod.removeEventDef(eventDefs[i]);
- undoFuncs[i]();
- currentPeriod.addEventDef(eventDefs[i]);
- }
- currentPeriod.thaw();
- };
- }
- return function() { };
- },
-
- buildMutatedEventInstanceGroup: function(eventDefId, eventDefMutation) {
- var eventDefs = this.getEventDefsById(eventDefId);
- var i;
- var defCopy;
- var allInstances = [];
- for (i = 0; i < eventDefs.length; i++) {
- defCopy = eventDefs[i].clone();
- if (defCopy instanceof SingleEventDef) {
- eventDefMutation.mutateSingle(defCopy);
- allInstances.push.apply(allInstances,
- defCopy.buildInstances()
- );
- }
- }
- return new EventInstanceGroup(allInstances);
- },
-
-
- freeze: function() {
- if (this.currentPeriod) {
- this.currentPeriod.freeze();
- }
- },
- thaw: function() {
- if (this.currentPeriod) {
- this.currentPeriod.thaw();
- }
- }
- });
- [
- 'getEventDefsById',
- 'getEventInstances',
- 'getEventInstancesWithId',
- 'getEventInstancesWithoutId'
- ].forEach(function(methodName) {
- EventManager.prototype[methodName] = function() {
- var currentPeriod = this.currentPeriod;
- if (currentPeriod) {
- return currentPeriod[methodName].apply(currentPeriod, arguments);
- }
- return [];
- };
- });
- function isSourcesEquivalent(source0, source1) {
- return source0.getPrimitive() == source1.getPrimitive();
- }
- ;;
- var EventPeriod = Class.extend(EmitterMixin, {
- start: null,
- end: null,
- timezone: null,
- unzonedRange: null,
- requestsByUid: null,
- pendingCnt: 0,
- freezeDepth: 0,
- stuntedReleaseCnt: 0,
- releaseCnt: 0,
- eventDefsByUid: null,
- eventDefsById: null,
- eventInstanceGroupsById: null,
- constructor: function(start, end, timezone) {
- this.start = start;
- this.end = end;
- this.timezone = timezone;
- this.unzonedRange = new UnzonedRange(
- start.clone().stripZone(),
- end.clone().stripZone()
- );
- this.requestsByUid = {};
- this.eventDefsByUid = {};
- this.eventDefsById = {};
- this.eventInstanceGroupsById = {};
- },
- isWithinRange: function(start, end) {
-
- return !start.isBefore(this.start) && !end.isAfter(this.end);
- },
-
-
- requestSources: function(sources) {
- this.freeze();
- for (var i = 0; i < sources.length; i++) {
- this.requestSource(sources[i]);
- }
- this.thaw();
- },
- requestSource: function(source) {
- var _this = this;
- var request = { source: source, status: 'pending' };
- this.requestsByUid[source.uid] = request;
- this.pendingCnt += 1;
- source.fetch(this.start, this.end, this.timezone).then(function(eventDefs) {
- if (request.status !== 'cancelled') {
- request.status = 'completed';
- request.eventDefs = eventDefs;
- _this.addEventDefs(eventDefs);
- _this.pendingCnt--;
- _this.tryRelease();
- }
- }, function() {
- if (request.status !== 'cancelled') {
- request.status = 'failed';
- _this.pendingCnt--;
- _this.tryRelease();
- }
- });
- },
- purgeSource: function(source) {
- var request = this.requestsByUid[source.uid];
- if (request) {
- delete this.requestsByUid[source.uid];
- if (request.status === 'pending') {
- request.status = 'cancelled';
- this.pendingCnt--;
- this.tryRelease();
- }
- else if (request.status === 'completed') {
- request.eventDefs.forEach(this.removeEventDef.bind(this));
- }
- }
- },
- purgeAllSources: function() {
- var requestsByUid = this.requestsByUid;
- var uid, request;
- var completedCnt = 0;
- for (uid in requestsByUid) {
- request = requestsByUid[uid];
- if (request.status === 'pending') {
- request.status = 'cancelled';
- }
- else if (request.status === 'completed') {
- completedCnt++;
- }
- }
- this.requestsByUid = {};
- this.pendingCnt = 0;
- if (completedCnt) {
- this.removeAllEventDefs();
- }
- },
-
-
- getEventDefByUid: function(eventDefUid) {
- return this.eventDefsByUid[eventDefUid];
- },
- getEventDefsById: function(eventDefId) {
- var a = this.eventDefsById[eventDefId];
- if (a) {
- return a.slice();
- }
- return [];
- },
- addEventDefs: function(eventDefs) {
- for (var i = 0; i < eventDefs.length; i++) {
- this.addEventDef(eventDefs[i]);
- }
- },
- addEventDef: function(eventDef) {
- var eventDefsById = this.eventDefsById;
- var eventDefId = eventDef.id;
- var eventDefs = eventDefsById[eventDefId] || (eventDefsById[eventDefId] = []);
- var eventInstances = eventDef.buildInstances(this.unzonedRange);
- var i;
- eventDefs.push(eventDef);
- this.eventDefsByUid[eventDef.uid] = eventDef;
- for (i = 0; i < eventInstances.length; i++) {
- this.addEventInstance(eventInstances[i], eventDefId);
- }
- },
- removeEventDefsById: function(eventDefId) {
- var _this = this;
- this.getEventDefsById(eventDefId).forEach(function(eventDef) {
- _this.removeEventDef(eventDef);
- });
- },
- removeAllEventDefs: function() {
- var isEmpty = $.isEmptyObject(this.eventDefsByUid);
- this.eventDefsByUid = {};
- this.eventDefsById = {};
- this.eventInstanceGroupsById = {};
- if (!isEmpty) {
- this.tryRelease();
- }
- },
- removeEventDef: function(eventDef) {
- var eventDefsById = this.eventDefsById;
- var eventDefs = eventDefsById[eventDef.id];
- delete this.eventDefsByUid[eventDef.uid];
- if (eventDefs) {
- removeExact(eventDefs, eventDef);
- if (!eventDefs.length) {
- delete eventDefsById[eventDef.id];
- }
- this.removeEventInstancesForDef(eventDef);
- }
- },
-
-
- getEventInstances: function() {
- var eventInstanceGroupsById = this.eventInstanceGroupsById;
- var eventInstances = [];
- var id;
- for (id in eventInstanceGroupsById) {
- eventInstances.push.apply(eventInstances,
- eventInstanceGroupsById[id].eventInstances
- );
- }
- return eventInstances;
- },
- getEventInstancesWithId: function(eventDefId) {
- var eventInstanceGroup = this.eventInstanceGroupsById[eventDefId];
- if (eventInstanceGroup) {
- return eventInstanceGroup.eventInstances.slice();
- }
- return [];
- },
- getEventInstancesWithoutId: function(eventDefId) {
- var eventInstanceGroupsById = this.eventInstanceGroupsById;
- var matchingInstances = [];
- var id;
- for (id in eventInstanceGroupsById) {
- if (id !== eventDefId) {
- matchingInstances.push.apply(matchingInstances,
- eventInstanceGroupsById[id].eventInstances
- );
- }
- }
- return matchingInstances;
- },
- addEventInstance: function(eventInstance, eventDefId) {
- var eventInstanceGroupsById = this.eventInstanceGroupsById;
- var eventInstanceGroup = eventInstanceGroupsById[eventDefId] ||
- (eventInstanceGroupsById[eventDefId] = new EventInstanceGroup());
- eventInstanceGroup.eventInstances.push(eventInstance);
- this.tryRelease();
- },
- removeEventInstancesForDef: function(eventDef) {
- var eventInstanceGroupsById = this.eventInstanceGroupsById;
- var eventInstanceGroup = eventInstanceGroupsById[eventDef.id];
- var removeCnt;
- if (eventInstanceGroup) {
- removeCnt = removeMatching(eventInstanceGroup.eventInstances, function(currentEventInstance) {
- return currentEventInstance.def === eventDef;
- });
- if (!eventInstanceGroup.eventInstances.length) {
- delete eventInstanceGroupsById[eventDef.id];
- }
- if (removeCnt) {
- this.tryRelease();
- }
- }
- },
-
-
- tryRelease: function() {
- if (!this.pendingCnt) {
- if (!this.freezeDepth) {
- this.release();
- }
- else {
- this.stuntedReleaseCnt++;
- }
- }
- },
- release: function() {
- this.releaseCnt++;
- this.trigger('release', this.eventInstanceGroupsById);
- },
- whenReleased: function() {
- var _this = this;
- if (this.releaseCnt) {
- return Promise.resolve(this.eventInstanceGroupsById);
- }
- else {
- return Promise.construct(function(onResolve) {
- _this.one('release', onResolve);
- });
- }
- },
- freeze: function() {
- if (!(this.freezeDepth++)) {
- this.stuntedReleaseCnt = 0;
- }
- },
- thaw: function() {
- if (!(--this.freezeDepth) && this.stuntedReleaseCnt && !this.pendingCnt) {
- this.release();
- }
- }
- });
- ;;
- var EventDefParser = {
- parse: function(eventInput, source) {
- if (
- isTimeString(eventInput.start) || moment.isDuration(eventInput.start) ||
- isTimeString(eventInput.end) || moment.isDuration(eventInput.end)
- ) {
- return RecurringEventDef.parse(eventInput, source);
- }
- else {
- return SingleEventDef.parse(eventInput, source);
- }
- }
- };
- ;;
- var EventDef = FC.EventDef = Class.extend(ParsableModelMixin, {
- source: null,
- id: null,
- rawId: null,
- uid: null,
-
- title: null,
- url: null,
- rendering: null,
- constraint: null,
- overlap: null,
- editable: null,
- startEditable: null,
- durationEditable: null,
- color: null,
- backgroundColor: null,
- borderColor: null,
- textColor: null,
- className: null,
- miscProps: null,
- constructor: function(source) {
- this.source = source;
- this.className = [];
- this.miscProps = {};
- },
- isAllDay: function() {
-
- },
- buildInstances: function(unzonedRange) {
-
- },
- clone: function() {
- var copy = new this.constructor(this.source);
- copy.id = this.id;
- copy.rawId = this.rawId;
- copy.uid = this.uid;
- EventDef.copyVerbatimStandardProps(this, copy);
- copy.className = this.className;
- copy.miscProps = $.extend({}, this.miscProps);
- return copy;
- },
- hasInverseRendering: function() {
- return this.getRendering() === 'inverse-background';
- },
- hasBgRendering: function() {
- var rendering = this.getRendering();
- return rendering === 'inverse-background' || rendering === 'background';
- },
- getRendering: function() {
- if (this.rendering != null) {
- return this.rendering;
- }
- return this.source.rendering;
- },
- getConstraint: function() {
- if (this.constraint != null) {
- return this.constraint;
- }
- if (this.source.constraint != null) {
- return this.source.constraint;
- }
- return this.source.calendar.opt('eventConstraint');
- },
- getOverlap: function() {
- if (this.overlap != null) {
- return this.overlap;
- }
- if (this.source.overlap != null) {
- return this.source.overlap;
- }
- return this.source.calendar.opt('eventOverlap');
- },
- isStartExplicitlyEditable: function() {
- if (this.startEditable !== null) {
- return this.startEditable;
- }
- return this.source.startEditable;
- },
- isDurationExplicitlyEditable: function() {
- if (this.durationEditable !== null) {
- return this.durationEditable;
- }
- return this.source.durationEditable;
- },
- isExplicitlyEditable: function() {
- if (this.editable !== null) {
- return this.editable;
- }
- return this.source.editable;
- },
- toLegacy: function() {
- var obj = $.extend({}, this.miscProps);
- obj._id = this.uid;
- obj.source = this.source;
- obj.className = this.className;
- obj.allDay = this.isAllDay();
- if (this.rawId != null) {
- obj.id = this.rawId;
- }
- EventDef.copyVerbatimStandardProps(this, obj);
- return obj;
- },
- applyManualRawProps: function(rawProps) {
- if (rawProps.id != null) {
- this.id = EventDef.normalizeId((this.rawId = rawProps.id));
- }
- else {
- this.id = EventDef.generateId();
- }
- if (rawProps._id != null) {
- this.uid = String(rawProps._id);
- }
- else {
- this.uid = EventDef.generateId();
- }
-
- if ($.isArray(rawProps.className)) {
- this.className = rawProps.className;
- }
- if (typeof rawProps.className === 'string') {
- this.className = rawProps.className.split(/\s+/);
- }
- return true;
- },
- applyOtherRawProps: function(rawProps) {
- this.miscProps = rawProps;
- }
- });
- EventDef.allowRawProps = ParsableModelMixin_allowRawProps;
- EventDef.copyVerbatimStandardProps = ParsableModelMixin_copyVerbatimStandardProps;
- EventDef.uuid = 0;
- EventDef.normalizeId = function(id) {
- return String(id);
- };
- EventDef.generateId = function() {
- return '_fc' + (EventDef.uuid++);
- };
- EventDef.allowRawProps({
-
- _id: false,
- id: false,
- className: false,
- source: false,
-
- title: true,
- url: true,
- rendering: true,
- constraint: true,
- overlap: true,
- editable: true,
- startEditable: true,
- durationEditable: true,
- color: true,
- backgroundColor: true,
- borderColor: true,
- textColor: true
- });
- EventDef.parse = function(rawInput, source) {
- var def = new this(source);
- var calendarTransform = source.calendar.opt('eventDataTransform');
- var sourceTransform = source.eventDataTransform;
- if (calendarTransform) {
- rawInput = calendarTransform(rawInput);
- }
- if (sourceTransform) {
- rawInput = sourceTransform(rawInput);
- }
- if (def.applyRawProps(rawInput)) {
- return def;
- }
- return false;
- };
- ;;
- var SingleEventDef = EventDef.extend({
- dateProfile: null,
-
- buildInstances: function() {
- return [ this.buildInstance() ];
- },
- buildInstance: function() {
- return new EventInstance(
- this,
- this.dateProfile
- );
- },
- isAllDay: function() {
- return this.dateProfile.isAllDay();
- },
- clone: function() {
- var def = EventDef.prototype.clone.call(this);
- def.dateProfile = this.dateProfile;
- return def;
- },
- rezone: function() {
- var calendar = this.source.calendar;
- var dateProfile = this.dateProfile;
- this.dateProfile = new EventDateProfile(
- calendar.moment(dateProfile.start),
- dateProfile.end ? calendar.moment(dateProfile.end) : null,
- calendar
- );
- },
-
- applyManualRawProps: function(rawProps) {
- var superSuccess = EventDef.prototype.applyManualRawProps.apply(this, arguments);
- var dateProfile = EventDateProfile.parse(rawProps, this.source);
- if (dateProfile) {
- this.dateProfile = dateProfile;
-
- if (rawProps.date != null) {
- this.miscProps.date = rawProps.date;
- }
- return superSuccess;
- }
- else {
- return false;
- }
- }
- });
- SingleEventDef.allowRawProps({
- start: false,
- date: false,
- end: false,
- allDay: false
- });
- ;;
- var RecurringEventDef = EventDef.extend({
- startTime: null,
- endTime: null,
- dowHash: null,
- isAllDay: function() {
- return !this.startTime && !this.endTime;
- },
- buildInstances: function(unzonedRange) {
- var calendar = this.source.calendar;
- var unzonedDate = unzonedRange.getStart();
- var unzonedEnd = unzonedRange.getEnd();
- var zonedDayStart;
- var instanceStart, instanceEnd;
- var instances = [];
- while (unzonedDate.isBefore(unzonedEnd)) {
-
- if (!this.dowHash || this.dowHash[unzonedDate.day()]) {
- zonedDayStart = calendar.applyTimezone(unzonedDate);
- instanceStart = zonedDayStart.clone();
- instanceEnd = null;
- if (this.startTime) {
- instanceStart.time(this.startTime);
- }
- else {
- instanceStart.stripTime();
- }
- if (this.endTime) {
- instanceEnd = zonedDayStart.clone().time(this.endTime);
- }
- instances.push(
- new EventInstance(
- this,
- new EventDateProfile(instanceStart, instanceEnd, calendar)
- )
- );
- }
- unzonedDate.add(1, 'days');
- }
- return instances;
- },
- setDow: function(dowNumbers) {
- if (!this.dowHash) {
- this.dowHash = {};
- }
- for (var i = 0; i < dowNumbers.length; i++) {
- this.dowHash[dowNumbers[i]] = true;
- }
- },
- clone: function() {
- var def = EventDef.prototype.clone.call(this);
- if (def.startTime) {
- def.startTime = moment.duration(this.startTime);
- }
- if (def.endTime) {
- def.endTime = moment.duration(this.endTime);
- }
- if (this.dowHash) {
- def.dowHash = $.extend({}, this.dowHash);
- }
- return def;
- },
-
- applyRawProps: function(rawProps) {
- var superSuccess = EventDef.prototype.applyRawProps.apply(this, arguments);
- if (rawProps.start) {
- this.startTime = moment.duration(rawProps.start);
- }
- if (rawProps.end) {
- this.endTime = moment.duration(rawProps.end);
- }
- if (rawProps.dow) {
- this.setDow(rawProps.dow);
- }
- return superSuccess;
- }
- });
- RecurringEventDef.allowRawProps({
- start: false,
- end: false,
- dow: false
- });
- ;;
- var EventInstance = Class.extend({
- def: null,
- dateProfile: null,
- constructor: function(def, dateProfile) {
- this.def = def;
- this.dateProfile = dateProfile;
- },
- toLegacy: function() {
- var dateProfile = this.dateProfile;
- var obj = this.def.toLegacy();
- obj.start = dateProfile.start.clone();
- obj.end = dateProfile.end ? dateProfile.end.clone() : null;
- return obj;
- }
- });
- ;;
- var EventInstanceGroup = Class.extend({
- eventInstances: null,
- explicitEventDef: null,
- constructor: function(eventInstances) {
- this.eventInstances = eventInstances || [];
- },
- getAllEventRanges: function() {
- return eventInstancesToEventRanges(this.eventInstances);
- },
- sliceRenderRanges: function(constraintRange) {
- if (this.isInverse()) {
- return this.sliceInverseRenderRanges(constraintRange);
- }
- else {
- return this.sliceNormalRenderRanges(constraintRange);
- }
- },
- sliceNormalRenderRanges: function(constraintRange) {
- var eventInstances = this.eventInstances;
- var i, eventInstance;
- var slicedRange;
- var slicedEventRanges = [];
- for (i = 0; i < eventInstances.length; i++) {
- eventInstance = eventInstances[i];
- slicedRange = eventInstance.dateProfile.unzonedRange.intersect(constraintRange);
- if (slicedRange) {
- slicedEventRanges.push(
- new EventRange(
- slicedRange,
- eventInstance.def,
- eventInstance
- )
- );
- }
- }
- return slicedEventRanges;
- },
- sliceInverseRenderRanges: function(constraintRange) {
- var unzonedRanges = eventInstancesToUnzonedRanges(this.eventInstances);
- var ownerDef = this.getEventDef();
- unzonedRanges = invertUnzonedRanges(unzonedRanges, constraintRange);
- return unzonedRanges.map(function(unzonedRange) {
- return new EventRange(unzonedRange, ownerDef);
- });
- },
- isInverse: function() {
- return this.getEventDef().hasInverseRendering();
- },
- getEventDef: function() {
- return this.explicitEventDef || this.eventInstances[0].def;
- }
- });
- ;;
- var EventDateProfile = Class.extend({
- start: null,
- end: null,
- unzonedRange: null,
- constructor: function(start, end, calendar) {
- this.start = start;
- this.end = end || null;
- this.unzonedRange = this.buildUnzonedRange(calendar);
- },
- isAllDay: function() {
- return !(this.start.hasTime() || (this.end && this.end.hasTime()));
- },
-
- buildUnzonedRange: function(calendar) {
- var startMs = this.start.clone().stripZone().valueOf();
- var endMs = this.getEnd(calendar).stripZone().valueOf();
- return new UnzonedRange(startMs, endMs);
- },
-
- getEnd: function(calendar) {
- return this.end ?
- this.end.clone() :
-
- calendar.getDefaultEventEnd(
- this.isAllDay(),
- this.start
- );
- }
- });
- EventDateProfile.parse = function(rawProps, source) {
- var startInput = rawProps.start || rawProps.date;
- var endInput = rawProps.end;
- if (!startInput) {
- return false;
- }
- var calendar = source.calendar;
- var start = calendar.moment(startInput);
- var end = endInput ? calendar.moment(endInput) : null;
- var forcedAllDay = rawProps.allDay;
- var forceEventDuration = calendar.opt('forceEventDuration');
- if (!start.isValid()) {
- return false;
- }
- if (end && (!end.isValid() || !end.isAfter(start))) {
- end = null;
- }
- if (forcedAllDay == null) {
- forcedAllDay = source.allDayDefault;
- if (forcedAllDay == null) {
- forcedAllDay = calendar.opt('allDayDefault');
- }
- }
- if (forcedAllDay === true) {
- start.stripTime();
- if (end) {
- end.stripTime();
- }
- }
- else if (forcedAllDay === false) {
- if (!start.hasTime()) {
- start.time(0);
- }
- if (end && !end.hasTime()) {
- end.time(0);
- }
- }
- if (!end && forceEventDuration) {
- end = calendar.getDefaultEventEnd(!start.hasTime(), start);
- }
- return new EventDateProfile(start, end, calendar);
- };
- ;;
- var EventRange = Class.extend({
- unzonedRange: null,
- eventDef: null,
- eventInstance: null,
- constructor: function(unzonedRange, eventDef, eventInstance) {
- this.unzonedRange = unzonedRange;
- this.eventDef = eventDef;
- if (eventInstance) {
- this.eventInstance = eventInstance;
- }
- }
- });
- ;;
- var EventFootprint = FC.EventFootprint = Class.extend({
- componentFootprint: null,
- eventDef: null,
- eventInstance: null,
- constructor: function(componentFootprint, eventDef, eventInstance) {
- this.componentFootprint = componentFootprint;
- this.eventDef = eventDef;
- if (eventInstance) {
- this.eventInstance = eventInstance;
- }
- },
- getEventLegacy: function() {
- return (this.eventInstance || this.eventDef).toLegacy();
- }
- });
- ;;
- var EventDefMutation = FC.EventDefMutation = Class.extend({
-
-
- dateMutation: null,
-
-
- rawProps: null,
-
- mutateSingle: function(eventDef) {
- var origDateProfile;
- if (this.dateMutation) {
- origDateProfile = eventDef.dateProfile;
- eventDef.dateProfile = this.dateMutation.buildNewDateProfile(
- origDateProfile,
- eventDef.source.calendar
- );
- }
-
- if (this.rawProps) {
- eventDef.applyRawProps(this.rawProps);
- }
- if (origDateProfile) {
- return function() {
- eventDef.dateProfile = origDateProfile;
- };
- }
- else {
- return function() { };
- }
- },
- setDateMutation: function(dateMutation) {
- if (dateMutation && !dateMutation.isEmpty()) {
- this.dateMutation = dateMutation;
- }
- else {
- this.dateMutation = null;
- }
- },
- isEmpty: function() {
- return !this.dateMutation;
- }
- });
- EventDefMutation.createFromRawProps = function(eventInstance, newRawProps, largeUnit) {
- var eventDef = eventInstance.def;
- var applicableRawProps = {};
- var propName;
- var newDateProfile;
- var dateMutation;
- var defMutation;
- for (propName in newRawProps) {
- if (
-
-
- typeof newRawProps[propName] !== 'object' &&
- propName !== 'start' && propName !== 'end' && propName !== 'allDay' &&
- propName !== 'source' && propName !== '_id'
- ) {
- applicableRawProps[propName] = newRawProps[propName];
- }
- }
- newDateProfile = EventDateProfile.parse(newRawProps, eventDef.source);
- if (newDateProfile) {
- dateMutation = EventDefDateMutation.createFromDiff(
- eventInstance.dateProfile,
- newDateProfile,
- largeUnit
- );
- }
- defMutation = new EventDefMutation();
- defMutation.rawProps = applicableRawProps;
- if (dateMutation) {
- defMutation.dateMutation = dateMutation;
- }
- return defMutation;
- };
- ;;
- var EventDefDateMutation = Class.extend({
- clearEnd: false,
- forceTimed: false,
- forceAllDay: false,
-
-
- dateDelta: null,
- startDelta: null,
- endDelta: null,
-
- buildNewDateProfile: function(eventDateProfile, calendar) {
- var start = eventDateProfile.start.clone();
- var end = null;
- var shouldRezone = false;
- if (!this.clearEnd && eventDateProfile.end) {
- end = eventDateProfile.end.clone();
- }
- if (this.forceTimed) {
- shouldRezone = true;
- if (!start.hasTime()) {
- start.time(0);
- }
- if (end && !end.hasTime()) {
- end.time(0);
- }
- }
- else if (this.forceAllDay) {
- if (start.hasTime()) {
- start.stripTime();
- }
- if (end && end.hasTime()) {
- end.stripTime();
- }
- }
- if (this.dateDelta) {
- shouldRezone = true;
- start.add(this.dateDelta);
- if (end) {
- end.add(this.dateDelta);
- }
- }
-
- if (this.endDelta) {
- shouldRezone = true;
- if (!end) {
- end = calendar.getDefaultEventEnd(eventDateProfile.isAllDay(), start);
- }
- end.add(this.endDelta);
- }
- if (this.startDelta) {
- shouldRezone = true;
- start.add(this.startDelta);
- }
- if (shouldRezone) {
- start = calendar.applyTimezone(start);
- if (end) {
- end = calendar.applyTimezone(end);
- }
- }
-
- if (!end && calendar.opt('forceEventDuration')) {
- end = calendar.getDefaultEventEnd(eventDateProfile.isAllDay(), start);
- }
- return new EventDateProfile(start, end, calendar);
- },
- setDateDelta: function(dateDelta) {
- if (dateDelta && dateDelta.valueOf()) {
- this.dateDelta = dateDelta;
- }
- else {
- this.dateDelta = null;
- }
- },
- setStartDelta: function(startDelta) {
- if (startDelta && startDelta.valueOf()) {
- this.startDelta = startDelta;
- }
- else {
- this.startDelta = null;
- }
- },
- setEndDelta: function(endDelta) {
- if (endDelta && endDelta.valueOf()) {
- this.endDelta = endDelta;
- }
- else {
- this.endDelta = null;
- }
- },
- isEmpty: function() {
- return !this.clearEnd && !this.forceTimed && !this.forceAllDay &&
- !this.dateDelta && !this.startDelta && !this.endDelta;
- }
- });
- EventDefDateMutation.createFromDiff = function(dateProfile0, dateProfile1, largeUnit) {
- var clearEnd = dateProfile0.end && !dateProfile1.end;
- var forceTimed = dateProfile0.isAllDay() && !dateProfile1.isAllDay();
- var forceAllDay = !dateProfile0.isAllDay() && dateProfile1.isAllDay();
- var dateDelta;
- var endDiff;
- var endDelta;
- var mutation;
-
- function subtractDates(date1, date0) {
- if (largeUnit) {
- return diffByUnit(date1, date0, largeUnit);
- }
- else if (dateProfile1.isAllDay()) {
- return diffDay(date1, date0);
- }
- else {
- return diffDayTime(date1, date0);
- }
- }
- dateDelta = subtractDates(dateProfile1.start, dateProfile0.start);
- if (dateProfile1.end) {
-
- endDiff = subtractDates(
- dateProfile1.unzonedRange.getEnd(),
- dateProfile0.unzonedRange.getEnd()
- );
- endDelta = endDiff.subtract(dateDelta);
- }
- mutation = new EventDefDateMutation();
- mutation.clearEnd = clearEnd;
- mutation.forceTimed = forceTimed;
- mutation.forceAllDay = forceAllDay;
- mutation.setDateDelta(dateDelta);
- mutation.setEndDelta(endDelta);
- return mutation;
- };
- ;;
- function eventDefsToEventInstances(eventDefs, unzonedRange) {
- var eventInstances = [];
- var i;
- for (i = 0; i < eventDefs.length; i++) {
- eventInstances.push.apply(eventInstances,
- eventDefs[i].buildInstances(unzonedRange)
- );
- }
- return eventInstances;
- }
- function eventInstancesToEventRanges(eventInstances) {
- return eventInstances.map(function(eventInstance) {
- return new EventRange(
- eventInstance.dateProfile.unzonedRange,
- eventInstance.def,
- eventInstance
- );
- });
- }
- function eventInstancesToUnzonedRanges(eventInstances) {
- return eventInstances.map(function(eventInstance) {
- return eventInstance.dateProfile.unzonedRange;
- });
- }
- function eventFootprintsToComponentFootprints(eventFootprints) {
- return eventFootprints.map(function(eventFootprint) {
- return eventFootprint.componentFootprint;
- });
- }
- ;;
- var EventSource = Class.extend(ParsableModelMixin, {
- calendar: null,
- id: null,
- uid: null,
- color: null,
- backgroundColor: null,
- borderColor: null,
- textColor: null,
- className: null,
- editable: null,
- startEditable: null,
- durationEditable: null,
- rendering: null,
- overlap: null,
- constraint: null,
- allDayDefault: null,
- eventDataTransform: null,
- constructor: function(calendar) {
- this.calendar = calendar;
- this.className = [];
- this.uid = String(EventSource.uuid++);
- },
- fetch: function(start, end, timezone) {
-
- },
- removeEventDefsById: function(eventDefId) {
-
- },
- removeAllEventDefs: function() {
-
- },
-
- getPrimitive: function(otherSource) {
-
- },
- parseEventDefs: function(rawEventDefs) {
- var i;
- var eventDef;
- var eventDefs = [];
- for (i = 0; i < rawEventDefs.length; i++) {
- eventDef = EventDefParser.parse(
- rawEventDefs[i],
- this
- );
- if (eventDef) {
- eventDefs.push(eventDef);
- }
- }
- return eventDefs;
- },
- applyManualRawProps: function(rawProps) {
- if (rawProps.id != null) {
- this.id = EventSource.normalizeId(rawProps.id);
- }
-
- if ($.isArray(rawProps.className)) {
- this.className = rawProps.className;
- }
- else if (typeof rawProps.className === 'string') {
- this.className = rawProps.className.split(/\s+/);
- }
- return true;
- }
- });
- EventSource.allowRawProps = ParsableModelMixin_allowRawProps;
- EventSource.uuid = 0;
- EventSource.normalizeId = function(id) {
- if (id) {
- return String(id);
- }
- return null;
- };
- EventSource.allowRawProps({
-
- id: false,
- className: false,
-
- color: true,
- backgroundColor: true,
- borderColor: true,
- textColor: true,
- editable: true,
- startEditable: true,
- durationEditable: true,
- rendering: true,
- overlap: true,
- constraint: true,
- allDayDefault: true,
- eventDataTransform: true
- });
- EventSource.parse = function(rawInput, calendar) {
- var source = new this(calendar);
- if (typeof rawInput === 'object') {
- if (source.applyRawProps(rawInput)) {
- return source;
- }
- }
- return false;
- };
- FC.EventSource = EventSource;
- ;;
- var EventSourceParser = {
- sourceClasses: [],
- registerClass: function(EventSourceClass) {
- this.sourceClasses.unshift(EventSourceClass);
- },
- parse: function(rawInput, calendar) {
- var sourceClasses = this.sourceClasses;
- var i;
- var eventSource;
- for (i = 0; i < sourceClasses.length; i++) {
- eventSource = sourceClasses[i].parse(rawInput, calendar);
- if (eventSource) {
- return eventSource;
- }
- }
- }
- };
- FC.EventSourceParser = EventSourceParser;
- ;;
- var ArrayEventSource = EventSource.extend({
- rawEventDefs: null,
- eventDefs: null,
- currentTimezone: null,
- constructor: function(calendar) {
- EventSource.apply(this, arguments);
- this.eventDefs = [];
- },
- setRawEventDefs: function(rawEventDefs) {
- this.rawEventDefs = rawEventDefs;
- this.eventDefs = this.parseEventDefs(rawEventDefs);
- },
- fetch: function(start, end, timezone) {
- var eventDefs = this.eventDefs;
- var i;
- if (
- this.currentTimezone !== null &&
- this.currentTimezone !== timezone
- ) {
- for (i = 0; i < eventDefs.length; i++) {
- if (eventDefs[i] instanceof SingleEventDef) {
- eventDefs[i].rezone();
- }
- }
- }
- this.currentTimezone = timezone;
- return Promise.resolve(eventDefs);
- },
- addEventDef: function(eventDef) {
- this.eventDefs.push(eventDef);
- },
-
- removeEventDefsById: function(eventDefId) {
- return removeMatching(this.eventDefs, function(eventDef) {
- return eventDef.id === eventDefId;
- });
- },
- removeAllEventDefs: function() {
- this.eventDefs = [];
- },
- getPrimitive: function() {
- return this.rawEventDefs;
- },
- applyManualRawProps: function(rawProps) {
- var superSuccess = EventSource.prototype.applyManualRawProps.apply(this, arguments);
- this.setRawEventDefs(rawProps.events);
- return superSuccess;
- }
- });
- ArrayEventSource.allowRawProps({
- events: false
- });
- ArrayEventSource.parse = function(rawInput, calendar) {
- var rawProps;
-
- if ($.isArray(rawInput.events)) {
- rawProps = rawInput;
- }
- else if ($.isArray(rawInput)) {
- rawProps = { events: rawInput };
- }
- if (rawProps) {
- return EventSource.parse.call(this, rawProps, calendar);
- }
- return false;
- };
- EventSourceParser.registerClass(ArrayEventSource);
- FC.ArrayEventSource = ArrayEventSource;
- ;;
- var FuncEventSource = EventSource.extend({
- func: null,
- fetch: function(start, end, timezone) {
- var _this = this;
- this.calendar.pushLoading();
- return Promise.construct(function(onResolve) {
- _this.func.call(
- this.calendar,
- start.clone(),
- end.clone(),
- timezone,
- function(rawEventDefs) {
- _this.calendar.popLoading();
- onResolve(_this.parseEventDefs(rawEventDefs));
- }
- );
- });
- },
- getPrimitive: function() {
- return this.func;
- },
- applyManualRawProps: function(rawProps) {
- var superSuccess = EventSource.prototype.applyManualRawProps.apply(this, arguments);
- this.func = rawProps.events;
- return superSuccess;
- }
- });
- FuncEventSource.allowRawProps({
- events: false
- });
- FuncEventSource.parse = function(rawInput, calendar) {
- var rawProps;
-
- if ($.isFunction(rawInput.events)) {
- rawProps = rawInput;
- }
- else if ($.isFunction(rawInput)) {
- rawProps = { events: rawInput };
- }
- if (rawProps) {
- return EventSource.parse.call(this, rawProps, calendar);
- }
- return false;
- };
- EventSourceParser.registerClass(FuncEventSource);
- FC.FuncEventSource = FuncEventSource;
- ;;
- var JsonFeedEventSource = EventSource.extend({
-
- startParam: null,
- endParam: null,
- timezoneParam: null,
- ajaxSettings: null,
- fetch: function(start, end, timezone) {
- var _this = this;
- var ajaxSettings = this.ajaxSettings;
- var onSuccess = ajaxSettings.success;
- var onError = ajaxSettings.error;
- var requestParams = this.buildRequestParams(start, end, timezone);
-
-
-
- this.calendar.pushLoading();
- return Promise.construct(function(onResolve, onReject) {
- $.ajax($.extend(
- {},
- JsonFeedEventSource.AJAX_DEFAULTS,
- ajaxSettings,
- {
- data: requestParams,
- success: function(rawEventDefs) {
- var callbackRes;
- _this.calendar.popLoading();
- if (rawEventDefs) {
- callbackRes = applyAll(onSuccess, this, arguments);
- if ($.isArray(callbackRes)) {
- rawEventDefs = callbackRes;
- }
- onResolve(_this.parseEventDefs(rawEventDefs));
- }
- else {
- onReject();
- }
- },
- error: function() {
- _this.calendar.popLoading();
- applyAll(onError, this, arguments);
- onReject();
- }
- }
- ));
- });
- },
- buildRequestParams: function(start, end, timezone) {
- var calendar = this.calendar;
- var ajaxSettings = this.ajaxSettings;
- var startParam, endParam, timezoneParam;
- var customRequestParams;
- var params = {};
- startParam = this.startParam;
- if (startParam == null) {
- startParam = calendar.opt('startParam');
- }
- endParam = this.endParam;
- if (endParam == null) {
- endParam = calendar.opt('endParam');
- }
- timezoneParam = this.timezoneParam;
- if (timezoneParam == null) {
- timezoneParam = calendar.opt('timezoneParam');
- }
-
- if ($.isFunction(ajaxSettings.data)) {
-
- customRequestParams = ajaxSettings.data();
- }
- else {
-
- customRequestParams = ajaxSettings.data || {};
- }
- $.extend(params, customRequestParams);
- params[startParam] = start.format();
- params[endParam] = end.format();
- if (timezone && timezone !== 'local') {
- params[timezoneParam] = timezone;
- }
- return params;
- },
- getPrimitive: function() {
- return this.ajaxSettings.url;
- },
- applyOtherRawProps: function(rawProps) {
- EventSource.prototype.applyOtherRawProps.apply(this, arguments);
- this.ajaxSettings = rawProps;
- }
- });
- JsonFeedEventSource.AJAX_DEFAULTS = {
- dataType: 'json',
- cache: false
- };
- JsonFeedEventSource.allowRawProps({
-
- startParam: true,
- endParam: true,
- timezoneParam: true
- });
- JsonFeedEventSource.parse = function(rawInput, calendar) {
- var rawProps;
-
- if (typeof rawInput.url === 'string') {
- rawProps = rawInput;
- }
- else if (typeof rawInput === 'string') {
- rawProps = { url: rawInput };
- }
- if (rawProps) {
- return EventSource.parse.call(this, rawProps, calendar);
- }
- return false;
- };
- EventSourceParser.registerClass(JsonFeedEventSource);
- FC.JsonFeedEventSource = JsonFeedEventSource;
- ;;
- var ThemeRegistry = FC.ThemeRegistry = {
- themeClassHash: {},
- register: function(themeName, themeClass) {
- this.themeClassHash[themeName] = themeClass;
- },
- getThemeClass: function(themeSetting) {
- if (!themeSetting) {
- return StandardTheme;
- }
- else if (themeSetting === true) {
- return JqueryUiTheme;
- }
- else {
- return this.themeClassHash[themeSetting];
- }
- }
- };
- ;;
- var Theme = FC.Theme = Class.extend({
- classes: {},
- iconClasses: {},
- baseIconClass: '',
- iconOverrideOption: null,
- iconOverrideCustomButtonOption: null,
- iconOverridePrefix: '',
- constructor: function(optionsModel) {
- this.optionsModel = optionsModel;
- this.processIconOverride();
- },
- processIconOverride: function() {
- if (this.iconOverrideOption) {
- this.setIconOverride(
- this.optionsModel.get(this.iconOverrideOption)
- );
- }
- },
- setIconOverride: function(iconOverrideHash) {
- var iconClassesCopy;
- var buttonName;
- if ($.isPlainObject(iconOverrideHash)) {
- iconClassesCopy = $.extend({}, this.iconClasses);
- for (buttonName in iconOverrideHash) {
- iconClassesCopy[buttonName] = this.applyIconOverridePrefix(
- iconOverrideHash[buttonName]
- );
- }
- this.iconClasses = iconClassesCopy;
- }
- else if (iconOverrideHash === false) {
- this.iconClasses = {};
- }
- },
- applyIconOverridePrefix: function(className) {
- var prefix = this.iconOverridePrefix;
- if (prefix && className.indexOf(prefix) !== 0) {
- className = prefix + className;
- }
- return className;
- },
- getClass: function(key) {
- return this.classes[key] || '';
- },
- getIconClass: function(buttonName) {
- var className = this.iconClasses[buttonName];
- if (className) {
- return this.baseIconClass + ' ' + className;
- }
- return '';
- },
- getCustomButtonIconClass: function(customButtonProps) {
- var className;
- if (this.iconOverrideCustomButtonOption) {
- className = customButtonProps[this.iconOverrideCustomButtonOption];
- if (className) {
- return this.baseIconClass + ' ' + this.applyIconOverridePrefix(className);
- }
- }
- return '';
- }
- });
- ;;
- var StandardTheme = Theme.extend({
- classes: {
- widget: 'fc-unthemed',
- widgetHeader: 'fc-widget-header',
- widgetContent: 'fc-widget-content',
- buttonGroup: 'fc-button-group',
- button: 'fc-button',
- cornerLeft: 'fc-corner-left',
- cornerRight: 'fc-corner-right',
- stateDefault: 'fc-state-default',
- stateActive: 'fc-state-active',
- stateDisabled: 'fc-state-disabled',
- stateHover: 'fc-state-hover',
- stateDown: 'fc-state-down',
- popoverHeader: 'fc-widget-header',
- popoverContent: 'fc-widget-content',
-
- headerRow: 'fc-widget-header',
- dayRow: 'fc-widget-content',
-
- listView: 'fc-widget-content'
- },
- baseIconClass: 'fc-icon',
- iconClasses: {
- close: 'fc-icon-x',
- prev: 'fc-icon-left-single-arrow',
- next: 'fc-icon-right-single-arrow',
- prevYear: 'fc-icon-left-double-arrow',
- nextYear: 'fc-icon-right-double-arrow'
- },
- iconOverrideOption: 'buttonIcons',
- iconOverrideCustomButtonOption: 'icon',
- iconOverridePrefix: 'fc-icon-'
- });
- ThemeRegistry.register('standard', StandardTheme);
- ;;
- var JqueryUiTheme = Theme.extend({
- classes: {
- widget: 'ui-widget',
- widgetHeader: 'ui-widget-header',
- widgetContent: 'ui-widget-content',
- buttonGroup: 'fc-button-group',
- button: 'ui-button',
- cornerLeft: 'ui-corner-left',
- cornerRight: 'ui-corner-right',
- stateDefault: 'ui-state-default',
- stateActive: 'ui-state-active',
- stateDisabled: 'ui-state-disabled',
- stateHover: 'ui-state-hover',
- stateDown: 'ui-state-down',
- today: 'ui-state-highlight',
- popoverHeader: 'ui-widget-header',
- popoverContent: 'ui-widget-content',
-
- headerRow: 'ui-widget-header',
- dayRow: 'ui-widget-content',
-
- listView: 'ui-widget-content'
- },
- baseIconClass: 'ui-icon',
- iconClasses: {
- close: 'ui-icon-closethick',
- prev: 'ui-icon-circle-triangle-w',
- next: 'ui-icon-circle-triangle-e',
- prevYear: 'ui-icon-seek-prev',
- nextYear: 'ui-icon-seek-next'
- },
- iconOverrideOption: 'themeButtonIcons',
- iconOverrideCustomButtonOption: 'themeIcon',
- iconOverridePrefix: 'ui-icon-'
- });
- ThemeRegistry.register('jquery-ui', JqueryUiTheme);
- ;;
- var BootstrapTheme = Theme.extend({
- classes: {
- widget: 'fc-bootstrap3',
- tableGrid: 'table-bordered',
- tableList: 'table table-striped',
- buttonGroup: 'btn-group',
- button: 'btn btn-default',
- stateActive: 'active',
- stateDisabled: 'disabled',
- today: 'alert alert-info',
- popover: 'panel panel-default',
- popoverHeader: 'panel-heading',
- popoverContent: 'panel-body',
-
- headerRow: 'panel-default',
- dayRow: 'panel-default',
-
- listView: 'panel panel-default'
- },
- baseIconClass: 'glyphicon',
- iconClasses: {
- close: 'glyphicon-remove',
- prev: 'glyphicon-chevron-left',
- next: 'glyphicon-chevron-right',
- prevYear: 'glyphicon-backward',
- nextYear: 'glyphicon-forward'
- },
- iconOverrideOption: 'bootstrapGlyphicons',
- iconOverrideCustomButtonOption: 'bootstrapGlyphicon',
- iconOverridePrefix: 'glyphicon-'
- });
- ThemeRegistry.register('bootstrap3', BootstrapTheme);
- ;;
- var BasicView = FC.BasicView = View.extend({
- scroller: null,
- dayGridClass: DayGrid,
- dayGrid: null,
- dayNumbersVisible: false,
- colWeekNumbersVisible: false,
- cellWeekNumbersVisible: false,
- weekNumberWidth: null,
- headContainerEl: null,
- headRowEl: null,
- initialize: function() {
- this.dayGrid = this.instantiateDayGrid();
- this.addChild(this.dayGrid);
- this.scroller = new Scroller({
- overflowX: 'hidden',
- overflowY: 'auto'
- });
- },
-
- instantiateDayGrid: function() {
-
-
- var subclass = this.dayGridClass.extend(basicDayGridMethods);
- return new subclass(this);
- },
-
- buildRenderRange: function(currentUnzonedRange, currentRangeUnit) {
- var renderUnzonedRange = View.prototype.buildRenderRange.apply(this, arguments);
- var start = this.calendar.msToUtcMoment(renderUnzonedRange.startMs, this.isRangeAllDay);
- var end = this.calendar.msToUtcMoment(renderUnzonedRange.endMs, this.isRangeAllDay);
-
- if (/^(year|month)$/.test(currentRangeUnit)) {
- start.startOf('week');
-
- if (end.weekday()) {
- end.add(1, 'week').startOf('week');
- }
- }
- return this.trimHiddenDays(new UnzonedRange(start, end));
- },
-
- renderDates: function() {
- this.dayGrid.breakOnWeeks = /year|month|week/.test(this.currentRangeUnit);
- this.dayGrid.setRange(this.renderUnzonedRange);
- this.dayNumbersVisible = this.dayGrid.rowCnt > 1;
- if (this.opt('weekNumbers')) {
- if (this.opt('weekNumbersWithinDays')) {
- this.cellWeekNumbersVisible = true;
- this.colWeekNumbersVisible = false;
- }
- else {
- this.cellWeekNumbersVisible = false;
- this.colWeekNumbersVisible = true;
- };
- }
- this.dayGrid.numbersVisible = this.dayNumbersVisible ||
- this.cellWeekNumbersVisible || this.colWeekNumbersVisible;
- this.el.addClass('fc-basic-view').html(this.renderSkeletonHtml());
- this.renderHead();
- this.scroller.render();
- var dayGridContainerEl = this.scroller.el.addClass('fc-day-grid-container');
- var dayGridEl = $('<div class="fc-day-grid" />').appendTo(dayGridContainerEl);
- this.el.find('.fc-body > tr > td').append(dayGridContainerEl);
- this.dayGrid.setElement(dayGridEl);
- this.dayGrid.renderDates(this.hasRigidRows());
- },
-
- renderHead: function() {
- this.headContainerEl =
- this.el.find('.fc-head-container')
- .html(this.dayGrid.renderHeadHtml());
- this.headRowEl = this.headContainerEl.find('.fc-row');
- },
-
-
- unrenderDates: function() {
- this.dayGrid.unrenderDates();
- this.dayGrid.removeElement();
- this.scroller.destroy();
- },
-
-
- renderSkeletonHtml: function() {
- var theme = this.calendar.theme;
- return '' +
- '<table class="' + theme.getClass('tableGrid') + '">' +
- '<thead class="fc-head">' +
- '<tr>' +
- '<td class="fc-head-container ' + theme.getClass('widgetHeader') + '"></td>' +
- '</tr>' +
- '</thead>' +
- '<tbody class="fc-body">' +
- '<tr>' +
- '<td class="' + theme.getClass('widgetContent') + '"></td>' +
- '</tr>' +
- '</tbody>' +
- '</table>';
- },
-
- weekNumberStyleAttr: function() {
- if (this.weekNumberWidth !== null) {
- return 'style="width:' + this.weekNumberWidth + 'px"';
- }
- return '';
- },
-
- hasRigidRows: function() {
- var eventLimit = this.opt('eventLimit');
- return eventLimit && typeof eventLimit !== 'number';
- },
-
-
- updateWidth: function() {
- if (this.colWeekNumbersVisible) {
-
-
- this.weekNumberWidth = matchCellWidths(
- this.el.find('.fc-week-number')
- );
- }
- },
-
- setHeight: function(totalHeight, isAuto) {
- var eventLimit = this.opt('eventLimit');
- var scrollerHeight;
- var scrollbarWidths;
-
- this.scroller.clear();
- uncompensateScroll(this.headRowEl);
- this.dayGrid.removeSegPopover();
-
- if (eventLimit && typeof eventLimit === 'number') {
- this.dayGrid.limitRows(eventLimit);
- }
-
-
- scrollerHeight = this.computeScrollerHeight(totalHeight);
- this.setGridHeight(scrollerHeight, isAuto);
-
- if (eventLimit && typeof eventLimit !== 'number') {
- this.dayGrid.limitRows(eventLimit);
- }
- if (!isAuto) {
- this.scroller.setHeight(scrollerHeight);
- scrollbarWidths = this.scroller.getScrollbarWidths();
- if (scrollbarWidths.left || scrollbarWidths.right) {
- compensateScroll(this.headRowEl, scrollbarWidths);
-
- scrollerHeight = this.computeScrollerHeight(totalHeight);
- this.scroller.setHeight(scrollerHeight);
- }
-
- this.scroller.lockOverflow(scrollbarWidths);
- }
- },
-
- computeScrollerHeight: function(totalHeight) {
- return totalHeight -
- subtractInnerElHeight(this.el, this.scroller.el);
- },
-
- setGridHeight: function(height, isAuto) {
- if (isAuto) {
- undistributeHeight(this.dayGrid.rowEls);
- }
- else {
- distributeHeight(this.dayGrid.rowEls, height, true);
- }
- },
-
- computeInitialDateScroll: function() {
- return { top: 0 };
- },
- queryDateScroll: function() {
- return { top: this.scroller.getScrollTop() };
- },
- applyDateScroll: function(scroll) {
- if (scroll.top !== undefined) {
- this.scroller.setScrollTop(scroll.top);
- }
- },
-
-
- renderEventsPayload: function(eventsPayload) {
- this.dayGrid.renderEventsPayload(eventsPayload);
-
-
- this.updateHeight();
- }
- });
- var basicDayGridMethods = {
-
- renderHeadIntroHtml: function() {
- var view = this.view;
- if (view.colWeekNumbersVisible) {
- return '' +
- '<th class="fc-week-number ' + view.calendar.theme.getClass('widgetHeader') + '" ' + view.weekNumberStyleAttr() + '>' +
- '<span>' +
- htmlEscape(this.opt('weekNumberTitle')) +
- '</span>' +
- '</th>';
- }
- return '';
- },
-
- renderNumberIntroHtml: function(row) {
- var view = this.view;
- var weekStart = this.getCellDate(row, 0);
- if (view.colWeekNumbersVisible) {
- return '' +
- '<td class="fc-week-number" ' + view.weekNumberStyleAttr() + '>' +
- view.buildGotoAnchorHtml(
- { date: weekStart, type: 'week', forceOff: this.colCnt === 1 },
- weekStart.format('w')
- ) +
- '</td>';
- }
- return '';
- },
-
- renderBgIntroHtml: function() {
- var view = this.view;
- if (view.colWeekNumbersVisible) {
- return '<td class="fc-week-number ' + view.calendar.theme.getClass('widgetContent') + '" ' +
- view.weekNumberStyleAttr() + '></td>';
- }
- return '';
- },
-
-
- renderIntroHtml: function() {
- var view = this.view;
- if (view.colWeekNumbersVisible) {
- return '<td class="fc-week-number" ' + view.weekNumberStyleAttr() + '></td>';
- }
- return '';
- }
- };
- ;;
- var MonthView = FC.MonthView = BasicView.extend({
-
- buildRenderRange: function() {
- var renderUnzonedRange = BasicView.prototype.buildRenderRange.apply(this, arguments);
- var start = this.calendar.msToUtcMoment(renderUnzonedRange.startMs, this.isRangeAllDay);
- var end = this.calendar.msToUtcMoment(renderUnzonedRange.endMs, this.isRangeAllDay);
- var rowCnt;
-
- if (this.isFixedWeeks()) {
- rowCnt = Math.ceil(
- end.diff(start, 'weeks', true)
- );
- end.add(6 - rowCnt, 'weeks');
- }
- return new UnzonedRange(start, end);
- },
-
- setGridHeight: function(height, isAuto) {
-
- if (isAuto) {
- height *= this.rowCnt / 6;
- }
- distributeHeight(this.dayGrid.rowEls, height, !isAuto);
- },
- isFixedWeeks: function() {
- return this.opt('fixedWeekCount');
- },
- isDateInOtherMonth: function(date) {
- return date.month() !== moment.utc(this.currentUnzonedRange.startMs).month();
- }
- });
- ;;
- fcViews.basic = {
- 'class': BasicView
- };
- fcViews.basicDay = {
- type: 'basic',
- duration: { days: 1 }
- };
- fcViews.basicWeek = {
- type: 'basic',
- duration: { weeks: 1 }
- };
- fcViews.month = {
- 'class': MonthView,
- duration: { months: 1 },
- defaults: {
- fixedWeekCount: true
- }
- };
- ;;
- var AgendaView = FC.AgendaView = View.extend({
- scroller: null,
- timeGridClass: TimeGrid,
- timeGrid: null,
- dayGridClass: DayGrid,
- dayGrid: null,
- axisWidth: null,
- headContainerEl: null,
- noScrollRowEls: null,
-
- bottomRuleEl: null,
-
- usesMinMaxTime: true,
- initialize: function() {
- this.timeGrid = this.instantiateTimeGrid();
- this.addChild(this.timeGrid);
- if (this.opt('allDaySlot')) {
- this.dayGrid = this.instantiateDayGrid();
- this.addChild(this.dayGrid);
- }
- this.scroller = new Scroller({
- overflowX: 'hidden',
- overflowY: 'auto'
- });
- },
-
- instantiateTimeGrid: function() {
- var subclass = this.timeGridClass.extend(agendaTimeGridMethods);
- return new subclass(this);
- },
-
- instantiateDayGrid: function() {
- var subclass = this.dayGridClass.extend(agendaDayGridMethods);
- return new subclass(this);
- },
-
-
- renderDates: function() {
- this.timeGrid.setRange(this.renderUnzonedRange);
- if (this.dayGrid) {
- this.dayGrid.setRange(this.renderUnzonedRange);
- }
- this.el.addClass('fc-agenda-view').html(this.renderSkeletonHtml());
- this.renderHead();
- this.scroller.render();
- var timeGridWrapEl = this.scroller.el.addClass('fc-time-grid-container');
- var timeGridEl = $('<div class="fc-time-grid" />').appendTo(timeGridWrapEl);
- this.el.find('.fc-body > tr > td').append(timeGridWrapEl);
- this.timeGrid.setElement(timeGridEl);
- this.timeGrid.renderDates();
-
- this.bottomRuleEl = $('<hr class="fc-divider ' + this.calendar.theme.getClass('widgetHeader') + '"/>')
- .appendTo(this.timeGrid.el);
- if (this.dayGrid) {
- this.dayGrid.setElement(this.el.find('.fc-day-grid'));
- this.dayGrid.renderDates();
-
- this.dayGrid.bottomCoordPadding = this.dayGrid.el.next('hr').outerHeight();
- }
- this.noScrollRowEls = this.el.find('.fc-row:not(.fc-scroller *)');
- },
-
- renderHead: function() {
- this.headContainerEl =
- this.el.find('.fc-head-container')
- .html(this.timeGrid.renderHeadHtml());
- },
-
-
-
- unrenderDates: function() {
- this.timeGrid.unrenderDates();
- this.timeGrid.removeElement();
- if (this.dayGrid) {
- this.dayGrid.unrenderDates();
- this.dayGrid.removeElement();
- }
- this.scroller.destroy();
- },
-
-
- renderSkeletonHtml: function() {
- var theme = this.calendar.theme;
- return '' +
- '<table class="' + theme.getClass('tableGrid') + '">' +
- '<thead class="fc-head">' +
- '<tr>' +
- '<td class="fc-head-container ' + theme.getClass('widgetHeader') + '"></td>' +
- '</tr>' +
- '</thead>' +
- '<tbody class="fc-body">' +
- '<tr>' +
- '<td class="' + theme.getClass('widgetContent') + '">' +
- (this.dayGrid ?
- '<div class="fc-day-grid"/>' +
- '<hr class="fc-divider ' + theme.getClass('widgetHeader') + '"/>' :
- ''
- ) +
- '</td>' +
- '</tr>' +
- '</tbody>' +
- '</table>';
- },
-
- axisStyleAttr: function() {
- if (this.axisWidth !== null) {
- return 'style="width:' + this.axisWidth + 'px"';
- }
- return '';
- },
-
- getNowIndicatorUnit: function() {
- return this.timeGrid.getNowIndicatorUnit();
- },
-
- updateSize: function(isResize) {
- this.timeGrid.updateSize(isResize);
- View.prototype.updateSize.call(this, isResize);
- },
-
- updateWidth: function() {
-
- this.axisWidth = matchCellWidths(this.el.find('.fc-axis'));
- },
-
- setHeight: function(totalHeight, isAuto) {
- var eventLimit;
- var scrollerHeight;
- var scrollbarWidths;
-
- this.bottomRuleEl.hide();
- this.scroller.clear();
- uncompensateScroll(this.noScrollRowEls);
-
- if (this.dayGrid) {
- this.dayGrid.removeSegPopover();
- eventLimit = this.opt('eventLimit');
- if (eventLimit && typeof eventLimit !== 'number') {
- eventLimit = AGENDA_ALL_DAY_EVENT_LIMIT;
- }
- if (eventLimit) {
- this.dayGrid.limitRows(eventLimit);
- }
- }
- if (!isAuto) {
- scrollerHeight = this.computeScrollerHeight(totalHeight);
- this.scroller.setHeight(scrollerHeight);
- scrollbarWidths = this.scroller.getScrollbarWidths();
- if (scrollbarWidths.left || scrollbarWidths.right) {
-
- compensateScroll(this.noScrollRowEls, scrollbarWidths);
-
-
- scrollerHeight = this.computeScrollerHeight(totalHeight);
- this.scroller.setHeight(scrollerHeight);
- }
-
- this.scroller.lockOverflow(scrollbarWidths);
-
-
- if (this.timeGrid.getTotalSlatHeight() < scrollerHeight) {
- this.bottomRuleEl.show();
- }
- }
- },
-
- computeScrollerHeight: function(totalHeight) {
- return totalHeight -
- subtractInnerElHeight(this.el, this.scroller.el);
- },
-
-
- computeInitialDateScroll: function() {
- var scrollTime = moment.duration(this.opt('scrollTime'));
- var top = this.timeGrid.computeTimeTop(scrollTime);
-
- top = Math.ceil(top);
- if (top) {
- top++;
- }
- return { top: top };
- },
- queryDateScroll: function() {
- return { top: this.scroller.getScrollTop() };
- },
- applyDateScroll: function(scroll) {
- if (scroll.top !== undefined) {
- this.scroller.setScrollTop(scroll.top);
- }
- },
-
-
- getHitFootprint: function(hit) {
-
- return hit.component.getHitFootprint(hit);
- },
- getHitEl: function(hit) {
-
- return hit.component.getHitEl(hit);
- },
-
-
- renderEventsPayload: function(eventsPayload) {
- var dayEventsPayload = {};
- var timedEventsPayload = {};
- var daySegs = [];
- var timedSegs;
- var id, eventInstanceGroup;
-
- for (id in eventsPayload) {
- eventInstanceGroup = eventsPayload[id];
- if (eventInstanceGroup.getEventDef().isAllDay()) {
- dayEventsPayload[id] = eventInstanceGroup;
- }
- else {
- timedEventsPayload[id] = eventInstanceGroup;
- }
- }
-
- timedSegs = this.timeGrid.renderEventsPayload(timedEventsPayload);
- if (this.dayGrid) {
- daySegs = this.dayGrid.renderEventsPayload(dayEventsPayload);
- }
-
-
- this.updateHeight();
- },
-
-
- renderDrag: function(eventFootprints, seg) {
- if (eventFootprints.length) {
- if (!eventFootprints[0].componentFootprint.isAllDay) {
- return this.timeGrid.renderDrag(eventFootprints, seg);
- }
- else if (this.dayGrid) {
- return this.dayGrid.renderDrag(eventFootprints, seg);
- }
- }
- },
-
-
- renderSelectionFootprint: function(componentFootprint) {
- if (!componentFootprint.isAllDay) {
- this.timeGrid.renderSelectionFootprint(componentFootprint);
- }
- else if (this.dayGrid) {
- this.dayGrid.renderSelectionFootprint(componentFootprint);
- }
- }
- });
- var agendaTimeGridMethods = {
-
- renderHeadIntroHtml: function() {
- var view = this.view;
- var weekStart = view.calendar.msToUtcMoment(this.unzonedRange.startMs, true);
- var weekText;
- if (this.opt('weekNumbers')) {
- weekText = weekStart.format(this.opt('smallWeekFormat'));
- return '' +
- '<th class="fc-axis fc-week-number ' + view.calendar.theme.getClass('widgetHeader') + '" ' + view.axisStyleAttr() + '>' +
- view.buildGotoAnchorHtml(
- { date: weekStart, type: 'week', forceOff: this.colCnt > 1 },
- htmlEscape(weekText)
- ) +
- '</th>';
- }
- else {
- return '<th class="fc-axis ' + view.calendar.theme.getClass('widgetHeader') + '" ' + view.axisStyleAttr() + '></th>';
- }
- },
-
- renderBgIntroHtml: function() {
- var view = this.view;
- return '<td class="fc-axis ' + view.calendar.theme.getClass('widgetContent') + '" ' + view.axisStyleAttr() + '></td>';
- },
-
-
- renderIntroHtml: function() {
- var view = this.view;
- return '<td class="fc-axis" ' + view.axisStyleAttr() + '></td>';
- }
- };
- var agendaDayGridMethods = {
-
- renderBgIntroHtml: function() {
- var view = this.view;
- return '' +
- '<td class="fc-axis ' + view.calendar.theme.getClass('widgetContent') + '" ' + view.axisStyleAttr() + '>' +
- '<span>' +
- view.getAllDayHtml() +
- '</span>' +
- '</td>';
- },
-
-
- renderIntroHtml: function() {
- var view = this.view;
- return '<td class="fc-axis" ' + view.axisStyleAttr() + '></td>';
- }
- };
- ;;
- var AGENDA_ALL_DAY_EVENT_LIMIT = 5;
- var AGENDA_STOCK_SUB_DURATIONS = [
- { hours: 1 },
- { minutes: 30 },
- { minutes: 15 },
- { seconds: 30 },
- { seconds: 15 }
- ];
- fcViews.agenda = {
- 'class': AgendaView,
- defaults: {
- allDaySlot: true,
- slotDuration: '00:30:00',
- slotEventOverlap: true
- }
- };
- fcViews.agendaDay = {
- type: 'agenda',
- duration: { days: 1 }
- };
- fcViews.agendaWeek = {
- type: 'agenda',
- duration: { weeks: 1 }
- };
- ;;
- var ListView = View.extend({
- grid: null,
- scroller: null,
- initialize: function() {
- this.grid = new ListViewGrid(this);
- this.addChild(this.grid);
- this.scroller = new Scroller({
- overflowX: 'hidden',
- overflowY: 'auto'
- });
- },
- renderSkeleton: function() {
- this.el.addClass(
- 'fc-list-view ' +
- this.calendar.theme.getClass('listView')
- );
- this.scroller.render();
- this.scroller.el.appendTo(this.el);
- this.grid.setElement(this.scroller.scrollEl);
- },
- unrenderSkeleton: function() {
- this.scroller.destroy();
- },
- setHeight: function(totalHeight, isAuto) {
- this.scroller.setHeight(this.computeScrollerHeight(totalHeight));
- },
- computeScrollerHeight: function(totalHeight) {
- return totalHeight -
- subtractInnerElHeight(this.el, this.scroller.el);
- },
- renderDates: function() {
- this.grid.setRange(this.renderUnzonedRange);
- },
- isEventDefResizable: function(eventDef) {
- return false;
- },
- isEventDefDraggable: function(eventDef) {
- return false;
- }
- });
- var ListViewGrid = Grid.extend({
- dayDates: null,
- dayRanges: null,
- segSelector: '.fc-list-item',
- hasDayInteractions: false,
- rangeUpdated: function() {
- var calendar = this.view.calendar;
- var dayStart = calendar.msToUtcMoment(this.unzonedRange.startMs, true);
- var viewEnd = calendar.msToUtcMoment(this.unzonedRange.endMs, true);
- var dayDates = [];
- var dayRanges = [];
- while (dayStart < viewEnd) {
- dayDates.push(dayStart.clone());
- dayRanges.push(new UnzonedRange(
- dayStart,
- dayStart.clone().add(1, 'day')
- ));
- dayStart.add(1, 'day');
- }
- this.dayDates = dayDates;
- this.dayRanges = dayRanges;
- },
-
- componentFootprintToSegs: function(footprint) {
- var view = this.view;
- var dayRanges = this.dayRanges;
- var dayIndex;
- var segRange;
- var seg;
- var segs = [];
- for (dayIndex = 0; dayIndex < dayRanges.length; dayIndex++) {
- segRange = footprint.unzonedRange.intersect(dayRanges[dayIndex]);
- if (segRange) {
- seg = {
- startMs: segRange.startMs,
- endMs: segRange.endMs,
- isStart: segRange.isStart,
- isEnd: segRange.isEnd,
- dayIndex: dayIndex
- };
- segs.push(seg);
-
-
- if (
- !seg.isEnd && !footprint.isAllDay &&
- footprint.unzonedRange.endMs < dayRanges[dayIndex + 1].startMs + view.nextDayThreshold
- ) {
- seg.endMs = footprint.unzonedRange.endMs;
- seg.isEnd = true;
- break;
- }
- }
- }
- return segs;
- },
-
- computeEventTimeFormat: function() {
- return this.opt('mediumTimeFormat');
- },
-
-
- handleSegClick: function(seg, ev) {
- var url;
- Grid.prototype.handleSegClick.apply(this, arguments);
-
- if (!$(ev.target).closest('a[href]').length) {
- url = seg.footprint.eventDef.url;
- if (url && !ev.isDefaultPrevented()) {
- window.location.href = url;
- }
- }
- },
-
- renderFgSegs: function(segs) {
- segs = this.renderFgSegEls(segs);
- if (!segs.length) {
- this.renderEmptyMessage();
- }
- else {
- this.renderSegList(segs);
- }
- return segs;
- },
- renderEmptyMessage: function() {
- this.el.html(
- '<div class="fc-list-empty-wrap2">' +
- '<div class="fc-list-empty-wrap1">' +
- '<div class="fc-list-empty">' +
- htmlEscape(this.opt('noEventsMessage')) +
- '</div>' +
- '</div>' +
- '</div>'
- );
- },
-
- renderSegList: function(allSegs) {
- var segsByDay = this.groupSegsByDay(allSegs);
- var dayIndex;
- var daySegs;
- var i;
- var tableEl = $('<table class="fc-list-table ' + this.view.calendar.theme.getClass('tableList') + '"><tbody/></table>');
- var tbodyEl = tableEl.find('tbody');
- for (dayIndex = 0; dayIndex < segsByDay.length; dayIndex++) {
- daySegs = segsByDay[dayIndex];
- if (daySegs) {
-
- tbodyEl.append(this.dayHeaderHtml(this.dayDates[dayIndex]));
- this.sortEventSegs(daySegs);
- for (i = 0; i < daySegs.length; i++) {
- tbodyEl.append(daySegs[i].el);
- }
- }
- }
- this.el.empty().append(tableEl);
- },
-
- groupSegsByDay: function(segs) {
- var segsByDay = [];
- var i, seg;
- for (i = 0; i < segs.length; i++) {
- seg = segs[i];
- (segsByDay[seg.dayIndex] || (segsByDay[seg.dayIndex] = []))
- .push(seg);
- }
- return segsByDay;
- },
-
- dayHeaderHtml: function(dayDate) {
- var view = this.view;
- var mainFormat = this.opt('listDayFormat');
- var altFormat = this.opt('listDayAltFormat');
- return '<tr class="fc-list-heading" data-date="' + dayDate.format('YYYY-MM-DD') + '">' +
- '<td class="' + view.calendar.theme.getClass('widgetHeader') + '" colspan="3">' +
- (mainFormat ?
- view.buildGotoAnchorHtml(
- dayDate,
- { 'class': 'fc-list-heading-main' },
- htmlEscape(dayDate.format(mainFormat))
- ) :
- '') +
- (altFormat ?
- view.buildGotoAnchorHtml(
- dayDate,
- { 'class': 'fc-list-heading-alt' },
- htmlEscape(dayDate.format(altFormat))
- ) :
- '') +
- '</td>' +
- '</tr>';
- },
-
- fgSegHtml: function(seg) {
- var view = this.view;
- var calendar = view.calendar;
- var theme = calendar.theme;
- var classes = [ 'fc-list-item' ].concat(this.getSegCustomClasses(seg));
- var bgColor = this.getSegBackgroundColor(seg);
- var eventFootprint = seg.footprint;
- var eventDef = eventFootprint.eventDef;
- var componentFootprint = eventFootprint.componentFootprint;
- var url = eventDef.url;
- var timeHtml;
- if (componentFootprint.isAllDay) {
- timeHtml = view.getAllDayHtml();
- }
-
- else if (view.isMultiDayRange(componentFootprint.unzonedRange)) {
- if (seg.isStart || seg.isEnd) {
- timeHtml = htmlEscape(this._getEventTimeText(
- calendar.msToMoment(seg.startMs),
- calendar.msToMoment(seg.endMs),
- componentFootprint.isAllDay
- ));
- }
- else {
- timeHtml = view.getAllDayHtml();
- }
- }
- else {
-
- timeHtml = htmlEscape(this.getEventTimeText(eventFootprint));
- }
- if (url) {
- classes.push('fc-has-url');
- }
- return '<tr class="' + classes.join(' ') + '">' +
- (this.displayEventTime ?
- '<td class="fc-list-item-time ' + theme.getClass('widgetContent') + '">' +
- (timeHtml || '') +
- '</td>' :
- '') +
- '<td class="fc-list-item-marker ' + theme.getClass('widgetContent') + '">' +
- '<span class="fc-event-dot"' +
- (bgColor ?
- ' style="background-color:' + bgColor + '"' :
- '') +
- '></span>' +
- '</td>' +
- '<td class="fc-list-item-title ' + theme.getClass('widgetContent') + '">' +
- '<a' + (url ? ' href="' + htmlEscape(url) + '"' : '') + '>' +
- htmlEscape(eventDef.title || '') +
- '</a>' +
- '</td>' +
- '</tr>';
- }
- });
- ;;
- fcViews.list = {
- 'class': ListView,
- buttonTextKey: 'list',
- defaults: {
- buttonText: 'list',
- listDayFormat: 'LL',
- noEventsMessage: 'No events to display'
- }
- };
- fcViews.listDay = {
- type: 'list',
- duration: { days: 1 },
- defaults: {
- listDayFormat: 'dddd'
- }
- };
- fcViews.listWeek = {
- type: 'list',
- duration: { weeks: 1 },
- defaults: {
- listDayFormat: 'dddd',
- listDayAltFormat: 'LL'
- }
- };
- fcViews.listMonth = {
- type: 'list',
- duration: { month: 1 },
- defaults: {
- listDayAltFormat: 'dddd'
- }
- };
- fcViews.listYear = {
- type: 'list',
- duration: { year: 1 },
- defaults: {
- listDayAltFormat: 'dddd'
- }
- };
- ;;
- return FC;
- });
|