{"version":3,"sources":["libs/fullcalendar.js"],"names":["factory","define","amd","exports","module","require","jQuery","moment","$","mergeOptions","optionObjs","mergeProps","complexOptions","massageOverrides","input","subObj","overrides","views","each","name","val","isPlainObject","test","inArray","subName","subVal","compensateScroll","rowEls","scrollbarWidths","left","css","border-left-width","margin-left","right","border-right-width","margin-right","uncompensateScroll","disableCursor","addClass","enableCursor","removeClass","distributeHeight","els","availableHeight","shouldRedistribute","minOffset1","Math","floor","length","minOffset2","flexEls","flexOffsets","flexHeights","usedHeight","undistributeHeight","i","el","minOffset","naturalOffset","outerHeight","push","height","naturalHeight","newHeight","matchCellWidths","maxInnerWidth","find","innerEl","innerWidth","outerWidth","width","subtractInnerElHeight","outerEl","diff","both","add","position","getScrollParent","scrollParent","parents","filter","parent","this","eq","ownerDocument","document","getOuterRect","origin","offset","top","bottom","getClientRect","getScrollbarWidths","getCssFloat","clientWidth","clientHeight","getContentRect","leftRightWidth","widths","innerHeight","getIsLeftRtlScrollbars","_isLeftRtlScrollbars","computeIsLeftRtlScrollbars","border","padding","overflow","direction","appendTo","children","res","remove","prop","parseFloat","isPrimaryMouseButton","ev","which","ctrlKey","getEvX","undefined","pageX","touches","originalEvent","getEvY","pageY","getEvIsTouch","type","preventSelection","on","preventDefault","bindAnyScroll","handler","window","addEventListener","unbindAnyScroll","removeEventListener","intersectRects","rect1","rect2","max","min","constrainPoint","point","rect","getRectCenter","diffPoints","point1","point2","parseFieldSpecs","token","specs","tokens","split","isArray","charAt","field","substring","order","func","compareByFieldSpecs","obj1","obj2","fieldSpecs","cmp","compareByFieldSpec","fieldSpec","flexibleCompare","a","b","String","localeCompare","intersectRanges","subjectRange","constraintRange","segStart","segEnd","isStart","isEnd","subjectStart","start","subjectEnd","end","constraintStart","constraintEnd","clone","diffDayTime","duration","days","stripTime","ms","time","diffDay","diffByUnit","unit","round","computeIntervalUnit","intervalUnits","computeRangeAs","isInt","isDuration","as","divideRangeByDuration","dur","months","durationHasTime","asMonths","abs","asDays","divideDurationByDuration","dur1","dur2","months1","months2","multiplyDuration","n","Boolean","hours","minutes","seconds","milliseconds","isNativeDate","Object","prototype","toString","call","Date","isTimeString","str","propObjs","complexProps","complexObjs","j","props","dest","unshift","createObject","proto","f","copyOwnProps","src","hasOwnProp","copyNativeMethods","names","obj","hasOwnPropMethod","isAtomic","applyAll","functions","thisObj","args","isFunction","ret","apply","firstDefined","arguments","htmlEscape","s","replace","stripHtmlEntities","text","cssToStr","cssProps","statements","join","capitaliseFirstLetter","toUpperCase","slice","compareNumbers","proxy","methodName","method","debounce","wait","immediate","timeout","context","timestamp","result","later","last","setTimeout","callNow","syncThen","promise","thenFunc","then","state","when","makeMoment","parseAsUTC","parseZone","isAmbigTime","isAmbigZone","ambigMatch","mom","isSingleString","isMoment","transferAmbigs","ambigDateOfMonthRegex","ambigTimeOrZoneRegex","exec","utc","_ambigTime","_ambigZone","utcOffset","zone","_fullCalendar","commonlyAmbiguate","inputs","preserveTime","anyAmbigTime","anyAmbigZone","len","moms","FC","stripZone","setMomentValues","year","month","date","oldMomentFormat","formatStr","oldMomentProto","format","formatDate","formatDateWithChunks","getFormatStringChunks","chunks","formatDateWithChunk","chunk","maybeStr","tokenOverrides","maybe","match","formatRange","date1","date2","separator","isRTL","localeData","lang","longDateFormat","formatRangeWithChunks","chunkStr","leftI","rightI","middleI","unzonedDate1","unzonedDate2","leftStr","rightStr","middleStr1","middleStr2","middleStr","formatSimilarChunk","similarUnitMap","isSame","formatStringChunkCache","chunkFormatString","chunker","Class","extendClass","superClass","members","subClass","constructor","mixIntoClass","theClass","isHitsEqual","hit0","hit1","component","isHitPropsWithin","subHit","superHit","propName","isBgEvent","event","rendering","getEventRendering","isInverseBgEvent","source","groupEventsById","events","eventsById","_id","compareRanges","range1","range2","getDraggedElMeta","eventProps","startTime","stick","prefix","dataAttrPrefix","data","extend","isDaySegCollision","seg","otherSegs","otherSeg","leftCol","rightCol","compareDaySegCols","buildSlotSegLevels","segs","levels","computeSlotSegCollisions","level","computeForwardSlotSegs","k","forwardSegs","computeSlotSegPressures","forwardSeg","forwardPressure","results","isSlotSegCollision","seg1","seg2","Calendar_constructor","element","localizeMoment","_locale","_lang","render","content","elementVisible","calcSize","renderView","initialRender","t","bindOption","theme","tm","toggleClass","bindOptions","prependTo","header","Header","renderHeader","options","defaultView","handleWindowResize","windowResizeProxy","windowResize","windowResizeDelay","resize","prepend","destroy","currentView","removeElement","unbind","is","viewType","explicitScrollState","ignoreWindowResize","freezeContentHeight","clearView","view","viewsByType","instantiateView","setElement","activateButton","massageCurrentDate","displaying","isWithin","intervalStart","intervalEnd","display","unfreezeContentHeight","updateHeaderTitle","updateTodayButton","getAndRenderEvents","deactivateButton","reinitView","scrollState","queryScroll","updateSize","shouldRecalc","_calcSize","contentHeightInput","contentHeight","heightInput","suggestedViewHeight","queryHeaderHeight","aspectRatio","target","trigger","_element","refetchEvents","fetchAndRenderEvents","refetchEventSources","matchInputs","fetchEventSources","getEventSourcesByMatchArray","renderEvents","displayEvents","lazyFetching","isFetchNeeded","fetchEvents","reportEvents","_events","reportEventChange","updateTitle","title","now","getNow","disableButton","enableButton","select","zonedStartInput","zonedEndInput","buildSelectSpan","unselect","prev","computePrevDate","next","computeNextDate","prevYear","nextYear","today","gotoDate","zonedDateInput","incrementDate","delta","zoomTo","newDate","spec","getViewSpec","getUnitViewSpec","getDate","applyTimezone","getCalendar","getView","option","value","newOptionHash","setOptions","optionName","optionCnt","dynamicOverrides","viewSpecCache","populateOptionsHash","triggerOptionHandlers","unrenderBusinessHours","renderBusinessHours","rezoneArrayEventSources","Array","triggerWith","rerenderEvents","changeView","optionHandlers","monthNames","monthNamesShort","dayNames","dayNamesShort","firstDay","weekNumberCalculation","getMomentLocaleData","_months","_monthsShort","_weekdays","_weekdaysShort","_week","dow","_fullCalendar_weekCalc","defaultAllDayEventDuration","defaultTimedEventDuration","timezone","hasTime","local","getIsAmbigTimezone","adjustedZonedDate","zonedDate","toArray","timeAdjust","getEventEnd","getDefaultEventEnd","allDay","zonedStart","humanizeDuration","locale","humanize","EventManager","defaultDate","getSuggestedViewHeight","isHeightAuto","initialize","populateInstanceComputableOptions","instanceComputableOptions","langCode","langData","calendar","sections","empty","append","renderSection","sectionEl","buttonStr","groupEl","groupChildren","isOnlyButtons","buttonName","customButtonProps","viewSpec","buttonClick","overrideText","defaultText","themeIcon","normalIcon","innerHtml","classes","button","customButtons","click","viewsWithButtons","buttonTextOverride","buttonTextDefault","buttonText","themeButtonIcons","icon","buttonIcons","hasClass","mousedown","not","mouseup","hover","first","getViewsWithButtons","rangeStart","rangeEnd","sources","specificSources","specialFetchType","cache","excludeEventsBySources","_status","pendingSourceCnt","_fetchId","tryFetchEventSource","fetchId","_fetchEventSource","eventInputs","eventInput","abstractEvent","isArraySource","buildEventFromInput","expandEvent","decrementPendingSourceCnt","rejectEventSource","wasPending","callback","fetchers","sourceFetchers","pushLoading","popLoading","url","customData","success","error","complete","startParam","endParam","timezoneParam","ajax","ajaxDefaults","addEventSource","sourceInput","buildEventSource","normalizers","sourceNormalizers","className","origArray","map","removeEventSource","matchInput","removeSpecificEventSources","getEventSourcesByMatch","removeEventSources","targetSources","isAll","grep","getEventSources","getEventSourceById","id","matchingSources","isSourcesEquivalent","source1","source2","getSourcePrimitive","googleCalendarId","specificEvents","updateEvent","mutateEvent","getMiscEventProps","isMiscEventPropName","renderEvent","stickySource","removeEvents","eventID","clientEvents","e","rezoneEventDates","backupEventDates","out","eventDataTransform","eventGUID","_recurring","isValid","allDayDefault","assignDatesToEvent","normalizeEvent","normalizeEventDates","normalizeEventTimes","isAfter","forceEventDuration","_rangeStart","_rangeEnd","dowHash","endTime","isBefore","day","newProps","largeUnit","diffDates","date0","oldProps","clearEnd","startDelta","endDelta","durationDelta","undoFunc","miscProps","_start","_end","_allDay","subtract","mutateEvents","dateDelta","undo","isAmbigTimezone","undoFunctions","valueOf","isEventSpanAllowed","span","constraint","eventConstraint","overlap","eventOverlap","isSpanAllowed","isExternalSpanAllowed","eventSpan","eventLocation","isSelectionSpanAllowed","selectConstraint","selectOverlap","constraintEvents","anyContainment","peerEvents","peerEvent","peerOverlap","constraintToEvents","spanContainsSpan","getPeerEvents","eventIntersectsRange","constraintInput","getCurrentBusinessHourEvents","range","eventStart","eventEnd","concat","eventSources","getEventCache","fullCalendar","version","internalApiVersion","fcViews","fn","singleRes","removeData","Calendar","dayIDs","log","console","warn","allowValueOptimization","setUTCValues","setLocalValues","hasOwnProperty","newMomentProto","week","weeks","weekCalc","isoWeek","dayHours","wasAmbigTime","hasZone","wasAmbigZone","tzo","toISOString","units","_d","setTime","UTC","updateOffset","T","Y","M","D","d","A","H","h","m","mixin","EmitterMixin","types","intercept","extra","guid","off","triggerHandler","ListenerMixin","listenerId","listenTo","other","arg","eventName","getListenerNamespace","stopListeningTo","MouseIgnorerMixin","isIgnoringMouse","delayUnignoreMouse","initMouseIgnoring","delay","tempIgnoreMouse","unignoreMouse","Popover","isHidden","margin","show","hide","_this","parentEl","autoHide","documentMousedown","closest","viewportTop","viewportLeft","viewportOffset","offsetParent","windowEl","viewportEl","scrollTop","scrollLeft","viewportConstrain","CoordCache","forcedOffsetParentEl","boundingRect","isHorizontal","isVertical","lefts","rights","tops","bottoms","build","offsetParentEl","queryBoundingRect","buildElHorizontals","buildElVerticals","clear","ensureBuilt","node","getHorizontalIndex","leftOffset","getVerticalIndex","topOffset","getLeftOffset","leftIndex","getLeftPosition","getRightOffset","getRightPosition","getWidth","getTopOffset","topIndex","getTopPosition","getBottomOffset","getBottomPosition","getHeight","scrollParentEl","isPointInBounds","isLeftInBounds","isTopInBounds","DragListener","subjectEl","subjectHref","originX","originY","scrollEl","isInteracting","isDistanceSurpassed","isDelayEnded","isDragging","isTouch","delayTimeoutId","minDistance","handleTouchScrollProxy","startInteraction","extraOptions","distance","bindHandlers","initAutoScroll","handleInteractionStart","startDelay","handleDistanceSurpassed","endInteraction","isCancelled","endDrag","clearTimeout","destroyAutoScroll","unbindHandlers","handleInteractionEnd","touchStartIgnores","touchmove","handleTouchMove","touchend","touchcancel","touchstart","handleTouchScroll","mousemove","handleMouseMove","selectstart","contextmenu","startDrag","handleDragStart","initHrefHack","handleMove","distanceSq","dx","dy","handleDrag","updateAutoScroll","handleDragEnd","destroyHrefHack","initialEv","handleDelayEnd","attr","removeAttr","isAutoScroll","scrollBounds","scrollTopVel","scrollLeftVel","scrollIntervalId","scrollSensitivity","scrollSpeed","scrollIntervalMs","scroll","handleDebouncedScroll","endAutoScroll","computeScrollBounds","topCloseness","bottomCloseness","leftCloseness","rightCloseness","sensitivity","bounds","topVel","leftVel","setScrollVel","constrainScrollVel","setInterval","scrollHeight","scrollWidth","scrollIntervalFunc","frac","clearInterval","handleScrollEnd","HitDragListener","origHit","hit","coordAdjust","subjectRect","origPoint","computeCoords","queryHit","subjectCenter","prepareHits","handleHitOver","handleHitOut","handleHitDone","isOrig","releaseHits","MouseFollower","sourceEl","top0","left0","y0","x0","topDelta","leftDelta","isFollowing","isAnimating","updatePosition","stop","shouldRevert","revertDuration","animate","getEl","additionalClass","visibility","opacity","zIndex","sourceOffset","Grid","elsByFill","eventTimeFormat","displayEventTime","displayEventEnd","minResizeDuration","dayDragListener","segDragListener","segResizeListener","externalDragListener","opt","buildDayDragListener","computeEventTimeFormat","computeDisplayEventTime","computeDisplayEventEnd","setRange","rangeUpdated","processRangeOptions","spanToSegs","getHitSpan","getHitEl","bindDayHandler","dayTouchStart","dayMousedown","bindSegHandlers","bindGlobalHandlers","unbindGlobalHandlers","clearDragListeners","renderSkeleton","renderDates","unrenderDates","dragstart","externalDragStart","sortstart","isSelected","selectedEvent","dayClickHit","selectionSpan","isSelectable","dragListener","interactionStart","dragStart","hitOver","computeSelection","renderSelection","hitOut","unrenderSelection","hitDone","interactionEnd","triggerDayClick","reportSelection","renderEventLocationHelper","sourceSeg","fakeEvent","fabricateHelperEvent","renderHelper","editable","unrenderHelper","renderHighlight","unrenderHighlight","span0","span1","computeSelectionSpan","dates","sort","renderFill","unrenderFill","highlightSegClasses","getNowIndicatorUnit","renderNowIndicator","unrenderNowIndicator","renderFillSegEls","segElMethod","html","renderedSegs","fillSegHtml","fillSegTag","classesMethod","cssMethod","getDayClasses","intervalDuration","highlightStateClass","mousedOverSeg","isDraggingSeg","isResizingSeg","isDraggingExternal","bgEvents","fgEvents","renderBgEvents","renderFgEvents","eventsToSegs","renderBgSegs","renderFgSegs","unrenderEvents","handleSegMouseout","unrenderFgSegs","unrenderBgSegs","getEventSegs","renderFgSegEls","disableResizing","fgSegHtml","resolveEventEl","bgEventSegEl","bgEventSegClasses","bgEventSegCss","background-color","getSegSkinCss","businessHoursSegClasses","buildBusinessHourSegs","wholeDay","businessHours","BUSINESS_HOUR_EVENT_DEFAULTS","bindSegHandlersToEl","bindSegHandlerToEl","handleSegTouchStart","handleSegTouchEnd","handleSegMouseover","handleSegMousedown","handleSegClick","isResizing","startSegResize","isEventDraggable","buildSegDragListener","isEventSelected","isDraggable","isResizable","isEventResizable","buildSegSelectListener","dragOptions","buildSegResizeListener","mouseFollower","dropLocation","selectEvent","segDragStart","hideEvent","dragHelperEls","computeEventDrop","eventToSpan","renderDrag","applyDragOpacity","unrenderDrag","showEvent","segDragStop","reportEventDrop","startSpan","endSpan","dragEnd","style","ui","accept","item","listenToExternalDrag","meta","computeExternalDrop","reportExternalDrop","resizeLocation","segResizeStart","origHitSpan","hitSpan","computeEventStartResize","computeEventEndResize","renderEventResize","unrenderEventResize","segResizeStop","reportEventResize","computeEventResize","defaultDuration","getEventTimeText","displayEnd","getSegClasses","eventColor","color","sourceColor","optionColor","backgroundColor","border-color","borderColor","textColor","eventToSegs","eventToSpans","eventToRange","eventRangeToSpans","allEvents","segSliceFunc","ranges","invertRanges","eventRangeToSegs","spans","eventSpanToSegs","eventStartMS","eventDurationMS","viewStart","viewEnd","inverseRanges","sortEventSegs","compareEventSegs","eventOrderSpecs","DayTableMixin","breakOnWeeks","dayDates","dayIndices","daysPerRow","rowCnt","colCnt","colHeadFormat","updateDayTable","dayIndex","isHiddenDay","ceil","updateDayTableCols","computeColCnt","computeColHeadFormat","getCellDate","row","col","getCellDayIndex","getCellRange","getColDayIndex","getDateDayIndex","dayOffset","sliceRangeByRow","rowFirst","rowLast","segFirst","segLast","normalRange","computeDayRange","rangeFirst","rangeLast","firstRowDayIndex","lastRowDayIndex","sliceRangeByDay","renderHeadHtml","widgetHeaderClass","renderHeadTrHtml","renderHeadIntroHtml","renderIntroHtml","renderHeadDateCellsHtml","htmls","renderHeadDateCellHtml","colspan","otherAttrs","renderBgTrHtml","renderBgIntroHtml","renderBgCellsHtml","renderBgCellHtml","widgetContentClass","bookendCells","trEl","introHtml","DayGrid","numbersVisible","bottomCoordPadding","cellEls","helperEls","rowCoordCache","colCoordCache","isRigid","renderDayRowHtml","getCellEl","removeSegPopover","renderNumberTrHtml","renderNumberIntroHtml","renderNumberCellsHtml","renderNumberCellHtml","dayNumbersVisible","getCellHit","rowStructs","helperNodes","renderSegRows","rowNode","skeletonTop","rowEl","skeletonEl","tbodyEl","nodes","renderFillRow","startCol","endCol","toLowerCase","popoverSegs","allDaySegs","rowStruct","pop","segRows","groupSegRows","renderSegRow","timeText","titleHtml","isResizableFromStart","isEventResizableFromStart","isResizableFromEnd","isEventResizableFromEnd","skinCss","timeHtml","rowSegs","emptyCellsUntil","td","loneCellMatrix","parseInt","tr","cellMatrix","levelSegs","segLevels","buildSegLevels","levelCnt","tbody","segMatrix","segPopover","limitRows","levelLimit","rowLevelLimit","unlimitRow","computeRowLevelLimit","limitRow","iterInnerHeights","childNode","trHeight","rowHeight","trEls","segsBelow","getCellSegs","moreLink","renderMoreLink","moreWrap","moreNodes","limitedNodes","totalSegsBelow","colSegsBelow","rowspan","segMoreNodes","moreTd","get","after","moreEls","limitedEls","hiddenSegs","getMoreLinkText","clickOption","moreEl","dayEl","allSegs","reslicedAllSegs","resliceDaySegs","reslicedHiddenSegs","showSegPopover","topEl","renderSegPopoverContent","isTheme","segContainer","dayDate","dayStart","dayEnd","dayRange","num","startLevel","TimeGrid","slotDuration","snapDuration","snapsPerSlot","minTime","maxTime","labelFormat","labelInterval","colEls","slatContainerEl","slatEls","nowIndicatorEls","slatCoordCache","processOptions","renderHtml","renderContentSkeleton","renderSlatRowHtml","slotDate","isLabeled","axisHtml","slotTime","axisStyleAttr","computeLabelInterval","slotsPerLabel","AGENDA_STOCK_SUB_DURATIONS","colIndex","slatIndex","slatTop","slatHeight","partial","localSnapIndex","snapIndex","snapTop","snapBottom","snap","computeSnapTime","sliceRangeByTimes","isResize","updateSegVerticals","fgSegs","bgSegs","businessSegs","getTotalSlatHeight","computeDateTop","startOfDayDate","computeTimeTop","slatRemainder","slatCoverage","renderHelperSegs","unrenderHelperSegs","renderBusinessSegs","unrenderBusinessSegs","colContainerEls","renderHighlightSegs","unrenderHighlightSegs","fgContainerEls","bgContainerEls","helperContainerEls","highlightContainerEls","businessContainerEls","helperSegs","highlightSegs","cellHtml","renderFgSegsIntoContainers","unrenderNamedSegs","attachSegsByCol","groupSegsByCol","segsByCol","containerEls","updateFgSegCoords","fullTimeText","startTimeText","isMultiDayEvent","computeSegVerticals","assignSegVerticals","generateSegVerticalCss","computeFgSegHorizontals","assignFgSegHorizontals","level0","computeFgSegForwardBack","seriesBackwardPressure","seriesBackwardCoord","forwardCoord","sortForwardSegs","backwardCoord","compareForwardSegs","generateFgSegHorizontalCss","shouldOverlap","View","isSkeletonRendered","isEventsRendered","intervalUnit","nextDayThreshold","isHiddenDayHash","isNowIndicatorRendered","initialNowDate","initialNowQueriedMs","nowIndicatorTimeoutID","nowIndicatorIntervalID","initThemingProps","initHiddenDays","setDate","computeRange","startOf","skipHiddenDays","computeTitle","computeTitleFormat","unrenderSkeleton","prevScrollState","displayView","setScroll","forceScroll","computeInitialScroll","triggerRender","clearEvents","startNowIndicator","stopNowIndicator","triggerUnrender","handleDocumentMousedown","processUnselect","update","updateNowIndicator","updateHeight","updateWidth","setHeight","isAuto","previousScrollState","triggerEventRender","triggerEventUnrender","destroyEvents","renderedEventSegEach","custom","startEditable","mutateResult","triggerEventDrop","triggerExternalDrop","durationEditable","triggerEventResize","triggerSelect","destroySelection","unselectEvent","processRangeUnselect","processEventUnselect","ignore","hiddenDays","dayCnt","inc","isExclusive","endTimeMS","startDay","endDay","Scroller","overflowX","overflowY","renderEl","applyOverflow","overflow-x","overflow-y","lockOverflow","getScrollTop","setScrollTop","getClientWidth","getClientHeight","dirDefaults","langDefaults","loadingLevel","langOptionHash","defaults","rtlDefaults","buildViewSpec","viewTypes","singleUnit","requestedViewType","viewOverrides","specChain","defaultsChain","overridesChain","class","buildViewSpecOptions","buildViewSpecButtonText","queryButtonText","isValidViewType","handlerFunc","optionNames","handlerObj","registerOptionHandlerObj","triggerOptionHandlerObj","handlerObjs","optionValues","titleRangeSeparator","monthYearFormat","center","weekends","weekNumbers","weekNumberTitle","scrollTime","dragOpacity","dragRevertDuration","dragScroll","unselectAuto","dropAccept","eventOrder","eventLimit","eventLimitText","eventLimitClick","dayPopoverFormat","longPressDelay","englishDefaults","langs","datepickerLang","dpLangCode","dpOptions","fcOptions","weekHeader","dpComputableOptions","datepicker","regional","en","setDefaults","newFcOptions","momOptions","momComputableOptions","prevText","nextText","currentText","showMonthAfterYear","yearSuffix","dayOfMonthFormat","mediumTimeFormat","smallTimeFormat","extraSmallTimeFormat","hourFormat","noMeridiemTimeFormat","smallDayDateFormat","weekFormat","smallWeekFormat","dataType","outerSpan","innerSpan","otherEvent","computeBusinessHourEvents","expandBusinessHourEvents","ignoreNoDow","BasicView","scroller","dayGridClass","dayGrid","weekNumbersVisible","weekNumberWidth","headContainerEl","headRowEl","instantiateDayGrid","subclass","basicDayGridMethods","weekday","renderSkeletonHtml","renderHead","dayGridContainerEl","dayGridEl","hasRigidRows","weekNumberStyleAttr","totalHeight","scrollerHeight","computeScrollerHeight","setGridHeight","MonthView","isFixedWeeks","weekMode","basic","basicDay","basicWeek","fixedWeekCount","AgendaView","timeGridClass","timeGrid","axisWidth","noScrollRowEls","bottomRuleEl","instantiateTimeGrid","agendaTimeGridMethods","agendaDayGridMethods","timeGridWrapEl","timeGridEl","AGENDA_ALL_DAY_EVENT_LIMIT","timedSegs","dayEvents","timedEvents","daySegs","weekText","agenda","allDaySlot","allDayText","slotEventOverlap","agendaDay","agendaWeek"],"mappings":"CAMA,SAAUA,GACa,kBAAXC,SAAyBA,OAAOC,IAC1CD,QAAS,SAAU,UAAYD,GAEJ,gBAAZG,SACfC,OAAOD,QAAUH,EAAQK,QAAQ,UAAWA,QAAQ,WAGpDL,EAAQM,OAAQC,SAEf,SAASC,EAAGD,GAqDf,QAASE,GAAaC,GACrB,MAAOC,GAAWD,EAAYE,IAM/B,QAASC,GAAiBC,GACzB,GACIC,GADAC,GAAcC,MAAOH,EAAMG,UA2C/B,OAvCAT,GAAEU,KAAKJ,EAAO,SAASK,EAAMC,GAChB,SAARD,IAIFX,EAAEa,cAAcD,KACf,6BAA6BE,KAAKH,IACnCX,EAAEe,QAAQJ,EAAMP,SAEhBG,EAAS,KAGTP,EAAEU,KAAKE,EAAK,SAASI,EAASC,GAGzB,gEAAgEH,KAAKE,IACnER,EAAUC,MAAMO,KACpBR,EAAUC,MAAMO,OAEjBR,EAAUC,MAAMO,GAASL,GAAQM,IAG5BV,IACJA,MAEDA,EAAOS,GAAWC,KAIhBV,IACHC,EAAUG,GAAQJ,IAInBC,EAAUG,GAAQC,KAKdJ,EAsBR,QAASU,GAAiBC,EAAQC,GAC7BA,EAAgBC,MACnBF,EAAOG,KACNC,oBAAqB,EACrBC,cAAeJ,EAAgBC,KAAO,IAGpCD,EAAgBK,OACnBN,EAAOG,KACNI,qBAAsB,EACtBC,eAAgBP,EAAgBK,MAAQ,IAO3C,QAASG,GAAmBT,GAC3BA,EAAOG,KACNE,cAAe,GACfG,eAAgB,GAChBJ,oBAAqB,GACrBG,qBAAsB,KAMxB,QAASG,KACR7B,EAAE,QAAQ8B,SAAS,kBAKpB,QAASC,KACR/B,EAAE,QAAQgC,YAAY,kBAQvB,QAASC,GAAiBC,EAAKC,EAAiBC,GAK/C,GAAIC,GAAaC,KAAKC,MAAMJ,EAAkBD,EAAIM,QAC9CC,EAAaH,KAAKC,MAAMJ,EAAkBE,GAAcH,EAAIM,OAAS,IACrEE,KACAC,KACAC,KACAC,EAAa,CAEjBC,GAAmBZ,GAInBA,EAAIxB,KAAK,SAASqC,EAAGC,GACpB,GAAIC,GAAYF,IAAMb,EAAIM,OAAS,EAAIC,EAAaJ,EAChDa,EAAgBlD,EAAEgD,GAAIG,aAAY,EAElCD,GAAgBD,GACnBP,EAAQU,KAAKJ,GACbL,EAAYS,KAAKF,GACjBN,EAAYQ,KAAKpD,EAAEgD,GAAIK,WAIvBR,GAAcK,IAKZd,IACHD,GAAmBU,EACnBR,EAAaC,KAAKC,MAAMJ,EAAkBO,EAAQF,QAClDC,EAAaH,KAAKC,MAAMJ,EAAkBE,GAAcK,EAAQF,OAAS,KAI1ExC,EAAE0C,GAAShC,KAAK,SAASqC,EAAGC,GAC3B,GAAIC,GAAYF,IAAML,EAAQF,OAAS,EAAIC,EAAaJ,EACpDa,EAAgBP,EAAYI,GAC5BO,EAAgBV,EAAYG,GAC5BQ,EAAYN,GAAaC,EAAgBI,EAEzCJ,GAAgBD,GACnBjD,EAAEgD,GAAIK,OAAOE,KAOhB,QAAST,GAAmBZ,GAC3BA,EAAImB,OAAO,IAOZ,QAASG,GAAgBtB,GACxB,GAAIuB,GAAgB,CAapB,OAXAvB,GAAIwB,KAAK,UAAUhD,KAAK,SAASqC,EAAGY,GACnC,GAAIC,GAAa5D,EAAE2D,GAASE,YACxBD,GAAaH,IAChBA,EAAgBG,KAIlBH,IAEAvB,EAAI4B,MAAML,GAEHA,EAMR,QAASM,GAAsBC,EAASL,GACvC,GACIM,GADAC,EAAOF,EAAQG,IAAIR,EAWvB,OAPAO,GAAK5C,KACJ8C,SAAU,WACV/C,UAED4C,EAAOD,EAAQb,cAAgBQ,EAAQR,cACvCe,EAAK5C,KAAM8C,SAAU,GAAI/C,KAAM,KAExB4C,EAcR,QAASI,GAAgBrB,GACxB,GAAIoB,GAAWpB,EAAG1B,IAAI,YACrBgD,EAAetB,EAAGuB,UAAUC,OAAO,WAClC,GAAIC,GAASzE,EAAE0E,KACf,OAAO,gBAAkB5D,KACxB2D,EAAOnD,IAAI,YAAcmD,EAAOnD,IAAI,cAAgBmD,EAAOnD,IAAI,iBAE9DqD,GAAG,EAEP,OAAoB,UAAbP,GAAyBE,EAAa9B,OAA8C8B,EAArCtE,EAAEgD,EAAG,GAAG4B,eAAiBC,UAOhF,QAASC,GAAa9B,EAAI+B,GACzB,GAAIC,GAAShC,EAAGgC,SACZ3D,EAAO2D,EAAO3D,MAAQ0D,EAASA,EAAO1D,KAAO,GAC7C4D,EAAMD,EAAOC,KAAOF,EAASA,EAAOE,IAAM,EAE9C,QACC5D,KAAMA,EACNI,MAAOJ,EAAO2B,EAAGa,aACjBoB,IAAKA,EACLC,OAAQD,EAAMjC,EAAGG,eASnB,QAASgC,GAAcnC,EAAI+B,GAC1B,GAAIC,GAAShC,EAAGgC,SACZ5D,EAAkBgE,EAAmBpC,GACrC3B,EAAO2D,EAAO3D,KAAOgE,EAAYrC,EAAI,qBAAuB5B,EAAgBC,MAAQ0D,EAASA,EAAO1D,KAAO,GAC3G4D,EAAMD,EAAOC,IAAMI,EAAYrC,EAAI,oBAAsB5B,EAAgB6D,KAAOF,EAASA,EAAOE,IAAM,EAE1G,QACC5D,KAAMA,EACNI,MAAOJ,EAAO2B,EAAG,GAAGsC,YACpBL,IAAKA,EACLC,OAAQD,EAAMjC,EAAG,GAAGuC,cAQtB,QAASC,GAAexC,EAAI+B,GAC3B,GAAIC,GAAShC,EAAGgC,SACZ3D,EAAO2D,EAAO3D,KAAOgE,EAAYrC,EAAI,qBAAuBqC,EAAYrC,EAAI,iBAC9E+B,EAASA,EAAO1D,KAAO,GACrB4D,EAAMD,EAAOC,IAAMI,EAAYrC,EAAI,oBAAsBqC,EAAYrC,EAAI,gBAC3E+B,EAASA,EAAOE,IAAM,EAExB,QACC5D,KAAMA,EACNI,MAAOJ,EAAO2B,EAAGc,QACjBmB,IAAKA,EACLC,OAAQD,EAAMjC,EAAGK,UAOnB,QAAS+B,GAAmBpC,GAC3B,GAAIyC,GAAiBzC,EAAGY,aAAeZ,EAAG,GAAGsC,YACzCI,GACHrE,KAAM,EACNI,MAAO,EACPwD,IAAK,EACLC,OAAQlC,EAAG2C,cAAgB3C,EAAG,GAAGuC,aAUlC,OAPIK,MAAmD,OAAvB5C,EAAG1B,IAAI,aACtCoE,EAAOrE,KAAOoE,EAGdC,EAAOjE,MAAQgE,EAGTC,EAQR,QAASE,KAIR,MAH6B,QAAzBC,KACHA,GAAuBC,KAEjBD,GAGR,QAASC,KACR,GAAI9C,GAAKhD,EAAE,qBACTsB,KACA8C,SAAU,WACVa,SACA5D,KAAM,EACN0E,OAAQ,EACRC,QAAS,EACTC,SAAU,SACVC,UAAW,QAEXC,SAAS,QACPxC,EAAUX,EAAGoD,WACbC,EAAM1C,EAAQqB,SAAS3D,KAAO2B,EAAGgC,SAAS3D,IAE9C,OADA2B,GAAGsD,SACID,EAMR,QAAShB,GAAYrC,EAAIuD,GACxB,MAAOC,YAAWxD,EAAG1B,IAAIiF,KAAU,EAWpC,QAASE,GAAqBC,GAC7B,MAAmB,IAAZA,EAAGC,QAAeD,EAAGE,QAI7B,QAASC,GAAOH,GACf,GAAiBI,SAAbJ,EAAGK,MACN,MAAOL,GAAGK,KAEX,IAAIC,GAAUN,EAAGO,cAAcD,OAC/B,OAAIA,GACIA,EAAQ,GAAGD,MADnB,OAMD,QAASG,GAAOR,GACf,GAAiBI,SAAbJ,EAAGS,MACN,MAAOT,GAAGS,KAEX,IAAIH,GAAUN,EAAGO,cAAcD,OAC/B,OAAIA,GACIA,EAAQ,GAAGG,MADnB,OAMD,QAASC,GAAaV,GACrB,MAAO,SAAS5F,KAAK4F,EAAGW,MAIzB,QAASC,GAAiBtE,GACzBA,EAAGlB,SAAS,mBACVyF,GAAG,cAAeC,GAKrB,QAASA,GAAed,GACvBA,EAAGc,iBAQJ,QAASC,GAAcC,GACtB,QAAIC,OAAOC,mBACVD,OAAOC,iBAAiB,SAAUF,GAAS,IACpC,GAQT,QAASG,GAAgBH,GACxB,QAAIC,OAAOG,sBACVH,OAAOG,oBAAoB,SAAUJ,GAAS,IACvC,GAYT,QAASK,GAAeC,EAAOC,GAC9B,GAAI5B,IACHhF,KAAMiB,KAAK4F,IAAIF,EAAM3G,KAAM4G,EAAM5G,MACjCI,MAAOa,KAAK6F,IAAIH,EAAMvG,MAAOwG,EAAMxG,OACnCwD,IAAK3C,KAAK4F,IAAIF,EAAM/C,IAAKgD,EAAMhD,KAC/BC,OAAQ5C,KAAK6F,IAAIH,EAAM9C,OAAQ+C,EAAM/C,QAGtC,OAAImB,GAAIhF,KAAOgF,EAAI5E,OAAS4E,EAAIpB,IAAMoB,EAAInB,QAClCmB,EAOT,QAAS+B,GAAeC,EAAOC,GAC9B,OACCjH,KAAMiB,KAAK6F,IAAI7F,KAAK4F,IAAIG,EAAMhH,KAAMiH,EAAKjH,MAAOiH,EAAK7G,OACrDwD,IAAK3C,KAAK6F,IAAI7F,KAAK4F,IAAIG,EAAMpD,IAAKqD,EAAKrD,KAAMqD,EAAKpD,SAMpD,QAASqD,GAAcD,GACtB,OACCjH,MAAOiH,EAAKjH,KAAOiH,EAAK7G,OAAS,EACjCwD,KAAMqD,EAAKrD,IAAMqD,EAAKpD,QAAU,GAMlC,QAASsD,GAAWC,EAAQC,GAC3B,OACCrH,KAAMoH,EAAOpH,KAAOqH,EAAOrH,KAC3B4D,IAAKwD,EAAOxD,IAAMyD,EAAOzD,KAc3B,QAAS0D,GAAgBrI,GACxB,GAEIyC,GAAG6F,EAFHC,KACAC,IAaJ,KAVqB,gBAAVxI,GACVwI,EAASxI,EAAMyI,MAAM,WAEI,kBAAVzI,GACfwI,GAAWxI,GAEHN,EAAEgJ,QAAQ1I,KAClBwI,EAASxI,GAGLyC,EAAI,EAAGA,EAAI+F,EAAOtG,OAAQO,IAC9B6F,EAAQE,EAAO/F,GAEM,gBAAV6F,GACVC,EAAMzF,KACc,KAAnBwF,EAAMK,OAAO,IACVC,MAAON,EAAMO,UAAU,GAAIC,WAC3BF,MAAON,EAAOQ,MAAO,IAGA,kBAAVR,IACfC,EAAMzF,MAAOiG,KAAMT,GAIrB,OAAOC,GAIR,QAASS,GAAoBC,EAAMC,EAAMC,GACxC,GAAI1G,GACA2G,CAEJ,KAAK3G,EAAI,EAAGA,EAAI0G,EAAWjH,OAAQO,IAElC,GADA2G,EAAMC,EAAmBJ,EAAMC,EAAMC,EAAW1G,IAE/C,MAAO2G,EAIT,OAAO,GAIR,QAASC,GAAmBJ,EAAMC,EAAMI,GACvC,MAAIA,GAAUP,KACNO,EAAUP,KAAKE,EAAMC,GAEtBK,EAAgBN,EAAKK,EAAUV,OAAQM,EAAKI,EAAUV,SAC3DU,EAAUR,OAAS,GAItB,QAASS,GAAgBC,EAAGC,GAC3B,MAAKD,IAAMC,EAGF,MAALA,KAGK,MAALD,EACI,EAEU,WAAd9J,EAAEqH,KAAKyC,IAAiC,WAAd9J,EAAEqH,KAAK0C,GAC7BC,OAAOF,GAAGG,cAAcD,OAAOD,IAEhCD,EAAIC,EAXH,EAsBT,QAASG,GAAgBC,EAAcC,GACtC,GAIIC,GAAUC,EACVC,EAASC,EALTC,EAAeN,EAAaO,MAC5BC,EAAaR,EAAaS,IAC1BC,EAAkBT,EAAgBM,MAClCI,EAAgBV,EAAgBQ,GAIpC,IAAID,EAAaE,GAAmBJ,EAAeK,EAoBlD,MAlBIL,IAAgBI,GACnBR,EAAWI,EAAaM,QACxBR,GAAU,IAGVF,EAAWQ,EAAgBE,QAC3BR,GAAW,GAGRI,GAAcG,GACjBR,EAASK,EAAWI,QACpBP,GAAQ,IAGRF,EAASQ,EAAcC,QACvBP,GAAQ,IAIRE,MAAOL,EACPO,IAAKN,EACLC,QAASA,EACTC,MAAOA,GAqBV,QAASQ,GAAYlB,EAAGC,GACvB,MAAOhK,GAAOkL,UACbC,KAAMpB,EAAEiB,QAAQI,YAAYlH,KAAK8F,EAAEgB,QAAQI,YAAa,QACxDC,GAAItB,EAAEuB,OAAStB,EAAEsB,SAMnB,QAASC,GAAQxB,EAAGC,GACnB,MAAOhK,GAAOkL,UACbC,KAAMpB,EAAEiB,QAAQI,YAAYlH,KAAK8F,EAAEgB,QAAQI,YAAa,UAM1D,QAASI,GAAWzB,EAAGC,EAAGyB,GACzB,MAAOzL,GAAOkL,SACb3I,KAAKmJ,MAAM3B,EAAE7F,KAAK8F,EAAGyB,GAAM,IAC3BA,GAQF,QAASE,GAAoBhB,EAAOE,GACnC,GAAI7H,GAAGyI,EACH5K,CAEJ,KAAKmC,EAAI,EAAGA,EAAI4I,GAAcnJ,SAC7BgJ,EAAOG,GAAc5I,GACrBnC,EAAMgL,EAAeJ,EAAMd,EAAOE,KAE9BhK,GAAO,GAAKiL,GAAMjL,KAJemC,KAStC,MAAOyI,GAQR,QAASI,GAAeJ,EAAMd,EAAOE,GAEpC,MAAW,OAAPA,EACIA,EAAI3G,KAAKyG,EAAOc,GAAM,GAErBzL,EAAO+L,WAAWpB,GACnBA,EAAMqB,GAAGP,GAGTd,EAAME,IAAI3G,KAAKyG,EAAMA,MAAOc,GAAM,GAM3C,QAASQ,GAAsBtB,EAAOE,EAAKqB,GAC1C,GAAIC,EAEJ,OAAIC,GAAgBF,IACXrB,EAAMF,GAASuB,GAExBC,EAASD,EAAIG,WACT9J,KAAK+J,IAAIH,IAAW,GAAKL,GAAMK,GAC3BtB,EAAI3G,KAAKyG,EAAO,UAAU,GAAQwB,EAEnCtB,EAAI3G,KAAKyG,EAAO,QAAQ,GAAQuB,EAAIK,UAK5C,QAASC,GAAyBC,EAAMC,GACvC,GAAIC,GAASC,CAEb,OAAIR,GAAgBK,IAASL,EAAgBM,GACrCD,EAAOC,GAEfC,EAAUF,EAAKJ,WACfO,EAAUF,EAAKL,WAEd9J,KAAK+J,IAAIK,IAAY,GAAKb,GAAMa,IAChCpK,KAAK+J,IAAIM,IAAY,GAAKd,GAAMc,GAEzBD,EAAUC,EAEXH,EAAKF,SAAWG,EAAKH,UAK7B,QAASM,GAAiBX,EAAKY,GAC9B,GAAIX,EAEJ,OAAIC,GAAgBF,GACZlM,EAAOkL,SAASgB,EAAMY,IAE9BX,EAASD,EAAIG,WACT9J,KAAK+J,IAAIH,IAAW,GAAKL,GAAMK,GAC3BnM,EAAOkL,UAAWiB,OAAQA,EAASW,IAEpC9M,EAAOkL,UAAWC,KAAMe,EAAIK,SAAWO,KAK/C,QAASV,GAAgBF,GACxB,MAAOa,SAAQb,EAAIc,SAAWd,EAAIe,WAAaf,EAAIgB,WAAahB,EAAIiB,gBAIrE,QAASC,GAAa7M,GACrB,MAAkD,kBAA1C8M,OAAOC,UAAUC,SAASC,KAAKjN,IAA8BA,YAAiBkN,MAKvF,QAASC,GAAaC,GACrB,MAAO,oCAAoC5M,KAAK4M,GAmCjD,QAASvN,GAAWwN,EAAUC,GAC7B,GACI7K,GAAGpC,EACHkN,EACAC,EAAGlN,EACHmN,EAJAC,IAMJ,IAAIJ,EACH,IAAK7K,EAAI,EAAGA,EAAI6K,EAAapL,OAAQO,IAAK,CAKzC,IAJApC,EAAOiN,EAAa7K,GACpB8K,KAGKC,EAAIH,EAASnL,OAAS,EAAGsL,GAAK,EAAGA,IAGrC,GAFAlN,EAAM+M,EAASG,GAAGnN,GAEC,gBAARC,GACViN,EAAYI,QAAQrN,OAEhB,IAAYkG,SAARlG,EAAmB,CAC3BoN,EAAKrN,GAAQC,CACb,OAKEiN,EAAYrL,SACfwL,EAAKrN,GAAQR,EAAW0N,IAM3B,IAAK9K,EAAI4K,EAASnL,OAAS,EAAGO,GAAK,EAAGA,IAAK,CAC1CgL,EAAQJ,EAAS5K,EAEjB,KAAKpC,IAAQoN,GACNpN,IAAQqN,KACbA,EAAKrN,GAAQoN,EAAMpN,IAKtB,MAAOqN,GAKR,QAASE,GAAaC,GACrB,GAAIC,GAAI,YAER,OADAA,GAAEf,UAAYc,EACP,GAAIC,GAIZ,QAASC,GAAaC,EAAKN,GAC1B,IAAK,GAAIrN,KAAQ2N,GACZC,EAAWD,EAAK3N,KACnBqN,EAAKrN,GAAQ2N,EAAI3N,IAQpB,QAAS6N,GAAkBF,EAAKN,GAC/B,GACIjL,GAAGpC,EADH8N,GAAU,cAAe,WAAY,UAGzC,KAAK1L,EAAI,EAAGA,EAAI0L,EAAMjM,OAAQO,IAC7BpC,EAAO8N,EAAM1L,GAETuL,EAAI3N,KAAUyM,OAAOC,UAAU1M,KAClCqN,EAAKrN,GAAQ2N,EAAI3N,IAMpB,QAAS4N,GAAWG,EAAK/N,GACxB,MAAOgO,IAAiBpB,KAAKmB,EAAK/N,GAKnC,QAASiO,GAAShO,GACjB,MAAO,uCAAuCE,KAAKd,EAAEqH,KAAKzG,IAI3D,QAASiO,IAASC,EAAWC,EAASC,GAIrC,GAHIhP,EAAEiP,WAAWH,KAChBA,GAAcA,IAEXA,EAAW,CACd,GAAI/L,GACAmM,CACJ,KAAKnM,EAAE,EAAGA,EAAE+L,EAAUtM,OAAQO,IAC7BmM,EAAMJ,EAAU/L,GAAGoM,MAAMJ,EAASC,IAASE,CAE5C,OAAOA,IAKT,QAASE,MACR,IAAK,GAAIrM,GAAE,EAAGA,EAAEsM,UAAU7M,OAAQO,IACjC,GAAqB+D,SAAjBuI,UAAUtM,GACb,MAAOsM,WAAUtM,GAMpB,QAASuM,IAAWC,GACnB,OAAQA,EAAI,IAAIC,QAAQ,KAAM,SAC5BA,QAAQ,KAAM,QACdA,QAAQ,KAAM,QACdA,QAAQ,KAAM,UACdA,QAAQ,KAAM,UACdA,QAAQ,MAAO,UAIlB,QAASC,IAAkBC,GAC1B,MAAOA,GAAKF,QAAQ,SAAU,IAM/B,QAASG,IAASC,GACjB,GAAIC,KAQJ,OANA7P,GAAEU,KAAKkP,EAAU,SAASjP,EAAMC,GACpB,MAAPA,GACHiP,EAAWzM,KAAKzC,EAAO,IAAMC,KAIxBiP,EAAWC,KAAK,KAIxB,QAASC,IAAsBrC,GAC9B,MAAOA,GAAIzE,OAAO,GAAG+G,cAAgBtC,EAAIuC,MAAM,GAIhD,QAASC,IAAepG,EAAGC,GAC1B,MAAOD,GAAIC,EAIZ,QAAS8B,IAAMgB,GACd,MAAOA,GAAI,IAAM,EAOlB,QAASsD,IAAMzB,EAAK0B,GACnB,GAAIC,GAAS3B,EAAI0B,EAEjB,OAAO,YACN,MAAOC,GAAOlB,MAAMT,EAAKW,YAU3B,QAASiB,IAASjH,EAAMkH,EAAMC,GAC7B,GAAIC,GAASzB,EAAM0B,EAASC,EAAWC,EAEnCC,EAAQ,WACX,GAAIC,IAAQ,GAAItD,MAASmD,CACrBG,GAAOP,EACVE,EAAUM,WAAWF,EAAON,EAAOO,IAGnCL,EAAU,KACLD,IACJI,EAASvH,EAAK8F,MAAMuB,EAAS1B,GAC7B0B,EAAU1B,EAAO,OAKpB,OAAO,YACN0B,EAAUhM,KACVsK,EAAOK,UACPsB,GAAa,GAAInD,KACjB,IAAIwD,GAAUR,IAAcC,CAQ5B,OAPKA,KACJA,EAAUM,WAAWF,EAAON,IAEzBS,IACHJ,EAASvH,EAAK8F,MAAMuB,EAAS1B,GAC7B0B,EAAU1B,EAAO,MAEX4B,GAQT,QAASK,IAASC,EAASC,GAE1B,MAAKD,IAAYA,EAAQE,MAA4B,aAApBF,EAAQG,QAGhCF,EACDD,EAAQE,KAAKD,GADhB,OAFGnR,EAAEsR,KAAKH,KAsDhB,QAASI,IAAWvC,EAAMwC,EAAYC,GACrC,GAEIC,GACAC,EACAC,EACAC,EALAvR,EAAQ0O,EAAK,GACb8C,EAAgC,GAAf9C,EAAKxM,QAAgC,gBAAVlC,EAgEhD,OA1DIP,GAAOgS,SAASzR,IACnBuR,EAAM9R,EAAOoP,MAAM,KAAMH,GACzBgD,GAAe1R,EAAOuR,IAEd1E,EAAa7M,IAAoBwG,SAAVxG,EAC/BuR,EAAM9R,EAAOoP,MAAM,KAAMH,IAGzB0C,GAAc,EACdC,GAAc,EAEVG,EACCG,GAAsBnR,KAAKR,IAE9BA,GAAS,MACT0O,GAAS1O,GACToR,GAAc,EACdC,GAAc,IAELC,EAAaM,GAAqBC,KAAK7R,MAChDoR,GAAeE,EAAW,GAC1BD,GAAc,GAGP3R,EAAEgJ,QAAQ1I,KAElBqR,GAAc,GAKdE,EADGL,GAAcE,EACX3R,EAAOqS,IAAIjD,MAAMpP,EAAQiP,GAGzBjP,EAAOoP,MAAM,KAAMH,GAGtB0C,GACHG,EAAIQ,YAAa,EACjBR,EAAIS,YAAa,GAETb,IACJE,EACHE,EAAIS,YAAa,EAETR,IACJD,EAAIU,UACPV,EAAIU,UAAUjS,GAGduR,EAAIW,KAAKlS,MAMbuR,EAAIY,eAAgB,EAEbZ,EA6SR,QAASa,IAAkBC,EAAQC,GAClC,GAII7P,GAAG8O,EAJHgB,GAAe,EACfC,GAAe,EACfC,EAAMJ,EAAOnQ,OACbwQ,IAIJ,KAAKjQ,EAAI,EAAGA,EAAIgQ,EAAKhQ,IACpB8O,EAAMc,EAAO5P,GACRhD,EAAOgS,SAASF,KACpBA,EAAMoB,GAAGlT,OAAO0R,UAAUI,IAE3BgB,EAAeA,GAAgBhB,EAAIQ,WACnCS,EAAeA,GAAgBjB,EAAIS,WACnCU,EAAK5P,KAAKyO,EAKX,KAAK9O,EAAI,EAAGA,EAAIgQ,EAAKhQ,IACpB8O,EAAMmB,EAAKjQ,GACN6P,IAAgBC,GAAiBhB,EAAIQ,WAGjCS,IAAiBjB,EAAIS,aAC7BU,EAAKjQ,GAAK8O,EAAI9G,QAAQmI,aAHtBF,EAAKjQ,GAAK8O,EAAI9G,QAAQI,WAOxB,OAAO6H,GAKR,QAAShB,IAAe1D,EAAKN,GACxBM,EAAI+D,WACPrE,EAAKqE,YAAa,EAEVrE,EAAKqE,aACbrE,EAAKqE,YAAa,GAGf/D,EAAIgE,WACPtE,EAAKsE,YAAa,EAEVtE,EAAKsE,aACbtE,EAAKsE,YAAa,GAOpB,QAASa,IAAgBtB,EAAK/H,GAC7B+H,EAAIuB,KAAKtJ,EAAE,IAAM,GACfuJ,MAAMvJ,EAAE,IAAM,GACdwJ,KAAKxJ,EAAE,IAAM,GACbiD,MAAMjD,EAAE,IAAM,GACdkD,QAAQlD,EAAE,IAAM,GAChBmD,QAAQnD,EAAE,IAAM,GAChBoD,aAAapD,EAAE,IAAM,GAqCxB,QAASyJ,IAAgB1B,EAAK2B,GAC7B,MAAOC,IAAeC,OAAOnG,KAAKsE,EAAK2B,GAMxC,QAASG,IAAWL,EAAME,GACzB,MAAOI,IAAqBN,EAAMO,GAAsBL,IAIzD,QAASI,IAAqBN,EAAMQ,GACnC,GACI/Q,GADAwM,EAAI,EAGR,KAAKxM,EAAE,EAAGA,EAAE+Q,EAAOtR,OAAQO,IAC1BwM,GAAKwE,GAAoBT,EAAMQ,EAAO/Q,GAGvC,OAAOwM,GAeR,QAASwE,IAAoBT,EAAMU,GAClC,GAAIpL,GACAqL,CAEJ,OAAqB,gBAAVD,GACHA,GAEEpL,EAAQoL,EAAMpL,OACnBsL,GAAetL,GACXsL,GAAetL,GAAO0K,GAEvBC,GAAgBD,EAAM1K,GAErBoL,EAAMG,QACdF,EAAWL,GAAqBN,EAAMU,EAAMG,OACxCF,EAASG,MAAM,UACXH,EAIF,GAYR,QAASI,IAAYC,EAAOC,EAAOf,EAAWgB,EAAWC,GACxD,GAAIC,EAcJ,OAZAJ,GAAQrB,GAAGlT,OAAO0R,UAAU6C,GAC5BC,EAAQtB,GAAGlT,OAAO0R,UAAU8C,GAE5BG,GAAcJ,EAAMI,YAAcJ,EAAMK,MAAMpH,KAAK+G,GAGnDd,EAAYkB,EAAWE,eAAepB,IAAcA,EAIpDgB,EAAYA,GAAa,MAElBK,GACNP,EACAC,EACAV,GAAsBL,GACtBgB,EACAC,GAMF,QAASI,IAAsBP,EAAOC,EAAOT,EAAQU,EAAWC,GAC/D,GAEIK,GACAC,EAEAC,EAEAC,EAPAC,EAAeZ,EAAMvJ,QAAQmI,YAC7BiC,EAAeZ,EAAMxJ,QAAQmI,YAG7BkC,EAAU,GAEVC,EAAW,GAEXC,EAAa,GACbC,EAAa,GACbC,EAAY,EAIhB,KAAKT,EAAM,EAAGA,EAAMjB,EAAOtR,SAC1BsS,EAAWW,GAAmBnB,EAAOC,EAAOW,EAAcC,EAAcrB,EAAOiB,IAC3ED,KAAa,GAFiBC,IAKlCK,GAAWN,CAIZ,KAAKE,EAAOlB,EAAOtR,OAAO,EAAGwS,EAAOD,IACnCD,EAAWW,GAAmBnB,EAAOC,EAAOW,EAAcC,EAAerB,EAAOkB,IAC5EF,KAAa,GAFyBE,IAK1CK,EAAWP,EAAWO,CAKvB,KAAKJ,EAAQF,EAAOE,GAASD,EAAQC,IACpCK,GAAcvB,GAAoBO,EAAOR,EAAOmB,IAChDM,GAAcxB,GAAoBQ,EAAOT,EAAOmB,GAYjD,QATIK,GAAcC,KAEhBC,EADGf,EACSc,EAAaf,EAAYc,EAGzBA,EAAad,EAAYe,GAIhCH,EAAUI,EAAYH,EAwB9B,QAASI,IAAmBnB,EAAOC,EAAOW,EAAcC,EAAcnB,GACrE,GAAIpL,GACA4C,CAEJ,OAAqB,gBAAVwI,GACHA,MAEEpL,EAAQoL,EAAMpL,SACvB4C,EAAOkK,GAAe9M,EAAMK,OAAO,IAI/BuC,GAAQ0J,EAAaS,OAAOR,EAAc3J,MACtC+H,GAAgBe,EAAO1L,GAiBjC,QAASiL,IAAsBL,GAC9B,MAAIA,KAAaoC,IACTA,GAAuBpC,GAEvBoC,GAAuBpC,GAAaqC,GAAkBrC,GAK/D,QAASqC,IAAkBrC,GAK1B,IAJA,GAEIY,GAFAN,KACAgC,EAAU,6DAGN1B,EAAQ0B,EAAQ3D,KAAKqB,IACxBY,EAAM,GACTN,EAAO1Q,KAAKgR,EAAM,IAEVA,EAAM,GACdN,EAAO1Q,MAAO+Q,MAAO0B,GAAkBzB,EAAM,MAErCA,EAAM,GACdN,EAAO1Q,MAAOwF,MAAOwL,EAAM,KAEnBA,EAAM,IACdN,EAAO1Q,KAAKgR,EAAM,GAIpB,OAAON,GAQR,QAASiC,OA4BT,QAASC,IAAYC,EAAYC,GAChC,GAAIC,EAsBJ,OAnBI5H,GAAW2H,EAAS,iBACvBC,EAAWD,EAAQE,aAEI,kBAAbD,KACVA,EAAWD,EAAQE,YAAc,WAChCH,EAAW9G,MAAMzK,KAAM2K,aAKzB8G,EAAS9I,UAAYa,EAAa+H,EAAW5I,WAG7CgB,EAAa6H,EAASC,EAAS9I,WAC/BmB,EAAkB0H,EAASC,EAAS9I,WAGpCgB,EAAa4H,EAAYE,GAElBA,EAIR,QAASE,IAAaC,EAAUJ,GAC/B7H,EAAa6H,EAASI,EAASjJ,WA0xChC,QAASkJ,IAAYC,EAAMC,GAE1B,OAAKD,IAASC,MAIVD,IAAQC,KACJD,EAAKE,YAAcD,EAAKC,WAC9BC,GAAiBH,EAAMC,IACvBE,GAAiBF,EAAMD,IAQ1B,QAASG,IAAiBC,EAAQC,GACjC,IAAK,GAAIC,KAAYF,GACpB,IAAK,sCAAsC9V,KAAKgW,IAC3CF,EAAOE,KAAcD,EAASC,GACjC,OAAO,CAIV,QAAO,EAi6DR,QAASC,IAAUC,GAClB,GAAIC,GAAYC,GAAkBF,EAClC,OAAqB,eAAdC,GAA4C,uBAAdA,EAKtC,QAASE,IAAiBH,GACzB,MAAoC,uBAA7BE,GAAkBF,GAI1B,QAASE,IAAkBF,GAC1B,MAAO5H,KAAc4H,EAAMI,YAAcH,UAAWD,EAAMC,WAI3D,QAASI,IAAgBC,GACxB,GACIvU,GAAGiU,EADHO,IAGJ,KAAKxU,EAAI,EAAGA,EAAIuU,EAAO9U,OAAQO,IAC9BiU,EAAQM,EAAOvU,IACdwU,EAAWP,EAAMQ,OAASD,EAAWP,EAAMQ,UAAYpU,KAAK4T,EAG9D,OAAOO,GAKR,QAASE,IAAcC,EAAQC,GAC9B,MAAOD,GAAOhN,MAAQiN,EAAOjN,MAc9B,QAASkN,IAAiB5U,GACzB,GACI6U,GACAC,EACA7M,EACA8M,EAJAC,EAAS/E,GAAGgF,cAuChB,OAjCID,KAAUA,GAAU,KACxBH,EAAa7U,EAAGkV,KAAKF,EAAS,UAAY,KAEtCH,IAEFA,EADyB,gBAAfA,GACG7X,EAAEmY,UAAWN,MAO3BC,EAAYD,EAAWnN,MACN,MAAboN,IAAqBA,EAAYD,EAAWxM,MAChDJ,EAAW4M,EAAW5M,SACtB8M,EAAQF,EAAWE,YACZF,GAAWnN,YACXmN,GAAWxM,WACXwM,GAAW5M,eACX4M,GAAWE,OAIF,MAAbD,IAAqBA,EAAY9U,EAAGkV,KAAKF,EAAS,UACrC,MAAbF,IAAqBA,EAAY9U,EAAGkV,KAAKF,EAAS,SACtC,MAAZ/M,IAAoBA,EAAWjI,EAAGkV,KAAKF,EAAS,aACvC,MAATD,IAAiBA,EAAQ/U,EAAGkV,KAAKF,EAAS,UAG9CF,EAAyB,MAAbA,EAAoB/X,EAAOkL,SAAS6M,GAAa,KAC7D7M,EAAuB,MAAZA,EAAmBlL,EAAOkL,SAASA,GAAY,KAC1D8M,EAAQjL,QAAQiL,IAEPF,WAAYA,EAAYC,UAAWA,EAAW7M,SAAUA,EAAU8M,MAAOA,GAimCnF,QAASK,IAAkBC,EAAKC,GAC/B,GAAIvV,GAAGwV,CAEP,KAAKxV,EAAI,EAAGA,EAAIuV,EAAU9V,OAAQO,IAGjC,GAFAwV,EAAWD,EAAUvV,GAGpBwV,EAASC,SAAWH,EAAII,UACxBF,EAASE,UAAYJ,EAAIG,QAEzB,OAAO,CAIT,QAAO,EAKR,QAASE,IAAkB5O,EAAGC,GAC7B,MAAOD,GAAE0O,QAAUzO,EAAEyO,QA84CtB,QAASG,IAAmBC,GAC3B,GACI7V,GAAGsV,EACHvK,EAFA+K,IAIJ,KAAK9V,EAAE,EAAGA,EAAE6V,EAAKpW,OAAQO,IAAK,CAI7B,IAHAsV,EAAMO,EAAK7V,GAGN+K,EAAE,EAAGA,EAAE+K,EAAOrW,QACbsW,GAAyBT,EAAKQ,EAAO/K,IAAItL,OADpBsL,KAM3BuK,EAAIU,MAAQjL,GAEX+K,EAAO/K,KAAO+K,EAAO/K,QAAU1K,KAAKiV,GAGtC,MAAOQ,GAMR,QAASG,IAAuBH,GAC/B,GAAI9V,GAAGgW,EACHjL,EAAGuK,EACHY,CAEJ,KAAKlW,EAAE,EAAGA,EAAE8V,EAAOrW,OAAQO,IAG1B,IAFAgW,EAAQF,EAAO9V,GAEV+K,EAAE,EAAGA,EAAEiL,EAAMvW,OAAQsL,IAIzB,IAHAuK,EAAMU,EAAMjL,GAEZuK,EAAIa,eACCD,EAAElW,EAAE,EAAGkW,EAAEJ,EAAOrW,OAAQyW,IAC5BH,GAAyBT,EAAKQ,EAAOI,GAAIZ,EAAIa,aASjD,QAASC,IAAwBd,GAChC,GAEItV,GAAGqW,EAFHF,EAAcb,EAAIa,YAClBG,EAAkB,CAGtB,IAA4BvS,SAAxBuR,EAAIgB,gBAA+B,CAEtC,IAAKtW,EAAE,EAAGA,EAAEmW,EAAY1W,OAAQO,IAC/BqW,EAAaF,EAAYnW,GAGzBoW,GAAwBC,GAIxBC,EAAkB/W,KAAK4F,IACtBmR,EACA,EAAID,EAAWC,gBAIjBhB,GAAIgB,gBAAkBA,GAOxB,QAASP,IAAyBT,EAAKC,EAAWgB,GACjDA,EAAUA,KAEV,KAAK,GAAIvW,GAAE,EAAGA,EAAEuV,EAAU9V,OAAQO,IAC7BwW,GAAmBlB,EAAKC,EAAUvV,KACrCuW,EAAQlW,KAAKkV,EAAUvV,GAIzB,OAAOuW,GAKR,QAASC,IAAmBC,EAAMC,GACjC,MAAOD,GAAKtU,OAASuU,EAAKxU,KAAOuU,EAAKvU,IAAMwU,EAAKvU,OA29ClD,QAASwU,IAAqBC,EAASnZ,GAwItC,QAASoZ,GAAe/H,GACnB,WAAaA,GAChBA,EAAIgI,QAAUnF,EAGd7C,EAAIiI,MAAQpF,EA+Hd,QAASqF,KACHC,EAGIC,MAERC,IACAC,KALAC,IAUF,QAASA,KACRT,EAAQ7X,SAAS,MAGjBuY,EAAEC,WAAW,QAAS,SAASC,GAC9BC,EAAKD,EAAQ,KAAO,KACpBZ,EAAQc,YAAY,YAAaF,GACjCZ,EAAQc,YAAY,eAAgBF,KAKrCF,EAAEK,aAAc,QAAS,QAAU,SAASjG,GAC3CkF,EAAQc,YAAY,UAAWhG,GAC/BkF,EAAQc,YAAY,SAAUhG,KAG/BuF,EAAUha,EAAE,oCAAoC2a,UAAUhB,GAE1DiB,EAASP,EAAEO,OAAS,GAAIC,IAAOR,GAC/BS,IAEAX,EAAWE,EAAEU,QAAQC,aAEjBX,EAAEU,QAAQE,qBACbC,GAAoB5K,GAAS6K,EAAcd,EAAEU,QAAQK,mBACrDpb,EAAE2H,QAAQ0T,OAAOH,KAMnB,QAASJ,KACRF,EAAOb,SACHa,EAAO5X,IACV2W,EAAQ2B,QAAQV,EAAO5X,IAKzB,QAASuY,KAEJC,GACHA,EAAYC,gBAMbb,EAAOa,gBACPzB,EAAQ1T,SACRqT,EAAQ3X,YAAY,0CAEhBkZ,IACHlb,EAAE2H,QAAQ+T,OAAO,SAAUR,IAK7B,QAASjB,KACR,MAAON,GAAQgC,GAAG,YAYnB,QAASxB,GAAWyB,EAAUC,GAC7BC,KAGIN,GAAeI,GAAYJ,EAAYnU,OAASuU,IACnDG,IACAC,MAIIR,GAAeI,IACnBJ,EAAcnB,EAAE4B,KACfC,GAAYN,KACXM,GAAYN,GAAYvB,EAAE8B,gBAAgBP,IAE5CJ,EAAYY,WACXpc,EAAE,0BAA4B4b,EAAW,aAAazV,SAAS6T,IAEhEY,EAAOyB,eAAeT,IAGnBJ,IAGHlI,GAAOkI,EAAYc,mBAAmBhJ,IAIpCkI,EAAYe,YACZjJ,GAAKkJ,SAAShB,EAAYiB,cAAejB,EAAYkB,cAElDzC,MAEHuB,EAAYmB,QAAQrJ,GAAMuI,GAC1Be,IAGAC,IACAC,IAEAC,MAKHH,IACAd,KAMD,QAASE,KACRpB,EAAOoC,iBAAiBxB,EAAYnU,MACpCmU,EAAYC,gBACZD,EAAcnB,EAAE4B,KAAO,KAOxB,QAASgB,KACRnB,KACAC,GAEA,IAAIH,GAAWJ,EAAYnU,KACvB6V,EAAc1B,EAAY2B,aAC9BnB,KACA7B,EAAWyB,EAAUsB,GAErBN,IACAd,KAsBD,QAASsB,GAAWC,GACnB,GAAIpD,IAUH,MARIoD,IACHC,IAGDxB,KACAN,EAAY4B,YAAW,GACvBtB,MAEO,EAKT,QAAS5B,KACJD,KACHqD,IAKF,QAASA,KACR,GAAIC,GAAqBlD,EAAEU,QAAQyC,cAC/BC,EAAcpD,EAAEU,QAAQ1X,MAG3Bqa,GADiC,gBAAvBH,GACYA,EAEgB,kBAAvBA,GACOA,IAES,gBAAhBE,GACOA,EAAcE,IAEL,kBAAhBF,GACOA,IAAgBE,IAEd,WAAhBF,EACc9D,EAAQlV,SAASpB,SAAWsa,IAG5Brb,KAAKmJ,MAAMuO,EAAQlW,QAAUxB,KAAK4F,IAAImS,EAAEU,QAAQ6C,YAAa,KAKrF,QAASD,KACR,MAAO/C,GAAO5X,GAAK4X,EAAO5X,GAAGG,aAAY,GAAQ,EAIlD,QAASgY,GAAazU,IAEnBoV,IACDpV,EAAGmX,SAAWlW,QACd6T,EAAY9Q,OAER0S,GAAW,IACd5B,EAAYsC,QAAQ,eAAgBC,IAYvC,QAASC,KACRC,IAKD,QAASC,GAAoBC,GAC5BC,GAAkB/D,EAAEgE,4BAA4BF,IAIjD,QAASG,KACJrE,MACH8B,IACAP,EAAY+C,cAAcjH,IAC1BsF,KAKF,QAASG,MACH1C,EAAEU,QAAQyD,cAAgBC,GAAcjD,EAAY9Q,MAAO8Q,EAAY5Q,KAC3EqT,IAGAK,IAKF,QAASL,KACRS,GAAYlD,EAAY9Q,MAAO8Q,EAAY5Q,KAO5C,QAAS+T,GAAaC,GACrBtH,GAASsH,EACTN,IAKD,QAASO,KACRP,IASD,QAASzB,KACRjC,EAAOkE,YAAYtD,EAAYuD,OAIhC,QAASjC,KACR,GAAIkC,GAAM3E,EAAE4E,QACRD,GAAIxC,SAAShB,EAAYiB,cAAejB,EAAYkB,aACvD9B,EAAOsE,cAAc,SAGrBtE,EAAOuE,aAAa,SAWtB,QAASC,GAAOC,EAAiBC,GAChC9D,EAAY4D,OACX/E,EAAEkF,gBAAgBpQ,MAAMkL,EAAGhL,YAK7B,QAASmQ,KACJhE,GACHA,EAAYgE,WAUd,QAASC,KACRnM,GAAOkI,EAAYkE,gBAAgBpM,IACnC6G,IAID,QAASwF,KACRrM,GAAOkI,EAAYoE,gBAAgBtM,IACnC6G,IAID,QAAS0F,KACRvM,GAAKnP,OAAQ,SACbgW,IAID,QAAS2F,KACRxM,GAAKnP,IAAI,EAAG,SACZgW,IAID,QAAS4F,KACRzM,GAAO+G,EAAE4E,SACT9E,IAID,QAAS6F,GAASC,GACjB3M,GAAO+G,EAAEta,OAAOkgB,GAAgB/M,YAChCiH,IAID,QAAS+F,GAAcC,GACtB7M,GAAKnP,IAAIpE,EAAOkL,SAASkV,IACzBhG,IAMD,QAASiG,GAAOC,EAASzE,GACxB,GAAI0E,EAEJ1E,GAAWA,GAAY,MACvB0E,EAAOjG,EAAEkG,YAAY3E,IAAavB,EAAEmG,gBAAgB5E,GAEpDtI,GAAO+M,EAAQtV,QACfoP,EAAWmG,EAAOA,EAAKjZ,KAAO,MAK/B,QAASoZ,KACR,MAAOpG,GAAEqG,cAAcpN,IAaxB,QAASyI,KACR/B,EAAQ1Y,KACPwC,MAAO,OACPT,OAAQ2W,EAAQ3W,SAChB4C,SAAU,WAKZ,QAAS2W,KACR5C,EAAQ1Y,KACPwC,MAAO,GACPT,OAAQ,GACR4C,SAAU,KAUZ,QAAS0a,KACR,MAAOtG,GAIR,QAASuG,KACR,MAAOpF,GAIR,QAASqF,GAAOlgB,EAAMmgB,GACrB,GAAIC,EAEJ,IAAoB,gBAATpgB,GAAmB,CAC7B,GAAcmG,SAAVga,EACH,MAAOzG,GAAEU,QAAQpa,EAGjBogB,MACAA,EAAcpgB,GAAQmgB,EACtBE,EAAWD,OAGY,gBAATpgB,IACfqgB,EAAWrgB,GAKb,QAASqgB,GAAWD,GACnB,GACIE,GADAC,EAAY,CAGhB,KAAKD,IAAcF,GAClB1G,EAAE8G,iBAAiBF,GAAcF,EAAcE,EAGhD5G,GAAE+G,iBACF/G,EAAEgH,qBAGF,KAAKJ,IAAcF,GAClB1G,EAAEiH,sBAAsBL,GACxBC,GAKD,IAAkB,IAAdA,EAAiB,CACpB,GAAmB,WAAfD,GAA0C,kBAAfA,GAAiD,gBAAfA,EAEhE,WADA7D,IAAW,EAGP,IAAmB,gBAAf6D,EACR,MAEI,IAAmB,kBAAfA,EAKR,YAJIzF,IACHA,EAAY+F,wBACZ/F,EAAYgG,uBAIT,IAAmB,aAAfP,EAGR,MAFA5G,GAAEoH,8BACFzD,KAMFlD,IACAoB,MACAe,IAID,QAASa,GAAQnd,EAAMoO,GACtB,GAAIC,GAAO0S,MAAMrU,UAAU4C,MAAM1C,KAAK8B,UAAW,EAKjD,IAHAN,EAAUA,GAAWgP,GACrBrZ,KAAKid,YAAYhhB,EAAMoO,EAASC,GAE5BqL,EAAEU,QAAQpa,GACb,MAAO0Z,GAAEU,QAAQpa,GAAMwO,MAAMJ,EAASC,GAtxBxC,GAAIqL,GAAI3V,IAMR2V,GAAEN,OAASA,EACXM,EAAEkB,QAAUA,EACZlB,EAAE2D,cAAgBA,EAClB3D,EAAE6D,oBAAsBA,EACxB7D,EAAEsE,aAAeA,EACjBtE,EAAEwE,kBAAoBA,EACtBxE,EAAEuH,eAAiBtD,EACnBjE,EAAEwH,WAAa1H,EACfE,EAAE+E,OAASA,EACX/E,EAAEmF,SAAWA,EACbnF,EAAEoF,KAAOA,EACTpF,EAAEsF,KAAOA,EACTtF,EAAEwF,SAAWA,EACbxF,EAAEyF,SAAWA,EACbzF,EAAE0F,MAAQA,EACV1F,EAAE2F,SAAWA,EACb3F,EAAE6F,cAAgBA,EAClB7F,EAAE+F,OAASA,EACX/F,EAAEoG,QAAUA,EACZpG,EAAEsG,YAAcA,EAChBtG,EAAEuG,QAAUA,EACZvG,EAAEwG,OAASA,EACXxG,EAAEyD,QAAUA,EAMZzD,EAAE8G,oBACF9G,EAAE+G,iBACF/G,EAAEyH,kBAIFzH,EAAE7Z,UAAYH,EAAiBG,OAE/B6Z,EAAEgH,qBAQF,IAAI3M,EAIJ2F,GAAEK,aACD,OAAQ,aAAc,kBAAmB,WAAY,gBAAiB,WAAY,yBAChF,SAAS/F,EAAMoN,EAAYC,EAAiBC,EAAUC,EAAeC,EAAUC,GAkBjF,GAhBA1N,EAAaxG,EACZmU,GAAoB1N,IAGjBoN,IACHrN,EAAW4N,QAAUP,GAElBC,IACHtN,EAAW6N,aAAeP,GAEvBC,IACHvN,EAAW8N,UAAYP,GAEpBC,IACHxN,EAAW+N,eAAiBP,GAEb,MAAZC,EAAkB,CACrB,GAAIO,GAAQxU,EAAawG,EAAWgO,MACpCA,GAAMC,IAAMR,EACZzN,EAAWgO,MAAQA,EAGU,QAA1BN,IACHA,EAAwB,OAGE,QAA1BA,GAC0B,UAA1BA,GACiC,kBAA1BA,KAEP1N,EAAWkO,uBAAyBR,GAKjC9O,IACHsG,EAAetG,MAUjB+G,EAAEwI,2BAA6B9iB,EAAOkL,SAASoP,EAAEU,QAAQ8H,4BACzDxI,EAAEyI,0BAA4B/iB,EAAOkL,SAASoP,EAAEU,QAAQ+H,2BAKxDzI,EAAEta,OAAS,WACV,GAAI8R,EAmBJ,OAjB2B,UAAvBwI,EAAEU,QAAQgI,UACblR,EAAMoB,GAAGlT,OAAOoP,MAAM,KAAME,WAGxBwC,EAAImR,WACPnR,EAAIoR,SAILpR,EAD+B,QAAvBwI,EAAEU,QAAQgI,SACZ9P,GAAGlT,OAAOqS,IAAIjD,MAAM,KAAME,WAG1B4D,GAAGlT,OAAO0R,UAAUtC,MAAM,KAAME,WAGvCuK,EAAe/H,GAERA,GAiBRwI,EAAE6I,mBAAqB,WACtB,MAA8B,UAAvB7I,EAAEU,QAAQgI,UAA+C,QAAvB1I,EAAEU,QAAQgI,UAKpD1I,EAAEqG,cAAgB,SAASpN,GAC1B,IAAKA,EAAK0P,UACT,MAAO1P,GAAKvI,OAGb,IAEIoY,GAFAC,EAAY/I,EAAEta,OAAOuT,EAAK+P,WAC1BC,EAAahQ,EAAKjI,OAAS+X,EAAU/X,MAWzC,OAPIiY,KACHH,EAAoBC,EAAUrY,QAAQ5G,IAAImf,GACtChQ,EAAKjI,OAAS8X,EAAkB9X,SAAW,IAC9C+X,EAAYD,IAIPC,GAMR/I,EAAE4E,OAAS,WACV,GAAID,GAAM3E,EAAEU,QAAQiE,GAIpB,OAHmB,kBAARA,KACVA,EAAMA,KAEA3E,EAAEta,OAAOif,GAAK9L,aAKtBmH,EAAEkJ,YAAc,SAASvM,GACxB,MAAIA,GAAMpM,IACFoM,EAAMpM,IAAIG,QAGVsP,EAAEmJ,mBAAmBxM,EAAMyM,OAAQzM,EAAMtM,QAOlD2P,EAAEmJ,mBAAqB,SAASC,EAAQC,GACvC,GAAI9Y,GAAM8Y,EAAW3Y,OAarB,OAXI0Y,GACH7Y,EAAIO,YAAYhH,IAAIkW,EAAEwI,4BAGtBjY,EAAIzG,IAAIkW,EAAEyI,2BAGPzI,EAAE6I,sBACLtY,EAAIsI,YAGEtI,GAMRyP,EAAEsJ,iBAAmB,SAAS1Y,GAC7B,OAAQA,EAAS2Y,QAAU3Y,EAAS0J,MAAMpH,KAAKtC,EAAUoP,EAAEU,QAAQpG,MACjEkP,YASHC,GAAavW,KAAK8M,EAClB,IAWIO,GACAZ,EACAQ,EACAgB,EAEAkC,EACAxC,GAGA5H,GApBAmL,GAAgBpE,EAAEoE,cAClBC,GAAcrE,EAAEqE,YAChBN,GAAoB/D,EAAE+D,kBAQtBL,GAAWpE,EAAQ,GAKnBuC,MAGAJ,GAAqB,EACrBxE,KAWHhE,IAD4B,MAAzB+G,EAAEU,QAAQgJ,YACN1J,EAAEta,OAAOsa,EAAEU,QAAQgJ,aAAa7Q,YAGhCmH,EAAE4E,SAyKV5E,EAAE2J,uBAAyB,WAI1B,MAH4Bld,UAAxB4W,GACHxD,IAEMwD,GAIRrD,EAAE4J,aAAe,WAChB,MAAmC,SAA5B5J,EAAEU,QAAQyC,eAAiD,SAArBnD,EAAEU,QAAQ1X,QA8OxDgX,EAAE0B,oBAAsBA,EACxB1B,EAAEuC,sBAAwBA,EAkH1BvC,EAAE6J,aAiXH,QAASC,IAAkCpJ,GAC1C/a,EAAEU,KAAK0jB,GAA2B,SAASzjB,EAAM0I,GAC3B,MAAjB0R,EAAQpa,KACXoa,EAAQpa,GAAQ0I,EAAK0R,MAQxB,QAASsH,IAAoBgC,GAC5B,GAAIhb,GAAOtJ,EAAO2U,YAAc3U,EAAOukB,QACvC,OAAOjb,GAAKkE,KAAKxN,EAAQskB,IACxBhb,EAAKkE,KAAKxN,EAAQ,MAcpB,QAAS8a,IAAO0J,GAqBf,QAASxK,KACR,GAAIgB,GAAUwJ,EAASxJ,QACnByJ,EAAWzJ,EAAQH,MAEvBJ,GAAKO,EAAQR,MAAQ,KAAO,KAExBiK,GACExhB,EAIJA,EAAGyhB,QAHHzhB,EAAK0B,KAAK1B,GAAKhD,EAAE,6BAKlBgD,EAAG0hB,OAAOC,EAAc,SACtBD,OAAOC,EAAc,UACrBD,OAAOC,EAAc,WACrBD,OAAO,4BAGTjJ,IAKF,QAASA,KACJzY,IACHA,EAAGsD,SACHtD,EAAKqX,EAAErX,GAAK,MAKd,QAAS2hB,GAAcvgB,GACtB,GAAIwgB,GAAY5kB,EAAE,kBAAoBoE,EAAW,OAC7C2W,EAAUwJ,EAASxJ,QACnB8J,EAAY9J,EAAQH,OAAOxW,EA4J/B,OA1JIygB,IACH7kB,EAAEU,KAAKmkB,EAAU9b,MAAM,KAAM,SAAShG,GACrC,GAEI+hB,GAFAC,EAAgB/kB,IAChBglB,GAAgB,CAGpBhlB,GAAEU,KAAKgE,KAAKqE,MAAM,KAAM,SAAS+E,EAAGmX,GACnC,GAAIC,GACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,CAEc,UAAdV,GACHF,EAAgBA,EAAc5gB,IAAInE,EAAE,oBACpCglB,GAAgB,KAGXE,GAAqBnK,EAAQ6K,mBAAqBX,KACtDG,EAAc,SAAS1e,GAClBwe,EAAkBW,OACrBX,EAAkBW,MAAMtY,KAAKoY,EAAO,GAAIjf,IAG1C2e,EAAe,GACfC,EAAcJ,EAAkBxV,OAEvByV,EAAWZ,EAAShE,YAAY0E,KACzCG,EAAc,WACbb,EAAS1C,WAAWoD,IAErBa,EAAiB1iB,KAAK6hB,GACtBI,EAAeF,EAASY,mBACxBT,EAAcH,EAASa,mBAEfzB,EAASU,KACjBG,EAAc,WACbb,EAASU,MAEVI,GAAgBd,EAAS/jB,UAAUylB,gBAAkBhB,GACrDK,EAAcvK,EAAQkL,WAAWhB,IAG9BG,IAEHG,EACCL,EACCA,EAAkBK,UAClBxK,EAAQmL,iBAAiBjB,GAE3BO,EACCN,EACCA,EAAkBiB,KAClBpL,EAAQqL,YAAYnB,GAGrBQ,EADGJ,EACS/V,GAAW+V,GAEfE,GAAaxK,EAAQR,MACjB,gCAAkCgL,EAAY,YAElDC,IAAezK,EAAQR,MACnB,gCAAkCiL,EAAa,YAG/ClW,GAAWgW,GAGxBI,GACC,MAAQT,EAAa,UACrBzK,EAAK,UACLA,EAAK,kBAGNmL,EAAS3lB,EACR,gCAAkC0lB,EAAQ5V,KAAK,KAAO,KACrD2V,EACD,aAECI,MAAM,SAASnf,GAEVif,EAAOU,SAAS7L,EAAK,qBAEzB4K,EAAY1e,IAKXif,EAAOU,SAAS7L,EAAK,kBACrBmL,EAAOU,SAAS7L,EAAK,qBAErBmL,EAAO3jB,YAAYwY,EAAK,mBAI1B8L,UAAU,WAGVX,EACEY,IAAI,IAAM/L,EAAK,iBACf+L,IAAI,IAAM/L,EAAK,mBACf1Y,SAAS0Y,EAAK,iBAEhBgM,QAAQ,WAERb,EAAO3jB,YAAYwY,EAAK,iBAExBiM,MACA,WAGCd,EACEY,IAAI,IAAM/L,EAAK,iBACf+L,IAAI,IAAM/L,EAAK,mBACf1Y,SAAS0Y,EAAK,iBAEjB,WAECmL,EACE3jB,YAAYwY,EAAK,gBACjBxY,YAAYwY,EAAK,iBAItBuK,EAAgBA,EAAc5gB,IAAIwhB,OAKjCX,GACHD,EACE2B,QAAQ5kB,SAAS0Y,EAAK,gBAAgB5P,MACtCkG,OAAOhP,SAAS0Y,EAAK,iBAAiB5P,MAGrCma,EAAcviB,OAAS,GAC1BsiB,EAAU9kB,EAAE,UACRglB,GACHF,EAAQhjB,SAAS,mBAElBgjB,EAAQJ,OAAOK,GACfH,EAAUF,OAAOI,IAGjBF,EAAUF,OAAOK,KAKbH,EAIR,QAAS9F,GAAYpP,GAChB1M,GACHA,EAAGU,KAAK,MAAMgM,KAAKA,GAKrB,QAAS2M,GAAe4I,GACnBjiB,GACHA,EAAGU,KAAK,OAASuhB,EAAa,WAC5BnjB,SAAS0Y,EAAK,iBAKlB,QAASwC,GAAiBiI,GACrBjiB,GACHA,EAAGU,KAAK,OAASuhB,EAAa,WAC5BjjB,YAAYwY,EAAK,iBAKrB,QAAS0E,GAAc+F,GAClBjiB,GACHA,EAAGU,KAAK,OAASuhB,EAAa,WAC5B1e,KAAK,YAAY,GACjBzE,SAAS0Y,EAAK,mBAKlB,QAAS2E,GAAa8F,GACjBjiB,GACHA,EAAGU,KAAK,OAASuhB,EAAa,WAC5B1e,KAAK,YAAY,GACjBvE,YAAYwY,EAAK,mBAKrB,QAASmM,KACR,MAAOb,GAjQR,GAAIzL,GAAI3V,IAGR2V,GAAEN,OAASA,EACXM,EAAEoB,cAAgBA,EAClBpB,EAAEyE,YAAcA,EAChBzE,EAAEgC,eAAiBA,EACnBhC,EAAE2C,iBAAmBA,EACrB3C,EAAE6E,cAAgBA,EAClB7E,EAAE8E,aAAeA,EACjB9E,EAAEsM,oBAAsBA,EACxBtM,EAAErX,GAAK,IAGP,IAAIA,GAEAwX,EADAsL,KAoQL,QAAShC,MAqDR,QAASrF,GAAc/T,EAAOE,GAC7B,OAAQgc,GACPlc,EAAQkc,GAAchc,EAAMic,EAI9B,QAASnI,GAAYhU,EAAOE,GAC3Bgc,EAAalc,EACbmc,EAAWjc,EACXwT,EAAkB0I,EAAS,SAM5B,QAAS1I,GAAkB2I,EAAiBC,GAC3C,GAAIjkB,GAAGqU,CASP,KAPyB,UAArB4P,EACHC,KAE6B,QAArBD,IACRC,EAAQC,EAAuBD,EAAOF,IAGlChkB,EAAI,EAAGA,EAAIgkB,EAAgBvkB,OAAQO,IACvCqU,EAAS2P,EAAgBhkB,GAGF,YAAnBqU,EAAO+P,SACVC,IAGDhQ,EAAOiQ,UAAYjQ,EAAOiQ,UAAY,GAAK,EAC3CjQ,EAAO+P,QAAU,SAGlB,KAAKpkB,EAAI,EAAGA,EAAIgkB,EAAgBvkB,OAAQO,IACvCqU,EAAS2P,EAAgBhkB,GAEzBukB,EAAoBlQ,EAAQA,EAAOiQ,UAOrC,QAASC,GAAoBlQ,EAAQmQ,GACpCC,EAAkBpQ,EAAQ,SAASqQ,GAClC,GACI1kB,GAAG2kB,EACHC,EAFAC,EAAgB5nB,EAAEgJ,QAAQoO,EAAOE,OAIrC,IAGCiQ,IAAYnQ,EAAOiQ,UAEA,aAAnBjQ,EAAO+P,QACN,CAGD,GAFA/P,EAAO+P,QAAU,WAEbM,EACH,IAAK1kB,EAAI,EAAGA,EAAI0kB,EAAYjlB,OAAQO,IACnC2kB,EAAaD,EAAY1kB,GAGxB4kB,EADGC,EACaF,EAGAG,EAAoBH,EAAYtQ,GAG7CuQ,GACHV,EAAM7jB,KAAK+L,MACV8X,EACAa,EAAYH,GAMhBI,QAMH,QAASC,GAAkB5Q,GAC1B,GAAI6Q,GAAgC,YAAnB7Q,EAAO+P,OAExB/P,GAAO+P,QAAU,WAEbc,GACHF,IAKF,QAASA,KACRX,IACKA,GACJzI,EAAasI,GAKf,QAASO,GAAkBpQ,EAAQ8Q,GAClC,GAAInlB,GAEAsD,EADA8hB,EAAWlV,GAAGmV,cAGlB,KAAKrlB,EAAE,EAAGA,EAAEolB,EAAS3lB,OAAQO,IAAK,CAUjC,GATAsD,EAAM8hB,EAASplB,GAAGwK,KACjB8M,EACAjD,EACAwP,EAAW7b,QACX8b,EAAS9b,QACTsP,EAAEU,QAAQgI,SACVmF,GAGG7hB,KAAQ,EAEX,MAEI,IAAkB,gBAAPA,GAGf,WADAmhB,GAAkBnhB,EAAK6hB,GAKzB,GAAI5Q,GAASF,EAAOE,MACpB,IAAIA,EACCtX,EAAEiP,WAAWqI,IAChB+C,EAAEgO,cACF/Q,EAAO/J,KACN8M,EACAuM,EAAW7b,QACX8b,EAAS9b,QACTsP,EAAEU,QAAQgI,SACV,SAASzL,GACR4Q,EAAS5Q,GACT+C,EAAEiO,gBAIItoB,EAAEgJ,QAAQsO,GAClB4Q,EAAS5Q,GAGT4Q,QAEG,CACJ,GAAIK,GAAMnR,EAAOmR,GACjB,IAAIA,EAAK,CACR,GAKIC,GALAC,EAAUrR,EAAOqR,QACjBC,EAAQtR,EAAOsR,MACfC,EAAWvR,EAAOuR,QAMrBH,GAFGxoB,EAAEiP,WAAWmI,EAAOc,MAEVd,EAAOc,OAIPd,EAAOc,IAKrB,IAAIA,GAAOlY,EAAEmY,UAAWqQ,OAEpBI,EAAaxZ,GAAagI,EAAOwR,WAAYvO,EAAEU,QAAQ6N,YACvDC,EAAWzZ,GAAagI,EAAOyR,SAAUxO,EAAEU,QAAQ8N,UACnDC,EAAgB1Z,GAAagI,EAAO0R,cAAezO,EAAEU,QAAQ+N,cAE7DF,KACH1Q,EAAK0Q,GAAchC,EAAWlT,UAE3BmV,IACH3Q,EAAK2Q,GAAYhC,EAASnT,UAEvB2G,EAAEU,QAAQgI,UAAkC,SAAtB1I,EAAEU,QAAQgI,WACnC7K,EAAK4Q,GAAiBzO,EAAEU,QAAQgI,UAGjC1I,EAAEgO,cACFroB,EAAE+oB,KAAK/oB,EAAEmY,UAAW6Q,GAAc5R,GACjCc,KAAMA,EACNuQ,QAAS,SAASnR,GACjBA,EAASA,KACT,IAAIjR,GAAMwI,GAAS4Z,EAAS/jB,KAAM2K,UAC9BrP,GAAEgJ,QAAQ3C,KACbiR,EAASjR,GAEV6hB,EAAS5Q,IAEVoR,MAAO,WACN7Z,GAAS6Z,EAAOhkB,KAAM2K,WACtB6Y,KAEDS,SAAU,WACT9Z,GAAS8Z,EAAUjkB,KAAM2K,WACzBgL,EAAEiO,qBAIJJ,MAWH,QAASe,GAAeC,GACvB,GAAI9R,GAAS+R,EAAiBD,EAC1B9R,KACH0P,EAAQ1jB,KAAKgU,GACbgH,GAAoBhH,GAAU,QAKhC,QAAS+R,GAAiBD,GACzB,GACI9R,GACArU,EAFAqmB,EAAcnW,GAAGoW,iBAcrB,IAVIrpB,EAAEiP,WAAWia,IAAgBlpB,EAAEgJ,QAAQkgB,GAC1C9R,GAAWE,OAAQ4R,GAEY,gBAAhBA,GACf9R,GAAWmR,IAAKW,GAEe,gBAAhBA,KACf9R,EAASpX,EAAEmY,UAAW+Q,IAGnB9R,EAAQ,CAqBX,IAlBIA,EAAOkS,UACsB,gBAArBlS,GAAOkS,YACjBlS,EAAOkS,UAAYlS,EAAOkS,UAAUvgB,MAAM,QAK3CqO,EAAOkS,aAIJtpB,EAAEgJ,QAAQoO,EAAOE,UACpBF,EAAOmS,UAAYnS,EAAOE,OAC1BF,EAAOE,OAAStX,EAAEwpB,IAAIpS,EAAOE,OAAQ,SAASoQ,GAC7C,MAAOG,GAAoBH,EAAYtQ,MAIpCrU,EAAE,EAAGA,EAAEqmB,EAAY5mB,OAAQO,IAC/BqmB,EAAYrmB,GAAGwK,KAAK8M,EAAGjD,EAGxB,OAAOA,IAKT,QAASqS,GAAkBC,GAC1BC,EACCC,EAAuBF,IAMzB,QAASG,GAAmB1L,GACR,MAAfA,EACHwL,EAA2B7C,GAAS,GAGpC6C,EACCtL,EAA4BF,IAM/B,QAASwL,GAA2BG,EAAeC,GAClD,GAAIhnB,EAGJ,KAAKA,EAAI,EAAGA,EAAI+mB,EAActnB,OAAQO,IACrCilB,EAAkB8B,EAAc/mB,GAG7BgnB,IACHjD,KACAG,OAIAH,EAAU9mB,EAAEgqB,KAAKlD,EAAS,SAAS1P,GAClC,IAAKrU,EAAI,EAAGA,EAAI+mB,EAActnB,OAAQO,IACrC,GAAIqU,IAAW0S,EAAc/mB,GAC5B,OAAO,CAGT,QAAO,IAGRkkB,EAAQC,EAAuBD,EAAO6C,IAGvCnL,EAAasI,GAId,QAASgD,KACR,MAAOnD,GAAQ7W,MAAM,GAItB,QAASia,GAAmBC,GAC3B,MAAOnqB,GAAEgqB,KAAKlD,EAAS,SAAS1P,GAC/B,MAAOA,GAAO+S,IAAM/S,EAAO+S,KAAOA,IAChC,GAKJ,QAAS9L,GAA4BF,GAG/BA,EAGKne,EAAEgJ,QAAQmV,KACnBA,GAAgBA,IAHhBA,IAMD,IACIpb,GADAqnB,IAIJ,KAAKrnB,EAAI,EAAGA,EAAIob,EAAY3b,OAAQO,IACnCqnB,EAAgBhnB,KAAK+L,MACpBib,EACAR,EAAuBzL,EAAYpb,IAIrC,OAAOqnB,GAMR,QAASR,GAAuBF,GAC/B,GAAI3mB,GAAGqU,CAGP,KAAKrU,EAAI,EAAGA,EAAI+jB,EAAQtkB,OAAQO,IAE/B,GADAqU,EAAS0P,EAAQ/jB,GACbqU,IAAWsS,EACd,OAAStS,EAMX,OADAA,GAAS8S,EAAmBR,GACxBtS,GACMA,GAGHpX,EAAEgqB,KAAKlD,EAAS,SAAS1P,GAC/B,MAAOiT,GAAoBX,EAAYtS,KAKzC,QAASiT,GAAoBC,EAASC,GACrC,MAAOD,IAAWC,GAAWC,EAAmBF,IAAYE,EAAmBD,GAIhF,QAASC,GAAmBpT,GAC3B,OACoB,gBAAXA,GACNA,EAAOmS,WAAanS,EAAOqT,kBAAoBrT,EAAOmR,KAAOnR,EAAOE,OACrE,OAEFF,EAMD,QAAS8P,GAAuBwD,EAAgB3D,GAC/C,MAAO/mB,GAAEgqB,KAAKU,EAAgB,SAAS1T,GACtC,IAAK,GAAIjU,GAAI,EAAGA,EAAIgkB,EAAgBvkB,OAAQO,IAC3C,GAAIiU,EAAMI,SAAW2P,EAAgBhkB,GACpC,OAAO,CAGT,QAAO,IAWT,QAAS4nB,GAAY3T,GAGpBA,EAAMtM,MAAQ2P,EAAEta,OAAOiX,EAAMtM,OACzBsM,EAAMpM,IACToM,EAAMpM,IAAMyP,EAAEta,OAAOiX,EAAMpM,KAG3BoM,EAAMpM,IAAM,KAGbggB,EAAY5T,EAAO6T,EAAkB7T,IACrC2H,EAAasI,GAKd,QAAS4D,GAAkB7T,GAC1B,GAAIjJ,KAUJ,OARA/N,GAAEU,KAAKsW,EAAO,SAASrW,EAAMC,GACxBkqB,EAAoBnqB,IACXmG,SAARlG,GAAqBgO,EAAShO,KACjCmN,EAAMpN,GAAQC,KAKVmN,EAIR,QAAS+c,GAAoBnqB,GAC5B,OAAQ,6BAA6BG,KAAKH,GAK3C,QAASoqB,GAAYrD,EAAY3P,GAChC,GACIT,GACAvU,EAAGiU,EAFH2Q,EAAgBE,EAAoBH,EAIxC,IAAIC,EAAe,CAGlB,IAFArQ,EAASwQ,EAAYH,GAEhB5kB,EAAI,EAAGA,EAAIuU,EAAO9U,OAAQO,IAC9BiU,EAAQM,EAAOvU,GAEViU,EAAMI,SACNW,IACHiT,EAAa1T,OAAOlU,KAAK4T,GACzBA,EAAMI,OAAS4T,GAEhB/D,EAAM7jB,KAAK4T,GAMb,OAFA2H,GAAasI,GAEN3P,EAGR,SAID,QAAS2T,GAAazmB,GACrB,GAAI0mB,GACAnoB,CAkBJ,KAhBc,MAAVyB,EACHA,EAAS,WAAa,OAAO,GAEpBxE,EAAEiP,WAAWzK,KACtB0mB,EAAU1mB,EAAS,GACnBA,EAAS,SAASwS,GACjB,MAAOA,GAAMQ,KAAO0T,IAKtBjE,EAAQjnB,EAAEgqB,KAAK/C,EAAOziB,GAAQ,GAKzBzB,EAAE,EAAGA,EAAE+jB,EAAQtkB,OAAQO,IACvB/C,EAAEgJ,QAAQ8d,EAAQ/jB,GAAGuU,UACxBwP,EAAQ/jB,GAAGuU,OAAStX,EAAEgqB,KAAKlD,EAAQ/jB,GAAGuU,OAAQ9S,GAAQ,GAIxDma,GAAasI,GAId,QAASkE,GAAa3mB,GACrB,MAAIxE,GAAEiP,WAAWzK,GACTxE,EAAEgqB,KAAK/C,EAAOziB,GAEH,MAAVA,GACRA,GAAU,GACHxE,EAAEgqB,KAAK/C,EAAO,SAASmE,GAC7B,MAAOA,GAAE5T,KAAOhT,KAGXyiB,EAsBR,QAASoE,GAAiBrU,GACzBA,EAAMtM,MAAQ2P,EAAEta,OAAOiX,EAAMtM,OACzBsM,EAAMpM,MACToM,EAAMpM,IAAMyP,EAAEta,OAAOiX,EAAMpM,MAE5B0gB,GAAiBtU,GAYlB,QAAS6Q,GAAoBvnB,EAAO8W,GACnC,GACI1M,GAAOE,EACP6Y,EAFA8H,IA4CJ,IAxCIlR,EAAEU,QAAQyQ,qBACblrB,EAAQ+Z,EAAEU,QAAQyQ,mBAAmBlrB,IAElC8W,GAAUA,EAAOoU,qBACpBlrB,EAAQ8W,EAAOoU,mBAAmBlrB,IAKnCN,EAAEmY,OAAOoT,EAAKjrB,GAEV8W,IACHmU,EAAInU,OAASA,GAGdmU,EAAI/T,IAAMlX,EAAMkX,MAAqB1Q,SAAbxG,EAAM6pB,GAAmB,MAAQsB,KAAcnrB,EAAM6pB,GAAK,IAE9E7pB,EAAMgpB,UACqB,gBAAnBhpB,GAAMgpB,UAChBiC,EAAIjC,UAAYhpB,EAAMgpB,UAAUvgB,MAAM,OAGtCwiB,EAAIjC,UAAYhpB,EAAMgpB,UAIvBiC,EAAIjC,aAGL5e,EAAQpK,EAAMoK,OAASpK,EAAMgT,KAC7B1I,EAAMtK,EAAMsK,IAGR6C,EAAa/C,KAChBA,EAAQ3K,EAAOkL,SAASP,IAErB+C,EAAa7C,KAChBA,EAAM7K,EAAOkL,SAASL,IAGnBtK,EAAMqiB,KAAO5iB,EAAO+L,WAAWpB,IAAU3K,EAAO+L,WAAWlB,GAG9D2gB,EAAI7gB,MAAQA,EAAQ3K,EAAOkL,SAASP,GAAS,KAC7C6gB,EAAI3gB,IAAMA,EAAM7K,EAAOkL,SAASL,GAAO,KACvC2gB,EAAIG,YAAa,MAEb,CAEJ,GAAIhhB,IACHA,EAAQ2P,EAAEta,OAAO2K,IACZA,EAAMihB,WACV,OAAO,CAIL/gB,KACHA,EAAMyP,EAAEta,OAAO6K,GACVA,EAAI+gB,YACR/gB,EAAM,OAIR6Y,EAASnjB,EAAMmjB,OACA3c,SAAX2c,IACHA,EAASrU,GACRgI,EAASA,EAAOwU,cAAgB9kB,OAChCuT,EAAEU,QAAQ6Q,gBAKZC,EAAmBnhB,EAAOE,EAAK6Y,EAAQ8H,GAKxC,MAFAlR,GAAEyR,eAAeP,GAEVA,EAOR,QAASM,GAAmBnhB,EAAOE,EAAK6Y,EAAQzM,GAC/CA,EAAMtM,MAAQA,EACdsM,EAAMpM,IAAMA,EACZoM,EAAMyM,OAASA,EACfsI,EAAoB/U,GACpBsU,GAAiBtU,GAMlB,QAAS+U,GAAoBlU,GAE5BmU,EAAoBnU,GAEhBA,EAAWjN,MAAQiN,EAAWjN,IAAIqhB,QAAQpU,EAAWnN,SACxDmN,EAAWjN,IAAM,MAGbiN,EAAWjN,MACXyP,EAAEU,QAAQmR,mBACbrU,EAAWjN,IAAMyP,EAAEmJ,mBAAmB3L,EAAW4L,OAAQ5L,EAAWnN,OAGpEmN,EAAWjN,IAAM,MAOpB,QAASohB,GAAoBnU,GACH,MAArBA,EAAW4L,SACd5L,EAAW4L,SAAW5L,EAAWnN,MAAMsY,WAAcnL,EAAWjN,KAAOiN,EAAWjN,IAAIoY,YAGnFnL,EAAW4L,QACd5L,EAAWnN,MAAMS,YACb0M,EAAWjN,KAEdiN,EAAWjN,IAAIO,cAIX0M,EAAWnN,MAAMsY,YACrBnL,EAAWnN,MAAQ2P,EAAEqG,cAAc7I,EAAWnN,MAAMW,KAAK,KAEtDwM,EAAWjN,MAAQiN,EAAWjN,IAAIoY,YACrCnL,EAAWjN,IAAMyP,EAAEqG,cAAc7I,EAAWjN,IAAIS,KAAK,MAUxD,QAASyc,GAAYH,EAAewE,EAAaC,GAChD,GACIC,GACA1J,EACA5f,EACAuQ,EACAwE,EAAWwU,EACX5hB,EAAOE,EACPoM,EAPAM,IAYJ,IAHA6U,EAAcA,GAAevF,EAC7BwF,EAAYA,GAAavF,EAErBc,EACH,GAAIA,EAAc+D,WAAY,CAG7B,GAAK/I,EAAMgF,EAAchF,IAExB,IADA0J,KACKtpB,EAAI,EAAGA,EAAI4f,EAAIngB,OAAQO,IAC3BspB,EAAQ1J,EAAI5f,KAAM,CAMpB,KADAuQ,EAAO6Y,EAAYphB,QAAQI,YACpBmI,EAAKiZ,SAASH,IAEfC,IAAWA,EAAQ/Y,EAAKkZ,SAE5B1U,EAAY6P,EAAcjd,MAC1B4hB,EAAU3E,EAAc/c,IACxBF,EAAQ4I,EAAKvI,QACbH,EAAM,KAEFkN,IACHpN,EAAQA,EAAMW,KAAKyM,IAEhBwU,IACH1hB,EAAM0I,EAAKvI,QAAQM,KAAKihB,IAGzBtV,EAAQhX,EAAEmY,UAAWwP,GACrBkE,EACCnhB,EAAOE,GACNkN,IAAcwU,EACftV,GAEDM,EAAOlU,KAAK4T,IAGb1D,EAAKnP,IAAI,EAAG,YAIbmT,GAAOlU,KAAKukB,EAId,OAAOrQ,GAiBR,QAASsT,GAAY5T,EAAOyV,EAAUC,GAUrC,QAASC,GAAUrY,EAAOsY,GACzB,MAAIF,GACInhB,EAAW+I,EAAOsY,EAAOF,GAExBD,EAAShJ,OACVnY,EAAQgJ,EAAOsY,GAGf5hB,EAAYsJ,EAAOsY,GAjB5B,GACIC,GACAC,EACAC,EACAC,EACAC,EACAC,EANAC,IA8EJ,OAzDAV,GAAWA,MAGNA,EAAS/hB,QACb+hB,EAAS/hB,MAAQsM,EAAMtM,MAAMK,SAETjE,SAAjB2lB,EAAS7hB,MACZ6hB,EAAS7hB,IAAMoM,EAAMpM,IAAMoM,EAAMpM,IAAIG,QAAU,MAEzB,MAAnB0hB,EAAShJ,SACZgJ,EAAShJ,OAASzM,EAAMyM,QAEzBsI,EAAoBU,GAIpBI,GACCniB,MAAOsM,EAAMoW,OAAOriB,QACpBH,IAAKoM,EAAMqW,KAAOrW,EAAMqW,KAAKtiB,QAAUsP,EAAEmJ,mBAAmBxM,EAAMsW,QAAStW,EAAMoW,QACjF3J,OAAQgJ,EAAShJ,QAElBsI,EAAoBc,GAGpBC,EAA0B,OAAf9V,EAAMqW,MAAkC,OAAjBZ,EAAS7hB,IAG3CmiB,EAAaJ,EAAUF,EAAS/hB,MAAOmiB,EAASniB,OAG5C+hB,EAAS7hB,KACZoiB,EAAWL,EAAUF,EAAS7hB,IAAKiiB,EAASjiB,KAC5CqiB,EAAgBD,EAASO,SAASR,IAGlCE,EAAgB,KAIjBjtB,EAAEU,KAAK+rB,EAAU,SAAS9rB,EAAMC,GAC3BkqB,EAAoBnqB,IACXmG,SAARlG,IACHusB,EAAUxsB,GAAQC,KAMrBssB,EAAWM,EACVrC,EAAanU,EAAMQ,KACnBsV,EACAL,EAAShJ,OACTsJ,EACAE,EACAE,IAIAM,UAAWV,EACXE,cAAeA,EACfS,KAAMR,GAgBR,QAASM,GAAalW,EAAQwV,EAAUrJ,EAAQgK,EAAWR,EAAeE,GACzE,GAAIQ,GAAkBtT,EAAE6I,qBACpB0K,IAuEJ,OApEIH,KAAcA,EAAUI,YAAaJ,EAAY,MACjDR,IAAkBA,EAAcY,YAAaZ,EAAgB,MAEjEjtB,EAAEU,KAAK4W,EAAQ,SAASvU,EAAGiU,GAC1B,GAAI6V,GACAJ,CAIJI,IACCniB,MAAOsM,EAAMtM,MAAMK,QACnBH,IAAKoM,EAAMpM,IAAMoM,EAAMpM,IAAIG,QAAU,KACrC0Y,OAAQzM,EAAMyM,QAEfzjB,EAAEU,KAAKysB,EAAW,SAASxsB,GAC1BksB,EAASlsB,GAAQqW,EAAMrW,KAKxB8rB,GACC/hB,MAAOsM,EAAMoW,OACbxiB,IAAKoM,EAAMqW,KACX5J,OAAQA,GAETsI,EAAoBU,GAGhBK,EACHL,EAAS7hB,IAAM,KAEPqiB,IAAkBR,EAAS7hB,MACnC6hB,EAAS7hB,IAAMyP,EAAEmJ,mBAAmBiJ,EAAShJ,OAAQgJ,EAAS/hB,QAG3D+iB,IACHhB,EAAS/hB,MAAMvG,IAAIspB,GACfhB,EAAS7hB,KACZ6hB,EAAS7hB,IAAIzG,IAAIspB,IAIfR,GACHR,EAAS7hB,IAAIzG,IAAI8oB,GAMjBU,IACClB,EAAShJ,SACTgK,GAAaR,KAEdR,EAAS/hB,MAAMwI,YACXuZ,EAAS7hB,KACZ6hB,EAAS7hB,IAAIsI,aAIflT,EAAEmY,OAAOnB,EAAOmW,EAAWV,GAC3BnB,GAAiBtU,GAEjB4W,EAAcxqB,KAAK,WAClBpD,EAAEmY,OAAOnB,EAAO6V,GAChBvB,GAAiBtU,OAIZ,WACN,IAAK,GAAIjU,GAAI,EAAGA,EAAI6qB,EAAcprB,OAAQO,IACzC6qB,EAAc7qB,MAejB,QAAS+qB,GAAmBC,EAAM/W,GACjC,GAAII,GAASJ,EAAMI,WACf4W,EAAa5e,GAChB4H,EAAMgX,WACN5W,EAAO4W,WACP3T,EAAEU,QAAQkT,iBAEPC,EAAU9e,GACb4H,EAAMkX,QACN9W,EAAO8W,QACP7T,EAAEU,QAAQoT,aAEX,OAAOC,GAAcL,EAAMC,EAAYE,EAASlX,GAKjD,QAASqX,GAAsBC,EAAWC,EAAe1W,GACxD,GAAI6P,GACA1Q,CAQJ,OALIa,KACH6P,EAAa1nB,EAAEmY,UAAWN,EAAY0W,GACtCvX,EAAQ8Q,EAAYD,EAAoBH,IAAa,IAGlD1Q,EACI8W,EAAmBQ,EAAWtX,GAI9BwX,EAAuBF,GAMhC,QAASE,GAAuBT,GAC/B,MAAOK,GAAcL,EAAM1T,EAAEU,QAAQ0T,iBAAkBpU,EAAEU,QAAQ2T,eAOlE,QAASN,GAAcL,EAAMC,EAAYE,EAASlX,GACjD,GAAI2X,GACAC,EACAC,EACA9rB,EAAG+rB,EACHC,CAGJ,IAAkB,MAAdf,EAAoB,CAOvB,IAHAW,EAAmBK,EAAmBhB,GAEtCY,GAAiB,EACZ7rB,EAAI,EAAGA,EAAI4rB,EAAiBnsB,OAAQO,IACxC,GAAIsX,EAAE4U,iBAAiBN,EAAiB5rB,GAAIgrB,GAAO,CAClDa,GAAiB,CACjB,OAIF,IAAKA,EACJ,OAAO,EAMT,IAFAC,EAAaxU,EAAE6U,cAAcnB,EAAM/W,GAE9BjU,EAAI,EAAGA,EAAI8rB,EAAWrsB,OAAQO,IAIlC,GAHA+rB,EAAYD,EAAW9rB,GAGnBosB,EAAqBL,EAAWf,GAAO,CAG1C,GAAIG,KAAY,EACf,OAAO,CAGH,IAAuB,kBAAZA,KAA2BA,EAAQY,EAAW9X,GAC7D,OAAO,CAKR,IAAIA,EAAO,CAMV,GALA+X,EAAc3f,GACb0f,EAAUZ,SACTY,EAAU1X,YAAc8W,SAGtBa,KAAgB,EACnB,OAAO,CAGR,IAA2B,kBAAhBA,KAA+BA,EAAY/X,EAAO8X,GAC5D,OAAO,GAMX,OAAO,EAQR,QAASE,GAAmBI,GAE3B,MAAwB,kBAApBA,EACI/U,EAAEgV,+BAGqB,gBAApBD,GACHtH,EAAYD,EAAoBuH,IAGjCjE,EAAaiE,GAMrB,QAASD,GAAqBnY,EAAOsY,GACpC,GAAIC,GAAavY,EAAMtM,MAAMK,QAAQmI,YACjCsc,EAAWnV,EAAEkJ,YAAYvM,GAAO9D,WAEpC,OAAOoc,GAAM5kB,MAAQ8kB,GAAYF,EAAM1kB,IAAM2kB,EAlpC9C,GAAIlV,GAAI3V,IAIR2V,GAAEoE,cAAgBA,EAClBpE,EAAEqE,YAAcA,EAChBrE,EAAE+D,kBAAoBA,EACtB/D,EAAE4P,gBAAkBA,EACpB5P,EAAE6P,mBAAqBA,EACvB7P,EAAEgE,4BAA8BA,EAChChE,EAAEuP,uBAAyBA,EAC3BvP,EAAE4O,eAAiBA,EACnB5O,EAAEoP,kBAAoBA,EACtBpP,EAAEwP,mBAAqBA,EACvBxP,EAAEsQ,YAAcA,EAChBtQ,EAAE0Q,YAAcA,EAChB1Q,EAAE4Q,aAAeA,EACjB5Q,EAAE8Q,aAAeA,EACjB9Q,EAAEuQ,YAAcA,EAChBvQ,EAAE0R,oBAAsBA,EACxB1R,EAAE2R,oBAAsBA,CAIxB,IAMIpF,GAAYC,EANZlI,EAAetE,EAAEsE,aAIjBqM,GAAiB1T,WACjBwP,GAAYkE,GAEZ5D,EAAmB,EACnBH,IAGJjnB,GAAEU,MACA2Z,EAAEU,QAAQzD,QAAW+C,EAAEU,QAAQzD,YAAemY,OAAOpV,EAAEU,QAAQ2U,kBAChE,SAAS3sB,EAAGmmB,GACX,GAAI9R,GAAS+R,EAAiBD,EAC1B9R,IACH0P,EAAQ1jB,KAAKgU,KAqiBhBiD,EAAEoH,wBAA0B,WAC3B,GAAI1e,GACAuU,EACAxJ,CAEJ,KAAK/K,EAAI,EAAGA,EAAI+jB,EAAQtkB,OAAQO,IAE/B,GADAuU,EAASwP,EAAQ/jB,GAAGuU,OAChBtX,EAAEgJ,QAAQsO,GAEb,IAAKxJ,EAAI,EAAGA,EAAIwJ,EAAO9U,OAAQsL,IAC9Bud,EAAiB/T,EAAOxJ,KA2G5BuM,EAAEwN,oBAAsBA,EA4HxBxN,EAAEyN,YAAcA,EAqMhBzN,EAAEyT,mBAAqBA,EACvBzT,EAAEgU,sBAAwBA,EAC1BhU,EAAEmU,uBAAyBA,EAiJ3BnU,EAAEsV,cAAgB,WACjB,MAAO1I,IA4CT,QAASqE,IAAiBtU,GACzBA,EAAMsW,QAAUtW,EAAMyM,OACtBzM,EAAMoW,OAASpW,EAAMtM,MAAMK,QAC3BiM,EAAMqW,KAAOrW,EAAMpM,IAAMoM,EAAMpM,IAAIG,QAAU,KAhyX9C,GAAIkI,IAAKjT,EAAE4vB,cACVC,QAAS,sBACTC,mBAAoB,GAEjBC,GAAU9c,GAAGxS,QAGjBT,GAAEgwB,GAAGJ,aAAe,SAAS7U,GAC5B,GAAI/L,GAAO0S,MAAMrU,UAAU4C,MAAM1C,KAAK8B,UAAW,GAC7ChJ,EAAM3B,IA2BV,OAzBAA,MAAKhE,KAAK,SAASqC,EAAGgb,GACrB,GAEIkS,GAFAtW,EAAU3Z,EAAE+d,GACZwG,EAAW5K,EAAQzB,KAAK,eAIL,iBAAZ6C,GACNwJ,GAAYvkB,EAAEiP,WAAWsV,EAASxJ,MACrCkV,EAAY1L,EAASxJ,GAAS5L,MAAMoV,EAAUvV,GACzCjM,IACJsD,EAAM4pB,GAES,YAAZlV,GACHpB,EAAQuW,WAAW,iBAKZ3L,IACTA,EAAW,GAAI4L,IAASxW,EAASoB,GACjCpB,EAAQzB,KAAK,eAAgBqM,GAC7BA,EAASxK,YAIJ1T,EAIR,IAAIjG,KACH,SACA,aACA,cACA,mBA8DD6S,IAAG/I,gBAAkBA,EACrB+I,GAAGpE,SAAWA,GACdoE,GAAG3C,SAAWA,GACd2C,GAAGpH,MAAQA,GACXoH,GAAG3D,WAAaA,GAChB2D,GAAGtD,SAAWA,GACdsD,GAAG9C,MAAQA,GACX8C,GAAGlD,sBAAwBA,GAwJ3BkD,GAAGnO,aAAeA,EAClBmO,GAAG9N,cAAgBA,EACnB8N,GAAGzN,eAAiBA,EACpByN,GAAG7N,mBAAqBA,CAgGxB,IAAIS,IAAuB,IAsC3BoN,IAAGzL,eAAiBA,EA2EpByL,GAAGlL,eAAiBA,EAgDpBkL,GAAGtK,gBAAkBA,EACrBsK,GAAG3J,oBAAsBA,EACzB2J,GAAGtJ,mBAAqBA,EACxBsJ,GAAGpJ,gBAAkBA,EA8HrBoJ,GAAGvH,oBAAsBA,EACzBuH,GAAGjH,sBAAwBA,EAC3BiH,GAAG1G,yBAA2BA,EAC9B0G,GAAGrG,iBAAmBA,EACtBqG,GAAG9G,gBAAkBA,CAErB,IAAIikB,KAAW,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,OACrDzkB,IAAkB,OAAQ,QAAS,OAAQ,MAAO,OAAQ,SAAU,SAAU,cAyIlFsH,IAAGod,IAAM,WACR,GAAIC,GAAU3oB,OAAO2oB,OAErB,IAAIA,GAAWA,EAAQD,IACtB,MAAOC,GAAQD,IAAIlhB,MAAMmhB,EAASjhB,YAIpC4D,GAAGsd,KAAO,WACT,GAAID,GAAU3oB,OAAO2oB,OAErB,OAAIA,IAAWA,EAAQC,KACfD,EAAQC,KAAKphB,MAAMmhB,EAASjhB,WAG5B4D,GAAGod,IAAIlhB,MAAM8D,GAAI5D,WAQ1B,IA4OImhB,IACAC,GACAC,GA9OA/hB,MAAsBgiB,eAuOtB1e,GAAwB,kBACxBC,GACH,iGACG0e,GAAiB7wB,EAAOiwB,GACxBvc,GAAiBzT,EAAEmY,UAAWyY,GAalC3d,IAAGlT,OAAS,WACX,MAAOwR,IAAWlC,YAInB4D,GAAGlT,OAAOqS,IAAM,WACf,GAAIP,GAAMN,GAAWlC,WAAW,EAQhC,OAJIwC,GAAImR,WACPnR,EAAIO,MAGEP,GAKRoB,GAAGlT,OAAO0R,UAAY,WACrB,MAAOF,IAAWlC,WAAW,GAAM,IAgFpCuhB,GAAe7lB,MAAQ,WACtB,GAAI8G,GAAM4B,GAAe1I,MAAMoE,MAAMzK,KAAM2K,UAQ3C,OALA2C,IAAetN,KAAMmN,GACjBnN,KAAK+N,gBACRZ,EAAIY,eAAgB,GAGdZ,GAUR+e,GAAeC,KAAOD,GAAeE,MAAQ,SAASxwB,GACrD,GAAIywB,IAAYrsB,KAAKmV,SAAWnV,KAAKoV,OACnC8I,sBAEF,OAAa,OAATtiB,GAAqC,kBAAbywB,GACpBA,EAASrsB,MAEK,QAAbqsB,EACDtd,GAAeud,QAAQ7hB,MAAMzK,KAAM2K,WAGpCoE,GAAeod,KAAK1hB,MAAMzK,KAAM2K,YAcxCuhB,GAAevlB,KAAO,SAASA,GAI9B,IAAK3G,KAAK+N,cACT,MAAOgB,IAAepI,KAAK8D,MAAMzK,KAAM2K,UAGxC,IAAY,MAARhE,EACH,MAAOtL,GAAOkL,UACb8B,MAAOrI,KAAKqI,QACZC,QAAStI,KAAKsI,UACdC,QAASvI,KAAKuI,UACdC,aAAcxI,KAAKwI,gBAKpBxI,MAAK2N,YAAa,EAEbtS,EAAO+L,WAAWT,IAAUtL,EAAOgS,SAAS1G,KAChDA,EAAOtL,EAAOkL,SAASI,GAKxB,IAAI4lB,GAAW,CAOf,OANIlxB,GAAO+L,WAAWT,KACrB4lB,EAAuC,GAA5B3uB,KAAKC,MAAM8I,EAAKiB,WAKrB5H,KAAKqI,MAAMkkB,EAAW5lB,EAAK0B,SAChCC,QAAQ3B,EAAK2B,WACbC,QAAQ5B,EAAK4B,WACbC,aAAa7B,EAAK6B,iBAOtB0jB,GAAezlB,UAAY,WAC1B,GAAIrB,EAiBJ,OAfKpF,MAAK2N,aAGTvI,EAAIpF,KAAK2e,UAGT3e,KAAK0N,MACLqe,GAAa/rB,KAAMoF,EAAEmG,MAAM,EAAG,IAI9BvL,KAAK2N,YAAa,EAClB3N,KAAK4N,YAAa,GAGZ5N,MAIRksB,GAAe5N,QAAU,WACxB,OAAQte,KAAK2N,YAWdue,GAAe1d,UAAY,WAC1B,GAAIpJ,GAAGonB,CAmBP,OAjBKxsB,MAAK4N,aAGTxI,EAAIpF,KAAK2e,UACT6N,EAAexsB,KAAK2N,WAEpB3N,KAAK0N,MACLqe,GAAa/rB,KAAMoF,GAGnBpF,KAAK2N,WAAa6e,IAAgB,EAIlCxsB,KAAK4N,YAAa,GAGZ5N,MAIRksB,GAAeO,QAAU,WACxB,OAAQzsB,KAAK4N,YAKdse,GAAe3N,MAAQ,WACtB,GAAInZ,GAAIpF,KAAK2e,UACT+N,EAAe1sB,KAAK4N,UAgBxB,OAdAmB,IAAewP,MAAM9T,MAAMzK,KAAM2K,WAIjC3K,KAAK2N,YAAa,EAClB3N,KAAK4N,YAAa,EAEd8e,GAIHV,GAAehsB,KAAMoF,GAGfpF,MAKRksB,GAAexe,IAAM,WAQpB,MAPAqB,IAAerB,IAAIjD,MAAMzK,KAAM2K,WAI/B3K,KAAK2N,YAAa,EAClB3N,KAAK4N,YAAa,EAEX5N,MAMR1E,EAAEU,MACD,OACA,aACE,SAASqC,EAAGpC,GACV8S,GAAe9S,KAGlBiwB,GAAejwB,GAAQ,SAAS0wB,GAS/B,MAPW,OAAPA,IAGH3sB,KAAK2N,YAAa,EAClB3N,KAAK4N,YAAa,GAGZmB,GAAe9S,GAAMwO,MAAMzK,KAAM2K,eAS3CuhB,GAAeld,OAAS,WACvB,MAAIhP,MAAK+N,eAAiBpD,UAAU,GAC5BsE,GAAWjP,KAAM2K,UAAU,IAE/B3K,KAAK2N,WACDkB,GAAgB7O,KAAM,cAE1BA,KAAK4N,WACDiB,GAAgB7O,KAAM,yBAEvB+O,GAAeC,OAAOvE,MAAMzK,KAAM2K,YAG1CuhB,GAAeU,YAAc,WAC5B,MAAI5sB,MAAK2N,WACDkB,GAAgB7O,KAAM,cAE1BA,KAAK4N,WACDiB,GAAgB7O,KAAM,yBAEvB+O,GAAe6d,YAAYniB,MAAMzK,KAAM2K,YAS/CuhB,GAAepU,SAAW,SAAS9R,EAAOE,GACzC,GAAId,GAAI4I,IAAoBhO,KAAMgG,EAAOE,GACzC,OAAOd,GAAE,IAAMA,EAAE,IAAMA,EAAE,GAAKA,EAAE;EAKjC8mB,GAAejb,OAAS,SAASrV,EAAOixB,GACvC,GAAIznB,EAGJ,OAAKpF,MAAK+N,cAIN8e,GACHznB,EAAI4I,IAAoBhO,KAAMpE,IAAS,GAChCmT,GAAekC,OAAOpI,KAAKzD,EAAE,GAAIA,EAAE,GAAIynB,KAG9CjxB,EAAQ2S,GAAGlT,OAAO0R,UAAUnR,GACrBmT,GAAekC,OAAOpI,KAAK7I,KAAMpE,IACvCwM,QAAQpI,KAAK2N,cAAgBvF,QAAQxM,EAAM+R,aAC3CvF,QAAQpI,KAAK4N,cAAgBxF,QAAQxM,EAAMgS,aAXrCmB,GAAekC,OAAOxG,MAAMzK,KAAM2K,YAgB3CrP,EAAEU,MACD,WACA,WACE,SAASqC,EAAGqN,GACdwgB,GAAexgB,GAAc,SAAS9P,EAAOixB,GAC5C,GAAIznB,EAGJ,OAAKpF,MAAK+N,eAIV3I,EAAI4I,IAAoBhO,KAAMpE,IACvBmT,GAAerD,GAAY7C,KAAKzD,EAAE,GAAIA,EAAE,GAAIynB,IAJ3C9d,GAAerD,GAAYjB,MAAMzK,KAAM2K,cAiFjDmhB,GAAyB,MAAQzwB,MAAY,gBAAkBA,GAI/D0wB,GAAeD,GAAyB,SAAS3e,EAAK/H,GAErD+H,EAAI2f,GAAGC,QAAQjkB,KAAKkkB,IAAIviB,MAAM3B,KAAM1D,IACpC/J,EAAO4xB,aAAa9f,GAAK,IACtBsB,GAIJud,GAAiBF,GAAyB,SAAS3e,EAAK/H,GAEvD+H,EAAI2f,GAAGC,SAAS,GAAIjkB,MACnB1D,EAAE,IAAM,EACRA,EAAE,IAAM,EACRA,EAAE,IAAM,EACRA,EAAE,IAAM,EACRA,EAAE,IAAM,EACRA,EAAE,IAAM,EACRA,EAAE,IAAM,IAET/J,EAAO4xB,aAAa9f,GAAK,IACtBsB,EAkCJ,IAAIe,KACHmG,EAAG,SAAS/G,GACX,MAAOC,IAAgBD,EAAM,KAAKrK,OAAO,IAE1C2oB,EAAG,SAASte,GACX,MAAOC,IAAgBD,EAAM,KAAKrK,OAAO,IA4D3CgK,IAAGoB,YAAcA,EAuDjB,IAAIqB,KACHmc,EAAG,OACHC,EAAG,QACHC,EAAG,MACHC,EAAG,MAEHC,EAAG,SACHnoB,EAAG,SACH8nB,EAAG,SACHvX,EAAG,SACH6X,EAAG,SACHC,EAAG,SACHC,EAAG,SACH7iB,EAAG,UAkCAqG,KAqCJ3C,IAAG8C,MAAQA,GAQXA,GAAMoC,OAAS,WACd,GACIpV,GACAmT,EAFAnD,EAAM1D,UAAU7M,MAIpB,KAAKO,EAAI,EAAGA,EAAIgQ,EAAKhQ,IACpBmT,EAAU7G,UAAUtM,GAChBA,EAAIgQ,EAAM,GACbsD,GAAa3R,KAAMwR,EAIrB,OAAOF,IAAYtR,KAAMwR,QAM1BH,GAAMsc,MAAQ,SAASnc,GACtBG,GAAa3R,KAAMwR,GAoCpB,IAAIoc,IAAerf,GAAGqf,cAMrB/qB,GAAI,SAASgrB,EAAO7qB,GAKnB,GAAI8qB,GAAY,SAAS9rB,EAAI+rB,GAC5B,MAAO/qB,GAAQyH,MACdsjB,EAAM/hB,SAAWhM,KACjB+tB,EAAMzjB,UAeR,OAPKtH,GAAQgrB,OACZhrB,EAAQgrB,KAAO1yB,EAAE0yB,QAElBF,EAAUE,KAAOhrB,EAAQgrB,KAEzB1yB,EAAE0E,MAAM6C,GAAGgrB,EAAOC,GAEX9tB,MAIRiuB,IAAK,SAASJ,EAAO7qB,GAGpB,MAFA1H,GAAE0E,MAAMiuB,IAAIJ,EAAO7qB,GAEZhD,MAIRoZ,QAAS,SAASyU,GACjB,GAAIvjB,GAAO0S,MAAMrU,UAAU4C,MAAM1C,KAAK8B,UAAW,EAKjD,OAFArP,GAAE0E,MAAMkuB,eAAeL,GAASvjB,KAAMA,IAE/BtK,MAIRid,YAAa,SAAS4Q,EAAO7hB,EAAS1B,GAMrC,MAFAhP,GAAE0E,MAAMkuB,eAAeL,GAAS7hB,QAASA,EAAS1B,KAAMA,IAEjDtK,OAWLmuB,GAAgB5f,GAAG4f,cAAgB,WACtC,GAAIH,GAAO,EACPG,GAEHC,WAAY,KAaZC,SAAU,SAASC,EAAOC,EAAK/K,GAC9B,GAAmB,gBAAR+K,GACV,IAAK,GAAIC,KAAaD,GACjBA,EAAItC,eAAeuC,IACtBxuB,KAAKquB,SAASC,EAAOE,EAAWD,EAAIC,QAIf,gBAARD,IACfD,EAAMzrB,GACL0rB,EAAM,IAAMvuB,KAAKyuB,uBACjBnzB,EAAEmQ,MAAM+X,EAAUxjB,QAWrB0uB,gBAAiB,SAASJ,EAAOE,GAChCF,EAAML,KAAKO,GAAa,IAAM,IAAMxuB,KAAKyuB,yBAM1CA,qBAAsB,WAIrB,MAHuB,OAAnBzuB,KAAKouB,aACRpuB,KAAKouB,WAAaJ,KAEZ,YAAchuB,KAAKouB,YAI5B,OAAOD,MAMJQ,IAEHC,iBAAiB,EACjBC,mBAAoB,KAGpBC,kBAAmB,SAASC,GAC3B/uB,KAAK6uB,mBAAqBjjB,GAASH,GAAMzL,KAAM,iBAAkB+uB,GAAS,MAK3EC,gBAAiB,WAChBhvB,KAAK4uB,iBAAkB,EACvB5uB,KAAK6uB,sBAKNI,cAAe,WACdjvB,KAAK4uB,iBAAkB,IAqBrBM,GAAU7d,GAAMoC,OAAO0a,IAE1BgB,UAAU,EACV9Y,QAAS,KACT/X,GAAI,KACJ8wB,OAAQ,GAGR1d,YAAa,SAAS2E,GACrBrW,KAAKqW,QAAUA,OAKhBgZ,KAAM,WACDrvB,KAAKmvB,WACHnvB,KAAK1B,IACT0B,KAAKqV,SAENrV,KAAK1B,GAAG+wB,OACRrvB,KAAKN,WACLM,KAAKmvB,UAAW,EAChBnvB,KAAKoZ,QAAQ,UAMfkW,KAAM,WACAtvB,KAAKmvB,WACTnvB,KAAK1B,GAAGgxB,OACRtvB,KAAKmvB,UAAW,EAChBnvB,KAAKoZ,QAAQ,UAMf/D,OAAQ,WACP,GAAIka,GAAQvvB,KACRqW,EAAUrW,KAAKqW,OAEnBrW,MAAK1B,GAAKhD,EAAE,6BACV8B,SAASiZ,EAAQuO,WAAa,IAC9BhoB,KAEA2D,IAAK,EACL5D,KAAM,IAENqjB,OAAO3J,EAAQf,SACf7T,SAAS4U,EAAQmZ,UAGnBxvB,KAAK1B,GAAGuE,GAAG,QAAS,YAAa,WAChC0sB,EAAMD,SAGHjZ,EAAQoZ,UACXzvB,KAAKquB,SAAS/yB,EAAE6E,UAAW,YAAaH,KAAK0vB,oBAM/CA,kBAAmB,SAAS1tB,GAEvBhC,KAAK1B,KAAOhD,EAAE0G,EAAGmX,QAAQwW,QAAQ3vB,KAAK1B,IAAIR,QAC7CkC,KAAKsvB,QAMPvY,cAAe,WACd/W,KAAKsvB,OAEDtvB,KAAK1B,KACR0B,KAAK1B,GAAGsD,SACR5B,KAAK1B,GAAK,MAGX0B,KAAK0uB,gBAAgBpzB,EAAE6E,UAAW,cAKnCT,SAAU,WACT,GAMIkwB,GACAC,EACAC,EACAvvB,EACA5D,EAVA0Z,EAAUrW,KAAKqW,QACfhW,EAASL,KAAK1B,GAAGyxB,eAAezvB,SAChClB,EAAQY,KAAK1B,GAAGa,aAChBR,EAASqB,KAAK1B,GAAGG,cACjBuxB,EAAW10B,EAAE2H,QACbgtB,EAAatwB,EAAgBK,KAAK1B,GAQtCiC,GAAM8V,EAAQ9V,KAAO,EAEpB5D,EADoByF,SAAjBiU,EAAQ1Z,KACJ0Z,EAAQ1Z,KAEWyF,SAAlBiU,EAAQtZ,MACTsZ,EAAQtZ,MAAQqC,EAGhB,EAGJ6wB,EAAWhZ,GAAGhU,SAAWgtB,EAAWhZ,GAAG9W,WAC1C8vB,EAAaD,EACbJ,EAAc,EACdC,EAAe,IAGfC,EAAiBG,EAAW3vB,SAC5BsvB,EAAcE,EAAevvB,IAC7BsvB,EAAeC,EAAenzB,MAI/BizB,GAAeI,EAASE,YACxBL,GAAgBG,EAASG,aAGrB9Z,EAAQ+Z,qBAAsB,IACjC7vB,EAAM3C,KAAK6F,IAAIlD,EAAKqvB,EAAcK,EAAWxxB,cAAgBE,EAASqB,KAAKovB,QAC3E7uB,EAAM3C,KAAK4F,IAAIjD,EAAKqvB,EAAc5vB,KAAKovB,QACvCzyB,EAAOiB,KAAK6F,IAAI9G,EAAMkzB,EAAeI,EAAW9wB,aAAeC,EAAQY,KAAKovB,QAC5EzyB,EAAOiB,KAAK4F,IAAI7G,EAAMkzB,EAAe7vB,KAAKovB,SAG3CpvB,KAAK1B,GAAG1B,KACP2D,IAAKA,EAAMF,EAAOE,IAClB5D,KAAMA,EAAO0D,EAAO1D,QAQtByc,QAAS,SAASnd,GACb+D,KAAKqW,QAAQpa,IAChB+D,KAAKqW,QAAQpa,GAAMwO,MAAMzK,KAAMgd,MAAMrU,UAAU4C,MAAM1C,KAAK8B,UAAW,OAiBpE0lB,GAAa9hB,GAAG8hB,WAAahf,GAAMoC,QAEtCjW,IAAK,KACL8yB,qBAAsB,KACtBjwB,OAAQ,KACRkwB,aAAc,KACdC,cAAc,EACdC,YAAY,EAGZC,MAAO,KACPC,OAAQ,KACRC,KAAM,KACNC,QAAS,KAGTnf,YAAa,SAAS2E,GACrBrW,KAAKxC,IAAMlC,EAAE+a,EAAQ7Y,KACrBwC,KAAKwwB,aAAena,EAAQma,aAC5BxwB,KAAKywB,WAAapa,EAAQoa,WAC1BzwB,KAAKswB,qBAAuBja,EAAQ0Z,aAAez0B,EAAE+a,EAAQ0Z,cAAgB,MAM9Ee,MAAO,WACN,GAAIC,GAAiB/wB,KAAKswB,sBAAwBtwB,KAAKxC,IAAIyC,GAAG,GAAG8vB,cAEjE/vB,MAAKK,OAAS0wB,EAAezwB,SAC7BN,KAAKuwB,aAAevwB,KAAKgxB,oBAErBhxB,KAAKwwB,cACRxwB,KAAKixB,qBAEFjxB,KAAKywB,YACRzwB,KAAKkxB,oBAMPC,MAAO,WACNnxB,KAAKK,OAAS,KACdL,KAAKuwB,aAAe,KACpBvwB,KAAK0wB,MAAQ,KACb1wB,KAAK2wB,OAAS,KACd3wB,KAAK4wB,KAAO,KACZ5wB,KAAK6wB,QAAU,MAKhBO,YAAa,WACPpxB,KAAKK,QACTL,KAAK8wB,SAMPG,mBAAoB,WACnB,GAAIP,MACAC,IAEJ3wB,MAAKxC,IAAIxB,KAAK,SAASqC,EAAGgzB,GACzB,GAAI/yB,GAAKhD,EAAE+1B,GACP10B,EAAO2B,EAAGgC,SAAS3D,KACnByC,EAAQd,EAAGa,YAEfuxB,GAAMhyB,KAAK/B,GACXg0B,EAAOjyB,KAAK/B,EAAOyC,KAGpBY,KAAK0wB,MAAQA,EACb1wB,KAAK2wB,OAASA,GAKfO,iBAAkB,WACjB,GAAIN,MACAC,IAEJ7wB,MAAKxC,IAAIxB,KAAK,SAASqC,EAAGgzB,GACzB,GAAI/yB,GAAKhD,EAAE+1B,GACP9wB,EAAMjC,EAAGgC,SAASC,IAClB5B,EAASL,EAAGG,aAEhBmyB,GAAKlyB,KAAK6B,GACVswB,EAAQnyB,KAAK6B,EAAM5B,KAGpBqB,KAAK4wB,KAAOA,EACZ5wB,KAAK6wB,QAAUA,GAMhBS,mBAAoB,SAASC,GAC5BvxB,KAAKoxB,aAEL,IAGI/yB,GAHAqyB,EAAQ1wB,KAAK0wB,MACbC,EAAS3wB,KAAK2wB,OACdtiB,EAAMqiB,EAAM5yB,MAGhB,KAAKO,EAAI,EAAGA,EAAIgQ,EAAKhQ,IACpB,GAAIkzB,GAAcb,EAAMryB,IAAMkzB,EAAaZ,EAAOtyB,GACjD,MAAOA,IAQVmzB,iBAAkB,SAASC,GAC1BzxB,KAAKoxB,aAEL,IAGI/yB,GAHAuyB,EAAO5wB,KAAK4wB,KACZC,EAAU7wB,KAAK6wB,QACfxiB,EAAMuiB,EAAK9yB,MAGf,KAAKO,EAAI,EAAGA,EAAIgQ,EAAKhQ,IACpB,GAAIozB,GAAab,EAAKvyB,IAAMozB,EAAYZ,EAAQxyB,GAC/C,MAAOA,IAOVqzB,cAAe,SAASC,GAEvB,MADA3xB,MAAKoxB,cACEpxB,KAAK0wB,MAAMiB,IAKnBC,gBAAiB,SAASD,GAEzB,MADA3xB,MAAKoxB,cACEpxB,KAAK0wB,MAAMiB,GAAa3xB,KAAKK,OAAO1D,MAM5Ck1B,eAAgB,SAASF,GAExB,MADA3xB,MAAKoxB,cACEpxB,KAAK2wB,OAAOgB,IAMpBG,iBAAkB,SAASH,GAE1B,MADA3xB,MAAKoxB,cACEpxB,KAAK2wB,OAAOgB,GAAa3xB,KAAKK,OAAO1D,MAK7Co1B,SAAU,SAASJ,GAElB,MADA3xB,MAAKoxB,cACEpxB,KAAK2wB,OAAOgB,GAAa3xB,KAAK0wB,MAAMiB,IAK5CK,aAAc,SAASC,GAEtB,MADAjyB,MAAKoxB,cACEpxB,KAAK4wB,KAAKqB,IAKlBC,eAAgB,SAASD,GAExB,MADAjyB,MAAKoxB,cACEpxB,KAAK4wB,KAAKqB,GAAYjyB,KAAKK,OAAOE,KAK1C4xB,gBAAiB,SAASF,GAEzB,MADAjyB,MAAKoxB,cACEpxB,KAAK6wB,QAAQoB,IAMrBG,kBAAmB,SAASH,GAE3B,MADAjyB,MAAKoxB,cACEpxB,KAAK6wB,QAAQoB,GAAYjyB,KAAKK,OAAOE,KAK7C8xB,UAAW,SAASJ,GAEnB,MADAjyB,MAAKoxB,cACEpxB,KAAK6wB,QAAQoB,GAAYjyB,KAAK4wB,KAAKqB,IAS3CjB,kBAAmB,WAClB,GAAIsB,GAAiB3yB,EAAgBK,KAAKxC,IAAIyC,GAAG,GAEjD,KAAKqyB,EAAerb,GAAG9W,UACtB,MAAOM,GAAc6xB,IAIvBC,gBAAiB,SAAShB,EAAYE,GACrC,MAAOzxB,MAAKwyB,eAAejB,IAAevxB,KAAKyyB,cAAchB,IAG9De,eAAgB,SAASjB,GACxB,OAAQvxB,KAAKuwB,cAAiBgB,GAAcvxB,KAAKuwB,aAAa5zB,MAAQ40B,EAAavxB,KAAKuwB,aAAaxzB,OAGtG01B,cAAe,SAAShB,GACvB,OAAQzxB,KAAKuwB,cAAiBkB,GAAazxB,KAAKuwB,aAAahwB,KAAOkxB,EAAYzxB,KAAKuwB,aAAa/vB,UAWhGkyB,GAAenkB,GAAGmkB,aAAerhB,GAAMoC,OAAO0a,GAAeQ,IAEhEtY,QAAS,KAGTsc,UAAW,KACXC,YAAa,KAGbC,QAAS,KACTC,QAAS,KAITC,SAAU,KAEVC,eAAe,EACfC,qBAAqB,EACrBC,cAAc,EACdC,YAAY,EACZC,SAAS,EAETrE,MAAO,KACPsE,eAAgB,KAChBC,YAAa,KAEbC,uBAAwB,KAGxB7hB,YAAa,SAAS2E,GACrBrW,KAAKqW,QAAUA,MACfrW,KAAKuzB,uBAAyB9nB,GAAMzL,KAAM,qBAC1CA,KAAK8uB,kBAAkB,MAQxB0E,iBAAkB,SAASxxB,EAAIyxB,GAC9B,GAAIL,GAAU1wB,EAAaV,EAE3B,IAAgB,cAAZA,EAAGW,KAAsB,CAC5B,GAAI3C,KAAK4uB,gBACR,MAEI,KAAK7sB,EAAqBC,GAC9B,MAGAA,GAAGc,iBAIA9C,KAAKgzB,gBAGTS,EAAeA,MACfzzB,KAAK+uB,MAAQrkB,GAAa+oB,EAAa1E,MAAO/uB,KAAKqW,QAAQ0Y,MAAO,GAClE/uB,KAAKszB,YAAc5oB,GAAa+oB,EAAaC,SAAU1zB,KAAKqW,QAAQqd,SAAU,GAC9E1zB,KAAK2yB,UAAY3yB,KAAKqW,QAAQsc,UAE9B3yB,KAAKgzB,eAAgB,EACrBhzB,KAAKozB,QAAUA,EACfpzB,KAAKkzB,cAAe,EACpBlzB,KAAKizB,qBAAsB,EAE3BjzB,KAAK6yB,QAAU1wB,EAAOH,GACtBhC,KAAK8yB,QAAUtwB,EAAOR,GACtBhC,KAAK+yB,SAAWpzB,EAAgBrE,EAAE0G,EAAGmX,SAErCnZ,KAAK2zB,eACL3zB,KAAK4zB,iBACL5zB,KAAK6zB,uBAAuB7xB,GAC5BhC,KAAK8zB,WAAW9xB,GAEXhC,KAAKszB,aACTtzB,KAAK+zB,wBAAwB/xB,KAMhC6xB,uBAAwB,SAAS7xB,GAChChC,KAAKoZ,QAAQ,mBAAoBpX,IAIlCgyB,eAAgB,SAAShyB,EAAIiyB,GACxBj0B,KAAKgzB,gBACRhzB,KAAKk0B,QAAQlyB,GAEThC,KAAKqzB,iBACRc,aAAan0B,KAAKqzB,gBAClBrzB,KAAKqzB,eAAiB,MAGvBrzB,KAAKo0B,oBACLp0B,KAAKq0B,iBAELr0B,KAAKgzB,eAAgB,EACrBhzB,KAAKs0B,qBAAqBtyB,EAAIiyB,GAK1Bj0B,KAAKozB,SACRpzB,KAAKgvB,oBAMRsF,qBAAsB,SAAStyB,EAAIiyB,GAClCj0B,KAAKoZ,QAAQ,iBAAkBpX,EAAIiyB,IAAe,IAQnDN,aAAc,WACb,GAAIpE,GAAQvvB,KACRu0B,EAAoB,CAEpBv0B,MAAKozB,SACRpzB,KAAKquB,SAAS/yB,EAAE6E,WACfq0B,UAAWx0B,KAAKy0B,gBAChBC,SAAU10B,KAAKg0B,eACfW,YAAa30B,KAAKg0B,eAMlBY,WAAY,SAAS5yB,GAChBuyB,EACHA,IAGAhF,EAAMyE,eAAehyB,GAAI,OAO1Be,EAAc/C,KAAKuzB,yBACpBvzB,KAAK+yB,UAEL/yB,KAAKquB,SAASruB,KAAK+yB,SAAU,SAAU/yB,KAAK60B,oBAI7C70B,KAAKquB,SAAS/yB,EAAE6E,WACf20B,UAAW90B,KAAK+0B,gBAChBjT,QAAS9hB,KAAKg0B,iBAIhBh0B,KAAKquB,SAAS/yB,EAAE6E,WACf60B,YAAalyB,EACbmyB,YAAanyB,KAKfuxB,eAAgB,WACfr0B,KAAK0uB,gBAAgBpzB,EAAE6E,WAGvBgD,EAAgBnD,KAAKuzB,wBACjBvzB,KAAK+yB,UACR/yB,KAAK0uB,gBAAgB1uB,KAAK+yB,SAAU,WAUtCmC,UAAW,SAASlzB,EAAIyxB,GACvBzzB,KAAKwzB,iBAAiBxxB,EAAIyxB,GAErBzzB,KAAKmzB,aACTnzB,KAAKmzB,YAAa,EAClBnzB,KAAKm1B,gBAAgBnzB,KAKvBmzB,gBAAiB,SAASnzB,GACzBhC,KAAKoZ,QAAQ,YAAapX,GAC1BhC,KAAKo1B,gBAINC,WAAY,SAASrzB,GACpB,GAGIszB,GAHAC,EAAKpzB,EAAOH,GAAMhC,KAAK6yB,QACvB2C,EAAKhzB,EAAOR,GAAMhC,KAAK8yB,QACvBQ,EAActzB,KAAKszB,WAGlBtzB,MAAKizB,sBACTqC,EAAaC,EAAKA,EAAKC,EAAKA,EACxBF,GAAchC,EAAcA,GAC/BtzB,KAAK+zB,wBAAwB/xB,IAI3BhC,KAAKmzB,YACRnzB,KAAKy1B,WAAWF,EAAIC,EAAIxzB,IAM1ByzB,WAAY,SAASF,EAAIC,EAAIxzB,GAC5BhC,KAAKoZ,QAAQ,OAAQmc,EAAIC,EAAIxzB,GAC7BhC,KAAK01B,iBAAiB1zB,IAIvBkyB,QAAS,SAASlyB,GACbhC,KAAKmzB,aACRnzB,KAAKmzB,YAAa,EAClBnzB,KAAK21B,cAAc3zB,KAKrB2zB,cAAe,SAAS3zB,GACvBhC,KAAKoZ,QAAQ,UAAWpX,GACxBhC,KAAK41B,mBAQN9B,WAAY,SAAS+B,GACpB,GAAItG,GAAQvvB,IAERA,MAAK+uB,MACR/uB,KAAKqzB,eAAiBhnB,WAAW,WAChCkjB,EAAMuG,eAAeD,IACnB71B,KAAK+uB,OAGR/uB,KAAK81B,eAAeD,IAKtBC,eAAgB,SAASD,GACxB71B,KAAKkzB,cAAe,EAEhBlzB,KAAKizB,qBACRjzB,KAAKk1B,UAAUW,IASjB9B,wBAAyB,SAAS/xB,GACjChC,KAAKizB,qBAAsB,EAEvBjzB,KAAKkzB,cACRlzB,KAAKk1B,UAAUlzB,IASjByyB,gBAAiB,SAASzyB,GAErBhC,KAAKmzB,YACRnxB,EAAGc,iBAGJ9C,KAAKq1B,WAAWrzB,IAIjB+yB,gBAAiB,SAAS/yB,GACzBhC,KAAKq1B,WAAWrzB,IAQjB6yB,kBAAmB,SAAS7yB,GAGtBhC,KAAKmzB,YACTnzB,KAAKg0B,eAAehyB,GAAI,IAS1BozB,aAAc,WACb,GAAIzC,GAAY3yB,KAAK2yB,WAGhB3yB,KAAK4yB,YAAcD,EAAYA,EAAUoD,KAAK,QAAU,OAC5DpD,EAAUqD,WAAW,SAKvBJ,gBAAiB,WAChB,GAAIjD,GAAY3yB,KAAK2yB,UACjBC,EAAc5yB,KAAK4yB,WAGvBvmB,YAAW,WACNumB,GACHD,EAAUoD,KAAK,OAAQnD,IAEtB,IAUJxZ,QAAS,SAASnd,GACb+D,KAAKqW,QAAQpa,IAChB+D,KAAKqW,QAAQpa,GAAMwO,MAAMzK,KAAMgd,MAAMrU,UAAU4C,MAAM1C,KAAK8B,UAAW,IAGlE3K,KAAK,IAAM/D,IACd+D,KAAK,IAAM/D,GAAMwO,MAAMzK,KAAMgd,MAAMrU,UAAU4C,MAAM1C,KAAK8B,UAAW,MAWtE+nB,IAAa/E,OAEZsI,cAAc,EAEdC,aAAc,KACdC,aAAc,KACdC,cAAe,KACfC,iBAAkB,KAGlBC,kBAAmB,GACnBC,YAAa,IACbC,iBAAkB,GAGlB5C,eAAgB,WACf,GAAIb,GAAW/yB,KAAK+yB,QAEpB/yB,MAAKi2B,aACJj2B,KAAKqW,QAAQogB,QACb1D,IACCA,EAAS9b,GAAGhU,UACZ8vB,EAAS9b,GAAG9W,UAEVH,KAAKi2B,cAERj2B,KAAKquB,SAAS0E,EAAU,SAAUnnB,GAAS5L,KAAK02B,sBAAuB,OAKzEtC,kBAAmB,WAClBp0B,KAAK22B,gBAGD32B,KAAKi2B,cACRj2B,KAAK0uB,gBAAgB1uB,KAAK+yB,SAAU,WAMtC6D,oBAAqB,WAChB52B,KAAKi2B,eACRj2B,KAAKk2B,aAAe91B,EAAaJ,KAAK+yB,YAOxC2C,iBAAkB,SAAS1zB,GAC1B,GAEI60B,GAAcC,EACdC,EAAeC,EAHfC,EAAcj3B,KAAKs2B,kBACnBY,EAASl3B,KAAKk2B,aAGdiB,EAAS,EACTC,EAAU,CAEVF,KAGHL,GAAgBI,GAAez0B,EAAOR,GAAMk1B,EAAO32B,MAAQ02B,EAC3DH,GAAmBG,GAAeC,EAAO12B,OAASgC,EAAOR,KAAQi1B,EACjEF,GAAiBE,GAAe90B,EAAOH,GAAMk1B,EAAOv6B,OAASs6B,EAC7DD,GAAkBC,GAAeC,EAAOn6B,MAAQoF,EAAOH,KAAQi1B,EAI3DJ,GAAgB,GAAKA,GAAgB,EACxCM,EAASN,EAAe72B,KAAKu2B,eAErBO,GAAmB,GAAKA,GAAmB,IACnDK,EAASL,EAAkB92B,KAAKu2B,aAI7BQ,GAAiB,GAAKA,GAAiB,EAC1CK,EAAUL,EAAgB/2B,KAAKu2B,eAEvBS,GAAkB,GAAKA,GAAkB,IACjDI,EAAUJ,EAAiBh3B,KAAKu2B,cAIlCv2B,KAAKq3B,aAAaF,EAAQC,IAK3BC,aAAc,SAASF,EAAQC,GAE9Bp3B,KAAKm2B,aAAegB,EACpBn3B,KAAKo2B,cAAgBgB,EAErBp3B,KAAKs3B,sBAGAt3B,KAAKm2B,eAAgBn2B,KAAKo2B,eAAmBp2B,KAAKq2B,mBACtDr2B,KAAKq2B,iBAAmBkB,YACvB9rB,GAAMzL,KAAM,sBACZA,KAAKw2B,oBAORc,mBAAoB,WACnB,GAAIh5B,GAAK0B,KAAK+yB,QAEV/yB,MAAKm2B,aAAe,EACnB73B,EAAG4xB,aAAe,IACrBlwB,KAAKm2B,aAAe,GAGbn2B,KAAKm2B,aAAe,GACxB73B,EAAG4xB,YAAc5xB,EAAG,GAAGuC,cAAgBvC,EAAG,GAAGk5B,eAChDx3B,KAAKm2B,aAAe,GAIlBn2B,KAAKo2B,cAAgB,EACpB93B,EAAG6xB,cAAgB,IACtBnwB,KAAKo2B,cAAgB,GAGdp2B,KAAKo2B,cAAgB,GACzB93B,EAAG6xB,aAAe7xB,EAAG,GAAGsC,aAAetC,EAAG,GAAGm5B,cAChDz3B,KAAKo2B,cAAgB,IAOxBsB,mBAAoB,WACnB,GAAIp5B,GAAK0B,KAAK+yB,SACV4E,EAAO33B,KAAKw2B,iBAAmB,GAG/Bx2B,MAAKm2B,cACR73B,EAAG4xB,UAAU5xB,EAAG4xB,YAAclwB,KAAKm2B,aAAewB,GAE/C33B,KAAKo2B,eACR93B,EAAG6xB,WAAW7xB,EAAG6xB,aAAenwB,KAAKo2B,cAAgBuB,GAGtD33B,KAAKs3B,qBAGAt3B,KAAKm2B,cAAiBn2B,KAAKo2B,eAC/Bp2B,KAAK22B,iBAMPA,cAAe,WACV32B,KAAKq2B,mBACRuB,cAAc53B,KAAKq2B,kBACnBr2B,KAAKq2B,iBAAmB,KAExBr2B,KAAK63B,oBAMPnB,sBAAuB,WAEjB12B,KAAKq2B,kBACTr2B,KAAK63B,mBAMPA,gBAAiB,cAalB,IAAIC,IAAkBpF,GAAajf,QAElCzB,UAAW,KAGX+lB,QAAS,KACTC,IAAK,KACLC,YAAa,KAGbvmB,YAAa,SAASM,EAAWqE,GAChCqc,GAAa7pB,KAAK7I,KAAMqW,GAExBrW,KAAKgS,UAAYA,GAMlB6hB,uBAAwB,SAAS7xB,GAChC,GACIk2B,GACAC,EACAx0B,EAHAgvB,EAAY3yB,KAAK2yB,SAKrB3yB,MAAKo4B,gBAEDp2B,GACHm2B,GAAcx7B,KAAMwF,EAAOH,GAAKzB,IAAKiC,EAAOR,IAC5C2B,EAAQw0B,EAGJxF,IACHuF,EAAc93B,EAAauyB,GAC3BhvB,EAAQD,EAAeC,EAAOu0B,IAG/Bl4B,KAAK+3B,QAAU/3B,KAAKq4B,SAAS10B,EAAMhH,KAAMgH,EAAMpD,KAG3CoyB,GAAa3yB,KAAKqW,QAAQiiB,gBAIzBt4B,KAAK+3B,UACRG,EAAc70B,EAAerD,KAAK+3B,QAASG,IAC1CA,GAGFv0B,EAAQE,EAAcq0B,IAGvBl4B,KAAKi4B,YAAcn0B,EAAWH,EAAOw0B,KAGrCn4B,KAAK+3B,QAAU,KACf/3B,KAAKi4B,YAAc,MAIpBvF,GAAa/pB,UAAUkrB,uBAAuBppB,MAAMzK,KAAM2K,YAK3DytB,cAAe,WACdp4B,KAAKgS,UAAUumB,cACfv4B,KAAK42B,uBAKNzB,gBAAiB,SAASnzB,GACzB,GAAIg2B,EAEJtF,IAAa/pB,UAAUwsB,gBAAgB1qB,MAAMzK,KAAM2K,WAGnDqtB,EAAMh4B,KAAKq4B,SAASl2B,EAAOH,GAAKQ,EAAOR,IAInCg2B,GACHh4B,KAAKw4B,cAAcR,IAMrBvC,WAAY,SAASF,EAAIC,EAAIxzB,GAC5B,GAAIg2B,EAEJtF,IAAa/pB,UAAU8sB,WAAWhrB,MAAMzK,KAAM2K,WAE9CqtB,EAAMh4B,KAAKq4B,SAASl2B,EAAOH,GAAKQ,EAAOR,IAElC6P,GAAYmmB,EAAKh4B,KAAKg4B,OACtBh4B,KAAKg4B,KACRh4B,KAAKy4B,eAEFT,GACHh4B,KAAKw4B,cAAcR,KAOtBrC,cAAe,WACd31B,KAAK04B,gBACLhG,GAAa/pB,UAAUgtB,cAAclrB,MAAMzK,KAAM2K,YAKlD6tB,cAAe,SAASR,GACvB,GAAIW,GAAS9mB,GAAYmmB,EAAKh4B,KAAK+3B,QAEnC/3B,MAAKg4B,IAAMA,EAEXh4B,KAAKoZ,QAAQ,UAAWpZ,KAAKg4B,IAAKW,EAAQ34B,KAAK+3B,UAKhDU,aAAc,WACTz4B,KAAKg4B,MACRh4B,KAAKoZ,QAAQ,SAAUpZ,KAAKg4B,KAC5Bh4B,KAAK04B,gBACL14B,KAAKg4B,IAAM,OAMbU,cAAe,WACV14B,KAAKg4B,KACRh4B,KAAKoZ,QAAQ,UAAWpZ,KAAKg4B,MAM/B1D,qBAAsB,WACrB5B,GAAa/pB,UAAU2rB,qBAAqB7pB,MAAMzK,KAAM2K,WAExD3K,KAAK+3B,QAAU,KACf/3B,KAAKg4B,IAAM,KAEXh4B,KAAKgS,UAAU4mB,eAKhBf,gBAAiB,WAChBnF,GAAa/pB,UAAUkvB,gBAAgBptB,MAAMzK,KAAM2K,WAEnD3K,KAAKo4B,iBAKNC,SAAU,SAAS17B,EAAM4D,GAOxB,MALIP,MAAKi4B,cACRt7B,GAAQqD,KAAKi4B,YAAYt7B,KACzB4D,GAAOP,KAAKi4B,YAAY13B,KAGlBP,KAAKgS,UAAUqmB,SAAS17B,EAAM4D,MAyCnCs4B,GAAgBxnB,GAAMoC,OAAO0a,IAEhC9X,QAAS,KAETyiB,SAAU,KACVx6B,GAAI,KACJkxB,SAAU,KAGVuJ,KAAM,KACNC,MAAO,KAGPC,GAAI,KACJC,GAAI,KAGJC,SAAU,KACVC,UAAW,KAEXC,aAAa,EACblK,UAAU,EACVmK,aAAa,EAEb5nB,YAAa,SAASonB,EAAUziB,GAC/BrW,KAAKqW,QAAUA,EAAUA,MACzBrW,KAAK84B,SAAWA,EAChB94B,KAAKwvB,SAAWnZ,EAAQmZ,SAAWl0B,EAAE+a,EAAQmZ,UAAYsJ,EAAS/4B,UAKnEiG,MAAO,SAAShE,GACVhC,KAAKq5B,cACTr5B,KAAKq5B,aAAc,EAEnBr5B,KAAKi5B,GAAKz2B,EAAOR,GACjBhC,KAAKk5B,GAAK/2B,EAAOH,GACjBhC,KAAKm5B,SAAW,EAChBn5B,KAAKo5B,UAAY,EAEZp5B,KAAKmvB,UACTnvB,KAAKu5B,iBAGF72B,EAAaV,GAChBhC,KAAKquB,SAAS/yB,EAAE6E,UAAW,YAAaH,KAAKq1B,YAG7Cr1B,KAAKquB,SAAS/yB,EAAE6E,UAAW,YAAaH,KAAKq1B,cAQhDmE,KAAM,SAASC,EAAcjW,GAI5B,QAASS,KACRsL,EAAM+J,aAAc,EACpB/J,EAAMxY,gBAENwY,EAAMwJ,KAAOxJ,EAAMyJ,MAAQ,KAEvBxV,GACHA,IAVF,GAAI+L,GAAQvvB,KACR05B,EAAiB15B,KAAKqW,QAAQqjB,cAa9B15B,MAAKq5B,cAAgBr5B,KAAKs5B,cAC7Bt5B,KAAKq5B,aAAc,EAEnBr5B,KAAK0uB,gBAAgBpzB,EAAE6E,WAEnBs5B,GAAgBC,IAAmB15B,KAAKmvB,UAC3CnvB,KAAKs5B,aAAc,EACnBt5B,KAAK1B,GAAGq7B,SACPp5B,IAAKP,KAAK+4B,KACVp8B,KAAMqD,KAAKg5B,QAEXzyB,SAAUmzB,EACVzV,SAAUA,KAIXA,MAOH2V,MAAO,WACN,GAAIt7B,GAAK0B,KAAK1B,EA0Bd,OAxBKA,KACJ0B,KAAK84B,SAAS15B,QACdd,EAAK0B,KAAK1B,GAAK0B,KAAK84B,SAASzyB,QAC3BjJ,SAAS4C,KAAKqW,QAAQwjB,iBAAmB,IACzCj9B,KACA8C,SAAU,WACVo6B,WAAY,GACZ7hB,QAASjY,KAAKmvB,SAAW,OAAS,GAClCC,OAAQ,EACRryB,MAAO,OACPyD,OAAQ,OACRpB,MAAOY,KAAK84B,SAAS15B,QACrBT,OAAQqB,KAAK84B,SAASn6B,SACtBo7B,QAAS/5B,KAAKqW,QAAQ0jB,SAAW,GACjCC,OAAQh6B,KAAKqW,QAAQ2jB,SAKvB17B,EAAGlB,SAAS,mBAEZkB,EAAGmD,SAASzB,KAAKwvB,WAGXlxB,GAKRyY,cAAe,WACV/W,KAAK1B,KACR0B,KAAK1B,GAAGsD,SACR5B,KAAK1B,GAAK,OAMZi7B,eAAgB,WACf,GAAIU,GACA55B,CAEJL,MAAK45B,QAGa,OAAd55B,KAAK+4B,OACR/4B,KAAK84B,SAAS15B,QACd66B,EAAej6B,KAAK84B,SAASx4B,SAC7BD,EAASL,KAAK1B,GAAGyxB,eAAezvB,SAChCN,KAAK+4B,KAAOkB,EAAa15B,IAAMF,EAAOE,IACtCP,KAAKg5B,MAAQiB,EAAat9B,KAAO0D,EAAO1D,MAGzCqD,KAAK1B,GAAG1B,KACP2D,IAAKP,KAAK+4B,KAAO/4B,KAAKm5B,SACtBx8B,KAAMqD,KAAKg5B,MAAQh5B,KAAKo5B,aAM1B/D,WAAY,SAASrzB,GACpBhC,KAAKm5B,SAAW32B,EAAOR,GAAMhC,KAAKi5B,GAClCj5B,KAAKo5B,UAAYj3B,EAAOH,GAAMhC,KAAKk5B,GAE9Bl5B,KAAKmvB,UACTnvB,KAAKu5B,kBAMPjK,KAAM,WACAtvB,KAAKmvB,WACTnvB,KAAKmvB,UAAW,EACZnvB,KAAK1B,IACR0B,KAAK1B,GAAGgxB,SAOXD,KAAM,WACDrvB,KAAKmvB,WACRnvB,KAAKmvB,UAAW,EAChBnvB,KAAKu5B,iBACLv5B,KAAK45B,QAAQvK,WAWZ6K,GAAO3rB,GAAG2rB,KAAO7oB,GAAMoC,OAAO0a,GAAeQ,IAEhDpX,KAAM,KACNxH,MAAO,KAEP/J,MAAO,KACPE,IAAK,KAEL5H,GAAI,KACJ67B,UAAW,KAGXC,gBAAiB,KACjBC,iBAAkB,KAClBC,gBAAiB,KAEjBC,kBAAmB,KAKnBvS,UAAW,KAEXwS,gBAAiB,KACjBC,gBAAiB,KACjBC,kBAAmB,KACnBC,qBAAsB,KAGtBjpB,YAAa,SAAS6F,GACrBvX,KAAKuX,KAAOA,EACZvX,KAAK+P,MAAQwH,EAAKqjB,IAAI,SACtB56B,KAAKm6B,aAELn6B,KAAKw6B,gBAAkBx6B,KAAK66B,uBAC5B76B,KAAK8uB,qBASNgM,uBAAwB,WACvB,MAAO96B,MAAKuX,KAAKqjB,IAAI,oBAMtBG,wBAAyB,WACxB,OAAO,GAKRC,uBAAwB,WACvB,OAAO,GAURC,SAAU,SAASrQ,GAClB5qB,KAAKgG,MAAQ4kB,EAAM5kB,MAAMK,QACzBrG,KAAKkG,IAAM0kB,EAAM1kB,IAAIG,QAErBrG,KAAKk7B,eACLl7B,KAAKm7B,uBAKND,aAAc,aAKdC,oBAAqB,WACpB,GACId,GACAC,EAFA/iB,EAAOvX,KAAKuX,IAIhBvX,MAAKo6B,gBACJ7iB,EAAKqjB,IAAI,oBACTrjB,EAAKqjB,IAAI,eACT56B,KAAK86B,yBAENT,EAAmB9iB,EAAKqjB,IAAI,oBACJ,MAApBP,IACHA,EAAmBr6B,KAAK+6B,2BAGzBT,EAAkB/iB,EAAKqjB,IAAI,mBACJ,MAAnBN,IACHA,EAAkBt6B,KAAKg7B,0BAGxBh7B,KAAKq6B,iBAAmBA,EACxBr6B,KAAKs6B,gBAAkBA,GAMxBc,WAAY,SAAS/R,KAOrBpB,UAAW,SAAS7iB,EAAGC,GACtB,MAAIrF,MAAKgoB,UACDnhB,EAAWzB,EAAGC,EAAGrF,KAAKgoB,WAGtB1hB,EAAYlB,EAAGC,IAUxBkzB,YAAa,aAKbK,YAAa,aAQbP,SAAU,SAAS9G,EAAYE,KAM/B4J,WAAY,SAASrD,KAMrBsD,SAAU,SAAStD,KAUnBtgB,WAAY,SAASpZ,GACpB0B,KAAK1B,GAAKA,EACVsE,EAAiBtE,GAEjB0B,KAAKu7B,eAAe,aAAcv7B,KAAKw7B,eACvCx7B,KAAKu7B,eAAe,YAAav7B,KAAKy7B,cAItCz7B,KAAK07B,kBAEL17B,KAAK27B,sBAINJ,eAAgB,SAASt/B,EAAM+G,GAC9B,GAAIusB,GAAQvvB,IAIZA,MAAK1B,GAAGuE,GAAG5G,EAAM,SAAS+F,GACzB,IACE1G,EAAE0G,EAAGmX,QAAQlC,GAAG,mCAEjB,MAAOjU,GAAQ6F,KAAK0mB,EAAOvtB,MAQ9B+U,cAAe,WACd/W,KAAK47B,uBACL57B,KAAK67B,qBAEL77B,KAAK1B,GAAGsD,UAOTk6B,eAAgB,aAOhBC,YAAa,aAMbC,cAAe,aAUfL,mBAAoB,WACnB37B,KAAKquB,SAAS/yB,EAAE6E,WACf87B,UAAWj8B,KAAKk8B,kBAChBC,UAAWn8B,KAAKk8B,qBAMlBN,qBAAsB,WACrB57B,KAAK0uB,gBAAgBpzB,EAAE6E,YAKxBs7B,aAAc,SAASz5B,GACjBhC,KAAK4uB,iBACT5uB,KAAKw6B,gBAAgBhH,iBAAiBxxB,OAOxCw5B,cAAe,SAASx5B,GACvB,GAAIuV,GAAOvX,KAAKuX,MAIZA,EAAK6kB,YAAc7kB,EAAK8kB,gBAC3Br8B,KAAKgvB,kBAGNhvB,KAAKw6B,gBAAgBhH,iBAAiBxxB,GACrC+sB,MAAO/uB,KAAKuX,KAAKqjB,IAAI,qBAOvBC,qBAAsB,WACrB,GAGIyB,GACAC,EAJAhN,EAAQvvB,KACRuX,EAAOvX,KAAKuX,KACZilB,EAAejlB,EAAKqjB,IAAI,cAOxB6B,EAAe,GAAI3E,IAAgB93B,MACtCy2B,OAAQlf,EAAKqjB,IAAI,cACjB8B,iBAAkB,WACjBJ,EAAcG,EAAa1E,QAC3BwE,EAAgB,MAEjBI,UAAW,WACVplB,EAAKuD,YAEN8hB,QAAS,SAAS5E,EAAKW,EAAQZ,GAC1BA,IAGEY,IACJ2D,EAAc,MAGXE,IACHD,EAAgBhN,EAAMsN,iBACrBtN,EAAM8L,WAAWtD,GACjBxI,EAAM8L,WAAWrD,IAEduE,EACHhN,EAAMuN,gBAAgBP,GAEdA,KAAkB,GAC1Bp/B,OAKJ4/B,OAAQ,WACPT,EAAc,KACdC,EAAgB,KAChBhN,EAAMyN,qBAEPC,QAAS,WACR5/B,KAED6/B,eAAgB,SAASl7B,EAAIiyB,GACvBA,IAEHqI,IACC/M,EAAMX,iBAEPrX,EAAK4lB,gBACJ5N,EAAM8L,WAAWiB,GACjB/M,EAAM+L,SAASgB,GACft6B,GAGEu6B,GAEHhlB,EAAK6lB,gBAAgBb,EAAev6B,MAMxC,OAAOy6B,IAORZ,mBAAoB,WACnB77B,KAAKw6B,gBAAgBxG,iBAEjBh0B,KAAKy6B,iBACRz6B,KAAKy6B,gBAAgBzG,iBAElBh0B,KAAK06B,mBACR16B,KAAK06B,kBAAkB1G,iBAEpBh0B,KAAK26B,sBACR36B,KAAK26B,qBAAqB3G,kBAY5BqJ,0BAA2B,SAASxT,EAAeyT,GAClD,GAAIC,GAAYv9B,KAAKw9B,qBAAqB3T,EAAeyT,EAEzD,OAAOt9B,MAAKy9B,aAAaF,EAAWD,IAOrCE,qBAAsB,SAAS3T,EAAeyT,GAC7C,GAAIC,GAAYD,EAAY9zB,EAAa8zB,EAAUhrB,SAenD,OAbAirB,GAAUv3B,MAAQ6jB,EAAc7jB,MAAMK,QACtCk3B,EAAUr3B,IAAM2jB,EAAc3jB,IAAM2jB,EAAc3jB,IAAIG,QAAU,KAChEk3B,EAAUxe,OAAS,KACnB/e,KAAKuX,KAAKsI,SAASwH,oBAAoBkW,GAGvCA,EAAU3Y,WAAa2Y,EAAU3Y,eAAiBmG,OAAO,aAGpDuS,IACJC,EAAUG,UAAW,GAGfH,GAMRE,aAAc,SAAS5T,EAAeyT,KAMtCK,eAAgB,aAWhBb,gBAAiB,SAASzT,GACzBrpB,KAAK49B,gBAAgBvU,IAKtB2T,kBAAmB,WAClBh9B,KAAK69B,qBAQNhB,iBAAkB,SAASiB,EAAOC,GACjC,GAAI1U,GAAOrpB,KAAKg+B,qBAAqBF,EAAOC,EAE5C,SAAI1U,IAASrpB,KAAKuX,KAAKsI,SAASiK,uBAAuBT,KAIhDA,GAMR2U,qBAAsB,SAASF,EAAOC,GACrC,GAAIE,IAAUH,EAAM93B,MAAO83B,EAAM53B,IAAK63B,EAAM/3B,MAAO+3B,EAAM73B,IAIzD,OAFA+3B,GAAMC,KAAK1yB,KAEFxF,MAAOi4B,EAAM,GAAG53B,QAASH,IAAK+3B,EAAM,GAAG53B,UASjDu3B,gBAAiB,SAASvU,GACzBrpB,KAAKm+B,WAAW,YAAan+B,KAAKo7B,WAAW/R,KAK9CwU,kBAAmB,WAClB79B,KAAKo+B,aAAa,cAKnBC,oBAAqB,WACpB,OAAS,iBAQVvhB,oBAAqB,aAIrBD,sBAAuB,aAQvByhB,oBAAqB,aAIrBC,mBAAoB,SAAS3vB,KAI7B4vB,qBAAsB,aAatBL,WAAY,SAASx7B,EAAMuR,KAM3BkqB,aAAc,SAASz7B,GACtB,GAAIrE,GAAK0B,KAAKm6B,UAAUx3B,EAEpBrE,KACHA,EAAGsD,eACI5B,MAAKm6B,UAAUx3B,KASxB87B,iBAAkB,SAAS97B,EAAMuR,GAChC,GAII7V,GAJAkxB,EAAQvvB,KACR0+B,EAAc1+B,KAAK2C,EAAO,SAC1Bg8B,EAAO,GACPC,IAGJ,IAAI1qB,EAAKpW,OAAQ,CAGhB,IAAKO,EAAI,EAAGA,EAAI6V,EAAKpW,OAAQO,IAC5BsgC,GAAQ3+B,KAAK6+B,YAAYl8B,EAAMuR,EAAK7V,GAKrC/C,GAAEqjC,GAAM3iC,KAAK,SAASqC,EAAGgzB,GACxB,GAAI1d,GAAMO,EAAK7V,GACXC,EAAKhD,EAAE+1B,EAGPqN,KACHpgC,EAAKogC,EAAY71B,KAAK0mB,EAAO5b,EAAKrV,IAG/BA,IACHA,EAAKhD,EAAEgD,GAGHA,EAAG2Y,GAAGsY,EAAMuP,cACfnrB,EAAIrV,GAAKA,EACTsgC,EAAalgC,KAAKiV,OAMtB,MAAOirB,IAIRE,WAAY,MAIZD,YAAa,SAASl8B,EAAMgR,GAG3B,GAAIorB,GAAgB/+B,KAAK2C,EAAO,cAC5Bq8B,EAAYh/B,KAAK2C,EAAO,UAExBqe,EAAU+d,EAAgBA,EAAcl2B,KAAK7I,KAAM2T,MACnD/W,EAAMqO,GAAS+zB,EAAYA,EAAUn2B,KAAK7I,KAAM2T,MAEpD,OAAO,IAAM3T,KAAK8+B,YAChB9d,EAAQljB,OAAS,WAAakjB,EAAQ5V,KAAK,KAAO,IAAM,KACxDxO,EAAM,WAAaA,EAAM,IAAM,IAChC,OAUFqiC,cAAe,SAASrwB,GACvB,GAAI2I,GAAOvX,KAAKuX,KACZ8D,EAAQ9D,EAAKsI,SAAStF,SACtByG,GAAY,MAAQ0K,GAAO9c,EAAKkZ,OAsBpC,OAnBuC,IAAtCvQ,EAAK2nB,iBAAiB73B,GAAG,WACzBuH,EAAKD,SAAW4I,EAAKQ,cAAcpJ,SAEnCqS,EAAQtiB,KAAK,kBAGVkQ,EAAKqC,OAAOoK,EAAO,OACtB2F,EAAQtiB,KACP,WACA6Y,EAAK4nB,qBAGEvwB,EAAOyM,EACf2F,EAAQtiB,KAAK,WAGbsiB,EAAQtiB,KAAK,aAGPsiB,IAUTkZ,IAAKvM,OAEJyR,cAAe,KACfC,eAAe,EACfC,eAAe,EACfC,oBAAoB,EACpBrrB,KAAM,KAIN0F,aAAc,SAAShH,GACtB,GAEIvU,GAFAmhC,KACAC,IAGJ,KAAKphC,EAAI,EAAGA,EAAIuU,EAAO9U,OAAQO,KAC7BgU,GAAUO,EAAOvU,IAAMmhC,EAAWC,GAAU/gC,KAAKkU,EAAOvU,GAG1D2B,MAAKkU,QAAU6W,OACd/qB,KAAK0/B,eAAeF,GACpBx/B,KAAK2/B,eAAeF,KAKtBC,eAAgB,SAAS9sB,GACxB,GAAIsB,GAAOlU,KAAK4/B,aAAahtB,EAG7B,OAAO5S,MAAK6/B,aAAa3rB,IAASA,GAInCyrB,eAAgB,SAAS/sB,GACxB,GAAIsB,GAAOlU,KAAK4/B,aAAahtB,EAG7B,OAAO5S,MAAK8/B,aAAa5rB,IAASA,GAKnC6rB,eAAgB,WACf//B,KAAKggC,oBACLhgC,KAAK67B,qBAEL77B,KAAKigC,iBACLjgC,KAAKkgC,iBAELlgC,KAAKkU,KAAO,MAKbisB,aAAc,WACb,MAAOngC,MAAKkU,UASb4rB,aAAc,SAAS5rB,KAMvB+rB,eAAgB,aAQhBG,eAAgB,SAASlsB,EAAMmsB,GAC9B,GAGIhiC,GAHAkZ,EAAOvX,KAAKuX,KACZonB,EAAO,GACPC,IAGJ,IAAI1qB,EAAKpW,OAAQ,CAGhB,IAAKO,EAAI,EAAGA,EAAI6V,EAAKpW,OAAQO,IAC5BsgC,GAAQ3+B,KAAKsgC,UAAUpsB,EAAK7V,GAAIgiC,EAKjC/kC,GAAEqjC,GAAM3iC,KAAK,SAASqC,EAAGgzB,GACxB,GAAI1d,GAAMO,EAAK7V,GACXC,EAAKiZ,EAAKgpB,eAAe5sB,EAAIrB,MAAOhX,EAAE+1B,GAEtC/yB,KACHA,EAAGkV,KAAK,SAAUG,GAClBA,EAAIrV,GAAKA,EACTsgC,EAAalgC,KAAKiV,MAKrB,MAAOirB,IAKR0B,UAAW,SAAS3sB,EAAK0sB,KAWzBR,aAAc,SAAS3rB,GACtB,MAAOlU,MAAKm+B,WAAW,UAAWjqB,IAKnCgsB,eAAgB,WACflgC,KAAKo+B,aAAa,YAKnBoC,aAAc,SAAS7sB,EAAKrV,GAC3B,MAAO0B,MAAKuX,KAAKgpB,eAAe5sB,EAAIrB,MAAOhU,IAM5CmiC,kBAAmB,SAAS9sB,GAC3B,GAAIrB,GAAQqB,EAAIrB,MACZI,EAASJ,EAAMI,UAEnB,QAAS,cAAeqY,OACvBzY,EAAMsS,UACNlS,EAAOkS,gBAOT8b,cAAe,SAAS/sB,GACvB,OACCgtB,mBAAoB3gC,KAAK4gC,cAAcjtB,GAAK,sBAO9CktB,wBAAyB,SAASltB,GACjC,OAAS,iBAAkB,eAU5BmtB,sBAAuB,SAASC,GAC/B,GAAInuB,GAAS5S,KAAKuX,KAAKsI,SAAS8K,6BAA6BoW,EAkB7D,QAZEnuB,EAAO9U,QACRkC,KAAKuX,KAAKsI,SAASxJ,QAAQ2qB,gBAE3BpuB,GACCtX,EAAEmY,UAAWwtB,IACZj7B,MAAOhG,KAAKuX,KAAKrR,IACjBA,IAAKlG,KAAKuX,KAAKrR,IACf+X,IAAK,SAKDje,KAAK4/B,aAAahtB,IAS1B8oB,gBAAiB,WAChB17B,KAAKkhC,oBAAoBlhC,KAAK1B,KAK/B4iC,oBAAqB,SAAS5iC,GAC7B0B,KAAKmhC,mBAAmB7iC,EAAI,aAAc0B,KAAKohC,qBAC/CphC,KAAKmhC,mBAAmB7iC,EAAI,WAAY0B,KAAKqhC,mBAC7CrhC,KAAKmhC,mBAAmB7iC,EAAI,aAAc0B,KAAKshC,oBAC/CthC,KAAKmhC,mBAAmB7iC,EAAI,aAAc0B,KAAKggC,mBAC/ChgC,KAAKmhC,mBAAmB7iC,EAAI,YAAa0B,KAAKuhC,oBAC9CvhC,KAAKmhC,mBAAmB7iC,EAAI,QAAS0B,KAAKwhC,iBAM3CL,mBAAoB,SAAS7iC,EAAIrC,EAAM+G,GACtC,GAAIusB,GAAQvvB,IAEZ1B,GAAGuE,GAAG5G,EAAM,0BAA2B,SAAS+F,GAC/C,GAAI2R,GAAMrY,EAAE0E,MAAMwT,KAAK,SAGvB,IAAIG,IAAQ4b,EAAM8P,gBAAkB9P,EAAM+P,cACzC,MAAOt8B,GAAQ6F,KAAK0mB,EAAO5b,EAAK3R,MAMnCw/B,eAAgB,SAAS7tB,EAAK3R,GAC7B,MAAOhC,MAAKuX,KAAK6B,QAAQ,aAAczF,EAAIrV,GAAG,GAAIqV,EAAIrB,MAAOtQ,IAK9Ds/B,mBAAoB,SAAS3tB,EAAK3R,GAE/BhC,KAAK4uB,iBACL5uB,KAAKo/B,gBAENp/B,KAAKo/B,cAAgBzrB,EACrBA,EAAIrV,GAAGlB,SAAS,yBAChB4C,KAAKuX,KAAK6B,QAAQ,iBAAkBzF,EAAIrV,GAAG,GAAIqV,EAAIrB,MAAOtQ,KAO5Dg+B,kBAAmB,SAASrsB,EAAK3R,GAChCA,EAAKA,MAEDhC,KAAKo/B,gBACRzrB,EAAMA,GAAO3T,KAAKo/B,cAClBp/B,KAAKo/B,cAAgB,KACrBzrB,EAAIrV,GAAGhB,YAAY,yBACnB0C,KAAKuX,KAAK6B,QAAQ,gBAAiBzF,EAAIrV,GAAG,GAAIqV,EAAIrB,MAAOtQ,KAK3Du/B,mBAAoB,SAAS5tB,EAAK3R,GACjC,GAAIy/B,GAAazhC,KAAK0hC,eAAe/tB,EAAK3R,GAAM0xB,SAAU,KAErD+N,GAAczhC,KAAKuX,KAAKoqB,iBAAiBhuB,EAAIrB,QACjDtS,KAAK4hC,qBAAqBjuB,GACxB6f,iBAAiBxxB,GACjB0xB,SAAU,KAMd0N,oBAAqB,SAASztB,EAAK3R,GAClC,GAMIy6B,GANAllB,EAAOvX,KAAKuX,KACZjF,EAAQqB,EAAIrB,MACZ8pB,EAAa7kB,EAAKsqB,gBAAgBvvB,GAClCwvB,EAAcvqB,EAAKoqB,iBAAiBrvB,GACpCyvB,EAAcxqB,EAAKyqB,iBAAiB1vB,GACpCmvB,GAAa,CAGbrF,IAAc2F,IAEjBN,EAAazhC,KAAK0hC,eAAe/tB,EAAK3R,IAGlCy/B,IAAeK,IAAeC,IAElCtF,EAAeqF,EACd9hC,KAAK4hC,qBAAqBjuB,GAC1B3T,KAAKiiC,uBAAuBtuB,GAE7B8oB,EAAajJ,iBAAiBxxB,GAC7B+sB,MAAOqN,EAAa,EAAIp8B,KAAKuX,KAAKqjB,IAAI,qBAKxC56B,KAAKgvB,mBAINqS,kBAAmB,SAAS1tB,EAAK3R,GAGhChC,KAAKgvB,mBAON0S,eAAgB,SAAS/tB,EAAK3R,EAAIkgC,GACjC,QAAI5mC,EAAE0G,EAAGmX,QAAQlC,GAAG,iBACnBjX,KAAKmiC,uBAAuBxuB,EAAKrY,EAAE0G,EAAGmX,QAAQlC,GAAG,sBAC/Cuc,iBAAiBxxB,EAAIkgC,IAChB,IAcTN,qBAAsB,SAASjuB,GAC9B,GAKIwf,GACAiP,EACAC,EAPA9S,EAAQvvB,KACRuX,EAAOvX,KAAKuX,KACZsI,EAAWtI,EAAKsI,SAChBvhB,EAAKqV,EAAIrV,GACTgU,EAAQqB,EAAIrB,KAKhB,IAAItS,KAAKy6B,gBACR,MAAOz6B,MAAKy6B,eAKb,IAAIgC,GAAez8B,KAAKy6B,gBAAkB,GAAI3C,IAAgBvgB,GAC7Dkf,OAAQlf,EAAKqjB,IAAI,cACjBjI,UAAWr0B,EACXg6B,eAAe,EACfoE,iBAAkB,SAAS16B,GAC1B2R,EAAI3B,UAAYud,EAChB4D,GAAa,EACbiP,EAAgB,GAAIvJ,IAAcllB,EAAIrV,IACrCu7B,gBAAiB,cACjBrK,SAAUjY,EAAKjZ,GACfy7B,QAAS0C,EAAarJ,QAAU,KAAO7b,EAAKqjB,IAAI,eAChDlB,eAAgBniB,EAAKqjB,IAAI,sBACzBZ,OAAQ,IAEToI,EAAc9S,OACd8S,EAAcp8B,MAAMhE,IAErB26B,UAAW,SAAS36B,GACfy6B,EAAarJ,UAAY7b,EAAKsqB,gBAAgBvvB,IAEjDiF,EAAK+qB,YAAYhwB,GAElB6gB,GAAa,EACb5D,EAAMyQ,kBAAkBrsB,EAAK3R,GAC7ButB,EAAMgT,aAAa5uB,EAAK3R,GACxBuV,EAAKirB,UAAUlwB,IAEhBsqB,QAAS,SAAS5E,EAAKW,EAAQZ,GAC9B,GAAI0K,EAGA9uB,GAAIqkB,MACPD,EAAUpkB,EAAIqkB,KAIfqK,EAAe9S,EAAMmT,iBACpB3K,EAAQ/lB,UAAUqpB,WAAWtD,GAC7BC,EAAIhmB,UAAUqpB,WAAWrD,GACzB1lB,GAGG+vB,IAAiBxiB,EAASuJ,mBAAmBmG,EAAMoT,YAAYN,GAAe/vB,KACjFnV,IACAklC,EAAe,MAIZA,IAAiBI,EAAgBlrB,EAAKqrB,WAAWP,EAAc1uB,KAElE8uB,EAAcrlC,SAAS,eAClBq/B,EAAarJ,SACjB7D,EAAMsT,iBAAiBJ,GAGxBL,EAAc9S,QAGd8S,EAAc/S,OAGXsJ,IACH0J,EAAe,OAGjBtF,OAAQ,WACPxlB,EAAKurB,eACLV,EAAc/S,OACdgT,EAAe,MAEhBpF,QAAS,WACR5/B,KAED6/B,eAAgB,SAASl7B,SACjB2R,GAAI3B,UAGXowB,EAAc5I,MAAM6I,EAAc,WAC7BlP,IACH5b,EAAKurB,eACLvrB,EAAKwrB,UAAUzwB,GACfid,EAAMyT,YAAYrvB,EAAK3R,IAEpBqgC,GACH9qB,EAAK0rB,gBAAgB3wB,EAAO+vB,EAAcriC,KAAKgoB,UAAW1pB,EAAI0D,KAGhEutB,EAAMkL,gBAAkB,OAI1B,OAAOgC,IAORwF,uBAAwB,SAAStuB,GAChC,GAAI4b,GAAQvvB,KACRuX,EAAOvX,KAAKuX,KACZjF,EAAQqB,EAAIrB,KAEhB,IAAItS,KAAKy6B,gBACR,MAAOz6B,MAAKy6B,eAGb,IAAIgC,GAAez8B,KAAKy6B,gBAAkB,GAAI/H,KAC7CiK,UAAW,SAAS36B,GACfy6B,EAAarJ,UAAY7b,EAAKsqB,gBAAgBvvB,IAEjDiF,EAAK+qB,YAAYhwB,IAGnB4qB,eAAgB,SAASl7B,GACxButB,EAAMkL,gBAAkB,OAI1B,OAAOgC,IAKR8F,aAAc,SAAS5uB,EAAK3R,GAC3BhC,KAAKq/B,eAAgB,EACrBr/B,KAAKuX,KAAK6B,QAAQ,iBAAkBzF,EAAIrV,GAAG,GAAIqV,EAAIrB,MAAOtQ,OAK3DghC,YAAa,SAASrvB,EAAK3R,GAC1BhC,KAAKq/B,eAAgB,EACrBr/B,KAAKuX,KAAK6B,QAAQ,gBAAiBzF,EAAIrV,GAAG,GAAIqV,EAAIrB,MAAOtQ,OAQ1D0gC,iBAAkB,SAASQ,EAAWC,EAAS7wB,GAC9C,GAGImJ,GACA4mB,EAJAxiB,EAAW7f,KAAKuX,KAAKsI,SACrB8c,EAAYuG,EAAUl9B,MACtBo9B,EAAUD,EAAQn9B,KAwCtB,OApCI22B,GAAUre,YAAc8kB,EAAQ9kB,WACnC7C,EAAQzb,KAAKioB,UAAUmb,EAASzG,GAI5BrqB,EAAMyM,QAAUtX,EAAgBgU,IACnC4mB,GACCr8B,MAAOsM,EAAMtM,MAAMK,QACnBH,IAAK2Z,EAAShB,YAAYvM,GAC1ByM,QAAQ,GAETc,EAASyH,oBAAoB+a,IAI7BA,GACCr8B,MAAOsM,EAAMtM,MAAMK,QACnBH,IAAKoM,EAAMpM,IAAMoM,EAAMpM,IAAIG,QAAU,KACrC0Y,OAAQzM,EAAMyM,QAIhBsjB,EAAar8B,MAAMvG,IAAIgc,GACnB4mB,EAAan8B,KAChBm8B,EAAan8B,IAAIzG,IAAIgc,IAKtB4mB,GACCr8B,MAAOo9B,EAAQ/8B,QACfH,IAAK,KACL6Y,QAASqkB,EAAQ9kB,WAIZ+jB,GAKRQ,iBAAkB,SAASrlC,GAC1B,GAAIu8B,GAAU/5B,KAAKuX,KAAKqjB,IAAI,cAEb,OAAXb,GACHv8B,EAAIxB,KAAK,SAASqC,EAAGgzB,GAGpBA,EAAKgS,MAAMtJ,QAAUA,KAWxBmC,kBAAmB,SAASl6B,EAAIshC,GAC/B,GACIhlC,GACAilC,EAFAhsB,EAAOvX,KAAKuX,IAIZA,GAAKqjB,IAAI,eACZt8B,EAAKhD,GAAGgoC,EAAKA,EAAGE,KAAO,OAASxhC,EAAGmX,QAInCoqB,EAAShsB,EAAKqjB,IAAI,eACdt/B,EAAEiP,WAAWg5B,GAAUA,EAAO16B,KAAKvK,EAAG,GAAIA,GAAMA,EAAG2Y,GAAGssB,MACpDvjC,KAAKu/B,oBACTv/B,KAAKyjC,qBAAqBnlC,EAAI0D,EAAIshC,MAQtCG,qBAAsB,SAASnlC,EAAI0D,EAAIshC,GACtC,GAGIjB,GAHA9S,EAAQvvB,KACR6f,EAAW7f,KAAKuX,KAAKsI,SACrB6jB,EAAOxwB,GAAiB5U,GAIxBm+B,EAAelN,EAAMoL,qBAAuB,GAAI7C,IAAgB93B,MACnE08B,iBAAkB,WACjBnN,EAAMgQ,oBAAqB,GAE5B3C,QAAS,SAAS5E,GACjBqK,EAAe9S,EAAMoU,oBACpB3L,EAAIhmB,UAAUqpB,WAAWrD,GACzB0L,GAIArB,IACCxiB,EAAS8J,sBAAsB4F,EAAMoT,YAAYN,GAAeA,EAAcqB,EAAKvwB,cAEpFhW,IACAklC,EAAe,MAGZA,GACH9S,EAAMqT,WAAWP,IAGnBtF,OAAQ,WACPsF,EAAe,MAEhBpF,QAAS,WACR5/B,IACAkyB,EAAMuT,gBAEP5F,eAAgB,SAASl7B,GACpBqgC,GACH9S,EAAMhY,KAAKqsB,mBAAmBF,EAAMrB,EAAc/jC,EAAI0D,EAAIshC,GAE3D/T,EAAMgQ,oBAAqB,EAC3BhQ,EAAMoL,qBAAuB,OAI/B8B,GAAavH,UAAUlzB,IAQxB2hC,oBAAqB,SAASta,EAAMqa,GACnC,GAAI7jB,GAAW7f,KAAKuX,KAAKsI,SACrBwiB,GACHr8B,MAAO6Z,EAAS7D,cAAcqN,EAAKrjB,OACnCE,IAAK,KAYN,OARIw9B,GAAKtwB,YAAcivB,EAAar8B,MAAMsY,WACzC+jB,EAAar8B,MAAMW,KAAK+8B,EAAKtwB,WAG1BswB,EAAKn9B,WACR87B,EAAan8B,IAAMm8B,EAAar8B,MAAMK,QAAQ5G,IAAIikC,EAAKn9B,WAGjD87B,GAcRO,WAAY,SAASP,EAAc1uB,KAMnCmvB,aAAc,aAWdX,uBAAwB,SAASxuB,EAAK9N,GACrC,GAMIstB,GACA0Q,EAPAtU,EAAQvvB,KACRuX,EAAOvX,KAAKuX,KACZsI,EAAWtI,EAAKsI,SAChBvhB,EAAKqV,EAAIrV,GACTgU,EAAQqB,EAAIrB,MACZwY,EAAWjL,EAAShB,YAAYvM,GAKhCmqB,EAAez8B,KAAK06B,kBAAoB,GAAI5C,IAAgB93B,MAC/Dy2B,OAAQlf,EAAKqjB,IAAI,cACjBjI,UAAWr0B,EACXo+B,iBAAkB,WACjBvJ,GAAa,GAEdwJ,UAAW,SAAS36B,GACnBmxB,GAAa,EACb5D,EAAMyQ,kBAAkBrsB,EAAK3R,GAC7ButB,EAAMuU,eAAenwB,EAAK3R,IAE3B46B,QAAS,SAAS5E,EAAKW,EAAQZ,GAC9B,GAAIgM,GAAcxU,EAAM8L,WAAWtD,GAC/BiM,EAAUzU,EAAM8L,WAAWrD,EAE/B6L,GAAiBh+B,EAChB0pB,EAAM0U,wBAAwBF,EAAaC,EAAS1xB,GACpDid,EAAM2U,sBAAsBH,EAAaC,EAAS1xB,GAE/CuxB,IACEhkB,EAASuJ,mBAAmBmG,EAAMoT,YAAYkB,GAAiBvxB,GAK3DuxB,EAAe79B,MAAMiL,OAAOqB,EAAMtM,QAAU69B,EAAe39B,IAAI+K,OAAO6Z,KAC9E+Y,EAAiB,OALjB1mC,IACA0mC,EAAiB,OAQfA,IACHtsB,EAAKirB,UAAUlwB,GACfid,EAAM4U,kBAAkBN,EAAgBlwB,KAG1CopB,OAAQ,WACP8G,EAAiB,MAElB5G,QAAS,WACR1N,EAAM6U,sBACN7sB,EAAKwrB,UAAUzwB,GACfjV,KAED6/B,eAAgB,SAASl7B,GACpBmxB,GACH5D,EAAM8U,cAAc1wB,EAAK3R,GAEtB6hC,GACHtsB,EAAK+sB,kBAAkBhyB,EAAOuxB,EAAgB7jC,KAAKgoB,UAAW1pB,EAAI0D,GAEnEutB,EAAMmL,kBAAoB,OAI5B,OAAO+B,IAKRqH,eAAgB,SAASnwB,EAAK3R,GAC7BhC,KAAKs/B,eAAgB,EACrBt/B,KAAKuX,KAAK6B,QAAQ,mBAAoBzF,EAAIrV,GAAG,GAAIqV,EAAIrB,MAAOtQ,OAK7DqiC,cAAe,SAAS1wB,EAAK3R,GAC5BhC,KAAKs/B,eAAgB,EACrBt/B,KAAKuX,KAAK6B,QAAQ,kBAAmBzF,EAAIrV,GAAG,GAAIqV,EAAIrB,MAAOtQ,OAK5DiiC,wBAAyB,SAASf,EAAWC,EAAS7wB,GACrD,MAAOtS,MAAKukC,mBAAmB,QAASrB,EAAWC,EAAS7wB,IAK7D4xB,sBAAuB,SAAShB,EAAWC,EAAS7wB,GACnD,MAAOtS,MAAKukC,mBAAmB,MAAOrB,EAAWC,EAAS7wB,IAO3DiyB,mBAAoB,SAAS5hC,EAAMugC,EAAWC,EAAS7wB,GACtD,GAEIuxB,GACAW,EAHA3kB,EAAW7f,KAAKuX,KAAKsI,SACrBpE,EAAQzb,KAAKioB,UAAUkb,EAAQxgC,GAAOugC,EAAUvgC,GAoCpD,OA/BAkhC,IACC79B,MAAOsM,EAAMtM,MAAMK,QACnBH,IAAK2Z,EAAShB,YAAYvM,GAC1ByM,OAAQzM,EAAMyM,QAIX8kB,EAAe9kB,QAAUtX,EAAgBgU,KAC5CooB,EAAe9kB,QAAS,EACxBc,EAASyH,oBAAoBuc,IAG9BA,EAAelhC,GAAMlD,IAAIgc,GAGpBooB,EAAe79B,MAAM6hB,SAASgc,EAAe39B,OAEjDs+B,EACCxkC,KAAKu6B,oBACJjoB,EAAMyM,OACNc,EAAS1B,2BACT0B,EAASzB,2BAEC,SAARzb,EACHkhC,EAAe79B,MAAQ69B,EAAe39B,IAAIG,QAAQwiB,SAAS2b,GAG3DX,EAAe39B,IAAM29B,EAAe79B,MAAMK,QAAQ5G,IAAI+kC,IAIjDX,GAORM,kBAAmB,SAASvZ,EAAOjX,KAMnCywB,oBAAqB,aAcrBK,iBAAkB,SAAS7Z,EAAO9b,EAAW41B,GAU5C,MARiB,OAAb51B,IACHA,EAAY9O,KAAKo6B,iBAGA,MAAdsK,IACHA,EAAa1kC,KAAKs6B,iBAGft6B,KAAKq6B,kBAAoBzP,EAAM5kB,MAAMsY,UACpComB,GAAc9Z,EAAM1kB,IAChBlG,KAAKuX,KAAK5H,YAAYib,EAAO9b,GAG7B8b,EAAM5kB,MAAMgJ,OAAOF,GAIrB,IAKR61B,cAAe,SAAShxB,EAAKmuB,EAAaC,GACzC,GAAIxqB,GAAOvX,KAAKuX,KACZjF,EAAQqB,EAAIrB,MACZ0O,GACH,WACArN,EAAI9N,QAAU,WAAa,eAC3B8N,EAAI7N,MAAQ,SAAW,cACtBilB,OACDzY,EAAMsS,UACNtS,EAAMI,OAASJ,EAAMI,OAAOkS,aAe7B,OAZIkd,IACH9gB,EAAQtiB,KAAK,gBAEVqjC,GACH/gB,EAAQtiB,KAAK,gBAIV6Y,EAAKsqB,gBAAgBvvB,IACxB0O,EAAQtiB,KAAK,eAGPsiB,GAKR4f,cAAe,SAASjtB,GACvB,GAAIrB,GAAQqB,EAAIrB,MACZiF,EAAOvX,KAAKuX,KACZ7E,EAASJ,EAAMI,WACfkyB,EAAatyB,EAAMuyB,MACnBC,EAAcpyB,EAAOmyB,MACrBE,EAAcxtB,EAAKqjB,IAAI,aAE3B,QACC+F,mBACCruB,EAAM0yB,iBACNJ,GACAlyB,EAAOsyB,iBACPF,GACAvtB,EAAKqjB,IAAI,yBACTmK,EACDE,eACC3yB,EAAM4yB,aACNN,GACAlyB,EAAOwyB,aACPJ,GACAvtB,EAAKqjB,IAAI,qBACTmK,EACDF,MACCvyB,EAAM6yB,WACNzyB,EAAOyyB,WACP5tB,EAAKqjB,IAAI,oBAWZwK,YAAa,SAAS9yB,GACrB,MAAOtS,MAAK4/B,cAAettB,KAI5BqwB,YAAa,SAASrwB,GACrB,MAAOtS,MAAKqlC,aAAa/yB,GAAO,IAOjC+yB,aAAc,SAAS/yB,GACtB,GAAIsY,GAAQ5qB,KAAKslC,aAAahzB,EAC9B,OAAOtS,MAAKulC,kBAAkB3a,EAAOtY,IAQtCstB,aAAc,SAAS4F,EAAWC,GACjC,GAAIlW,GAAQvvB,KACR6S,EAAaF,GAAgB6yB,GAC7BtxB,IA4BJ,OA1BA5Y,GAAEU,KAAK6W,EAAY,SAAS4S,EAAI7S,GAC/B,GACIvU,GADAqnC,IAGJ,KAAKrnC,EAAI,EAAGA,EAAIuU,EAAO9U,OAAQO,IAC9BqnC,EAAOhnC,KAAK6wB,EAAM+V,aAAa1yB,EAAOvU,IAIvC,IAAIoU,GAAiBG,EAAO,IAG3B,IAFA8yB,EAASnW,EAAMoW,aAAaD,GAEvBrnC,EAAI,EAAGA,EAAIqnC,EAAO5nC,OAAQO,IAC9B6V,EAAKxV,KAAK+L,MAAMyJ,EACfqb,EAAMqW,iBAAiBF,EAAOrnC,GAAIuU,EAAO,GAAI6yB,QAK/C,KAAKpnC,EAAI,EAAGA,EAAIqnC,EAAO5nC,OAAQO,IAC9B6V,EAAKxV,KAAK+L,MAAMyJ,EACfqb,EAAMqW,iBAAiBF,EAAOrnC,GAAIuU,EAAOvU,GAAIonC,MAK1CvxB,GAMRoxB,aAAc,SAAShzB,GACtB,OACCtM,MAAOsM,EAAMtM,MAAMK,QAAQmI,YAC3BtI,KACCoM,EAAMpM,IACLoM,EAAMpM,IAAIG,QAEVrG,KAAKuX,KAAKsI,SAASf,mBACF,MAAhBxM,EAAMyM,OACLzM,EAAMyM,QACLzM,EAAMtM,MAAMsY,UACdhM,EAAMtM,QAEPwI,cAOJo3B,iBAAkB,SAAShb,EAAOtY,EAAOmzB,GACxC,GAEIpnC,GAFAwnC,EAAQ7lC,KAAKulC,kBAAkB3a,EAAOtY,GACtC4B,IAGJ,KAAK7V,EAAI,EAAGA,EAAIwnC,EAAM/nC,OAAQO,IAC7B6V,EAAKxV,KAAK+L,MAAMyJ,EACflU,KAAK8lC,gBAAgBD,EAAMxnC,GAAIiU,EAAOmzB,GAGxC,OAAOvxB,IAMRqxB,kBAAmB,SAAS3a,EAAOtY,GAClC,OAAShX,EAAEmY,UAAWmX,KAMvBkb,gBAAiB,SAASzc,EAAM/W,EAAOmzB,GACtC,GACIpnC,GAAGsV,EADHO,EAAOuxB,EAAeA,EAAapc,GAAQrpB,KAAKo7B,WAAW/R,EAG/D,KAAKhrB,EAAI,EAAGA,EAAI6V,EAAKpW,OAAQO,IAC5BsV,EAAMO,EAAK7V,GACXsV,EAAIrB,MAAQA,EACZqB,EAAIoyB,cAAgB1c,EAAKrjB,MACzB2N,EAAIqyB,gBAAkB3c,EAAKnjB,IAAMmjB,EAAKrjB,KAGvC,OAAOkO,IAMRyxB,aAAc,SAASD,GACtB,GAKIrnC,GAAGusB,EALHrT,EAAOvX,KAAKuX,KACZ0uB,EAAY1uB,EAAKvR,MAAMK,QACvB6/B,EAAU3uB,EAAKrR,IAAIG,QACnB8/B,KACAngC,EAAQigC,CAMZ,KAFAP,EAAOxH,KAAKnrB,IAEP1U,EAAI,EAAGA,EAAIqnC,EAAO5nC,OAAQO,IAC9BusB,EAAQ8a,EAAOrnC,GAGXusB,EAAM5kB,MAAQA,GACjBmgC,EAAcznC,MACbsH,MAAOA,EACPE,IAAK0kB,EAAM5kB,QAIbA,EAAQ4kB,EAAM1kB,GAWf,OAPIF,GAAQkgC,GACXC,EAAcznC,MACbsH,MAAOA,EACPE,IAAKggC,IAIAC,GAIRC,cAAe,SAASlyB,GACvBA,EAAKgqB,KAAKzyB,GAAMzL,KAAM,sBAKvBqmC,iBAAkB,SAASvxB,EAAMC,GAChC,MAAOD,GAAKixB,aAAehxB,EAAKgxB,cAC/BhxB,EAAKixB,gBAAkBlxB,EAAKkxB,iBAC5BjxB,EAAKzC,MAAMyM,OAASjK,EAAKxC,MAAMyM,QAC/Bna,EAAoBkQ,EAAKxC,MAAOyC,EAAKzC,MAAOtS,KAAKuX,KAAK+uB,oBAczD/3B,GAAG8D,UAAYA,GAqCf9D,GAAGgF,eAAiB,EAuDpB,IAAIgzB,IAAgBh4B,GAAGg4B,eAEtBC,cAAc,EACdC,SAAU,KACVC,WAAY,KACZC,WAAY,KACZC,OAAQ,KACRC,OAAQ,KACRC,cAAe,KAIfC,eAAgB,WAUf,IATA,GAKIJ,GACAlpB,EACAmpB,EAPArvB,EAAOvX,KAAKuX,KACZ3I,EAAO5O,KAAKgG,MAAMK,QAClB2gC,KACAN,KACAD,KAKG73B,EAAKiZ,SAAS7nB,KAAKkG,MACrBqR,EAAK0vB,YAAYr4B,GACpB83B,EAAWhoC,KAAKsoC,EAAW,KAG3BA,IACAN,EAAWhoC,KAAKsoC;AAChBP,EAAS/nC,KAAKkQ,EAAKvI,UAEpBuI,EAAKnP,IAAI,EAAG,OAGb,IAAIO,KAAKwmC,aAAc,CAGtB,IADA/oB,EAAWgpB,EAAS,GAAG3e,MAClB6e,EAAa,EAAGA,EAAaF,EAAS3oC,QACtC2oC,EAASE,GAAY7e,OAASrK,EADgBkpB,KAKnDC,EAAShpC,KAAKspC,KAAKT,EAAS3oC,OAAS6oC,OAGrCC,GAAS,EACTD,EAAaF,EAAS3oC,MAGvBkC,MAAKymC,SAAWA,EAChBzmC,KAAK0mC,WAAaA,EAClB1mC,KAAK2mC,WAAaA,EAClB3mC,KAAK4mC,OAASA,EAEd5mC,KAAKmnC,sBAKNA,mBAAoB,WACnBnnC,KAAK6mC,OAAS7mC,KAAKonC,gBACnBpnC,KAAK8mC,cAAgB9mC,KAAKuX,KAAKqjB,IAAI,iBAAmB56B,KAAKqnC,wBAK5DD,cAAe,WACd,MAAOpnC,MAAK2mC,YAKbW,YAAa,SAASC,EAAKC,GAC1B,MAAOxnC,MAAKymC,SACVzmC,KAAKynC,gBAAgBF,EAAKC,IACzBnhC,SAKJqhC,aAAc,SAASH,EAAKC,GAC3B,GAAIxhC,GAAQhG,KAAKsnC,YAAYC,EAAKC,GAC9BthC,EAAMF,EAAMK,QAAQ5G,IAAI,EAAG,OAE/B,QAASuG,MAAOA,EAAOE,IAAKA,IAK7BuhC,gBAAiB,SAASF,EAAKC,GAC9B,MAAOD,GAAMvnC,KAAK2mC,WAAa3mC,KAAK2nC,eAAeH,IAKpDG,eAAgB,SAASH,GACxB,MAAIxnC,MAAK+P,MACD/P,KAAK6mC,OAAS,EAAIW,EAGlBA,GAUTI,gBAAiB,SAASh5B,GACzB,GAAI83B,GAAa1mC,KAAK0mC,WAClBmB,EAAYj5B,EAAKrP,KAAKS,KAAKgG,MAAO,OAEtC,OAAI6hC,GAAY,EACRnB,EAAW,GAAK,EAEfmB,GAAanB,EAAW5oC,OACzB4oC,EAAWA,EAAW5oC,OAAS,GAAK,EAGpC4oC,EAAWmB,IAUpBR,qBAAsB,WAGrB,MAAIrnC,MAAK4mC,OAAS,GAAK5mC,KAAK6mC,OAAS,GAC7B,MAGC7mC,KAAK6mC,OAAS,EACf7mC,KAAKuX,KAAKqjB,IAAI,oBAId,QAUTkN,gBAAiB,SAASld,GACzB,GAKI2c,GACAQ,EAAUC,EACVC,EAAUC,EAPVvB,EAAa3mC,KAAK2mC,WAClBwB,EAAcnoC,KAAKuX,KAAK6wB,gBAAgBxd,GACxCyd,EAAaroC,KAAK4nC,gBAAgBO,EAAYniC,OAC9CsiC,EAAYtoC,KAAK4nC,gBAAgBO,EAAYjiC,IAAIG,QAAQwiB,SAAS,EAAG,SACrE3U,IAKJ,KAAKqzB,EAAM,EAAGA,EAAMvnC,KAAK4mC,OAAQW,IAChCQ,EAAWR,EAAMZ,EACjBqB,EAAUD,EAAWpB,EAAa,EAGlCsB,EAAWrqC,KAAK4F,IAAI6kC,EAAYN,GAChCG,EAAUtqC,KAAK6F,IAAI6kC,EAAWN,GAG9BC,EAAWrqC,KAAKspC,KAAKe,GACrBC,EAAUtqC,KAAKC,MAAMqqC,GAEjBD,GAAYC,GACfh0B,EAAKxV,MACJ6oC,IAAKA,EAGLgB,iBAAkBN,EAAWF,EAC7BS,gBAAiBN,EAAUH,EAG3BliC,QAASoiC,IAAaI,EACtBviC,MAAOoiC,IAAYI,GAKtB,OAAOp0B,IAMRu0B,gBAAiB,SAAS7d,GACzB,GAKI2c,GACAQ,EAAUC,EACV3pC,EACA4pC,EAAUC,EARVvB,EAAa3mC,KAAK2mC,WAClBwB,EAAcnoC,KAAKuX,KAAK6wB,gBAAgBxd,GACxCyd,EAAaroC,KAAK4nC,gBAAgBO,EAAYniC,OAC9CsiC,EAAYtoC,KAAK4nC,gBAAgBO,EAAYjiC,IAAIG,QAAQwiB,SAAS,EAAG,SACrE3U,IAMJ,KAAKqzB,EAAM,EAAGA,EAAMvnC,KAAK4mC,OAAQW,IAIhC,IAHAQ,EAAWR,EAAMZ,EACjBqB,EAAUD,EAAWpB,EAAa,EAE7BtoC,EAAI0pC,EAAU1pC,GAAK2pC,EAAS3pC,IAGhC4pC,EAAWrqC,KAAK4F,IAAI6kC,EAAYhqC,GAChC6pC,EAAUtqC,KAAK6F,IAAI6kC,EAAWjqC,GAG9B4pC,EAAWrqC,KAAKspC,KAAKe,GACrBC,EAAUtqC,KAAKC,MAAMqqC,GAEjBD,GAAYC,GACfh0B,EAAKxV,MACJ6oC,IAAKA,EAGLgB,iBAAkBN,EAAWF,EAC7BS,gBAAiBN,EAAUH,EAG3BliC,QAASoiC,IAAaI,EACtBviC,MAAOoiC,IAAYI,GAMvB,OAAOp0B,IAQRw0B,eAAgB,WACf,GAAInxB,GAAOvX,KAAKuX,IAEhB,OAAO,sBACkBA,EAAKoxB,kBAAoB,mBAG9C3oC,KAAK4oC,mBACN,0BAMJC,oBAAqB,WACpB,MAAO7oC,MAAK8oC,mBAIbF,iBAAkB,WACjB,MAAO,QAEJ5oC,KAAK+P,MAAQ,GAAK/P,KAAK6oC,uBACxB7oC,KAAK+oC,2BACJ/oC,KAAK+P,MAAQ/P,KAAK6oC,sBAAwB,IAC5C,SAIFE,wBAAyB,WACxB,GACIvB,GAAK54B,EADLo6B,IAGJ,KAAKxB,EAAM,EAAGA,EAAMxnC,KAAK6mC,OAAQW,IAChC54B,EAAO5O,KAAKsnC,YAAY,EAAGE,GAC3BwB,EAAMtqC,KAAKsB,KAAKipC,uBAAuBr6B,GAGxC,OAAOo6B,GAAM59B,KAAK,KAMnB69B,uBAAwB,SAASr6B,EAAMs6B,EAASC,GAC/C,GAAI5xB,GAAOvX,KAAKuX,IAEhB,OAAO,4BACwBA,EAAKoxB,kBAAoB,OAASjd,GAAO9c,EAAKkZ,OAAS,KACpE,GAAf9nB,KAAK4mC,OACL,eAAiBh4B,EAAKI,OAAO,cAAgB,IAC7C,KACAk6B,EAAU,EACV,aAAeA,EAAU,IACzB,KACAC,EACA,IAAMA,EACN,IACF,IACCv+B,GAAWgE,EAAKI,OAAOhP,KAAK8mC,gBAC7B,SAQFsC,eAAgB,SAAS7B,GACxB,MAAO,QAEJvnC,KAAK+P,MAAQ,GAAK/P,KAAKqpC,kBAAkB9B,IAC1CvnC,KAAKspC,kBAAkB/B,IACtBvnC,KAAK+P,MAAQ/P,KAAKqpC,kBAAkB9B,GAAO,IAC7C,SAIF8B,kBAAmB,SAAS9B,GAC3B,MAAOvnC,MAAK8oC,mBAIbQ,kBAAmB,SAAS/B,GAC3B,GACIC,GAAK54B,EADLo6B,IAGJ,KAAKxB,EAAM,EAAGA,EAAMxnC,KAAK6mC,OAAQW,IAChC54B,EAAO5O,KAAKsnC,YAAYC,EAAKC,GAC7BwB,EAAMtqC,KAAKsB,KAAKupC,iBAAiB36B,GAGlC,OAAOo6B,GAAM59B,KAAK,KAInBm+B,iBAAkB,SAAS36B,EAAMu6B,GAChC,GAAI5xB,GAAOvX,KAAKuX,KACZyJ,EAAUhhB,KAAKi/B,cAAcrwB,EAIjC,OAFAoS,GAAQzX,QAAQ,SAAUgO,EAAKiyB,oBAExB,cAAgBxoB,EAAQ5V,KAAK,KAAO,gBACzBwD,EAAKI,OAAO,cAAgB,KAC5Cm6B,EACA,IAAMA,EACN,IACD,UASFL,gBAAiB,aAejBW,aAAc,SAASC,GACtB,GAAIC,GAAY3pC,KAAK8oC,iBAEjBa,KACC3pC,KAAK+P,MACR25B,EAAK1pB,OAAO2pB,GAGZD,EAAK9yB,QAAQ+yB,MAYbC,GAAUr7B,GAAGq7B,QAAU1P,GAAKzmB,OAAO8yB,IAEtCsD,gBAAgB,EAChBC,mBAAoB,EAEpBrtC,OAAQ,KACRstC,QAAS,KACTC,UAAW,KAEXC,cAAe,KACfC,cAAe,KAMfnO,YAAa,SAASoO,GACrB,GAII5C,GACAC,EALAjwB,EAAOvX,KAAKuX,KACZqvB,EAAS5mC,KAAK4mC,OACdC,EAAS7mC,KAAK6mC,OACdlI,EAAO,EAIX,KAAK4I,EAAM,EAAGA,EAAMX,EAAQW,IAC3B5I,GAAQ3+B,KAAKoqC,iBAAiB7C,EAAK4C,EAiBpC,KAfAnqC,KAAK1B,GAAGqgC,KAAKA,GAEb3+B,KAAKvD,OAASuD,KAAK1B,GAAGU,KAAK,WAC3BgB,KAAK+pC,QAAU/pC,KAAK1B,GAAGU,KAAK,WAE5BgB,KAAKiqC,cAAgB,GAAI5Z,KACxB7yB,IAAKwC,KAAKvD,OACVg0B,YAAY,IAEbzwB,KAAKkqC,cAAgB,GAAI7Z,KACxB7yB,IAAKwC,KAAK+pC,QAAQx+B,MAAM,EAAGvL,KAAK6mC,QAChCrW,cAAc,IAIV+W,EAAM,EAAGA,EAAMX,EAAQW,IAC3B,IAAKC,EAAM,EAAGA,EAAMX,EAAQW,IAC3BjwB,EAAK6B,QACJ,YACA,KACApZ,KAAKsnC,YAAYC,EAAKC,GACtBxnC,KAAKqqC,UAAU9C,EAAKC,KAOxBxL,cAAe,WACdh8B,KAAKsqC,oBAINxtB,oBAAqB,WACpB,GAAI5I,GAAOlU,KAAK8gC,uBAAsB,EACtC9gC,MAAKm+B,WAAW,gBAAiBjqB,EAAM,YAIxC2I,sBAAuB,WACtB7c,KAAKo+B,aAAa,kBAMnBgM,iBAAkB,SAAS7C,EAAK4C,GAC/B,GAAI5yB,GAAOvX,KAAKuX,KACZyJ,GAAY,SAAU,UAAWzJ,EAAKiyB,mBAM1C,OAJIW,IACHnpB,EAAQtiB,KAAK,YAGP,eACWsiB,EAAQ5V,KAAK,KAAO,+BAGlCpL,KAAKopC,eAAe7B,GACrB,0DAIEvnC,KAAK6pC,eACL,UACC7pC,KAAKuqC,mBAAmBhD,GACzB,WACA,IAEF,wBAUJgD,mBAAoB,SAAShD,GAC5B,MAAO,QAEJvnC,KAAK+P,MAAQ,GAAK/P,KAAKwqC,sBAAsBjD,IAC9CvnC,KAAKyqC,sBAAsBlD,IAC1BvnC,KAAK+P,MAAQ/P,KAAKwqC,sBAAsBjD,GAAO,IACjD,SAIFiD,sBAAuB,SAASjD,GAC/B,MAAOvnC,MAAK8oC,mBAIb2B,sBAAuB,SAASlD,GAC/B,GACIC,GAAK54B,EADLo6B,IAGJ,KAAKxB,EAAM,EAAGA,EAAMxnC,KAAK6mC,OAAQW,IAChC54B,EAAO5O,KAAKsnC,YAAYC,EAAKC,GAC7BwB,EAAMtqC,KAAKsB,KAAK0qC,qBAAqB97B,GAGtC,OAAOo6B,GAAM59B,KAAK,KAMnBs/B,qBAAsB,SAAS97B,GAC9B,GAAIoS,EAEJ,OAAKhhB,MAAKuX,KAAKozB,mBAIf3pB,EAAUhhB,KAAKi/B,cAAcrwB,GAC7BoS,EAAQzX,QAAQ,iBAET,cACUyX,EAAQ5V,KAAK,KAAO,gBAAkBwD,EAAKI,SAAW,KACrEJ,EAAKA,OACN,SATO,SAkBTksB,uBAAwB,WACvB,MAAO96B,MAAKuX,KAAKqjB,IAAI,yBAKtBI,uBAAwB,WACvB,MAAsB,IAAfh7B,KAAK6mC,QAQb3L,aAAc,WACbl7B,KAAK+mC,kBAKN3L,WAAY,SAAS/R,GACpB,GACIhrB,GAAGsV,EADHO,EAAOlU,KAAK8nC,gBAAgBze,EAGhC,KAAKhrB,EAAI,EAAGA,EAAI6V,EAAKpW,OAAQO,IAC5BsV,EAAMO,EAAK7V,GACP2B,KAAK+P,OACR4D,EAAIG,QAAU9T,KAAK2mC,WAAa,EAAIhzB,EAAI60B,gBACxC70B,EAAII,SAAW/T,KAAK2mC,WAAa,EAAIhzB,EAAI40B,mBAGzC50B,EAAIG,QAAUH,EAAI40B,iBAClB50B,EAAII,SAAWJ,EAAI60B,gBAIrB,OAAOt0B,IAQRqkB,YAAa,WACZv4B,KAAKkqC,cAAcpZ,QACnB9wB,KAAKiqC,cAAcnZ,QACnB9wB,KAAKiqC,cAAcpZ,QAAQ7wB,KAAK4mC,OAAS,IAAM5mC,KAAK8pC,oBAIrDlR,YAAa,WACZ54B,KAAKkqC,cAAc/Y,QACnBnxB,KAAKiqC,cAAc9Y,SAIpBkH,SAAU,SAAS9G,EAAYE,GAC9B,GAAIzxB,KAAKkqC,cAAc1X,eAAejB,IAAevxB,KAAKiqC,cAAcxX,cAAchB,GAAY,CACjG,GAAI+V,GAAMxnC,KAAKkqC,cAAc5Y,mBAAmBC,GAC5CgW,EAAMvnC,KAAKiqC,cAAczY,iBAAiBC,EAE9C,IAAW,MAAP8V,GAAsB,MAAPC,EAClB,MAAOxnC,MAAK4qC,WAAWrD,EAAKC,KAM/BnM,WAAY,SAASrD,GACpB,MAAOh4B,MAAK0nC,aAAa1P,EAAIuP,IAAKvP,EAAIwP,MAIvClM,SAAU,SAAStD,GAClB,MAAOh4B,MAAKqqC,UAAUrS,EAAIuP,IAAKvP,EAAIwP,MASpCoD,WAAY,SAASrD,EAAKC,GACzB,OACCD,IAAKA,EACLC,IAAKA,EACLx1B,UAAWhS,KACXrD,KAAMqD,KAAKkqC,cAAcxY,cAAc8V,GACvCzqC,MAAOiD,KAAKkqC,cAAcrY,eAAe2V,GACzCjnC,IAAKP,KAAKiqC,cAAcjY,aAAauV,GACrC/mC,OAAQR,KAAKiqC,cAAc9X,gBAAgBoV,KAK7C8C,UAAW,SAAS9C,EAAKC,GACxB,MAAOxnC,MAAK+pC,QAAQ9pC,GAAGsnC,EAAMvnC,KAAK6mC,OAASW,IAW5C5E,WAAY,SAAS/Y,EAAelW,GAMnC,GAHA3T,KAAK49B,gBAAgB59B,KAAK2iC,YAAY9Y,IAGlClW,GAAOA,EAAI3B,YAAchS,KAC5B,MAAOA,MAAKq9B,0BAA0BxT,EAAelW,IAMvDmvB,aAAc,WACb9iC,KAAK69B,oBACL79B,KAAK29B,kBASNwG,kBAAmB,SAASta,EAAelW,GAE1C,MADA3T,MAAK49B,gBAAgB59B,KAAK2iC,YAAY9Y,IAC/B7pB,KAAKq9B,0BAA0BxT,EAAelW,IAKtDywB,oBAAqB,WACpBpkC,KAAK69B,oBACL79B,KAAK29B,kBASNF,aAAc,SAASnrB,EAAOgrB,GAC7B,GAEIuN,GAFAC,KACA52B,EAAOlU,KAAKolC,YAAY9yB,EA4B5B,OAzBA4B,GAAOlU,KAAKogC,eAAelsB,GAC3B22B,EAAa7qC,KAAK+qC,cAAc72B,GAGhClU,KAAKvD,OAAOT,KAAK,SAASurC,EAAKyD,GAC9B,GAEIC,GAFAC,EAAQ5vC,EAAE0vC,GACVG,EAAa7vC,EAAE,iDAKlB2vC,GADG3N,GAAaA,EAAUiK,MAAQA,EACpBjK,EAAUh/B,GAAGoB,WAAWa,IAGxB2qC,EAAMlsC,KAAK,8BAA8BU,WAAWa,IAGnE4qC,EAAWvuC,IAAI,MAAOquC,GACpBjsC,KAAK,SACJghB,OAAO6qB,EAAWtD,GAAK6D,SAE1BF,EAAMlrB,OAAOmrB,GACbL,EAAYpsC,KAAKysC,EAAW,MAI5BnrC,KAAKgqC,UAAY1uC,EAAEwvC,IAMrBnN,eAAgB,WACX39B,KAAKgqC,YACRhqC,KAAKgqC,UAAUpoC,SACf5B,KAAKgqC,UAAY,OASnBlL,WAAY,KAKZX,WAAY,SAASx7B,EAAMuR,EAAM0Q,GAChC,GACIvmB,GAAGsV,EACHw3B,EAFAE,IAMJ,KAFAn3B,EAAOlU,KAAKy+B,iBAAiB97B,EAAMuR,GAE9B7V,EAAI,EAAGA,EAAI6V,EAAKpW,OAAQO,IAC5BsV,EAAMO,EAAK7V,GACX8sC,EAAanrC,KAAKsrC,cAAc3oC,EAAMgR,EAAKiR,GAC3C5kB,KAAKvD,OAAOwD,GAAG0T,EAAI4zB,KAAKvnB,OAAOmrB,GAC/BE,EAAM3sC,KAAKysC,EAAW,GAKvB,OAFAnrC,MAAKm6B,UAAUx3B,GAAQrH,EAAE+vC,GAElBn3B,GAKRo3B,cAAe,SAAS3oC,EAAMgR,EAAKiR,GAClC,GAGIumB,GACAzB,EAJA7C,EAAS7mC,KAAK6mC,OACd0E,EAAW53B,EAAIG,QACf03B,EAAS73B,EAAII,SAAW,CA2B5B,OAvBA6Q,GAAYA,GAAajiB,EAAK8oC,cAE9BN,EAAa7vC,EACZ,kBAAoBspB,EAAY,yCAIjC8kB,EAAOyB,EAAWnsC,KAAK,MAEnBusC,EAAW,GACd7B,EAAK1pB,OAAO,gBAAkBurB,EAAW,OAG1C7B,EAAK1pB,OACJrM,EAAIrV,GAAGy3B,KAAK,UAAWyV,EAASD,IAG7BC,EAAS3E,GACZ6C,EAAK1pB,OAAO,iBAAmB6mB,EAAS2E,GAAU,OAGnDxrC,KAAKypC,aAAaC,GAEXyB,IAUTvB,IAAQjc,OAEPkd,WAAY,KAIZ9K,eAAgB,WACf//B,KAAKsqC,mBACLpQ,GAAKvxB,UAAUo3B,eAAet1B,MAAMzK,KAAM2K,YAK3Cw1B,aAAc,WACb,MAAOjG,IAAKvxB,UAAUw3B,aAAat3B,KAAK7I,MACtC+qB,OAAO/qB,KAAK0rC,kBAKf7L,aAAc,SAAS3rB,GAGtB,GAAIy3B,GAAarwC,EAAEgqB,KAAKpR,EAAM,SAASP,GACtC,MAAOA,GAAIrB,MAAMyM,QAGlB,OAAOmb,IAAKvxB,UAAUk3B,aAAah3B,KAAK7I,KAAM2rC,IAK/C7L,aAAc,SAAS5rB,GACtB,GAAI22B,EAeJ,OAXA32B,GAAOlU,KAAKogC,eAAelsB,GAE3B22B,EAAa7qC,KAAK6qC,WAAa7qC,KAAK+qC,cAAc72B,GAGlDlU,KAAKvD,OAAOT,KAAK,SAASqC,EAAG2sC,GAC5B1vC,EAAE0vC,GAAShsC,KAAK,gCAAgCghB,OAC/C6qB,EAAWxsC,GAAG+sC,WAITl3B,GAKR+rB,eAAgB,WAIf,IAHA,GACI2L,GADAf,EAAa7qC,KAAK6qC,eAGde,EAAYf,EAAWgB,OAC9BD,EAAUR,QAAQxpC,QAGnB5B,MAAK6qC,WAAa,MAOnBE,cAAe,SAAS72B,GACvB,GACI43B,GACAvE,EAFAsD,IAOJ,KAHAiB,EAAU9rC,KAAK+rC,aAAa73B,GAGvBqzB,EAAM,EAAGA,EAAMuE,EAAQhuC,OAAQypC,IACnCsD,EAAWnsC,KACVsB,KAAKgsC,aAAazE,EAAKuE,EAAQvE,IAIjC,OAAOsD,IAKRvK,UAAW,SAAS3sB,EAAK0sB,GACxB,GAUI4L,GACAC,EAXA30B,EAAOvX,KAAKuX,KACZjF,EAAQqB,EAAIrB,MACZwvB,EAAcvqB,EAAKoqB,iBAAiBrvB,GACpC65B,GAAwB9L,GAAmB/tB,EAAMyM,QACpDpL,EAAI9N,SAAW0R,EAAK60B,0BAA0B95B,GAC3C+5B,GAAsBhM,GAAmB/tB,EAAMyM,QAClDpL,EAAI7N,OAASyR,EAAK+0B,wBAAwBh6B,GACvC0O,EAAUhhB,KAAK2kC,cAAchxB,EAAKmuB,EAAaqK,GAAwBE,GACvEE,EAAUthC,GAASjL,KAAK4gC,cAAcjtB,IACtC64B,EAAW,EAmBf,OAfAxrB,GAAQzX,QAAQ,oBAAqB,cAGjCoK,EAAI9N,UACPomC,EAAWjsC,KAAKykC,iBAAiBnyB,GAC7B25B,IACHO,EAAW,yBAA2B5hC,GAAWqhC,GAAY,YAI/DC,EACC,2BACEthC,GAAW0H,EAAM+H,OAAS,KAAO,UACnC,UAEM,aAAe2G,EAAQ5V,KAAK,KAAO,KACvCkH,EAAMuR,IACN,UAAYjZ,GAAW0H,EAAMuR,KAAO,IACpC,KAEA0oB,EACA,WAAaA,EAAU,IACvB,IAEF,6BAEGvsC,KAAK+P,MACLm8B,EAAY,IAAMM,EAClBA,EAAW,IAAMN,GAEnB,UACCC,EACA,8CACA,KAEAE,EACA,4CACA,IAEF,QAOFL,aAAc,SAASzE,EAAKkF,GAe3B,QAASC,GAAgBlB,GACxB,KAAOhE,EAAMgE,GAEZmB,GAAMC,EAAevuC,EAAI,QAAUmpC,GAC/BmF,EACHA,EAAG5W,KACF,UACA8W,SAASF,EAAG5W,KAAK,YAAc,EAAG,IAAM,IAIzC4W,EAAKrxC,EAAE,SACPwxC,EAAG9sB,OAAO2sB,IAEXI,EAAW1uC,GAAGmpC,GAAOmF,EACrBC,EAAevuC,GAAGmpC,GAAOmF,EACzBnF,IA9BF,GAOInpC,GAAG2uC,EACHxF,EACAsF,EACA1jC,EAAGuK,EACHg5B,EAXA9F,EAAS7mC,KAAK6mC,OACdoG,EAAYjtC,KAAKktC,eAAeT,GAChCU,EAAWvvC,KAAK4F,IAAI,EAAGypC,EAAUnvC,QACjCsvC,EAAQ9xC,EAAE,YACV+xC,KACAN,KACAH,IA4BJ,KAAKvuC,EAAI,EAAGA,EAAI8uC,EAAU9uC,IAAK,CAW9B,GAVA2uC,EAAYC,EAAU5uC,GACtBmpC,EAAM,EACNsF,EAAKxxC,EAAE,SAEP+xC,EAAU3uC,SACVquC,EAAWruC,SACXkuC,EAAeluC,SAIXsuC,EACH,IAAK5jC,EAAI,EAAGA,EAAI4jC,EAAUlvC,OAAQsL,IAAK,CActC,IAbAuK,EAAMq5B,EAAU5jC,GAEhBsjC,EAAgB/4B,EAAIG,SAGpB64B,EAAKrxC,EAAE,oCAAoC0kB,OAAOrM,EAAIrV,IAClDqV,EAAIG,SAAWH,EAAII,SACtB44B,EAAG5W,KAAK,UAAWpiB,EAAII,SAAWJ,EAAIG,QAAU,GAGhD84B,EAAevuC,GAAGmpC,GAAOmF,EAGnBnF,GAAO7zB,EAAII,UACjBg5B,EAAW1uC,GAAGmpC,GAAOmF,EACrBU,EAAUhvC,GAAGmpC,GAAO7zB,EACpB6zB,GAGDsF,GAAG9sB,OAAO2sB,GAIZD,EAAgB7F,GAChB7mC,KAAKypC,aAAaqD,GAClBM,EAAMptB,OAAO8sB,GAGd,OACCvF,IAAKA,EACL6D,QAASgC,EACTL,WAAYA,EACZM,UAAWA,EACXJ,UAAWA,EACX/4B,KAAMu4B,IAORS,eAAgB,SAASh5B,GACxB,GACI7V,GAAGsV,EACHvK,EAFA+K,IAQJ,KAFAnU,KAAKomC,cAAclyB,GAEd7V,EAAI,EAAGA,EAAI6V,EAAKpW,OAAQO,IAAK,CAIjC,IAHAsV,EAAMO,EAAK7V,GAGN+K,EAAI,EAAGA,EAAI+K,EAAOrW,QACjB4V,GAAkBC,EAAKQ,EAAO/K,IADLA,KAM/BuK,EAAIU,MAAQjL,GAGX+K,EAAO/K,KAAO+K,EAAO/K,QAAU1K,KAAKiV,GAItC,IAAKvK,EAAI,EAAGA,EAAI+K,EAAOrW,OAAQsL,IAC9B+K,EAAO/K,GAAG80B,KAAKlqB,GAGhB,OAAOG,IAKR43B,aAAc,SAAS73B,GACtB,GACI7V,GADAytC,IAGJ,KAAKztC,EAAI,EAAGA,EAAI2B,KAAK4mC,OAAQvoC,IAC5BytC,EAAQptC,QAGT,KAAKL,EAAI,EAAGA,EAAI6V,EAAKpW,OAAQO,IAC5BytC,EAAQ53B,EAAK7V,GAAGkpC,KAAK7oC,KAAKwV,EAAK7V,GAGhC,OAAOytC,MAoCTlC,GAAQjc,OAEP2f,WAAY,KACZ5B,YAAa,KAGbpB,iBAAkB,WACbtqC,KAAKstC,YACRttC,KAAKstC,WAAWhe,QAOlBie,UAAW,SAASC,GACnB,GACIjG,GACAkG,EAFA5C,EAAa7qC,KAAK6qC,cAItB,KAAKtD,EAAM,EAAGA,EAAMsD,EAAW/sC,OAAQypC,IACtCvnC,KAAK0tC,WAAWnG,GAMfkG,IAJID,IAG0B,gBAAfA,GACCA,EAGAxtC,KAAK2tC,qBAAqBpG,IAGvCkG,KAAkB,GACrBztC,KAAK4tC,SAASrG,EAAKkG,IAStBE,qBAAsB,SAASpG,GAO9B,QAASsG,GAAiBxvC,EAAGyvC,GAC5BC,EAAWnwC,KAAK4F,IAAIuqC,EAAUzyC,EAAEwyC,GAAWrvC,eAP5C,GAGIJ,GAAGqrC,EACHqE,EAJA7C,EAAQlrC,KAAKvD,OAAOwD,GAAGsnC,GACvByG,EAAY9C,EAAMvsC,SAClBsvC,EAAQjuC,KAAK6qC,WAAWtD,GAAK6D,QAAQ1pC,UASzC,KAAKrD,EAAI,EAAGA,EAAI4vC,EAAMnwC,OAAQO,IAQ7B,GAPAqrC,EAAOuE,EAAMhuC,GAAG5B,GAAGf,YAAY,cAI/BywC,EAAW,EACXrE,EAAK1qC,KAAK,uBAAuBhD,KAAK6xC,GAElCnE,EAAKhqC,WAAWa,IAAMwtC,EAAWC,EACpC,MAAO3vC,EAIT,QAAO,GAORuvC,SAAU,SAASrG,EAAKiG,GAkBvB,QAASd,GAAgBlB,GACxB,KAAOhE,EAAMgE,GACZ0C,EAAY3e,EAAM4e,YAAY5G,EAAKC,EAAKgG,GACpCU,EAAUpwC,SACb6uC,EAAKI,EAAWS,EAAa,GAAGhG,GAChC4G,EAAW7e,EAAM8e,eAAe9G,EAAKC,EAAK0G,GAC1CI,EAAWhzC,EAAE,UAAU0kB,OAAOouB,GAC9BzB,EAAG3sB,OAAOsuB,GACVC,EAAU7vC,KAAK4vC,EAAS,KAEzB9G,IA3BF,GAIIwF,GACAD,EACAyB,EACAnwC,EAAGsV,EACHu6B,EACAO,EACAC,EACA/B,EAAIgC,EACJC,EACAxlC,EACAylC,EAAQP,EAAUF,EAdlB7e,EAAQvvB,KACR4rC,EAAY5rC,KAAK6qC,WAAWtD,GAC5BgH,KACA/G,EAAM,CA4BV,IAAIgG,GAAcA,EAAa5B,EAAUqB,UAAUnvC,OAAQ,CAQ1D,IAPAkvC,EAAYpB,EAAUqB,UAAUO,EAAa,GAC7CT,EAAanB,EAAUmB,WAEvByB,EAAe5C,EAAUR,QAAQ1pC,WAAW6J,MAAMiiC,GAChDpwC,SAAS,cAAc0xC,MAGpBzwC,EAAI,EAAGA,EAAI2uC,EAAUlvC,OAAQO,IAAK,CAOtC,IANAsV,EAAMq5B,EAAU3uC,GAChBquC,EAAgB/4B,EAAIG,SAGpB46B,KACAD,EAAiB,EACVjH,GAAO7zB,EAAII,UACjBm6B,EAAYluC,KAAKmuC,YAAY5G,EAAKC,EAAKgG,GACvCkB,EAAahwC,KAAKwvC,GAClBO,GAAkBP,EAAUpwC,OAC5B0pC,GAGD,IAAIiH,EAAgB,CAMnB,IALA9B,EAAKI,EAAWS,EAAa,GAAG75B,EAAIG,SACpC66B,EAAUhC,EAAG5W,KAAK,YAAc,EAChC6Y,KAGKxlC,EAAI,EAAGA,EAAIslC,EAAa5wC,OAAQsL,IACpCylC,EAASvzC,EAAE,8BAA8By6B,KAAK,UAAW4Y,GACzDT,EAAYQ,EAAatlC,GACzBglC,EAAWpuC,KAAKquC,eACf9G,EACA5zB,EAAIG,QAAU1K,GACZuK,GAAMoX,OAAOmjB,IAEhBI,EAAWhzC,EAAE,UAAU0kB,OAAOouB,GAC9BS,EAAO7uB,OAAOsuB,GACdM,EAAalwC,KAAKmwC,EAAO,IACzBN,EAAU7vC,KAAKmwC,EAAO,GAGvBlC,GAAGvvC,SAAS,cAAc2xC,MAAMzzC,EAAEszC,IAClCJ,EAAa9vC,KAAKiuC,EAAG,KAIvBD,EAAgB1sC,KAAK6mC,QACrB+E,EAAUoD,QAAU1zC,EAAEizC,GACtB3C,EAAUqD,WAAa3zC,EAAEkzC,KAO3Bd,WAAY,SAASnG,GACpB,GAAIqE,GAAY5rC,KAAK6qC,WAAWtD,EAE5BqE,GAAUoD,UACbpD,EAAUoD,QAAQptC,SAClBgqC,EAAUoD,QAAU,MAGjBpD,EAAUqD,aACbrD,EAAUqD,WAAW3xC,YAAY,cACjCsuC,EAAUqD,WAAa,OAOzBZ,eAAgB,SAAS9G,EAAKC,EAAK0H,GAClC,GAAI3f,GAAQvvB,KACRuX,EAAOvX,KAAKuX,IAEhB,OAAOjc,GAAE,wBACP0P,KACAhL,KAAKmvC,gBAAgBD,EAAWpxC,SAEhC+E,GAAG,QAAS,SAASb,GACrB,GAAIotC,GAAc73B,EAAKqjB,IAAI,mBACvBhsB,EAAO2gB,EAAM+X,YAAYC,EAAKC,GAC9B6H,EAAS/zC,EAAE0E,MACXsvC,EAAQ/f,EAAM8a,UAAU9C,EAAKC,GAC7B+H,EAAUhgB,EAAM4e,YAAY5G,EAAKC,GAGjCgI,EAAkBjgB,EAAMkgB,eAAeF,EAAS3gC,GAChD8gC,EAAqBngB,EAAMkgB,eAAeP,EAAYtgC,EAE/B,mBAAhBwgC,KAEVA,EAAc73B,EAAK6B,QAAQ,kBAAmB,MAC7CxK,KAAMA,EACN0gC,MAAOA,EACPD,OAAQA,EACRn7B,KAAMs7B,EACNN,WAAYQ,GACV1tC,IAGgB,YAAhBotC,EACH7f,EAAMogB,eAAepI,EAAKC,EAAK6H,EAAQG,GAER,gBAAhBJ,IACf73B,EAAKsI,SAASnE,OAAO9M,EAAMwgC,MAO/BO,eAAgB,SAASpI,EAAKC,EAAK4G,EAAUl6B,GAC5C,GAGI07B,GACAv5B,EAJAkZ,EAAQvvB,KACRuX,EAAOvX,KAAKuX,KACZ+2B,EAAWF,EAASruC,QAKvB6vC,GADkB,GAAf5vC,KAAK4mC,OACArvB,EAAKjZ,GAGL0B,KAAKvD,OAAOwD,GAAGsnC,GAGxBlxB,GACCuO,UAAW,kBACXtP,QAAStV,KAAK6vC,wBAAwBtI,EAAKC,EAAKtzB,GAChDsb,SAAUxvB,KAAKuX,KAAKjZ,GACpBiC,IAAKqvC,EAAMtvC,SAASC,IACpBkvB,UAAU,EACVW,kBAAmB7Y,EAAKqjB,IAAI,4BAC5BtL,KAAM,WAELC,EAAM+d,WAAWv2B,gBACjBwY,EAAM+d,WAAa,KACnB/d,EAAMmc,YAAc,OAMlB1rC,KAAK+P,MACRsG,EAAQtZ,MAAQuxC,EAAShuC,SAAS3D,KAAO2xC,EAASnvC,aAAe,EAGjEkX,EAAQ1Z,KAAO2xC,EAAShuC,SAAS3D,KAAO,EAGzCqD,KAAKstC,WAAa,GAAIpe,IAAQ7Y,GAC9BrW,KAAKstC,WAAWje,OAIhBrvB,KAAKkhC,oBAAoBlhC,KAAKstC,WAAWhvC,KAK1CuxC,wBAAyB,SAAStI,EAAKC,EAAKtzB,GAC3C,GAkBI7V,GAlBAkZ,EAAOvX,KAAKuX,KACZu4B,EAAUv4B,EAAKqjB,IAAI,SACnBvgB,EAAQra,KAAKsnC,YAAYC,EAAKC,GAAKx4B,OAAOuI,EAAKqjB,IAAI,qBACnDtlB,EAAUha,EACb,yBAA2Bic,EAAKoxB,kBAAoB,4BAEjDmH,EAAU,6BAA+B,qBAC3C,mCAECllC,GAAWyP,GACZ,2DAGwB9C,EAAKiyB,mBAAqB,kDAIhDuG,EAAez6B,EAAQtW,KAAK,sBAOhC,KAHAkV,EAAOlU,KAAKogC,eAAelsB,GAAM,GACjClU,KAAK0rC,YAAcx3B,EAEd7V,EAAI,EAAGA,EAAI6V,EAAKpW,OAAQO,IAI5B2B,KAAKu4B,cACLrkB,EAAK7V,GAAG25B,IAAMh4B,KAAK4qC,WAAWrD,EAAKC,GACnCxnC,KAAK44B,cAELmX,EAAa/vB,OAAO9L,EAAK7V,GAAGC,GAG7B,OAAOgX,IAKRm6B,eAAgB,SAASv7B,EAAM87B,GAG9B,GAAIp9B,GAAStX,EAAEwpB,IAAI5Q,EAAM,SAASP,GACjC,MAAOA,GAAIrB,QAGR29B,EAAWD,EAAQ3pC,QACnB6pC,EAASD,EAAS5pC,QAAQ5G,IAAI,EAAG,QACjC0wC,GAAanqC,MAAOiqC,EAAU/pC,IAAKgqC,EAcvC,OAXAh8B,GAAOlU,KAAK4/B,aACXhtB,EACA,SAASgY,GACR,GAAIjX,GAAMnO,EAAgBolB,EAAOulB,EACjC,OAAOx8B,IAAQA,QAKjB3T,KAAKomC,cAAclyB,GAEZA,GAKRi7B,gBAAiB,SAASiB,GACzB,GAAIxV,GAAM56B,KAAKuX,KAAKqjB,IAAI,iBAExB,OAAmB,kBAARA,GACHA,EAAIwV,GAGJ,IAAMA,EAAM,IAAMxV,GAO3BuT,YAAa,SAAS5G,EAAKC,EAAK6I,GAM/B,IALA,GAGI18B,GAHA05B,EAAYrtC,KAAK6qC,WAAWtD,GAAK8F,UACjCh5B,EAAQg8B,GAAc,EACtBn8B,KAGGG,EAAQg5B,EAAUvvC,QACxB6V,EAAM05B,EAAUh5B,GAAOmzB,GACnB7zB,GACHO,EAAKxV,KAAKiV,GAEXU,GAGD,OAAOH,KAWT,IAAIo8B,IAAW/hC,GAAG+hC,SAAWpW,GAAKzmB,OAAO8yB,IAExCgK,aAAc,KACdC,aAAc,KACdC,aAAc,KACdC,QAAS,KACTC,QAAS,KACTC,YAAa,KACbC,cAAe,KAEfC,OAAQ,KACRC,gBAAiB,KACjBC,QAAS,KACTC,gBAAiB,KAEjB/G,cAAe,KACfgH,eAAgB,KAGhBx/B,YAAa,WACZwoB,GAAKzvB,MAAMzK,KAAM2K,WAEjB3K,KAAKmxC,kBAMNpV,YAAa,WACZ/7B,KAAK1B,GAAGqgC,KAAK3+B,KAAKoxC,cAClBpxC,KAAK8wC,OAAS9wC,KAAK1B,GAAGU,KAAK,WAC3BgB,KAAK+wC,gBAAkB/wC,KAAK1B,GAAGU,KAAK,aACpCgB,KAAKgxC,QAAUhxC,KAAK+wC,gBAAgB/xC,KAAK,MAEzCgB,KAAKkqC,cAAgB,GAAI7Z,KACxB7yB,IAAKwC,KAAK8wC,OACVtgB,cAAc,IAEfxwB,KAAKkxC,eAAiB,GAAI7gB,KACzB7yB,IAAKwC,KAAKgxC,QACVvgB,YAAY,IAGbzwB,KAAKqxC,yBAKND,WAAY,WACX,MAAO,6BAGJpxC,KAAKopC,eAAe,GACrB,8CAICppC,KAAKsxC,oBACN,kBAMHA,kBAAmB,WAUlB,IATA,GAIIC,GACAC,EACAC,EANAl6B,EAAOvX,KAAKuX,KACZxH,EAAQ/P,KAAK+P,MACb4uB,EAAO,GACP+S,EAAWr2C,EAAOkL,UAAUvG,KAAK0wC,SAM9BgB,EAAW1xC,KAAK2wC,SACtBY,EAAWvxC,KAAKgG,MAAMK,QAAQM,KAAK+qC,GACnCF,EAAYrqC,GAAMU,EAAyB6pC,EAAU1xC,KAAK6wC,gBAE1DY,EACC,8BAAgCl6B,EAAKiyB,mBAAqB,KAAOjyB,EAAKo6B,gBAAkB,KACtFH,EACA,SACC5mC,GAAW2mC,EAASviC,OAAOhP,KAAK4wC,cACjC,UACA,IAEF,QAEDjS,GACC,kBAAoB4S,EAASviC,OAAO,YAAc,KAChDwiC,EAAY,GAAK,qBAClB,KACEzhC,EAAmB,GAAX0hC,GACV,cAAgBl6B,EAAKiyB,mBAAqB,OACzCz5B,EAAQ0hC,EAAW,IACrB,QAEDC,EAASjyC,IAAIO,KAAKuwC,aAGnB,OAAO5R,IASRwS,eAAgB,WACf,GAGIv1C,GAHA2b,EAAOvX,KAAKuX,KACZg5B,EAAeh5B,EAAKqjB,IAAI,gBACxB4V,EAAej5B,EAAKqjB,IAAI,eAG5B2V,GAAel1C,EAAOkL,SAASgqC,GAC/BC,EAAeA,EAAen1C,EAAOkL,SAASiqC,GAAgBD,EAE9DvwC,KAAKuwC,aAAeA,EACpBvwC,KAAKwwC,aAAeA,EACpBxwC,KAAKywC,aAAeF,EAAeC,EAEnCxwC,KAAKu6B,kBAAoBiW,EAEzBxwC,KAAK0wC,QAAUr1C,EAAOkL,SAASgR,EAAKqjB,IAAI,YACxC56B,KAAK2wC,QAAUt1C,EAAOkL,SAASgR,EAAKqjB,IAAI,YAIxCh/B,EAAQ2b,EAAKqjB,IAAI,mBACbt/B,EAAEgJ,QAAQ1I,KACbA,EAAQA,EAAMA,EAAMkC,OAAS,IAG9BkC,KAAK4wC,YACJh1C,GACA2b,EAAKqjB,IAAI,eACTrjB,EAAKqjB,IAAI,mBAEVh/B,EAAQ2b,EAAKqjB,IAAI,qBACjB56B,KAAK6wC,cAAgBj1C,EACpBP,EAAOkL,SAAS3K,GAChBoE,KAAK4xC,qBAAqBrB,IAK5BqB,qBAAsB,SAASrB,GAC9B,GAAIlyC,GACAwyC,EACAgB,CAGJ,KAAKxzC,EAAIyzC,GAA2Bh0C,OAAS,EAAGO,GAAK,EAAGA,IAGvD,GAFAwyC,EAAgBx1C,EAAOkL,SAASurC,GAA2BzzC,IAC3DwzC,EAAgBhqC,EAAyBgpC,EAAeN,GACpDppC,GAAM0qC,IAAkBA,EAAgB,EAC3C,MAAOhB,EAIT,OAAOx1C,GAAOkL,SAASgqC,IAKxBzV,uBAAwB,WACvB,MAAO96B,MAAKuX,KAAKqjB,IAAI,yBAKtBI,uBAAwB,WACvB,OAAO,GAQRzC,YAAa,WACZv4B,KAAKkqC,cAAcpZ,QACnB9wB,KAAKkxC,eAAepgB,SAIrB8H,YAAa,WACZ54B,KAAKkqC,cAAc/Y,SAKpBkH,SAAU,SAAS9G,EAAYE,GAC9B,GAAIgf,GAAezwC,KAAKywC,aACpBvG,EAAgBlqC,KAAKkqC,cACrBgH,EAAiBlxC,KAAKkxC,cAE1B,IAAIhH,EAAc1X,eAAejB,IAAe2f,EAAeze,cAAchB,GAAY,CACxF,GAAIsgB,GAAW7H,EAAc5Y,mBAAmBC,GAC5CygB,EAAYd,EAAe1f,iBAAiBC,EAEhD,IAAgB,MAAZsgB,GAAiC,MAAbC,EAAmB,CAC1C,GAAIC,GAAUf,EAAelf,aAAaggB,GACtCE,EAAahB,EAAe7e,UAAU2f,GACtCG,GAAW1gB,EAAYwgB,GAAWC,EAClCE,EAAiBx0C,KAAKC,MAAMs0C,EAAU1B,GACtC4B,EAAYL,EAAYvB,EAAe2B,EACvCE,EAAUL,EAAWG,EAAiB3B,EAAgByB,EACtDK,EAAaN,GAAYG,EAAiB,GAAK3B,EAAgByB,CAEnE,QACC1K,IAAKuK,EACLS,KAAMH,EACNrgC,UAAWhS,KACXrD,KAAMutC,EAAcxY,cAAcqgB,GAClCh1C,MAAOmtC,EAAcrY,eAAekgB,GACpCxxC,IAAK+xC,EACL9xC,OAAQ+xC,MAOZlX,WAAY,SAASrD,GACpB,GAEI9xB,GAFAF,EAAQhG,KAAKsnC,YAAY,EAAGtP,EAAIwP,KAChC7gC,EAAO3G,KAAKyyC,gBAAgBza,EAAIwa,KAMpC,OAHAxsC,GAAMW,KAAKA,GACXT,EAAMF,EAAMK,QAAQ5G,IAAIO,KAAKwwC,eAEpBxqC,MAAOA,EAAOE,IAAKA,IAI7Bo1B,SAAU,SAAStD,GAClB,MAAOh4B,MAAK8wC,OAAO7wC,GAAG+3B,EAAIwP,MAQ3BtM,aAAc,WACbl7B,KAAK+mC,kBAKN0L,gBAAiB,SAASJ,GACzB,MAAOh3C,GAAOkL,SAASvG,KAAK0wC,QAAU1wC,KAAKwwC,aAAe6B,IAK3DjX,WAAY,SAAS/R,GACpB,GACIhrB,GADA6V,EAAOlU,KAAK0yC,kBAAkBrpB,EAGlC,KAAKhrB,EAAI,EAAGA,EAAI6V,EAAKpW,OAAQO,IACxB2B,KAAK+P,MACRmE,EAAK7V,GAAGmpC,IAAMxnC,KAAK2mC,WAAa,EAAIzyB,EAAK7V,GAAG2oC,SAG5C9yB,EAAK7V,GAAGmpC,IAAMtzB,EAAK7V,GAAG2oC,QAIxB,OAAO9yB,IAIRw+B,kBAAmB,SAAS9nB,GAC3B,GACIjX,GACAqzB,EACAgJ,EACAG,EAJAj8B,IAMJ,KAAK8yB,EAAW,EAAGA,EAAWhnC,KAAK2mC,WAAYK,IAC9CgJ,EAAUhwC,KAAKymC,SAASO,GAAU3gC,QAClC8pC,GACCnqC,MAAOgqC,EAAQ3pC,QAAQM,KAAK3G,KAAK0wC,SACjCxqC,IAAK8pC,EAAQ3pC,QAAQM,KAAK3G,KAAK2wC,UAEhCh9B,EAAMnO,EAAgBolB,EAAOulB,GACzBx8B,IACHA,EAAIqzB,SAAWA,EACf9yB,EAAKxV,KAAKiV,GAIZ,OAAOO,IAQRwE,WAAY,SAASi6B,GACpB3yC,KAAKkxC,eAAepgB,QAEhB6hB,GACH3yC,KAAK4yC,sBACD7nB,OAAO/qB,KAAK6yC,WAAc7yC,KAAK8yC,WAAc9yC,KAAK+yC,oBAMxDC,mBAAoB,WACnB,MAAOhzC,MAAK+wC,gBAAgBtyC,eAM7Bw0C,eAAgB,SAASrkC,EAAMskC,GAC9B,MAAOlzC,MAAKmzC,eACX93C,EAAOkL,SACNqI,EAAOskC,EAAe7sC,QAAQI,eAOjC0sC,eAAgB,SAASxsC,GACxB,GAEIqrC,GACAoB,EAHA/kC,EAAMrO,KAAKgxC,QAAQlzC,OACnBu1C,GAAgB1sC,EAAO3G,KAAK0wC,SAAW1wC,KAAKuwC,YAmBhD,OAZA8C,GAAez1C,KAAK4F,IAAI,EAAG6vC,GAC3BA,EAAez1C,KAAK6F,IAAI4K,EAAKglC,GAI7BrB,EAAYp0C,KAAKC,MAAMw1C,GACvBrB,EAAYp0C,KAAK6F,IAAIuuC,EAAW3jC,EAAM,GAItC+kC,EAAgBC,EAAerB,EAExBhyC,KAAKkxC,eAAehf,eAAe8f,GACzChyC,KAAKkxC,eAAe7e,UAAU2f,GAAaoB,GAW7CxQ,WAAY,SAAS/Y,EAAelW,GAEnC,MAAIA,GAII3T,KAAKq9B,0BAA0BxT,EAAelW,OAIrD3T,MAAK49B,gBAAgB59B,KAAK2iC,YAAY9Y,KAMxCiZ,aAAc,WACb9iC,KAAK29B,iBACL39B,KAAK69B,qBASNsG,kBAAmB,SAASta,EAAelW,GAC1C,MAAO3T,MAAKq9B,0BAA0BxT,EAAelW,IAKtDywB,oBAAqB,WACpBpkC,KAAK29B,kBASNF,aAAc,SAASnrB,EAAOgrB,GAC7B,MAAOt9B,MAAKszC,iBAAiBtzC,KAAKolC,YAAY9yB,GAAQgrB,IAKvDK,eAAgB,WACf39B,KAAKuzC,sBAQNz2B,oBAAqB,WACpB9c,KAAKwzC,mBACJxzC,KAAK8gC,0BAKPjkB,sBAAuB,WACtB7c,KAAKyzC,wBAQNnV,oBAAqB,WACpB,MAAO,UAIRC,mBAAoB,SAAS3vB,GAG5B,GAGIvQ,GAHA6V,EAAOlU,KAAKo7B,YAAap1B,MAAO4I,EAAM1I,IAAK0I,IAC3CrO,EAAMP,KAAKizC,eAAerkC,EAAMA,GAChCy8B,IAIJ,KAAKhtC,EAAI,EAAGA,EAAI6V,EAAKpW,OAAQO,IAC5BgtC,EAAM3sC,KAAKpD,EAAE,8DACXsB,IAAI,MAAO2D,GACXkB,SAASzB,KAAK0zC,gBAAgBzzC,GAAGiU,EAAK7V,GAAGmpC,MAAM,GAI9CtzB,GAAKpW,OAAS,GACjButC,EAAM3sC,KAAKpD,EAAE,+DACXsB,IAAI,MAAO2D,GACXkB,SAASzB,KAAK1B,GAAGU,KAAK,yBAAyB,IAGlDgB,KAAKixC,gBAAkB31C,EAAE+vC,IAI1B7M,qBAAsB,WACjBx+B,KAAKixC,kBACRjxC,KAAKixC,gBAAgBrvC,SACrB5B,KAAKixC,gBAAkB,OAUzBnU,gBAAiB,SAASzT,GACrBrpB,KAAKuX,KAAKqjB,IAAI,gBAGjB56B,KAAKq9B,0BAA0BhU,GAG/BrpB,KAAK49B,gBAAgBvU,IAMvB2T,kBAAmB,WAClBh9B,KAAK29B,iBACL39B,KAAK69B,qBAQND,gBAAiB,SAASvU,GACzBrpB,KAAK2zC,oBAAoB3zC,KAAKo7B,WAAW/R,KAI1CwU,kBAAmB,WAClB79B,KAAK4zC,0BAWPtD,IAAS3iB,OAER+lB,gBAAiB,KAGjBG,eAAgB,KAChBC,eAAgB,KAChBC,mBAAoB,KACpBC,sBAAuB,KACvBC,qBAAsB,KAGtBpB,OAAQ,KACRC,OAAQ,KACRoB,WAAY,KACZC,cAAe,KACfpB,aAAc,KAId1B,sBAAuB,WACtB,GACIhzC,GACA8sC,EAFAiJ,EAAW,EAIf,KAAK/1C,EAAI,EAAGA,EAAI2B,KAAK6mC,OAAQxoC,IAC5B+1C,GACC,wQAWFjJ,GAAa7vC,EACZ,+CAEW84C,EAAW,uBAKvBp0C,KAAK0zC,gBAAkBvI,EAAWnsC,KAAK,mBACvCgB,KAAK+zC,mBAAqB5I,EAAWnsC,KAAK,wBAC1CgB,KAAK6zC,eAAiB1I,EAAWnsC,KAAK,iDACtCgB,KAAK8zC,eAAiB3I,EAAWnsC,KAAK,yBACtCgB,KAAKg0C,sBAAwB7I,EAAWnsC,KAAK,2BAC7CgB,KAAKi0C,qBAAuB9I,EAAWnsC,KAAK,0BAE5CgB,KAAKypC,aAAa0B,EAAWnsC,KAAK,OAClCgB,KAAK1B,GAAG0hB,OAAOmrB,IAQhBrL,aAAc,SAAS5rB,GAGtB,MAFAA,GAAOlU,KAAKq0C,2BAA2BngC,EAAMlU,KAAK6zC,gBAClD7zC,KAAK6yC,OAAS3+B,EACPA,GAIR+rB,eAAgB,WACfjgC,KAAKs0C,kBAAkB,WAQxBhB,iBAAkB,SAASp/B,EAAMopB,GAChC,GACIj/B,GAAGsV,EACHmlB,EAFAkR,IAOJ,KAHA91B,EAAOlU,KAAKq0C,2BAA2BngC,EAAMlU,KAAK+zC,oBAG7C11C,EAAI,EAAGA,EAAI6V,EAAKpW,OAAQO,IAC5BsV,EAAMO,EAAK7V,GACPi/B,GAAaA,EAAUkK,MAAQ7zB,EAAI6zB,MACtC1O,EAAWwE,EAAUh/B,GACrBqV,EAAIrV,GAAG1B,KACND,KAAMm8B,EAASl8B,IAAI,QACnBG,MAAO+7B,EAASl8B,IAAI,SACpBE,cAAeg8B,EAASl8B,IAAI,eAC5BK,eAAgB67B,EAASl8B,IAAI,mBAG/BotC,EAAUtrC,KAAKiV,EAAIrV,GAAG,GAKvB,OAFA0B,MAAKk0C,WAAahgC,EAEX5Y,EAAE0uC,IAIVuJ,mBAAoB,WACnBvzC,KAAKs0C,kBAAkB,eAQxBzU,aAAc,SAAS3rB,GAKtB,MAJAA,GAAOlU,KAAKy+B,iBAAiB,UAAWvqB,GACxClU,KAAK4yC,mBAAmB1+B,GACxBlU,KAAKu0C,gBAAgBv0C,KAAKw0C,eAAetgC,GAAOlU,KAAK8zC,gBACrD9zC,KAAK8yC,OAAS5+B,EACPA,GAIRgsB,eAAgB,WACflgC,KAAKs0C,kBAAkB,WAQxBX,oBAAqB,SAASz/B,GAC7BA,EAAOlU,KAAKy+B,iBAAiB,YAAavqB,GAC1ClU,KAAK4yC,mBAAmB1+B,GACxBlU,KAAKu0C,gBAAgBv0C,KAAKw0C,eAAetgC,GAAOlU,KAAKg0C,uBACrDh0C,KAAKm0C,cAAgBjgC,GAItB0/B,sBAAuB,WACtB5zC,KAAKs0C,kBAAkB,kBAQxBd,mBAAoB,SAASt/B,GAC5BA,EAAOlU,KAAKy+B,iBAAiB,gBAAiBvqB,GAC9ClU,KAAK4yC,mBAAmB1+B,GACxBlU,KAAKu0C,gBAAgBv0C,KAAKw0C,eAAetgC,GAAOlU,KAAKi0C,sBACrDj0C,KAAK+yC,aAAe7+B,GAIrBu/B,qBAAsB,WACrBzzC,KAAKs0C,kBAAkB,iBASxBE,eAAgB,SAAStgC,GACxB,GACI7V,GADAo2C,IAGJ,KAAKp2C,EAAI,EAAGA,EAAI2B,KAAK6mC,OAAQxoC,IAC5Bo2C,EAAU/1C,QAGX,KAAKL,EAAI,EAAGA,EAAI6V,EAAKpW,OAAQO,IAC5Bo2C,EAAUvgC,EAAK7V,GAAGmpC,KAAK9oC,KAAKwV,EAAK7V,GAGlC,OAAOo2C,IAMRF,gBAAiB,SAASE,EAAWC,GACpC,GAAIlN,GACAtzB,EACA7V,CAEJ,KAAKmpC,EAAM,EAAGA,EAAMxnC,KAAK6mC,OAAQW,IAGhC,IAFAtzB,EAAOugC,EAAUjN,GAEZnpC,EAAI,EAAGA,EAAI6V,EAAKpW,OAAQO,IAC5Bq2C,EAAaz0C,GAAGunC,GAAKxnB,OAAO9L,EAAK7V,GAAGC,KAQvCg2C,kBAAmB,SAASliC,GAC3B,GACI/T,GADA6V,EAAOlU,KAAKoS,EAGhB,IAAI8B,EAAM,CACT,IAAK7V,EAAI,EAAGA,EAAI6V,EAAKpW,OAAQO,IAC5B6V,EAAK7V,GAAGC,GAAGsD,QAEZ5B,MAAKoS,GAAY,OAYnBiiC,2BAA4B,SAASngC,EAAMwgC,GAC1C,GAAID,GACAjN,CAKJ,KAHAtzB,EAAOlU,KAAKogC,eAAelsB,GAC3BugC,EAAYz0C,KAAKw0C,eAAetgC,GAE3BszB,EAAM,EAAGA,EAAMxnC,KAAK6mC,OAAQW,IAChCxnC,KAAK20C,kBAAkBF,EAAUjN,GAKlC,OAFAxnC,MAAKu0C,gBAAgBE,EAAWC,GAEzBxgC,GAKRosB,UAAW,SAAS3sB,EAAK0sB,GACxB,GAOI4L,GACA2I,EACAC,EATAt9B,EAAOvX,KAAKuX,KACZjF,EAAQqB,EAAIrB,MACZwvB,EAAcvqB,EAAKoqB,iBAAiBrvB,GACpC65B,GAAwB9L,GAAmB1sB,EAAI9N,SAAW0R,EAAK60B,0BAA0B95B,GACzF+5B,GAAsBhM,GAAmB1sB,EAAI7N,OAASyR,EAAK+0B,wBAAwBh6B,GACnF0O,EAAUhhB,KAAK2kC,cAAchxB,EAAKmuB,EAAaqK,GAAwBE,GACvEE,EAAUthC,GAASjL,KAAK4gC,cAAcjtB,GAuB1C,OAlBAqN,GAAQzX,QAAQ,qBAAsB,cAElCgO,EAAKu9B,gBAAgBxiC,IAIpBqB,EAAI9N,SAAW8N,EAAI7N,SACtBmmC,EAAWjsC,KAAKykC,iBAAiB9wB,GACjCihC,EAAe50C,KAAKykC,iBAAiB9wB,EAAK,MAC1CkhC,EAAgB70C,KAAKykC,iBAAiB9wB,EAAK,MAAM,KAIlDs4B,EAAWjsC,KAAKykC,iBAAiBnyB,GACjCsiC,EAAe50C,KAAKykC,iBAAiBnyB,EAAO,MAC5CuiC,EAAgB70C,KAAKykC,iBAAiBnyB,EAAO,MAAM,IAG7C,aAAe0O,EAAQ5V,KAAK,KAAO,KACxCkH,EAAMuR,IACN,UAAYjZ,GAAW0H,EAAMuR,KAAO,IACpC,KAEA0oB,EACA,WAAaA,EAAU,IACvB,IAED,6BAEGN,EACA,oCACkBrhC,GAAWiqC,GAAiB,gBAC7BjqC,GAAWgqC,GAAgB,WAEhChqC,GAAWqhC,GAAY,gBAEnC,KAEA35B,EAAM+H,MACN,yBACCzP,GAAW0H,EAAM+H,OAClB,SACA,IAEF,8BAQCgyB,EACA,4CACA,IAEF,QAUFuG,mBAAoB,SAAS1+B,GAC5BlU,KAAK+0C,oBAAoB7gC,GACzBlU,KAAKg1C,mBAAmB9gC,IAKzB6gC,oBAAqB,SAAS7gC,GAC7B,GAAI7V,GAAGsV,CAEP,KAAKtV,EAAI,EAAGA,EAAI6V,EAAKpW,OAAQO,IAC5BsV,EAAMO,EAAK7V,GACXsV,EAAIpT,IAAMP,KAAKizC,eAAet/B,EAAI3N,MAAO2N,EAAI3N,OAC7C2N,EAAInT,OAASR,KAAKizC,eAAet/B,EAAIzN,IAAKyN,EAAI3N,QAOhDgvC,mBAAoB,SAAS9gC,GAC5B,GAAI7V,GAAGsV,CAEP,KAAKtV,EAAI,EAAGA,EAAI6V,EAAKpW,OAAQO,IAC5BsV,EAAMO,EAAK7V,GACXsV,EAAIrV,GAAG1B,IAAIoD,KAAKi1C,uBAAuBthC,KAMzCshC,uBAAwB,SAASthC,GAChC,OACCpT,IAAKoT,EAAIpT,IACTC,QAASmT,EAAInT,SAWfm0C,kBAAmB,SAASzgC,GAC3BlU,KAAK+0C,oBAAoB7gC,GACzBlU,KAAKk1C,wBAAwBhhC,GAC7BlU,KAAKg1C,mBAAmB9gC,GACxBlU,KAAKm1C,uBAAuBjhC,IAM7BghC,wBAAyB,SAAShhC,GACjC,GAAIC,GACAihC,EACA/2C,CAMJ,IAJA2B,KAAKomC,cAAclyB,GACnBC,EAASF,GAAmBC,GAC5BI,GAAuBH,GAElBihC,EAASjhC,EAAO,GAAK,CAEzB,IAAK9V,EAAI,EAAGA,EAAI+2C,EAAOt3C,OAAQO,IAC9BoW,GAAwB2gC,EAAO/2C,GAGhC,KAAKA,EAAI,EAAGA,EAAI+2C,EAAOt3C,OAAQO,IAC9B2B,KAAKq1C,wBAAwBD,EAAO/2C,GAAI,EAAG,KAc9Cg3C,wBAAyB,SAAS1hC,EAAK2hC,EAAwBC,GAC9D,GACIl3C,GADAmW,EAAcb,EAAIa,WAGtB,IAAyBpS,SAArBuR,EAAI6hC,aAyBP,IAvBKhhC,EAAY1W,QAQhBkC,KAAKy1C,gBAAgBjhC,GAIrBxU,KAAKq1C,wBAAwB7gC,EAAY,GAAI8gC,EAAyB,EAAGC,GACzE5hC,EAAI6hC,aAAehhC,EAAY,GAAGkhC,eAVlC/hC,EAAI6hC,aAAe,EAcpB7hC,EAAI+hC,cAAgB/hC,EAAI6hC,cACtB7hC,EAAI6hC,aAAeD,IACnBD,EAAyB,GAItBj3C,EAAE,EAAGA,EAAEmW,EAAY1W,OAAQO,IAC/B2B,KAAKq1C,wBAAwB7gC,EAAYnW,GAAI,EAAGsV,EAAI6hC,eAMvDC,gBAAiB,SAASjhC,GACzBA,EAAY0pB,KAAKzyB,GAAMzL,KAAM,wBAK9B21C,mBAAoB,SAAS7gC,EAAMC,GAElC,MAAOA,GAAKJ,gBAAkBG,EAAKH,kBAEjCG,EAAK4gC,eAAiB,IAAM3gC,EAAK2gC,eAAiB,IAEnD11C,KAAKqmC,iBAAiBvxB,EAAMC,IAM9BogC,uBAAwB,SAASjhC,GAChC,GAAI7V,GAAGsV,CAEP,KAAKtV,EAAI,EAAGA,EAAI6V,EAAKpW,OAAQO,IAC5BsV,EAAMO,EAAK7V,GACXsV,EAAIrV,GAAG1B,IAAIoD,KAAK41C,2BAA2BjiC,IAGvCA,EAAInT,OAASmT,EAAIpT,IAAM,IAC1BoT,EAAIrV,GAAGlB,SAAS,aAQnBw4C,2BAA4B,SAASjiC,GACpC,GAIIhX,GACAI,EALA84C,EAAgB71C,KAAKuX,KAAKqjB,IAAI,oBAC9B8a,EAAgB/hC,EAAI+hC,cACpBF,EAAe7hC,EAAI6hC,aACnBnsC,EAAQrJ,KAAKi1C,uBAAuBthC,EA2BxC,OAvBIkiC,KAEHL,EAAe53C,KAAK6F,IAAI,EAAGiyC,EAAiD,GAAhCF,EAAeE,KAGxD11C,KAAK+P,OACRpT,EAAO,EAAI64C,EACXz4C,EAAQ24C,IAGR/4C,EAAO+4C,EACP34C,EAAQ,EAAIy4C,GAGbnsC,EAAM2wB,OAASrmB,EAAIU,MAAQ,EAC3BhL,EAAM1M,KAAc,IAAPA,EAAa,IAC1B0M,EAAMtM,MAAgB,IAARA,EAAc,IAExB84C,GAAiBliC,EAAIgB,kBAExBtL,EAAMrJ,KAAK+P,MAAQ,aAAe,eAAiB,IAG7C1G,IA2GT,IAAIysC,IAAOvnC,GAAGunC,KAAOzkC,GAAMoC,OAAOma,GAAcO,IAE/CxrB,KAAM,KACN1G,KAAM,KACNoe,MAAO,KAEPwF,SAAU,KACVxJ,QAAS,KACT/X,GAAI,KAEJuZ,WAAY,KACZk+B,oBAAoB,EACpBC,kBAAkB,EAGlBhwC,MAAO,KACPE,IAAK,KAIL6R,cAAe,KACfC,YAAa,KACbknB,iBAAkB,KAClB+W,aAAc,KAEdlmC,OAAO,EACPqsB,YAAY,EACZC,cAAe,KAEfiK,gBAAiB,KAGjBqC,kBAAmB,KACnBa,mBAAoB,KACpBrK,oBAAqB,KAGrB+W,iBAAkB,KAClBC,gBAAiB,KAGjBC,uBAAwB,KACxBC,eAAgB,KAChBC,oBAAqB,KACrBC,sBAAuB,KACvBC,uBAAwB,KAGxB9kC,YAAa,SAASmO,EAAUld,EAAM0T,EAAS6oB,GAE9Cl/B,KAAK6f,SAAWA,EAChB7f,KAAK2C,KAAO3C,KAAK/D,KAAO0G,EACxB3C,KAAKqW,QAAUA,EACfrW,KAAKk/B,iBAAmBA,GAAoB7jC,EAAOkL,SAAS,EAAG,OAE/DvG,KAAKk2C,iBAAmB76C,EAAOkL,SAASvG,KAAK46B,IAAI,qBACjD56B,KAAKy2C,mBACLz2C,KAAK02C,iBACL12C,KAAK+P,MAAQ/P,KAAK46B,IAAI,SAEtB56B,KAAKsmC,gBAAkBriC,EAAgBjE,KAAK46B,IAAI,eAEhD56B,KAAKwf,cAKNA,WAAY,aAMZob,IAAK,SAAS3+B,GACb,MAAO+D,MAAKqW,QAAQpa,IAKrBmd,QAAS,SAASnd,EAAMoO,GACvB,GAAIwV,GAAW7f,KAAK6f,QAEpB,OAAOA,GAASzG,QAAQ3O,MACvBoV,GACC5jB,EAAMoO,GAAWrK,MAAM+qB,OACvB/N,MAAMrU,UAAU4C,MAAM1C,KAAK8B,UAAW,IACpC3K,SAWL22C,QAAS,SAAS/nC,GACjB5O,KAAKi7B,SAASj7B,KAAK42C,aAAahoC,KAKjCqsB,SAAU,SAASrQ,GAClBtvB,EAAEmY,OAAOzT,KAAM4qB,GACf5qB,KAAKoa,eAMNw8B,aAAc,SAAShoC,GACtB,GAGI5I,GAAOE,EAHP+vC,EAAejvC,EAAoBhH,KAAKk/B,kBACxCnnB,EAAgBnJ,EAAKvI,QAAQwwC,QAAQZ,GACrCj+B,EAAcD,EAAc1R,QAAQ5G,IAAIO,KAAKk/B,iBAsBjD,OAlBI,sBAAsB9iC,KAAK65C,IAC9Bl+B,EAActR,YACduR,EAAYvR,cAGPsR,EAAcuG,YAClBvG,EAAgB/X,KAAK6f,SAASlZ,KAAK,IAE/BqR,EAAYsG,YAChBtG,EAAchY,KAAK6f,SAASlZ,KAAK,KAInCX,EAAQ+R,EAAc1R,QACtBL,EAAQhG,KAAK82C,eAAe9wC,GAC5BE,EAAM8R,EAAY3R,QAClBH,EAAMlG,KAAK82C,eAAe5wC,MAAS,IAGlC+vC,aAAcA,EACdl+B,cAAeA,EACfC,YAAaA,EACbhS,MAAOA,EACPE,IAAKA,IAMP8U,gBAAiB,SAASpM,GACzB,MAAO5O,MAAK4X,mBACXhJ,EAAKvI,QAAQwwC,QAAQ72C,KAAKi2C,cAAcptB,SAAS7oB,KAAKk/B,uBAMxDhkB,gBAAiB,SAAStM,GACzB,MAAO5O,MAAK4X,mBACXhJ,EAAKvI,QAAQwwC,QAAQ72C,KAAKi2C,cAAcx2C,IAAIO,KAAKk/B,oBAQnDtnB,mBAAoB,SAAShJ,EAAMpN,GAQlC,MAPIxB,MAAKk/B,iBAAiB73B,GAAG,SAAW,GACnCrH,KAAKinC,YAAYr4B,KACpBA,EAAO5O,KAAK82C,eAAeloC,EAAMpN,GACjCoN,EAAKioC,QAAQ,QAIRjoC,GASRwL,YAAa,WACZpa,KAAKqa,MAAQra,KAAK+2C,gBAKnBA,aAAc,WACb,MAAO/2C,MAAK2P,aAGV3J,MAAOhG,KAAK6f,SAAS7D,cAAchc,KAAK+X,eACxC7R,IAAKlG,KAAK6f,SAAS7D,cAAchc,KAAKgY,cAEvChY,KAAK46B,IAAI,gBAAkB56B,KAAKg3C,qBAChCh3C,KAAK46B,IAAI,yBAOXoc,mBAAoB,WACnB,MAAyB,QAArBh3C,KAAKi2C,aACD,OAEsB,SAArBj2C,KAAKi2C,aACNj2C,KAAK46B,IAAI,mBAER56B,KAAKk/B,iBAAiB73B,GAAG,QAAU,EACpC,KAGA,MAQTsI,YAAa,SAASib,EAAO9b,EAAWgB,GACvC,GAAI5J,GAAM0kB,EAAM1kB,GAMhB,OAJKA,GAAIoY,YACRpY,EAAMA,EAAIG,QAAQwiB,SAAS,IAGrBlZ,GAAYib,EAAM5kB,MAAOE,EAAK4I,EAAWgB,EAAW9P,KAAK46B,IAAI,WAUrEljB,WAAY,SAASpZ,GACpB0B,KAAK1B,GAAKA,EACV0B,KAAK27B,sBAMN5kB,cAAe,WACd/W,KAAKmxB,QAGDnxB,KAAK+1C,qBACR/1C,KAAKi3C,mBACLj3C,KAAK+1C,oBAAqB,GAG3B/1C,KAAK47B,uBAEL57B,KAAK1B,GAAGsD,UAWTqW,QAAS,SAASrJ,EAAMuI,GACvB,GAAIoY,GAAQvvB,KACRk3C,EAAkB,IAQtB,OAN2B,OAAvB//B,GAA+BnX,KAAK6X,aACvCq/B,EAAkBl3C,KAAKyY,eAGxBzY,KAAK6f,SAASxI,sBAEP9K,GAASvM,KAAKmxB,QAAS,WAC7B,MACC5B,GAAM1X,WACLtL,GAASgjB,EAAM4nB,YAAYvoC,GAAO,WAGN,MAAvBuI,EAGHoY,EAAM6nB,UAAUjgC,GAGhBoY,EAAM8nB,YAAY9nB,EAAM+nB,qBAAqBJ,IAG9C3nB,EAAM1P,SAAS3H,wBACfqX,EAAMgoB,qBAUXpmB,MAAO,WACN,GAAI5B,GAAQvvB,KACR6X,EAAa7X,KAAK6X,UAEtB,OAAIA,GACItL,GAASsL,EAAY,WAG3B,MAFA0X,GAAM1X,WAAa,KACnB0X,EAAMioB,cACCjoB,EAAMjY,cAIPhc,EAAEsR,QAQXuqC,YAAa,SAASvoC,GAChB5O,KAAK+1C,qBACT/1C,KAAK87B,iBACL97B,KAAK+1C,oBAAqB,GAEvBnnC,GACH5O,KAAK22C,QAAQ/nC,GAEV5O,KAAKqV,QACRrV,KAAKqV,SAENrV,KAAK+7B,cACL/7B,KAAK0Y,aACL1Y,KAAK8c,sBACL9c,KAAKy3C,qBAMNngC,UAAW,WACVtX,KAAK8a,WACL9a,KAAK03C,mBACL13C,KAAK23C,kBACL33C,KAAK6c,wBACL7c,KAAKg8B,gBACDh8B,KAAK6W,SACR7W,KAAK6W,WAMPilB,eAAgB,aAMhBmb,iBAAkB,aAOlBlb,YAAa,aAMbC,cAAe,aAMfub,cAAe,WACdv3C,KAAKoZ,QAAQ,aAAcpZ,KAAMA,KAAMA,KAAK1B,KAK7Cq5C,gBAAiB,WAChB33C,KAAKoZ,QAAQ,cAAepZ,KAAMA,KAAMA,KAAK1B,KAK9Cq9B,mBAAoB,WACnB37B,KAAKquB,SAAS/yB,EAAE6E,UAAW,YAAaH,KAAK43C,yBAC7C53C,KAAKquB,SAAS/yB,EAAE6E,UAAW,aAAcH,KAAK63C,kBAK/Cjc,qBAAsB,WACrB57B,KAAK0uB,gBAAgBpzB,EAAE6E,YAKxBs2C,iBAAkB,WACjB,GAAI3gC,GAAK9V,KAAK46B,IAAI,SAAW,KAAO,IAEpC56B,MAAK2oC,kBAAoB7yB,EAAK,iBAC9B9V,KAAKwpC,mBAAqB1zB,EAAK,kBAC/B9V,KAAKm/B,oBAAsBrpB,EAAK,oBASjCgH,oBAAqB,aAMrBD,sBAAuB,aAYvB46B,kBAAmB,WAClB,GACI3wC,GACAgxC,EACA/oB,EAHAQ,EAAQvvB,IAKRA,MAAK46B,IAAI,kBACZ9zB,EAAO9G,KAAKs+B,sBACRx3B,IACHgxC,EAASrsC,GAAMzL,KAAM,sBAErBA,KAAKq2C,eAAiBr2C,KAAK6f,SAAStF,SACpCva,KAAKs2C,qBAAuB,GAAIxtC,MAChC9I,KAAKu+B,mBAAmBv+B,KAAKq2C,gBAC7Br2C,KAAKo2C,wBAAyB,EAG9BrnB,EAAQ/uB,KAAKq2C,eAAehwC,QAAQwwC,QAAQ/vC,GAAMrH,IAAI,EAAGqH,GAAQ9G,KAAKq2C,eACtEr2C,KAAKu2C,sBAAwBlqC,WAAW,WACvCkjB,EAAMgnB,sBAAwB,KAC9BuB,IACA/oB,GAAS1zB,EAAOkL,SAAS,EAAGO,GAC5BioB,EAAQnxB,KAAK4F,IAAI,IAAKurB,GACtBQ,EAAMinB,uBAAyBjf,YAAYugB,EAAQ/oB,IACjDA,MAQNgpB,mBAAoB,WACf/3C,KAAKo2C,yBACRp2C,KAAKw+B,uBACLx+B,KAAKu+B,mBACJv+B,KAAKq2C,eAAehwC,QAAQ5G,IAAI,GAAIqJ,MAAS9I,KAAKs2C,wBAQrDoB,iBAAkB,WACb13C,KAAKo2C,yBAEJp2C,KAAKu2C,wBACRpiB,aAAan0B,KAAKu2C,uBAClBv2C,KAAKu2C,sBAAwB,MAE1Bv2C,KAAKw2C,yBACRriB,aAAan0B,KAAKw2C,wBAClBx2C,KAAKw2C,uBAAyB,MAG/Bx2C,KAAKw+B,uBACLx+B,KAAKo2C,wBAAyB,IAOhC9X,oBAAqB,aAMrBC,mBAAoB,SAAS3vB,KAM7B4vB,qBAAsB,aAUtB9lB,WAAY,SAASi6B,GACpB,GAAIn6B,EAEAm6B,KACHn6B,EAAcxY,KAAKyY,eAGpBzY,KAAKg4C,aAAarF,GAClB3yC,KAAKi4C,YAAYtF,GACjB3yC,KAAK+3C,qBAEDpF,GACH3yC,KAAKo3C,UAAU5+B,IAMjBy/B,YAAa,SAAStF,KAMtBqF,aAAc,SAASrF,GACtB,GAAI9yB,GAAW7f,KAAK6f,QAEpB7f,MAAKk4C,UACJr4B,EAASP,yBACTO,EAASN,iBAOX24B,UAAW,SAASv5C,EAAQw5C,KAW5Bb,qBAAsB,SAASc,GAC9B,MAAO,IAKR3/B,YAAa,aAMb2+B,UAAW,SAAS5+B,KAMpB6+B,YAAa,SAAS7+B,GACrB,GAAI+W,GAAQvvB,IAEZA,MAAKo3C,UAAU5+B,GACfnM,WAAW,WACVkjB,EAAM6nB,UAAU5+B,IACd,IASJqB,cAAe,SAASjH,GACvB,GAAI4F,GAAcxY,KAAKyY,aAEvBzY,MAAKw3C,cACLx3C,KAAK4Z,aAAahH,GAClB5S,KAAKg2C,kBAAmB,EACxBh2C,KAAKo3C,UAAU5+B,GACfxY,KAAKq4C,sBAKNb,YAAa,WACZ,GAAIh/B,EAEAxY,MAAKg2C,mBAGRx9B,EAAcxY,KAAKyY,cAEnBzY,KAAKs4C,uBACDt4C,KAAKu4C,eACRv4C,KAAKu4C,gBAENv4C,KAAK+/B,iBACL//B,KAAKo3C,UAAU5+B,GACfxY,KAAKg2C,kBAAmB,IAM1Bp8B,aAAc,SAAShH,KAMvBmtB,eAAgB,aAMhBsY,mBAAoB,WACnBr4C,KAAKw4C,qBAAqB,SAAS7kC,GAClC3T,KAAKoZ,QAAQ,mBAAoBzF,EAAIrB,MAAOqB,EAAIrB,MAAOqB,EAAIrV,MAE5D0B,KAAKoZ,QAAQ;AAKdk/B,qBAAsB,WACrBt4C,KAAKw4C,qBAAqB,SAAS7kC,GAClC3T,KAAKoZ,QAAQ,eAAgBzF,EAAIrB,MAAOqB,EAAIrB,MAAOqB,EAAIrV,OAOzDiiC,eAAgB,SAASjuB,EAAOhU,GAC/B,GAAIm6C,GAASz4C,KAAKoZ,QAAQ,cAAe9G,EAAOA,EAAOhU,EASvD,OAPIm6C,MAAW,EACdn6C,EAAK,KAEGm6C,GAAUA,KAAW,IAC7Bn6C,EAAKhD,EAAEm9C,IAGDn6C,GAKRykC,UAAW,SAASzwB,GACnBtS,KAAKw4C,qBAAqB,SAAS7kC,GAClCA,EAAIrV,GAAG1B,IAAI,aAAc,KACvB0V,IAKJkwB,UAAW,SAASlwB,GACnBtS,KAAKw4C,qBAAqB,SAAS7kC,GAClCA,EAAIrV,GAAG1B,IAAI,aAAc,WACvB0V,IAOJkmC,qBAAsB,SAAS7zC,EAAM2N,GACpC,GACIjU,GADA6V,EAAOlU,KAAKmgC,cAGhB,KAAK9hC,EAAI,EAAGA,EAAI6V,EAAKpW,OAAQO,IACvBiU,GAAS4B,EAAK7V,GAAGiU,MAAMQ,MAAQR,EAAMQ,KACrCoB,EAAK7V,GAAGC,IACXqG,EAAKkE,KAAK7I,KAAMkU,EAAK7V,KAQzB8hC,aAAc,WAEb,UASDwB,iBAAkB,SAASrvB,GAC1B,GAAII,GAASJ,EAAMI,UAEnB,OAAOhI,IACN4H,EAAMomC,cACNhmC,EAAOgmC,cACP14C,KAAK46B,IAAI,sBACTtoB,EAAMorB,SACNhrB,EAAOgrB,SACP19B,KAAK46B,IAAI,cAOXqI,gBAAiB,SAAS3wB,EAAO+vB,EAAcra,EAAW1pB,EAAI0D,GAC7D,GAAI6d,GAAW7f,KAAK6f,SAChB84B,EAAe94B,EAASqG,YAAY5T,EAAO+vB,EAAcra,GACzDQ,EAAW,WACdmwB,EAAa3vB,OACbnJ,EAAS1F,oBAGVna,MAAK44C,iBAAiBtmC,EAAOqmC,EAAa5vB,UAAWP,EAAUlqB,EAAI0D,GACnE6d,EAAS1F,qBAKVy+B,iBAAkB,SAAStmC,EAAOyW,EAAWP,EAAUlqB,EAAI0D,GAC1DhC,KAAKoZ,QAAQ,YAAa9a,EAAG,GAAIgU,EAAOyW,EAAWP,EAAUxmB,OAW9D4hC,mBAAoB,SAASF,EAAMrB,EAAc/jC,EAAI0D,EAAIshC,GACxD,GACItgB,GACA1Q,EAFAa,EAAauwB,EAAKvwB,UAKlBA,KACH6P,EAAa1nB,EAAEmY,UAAWN,EAAYkvB,GACtC/vB,EAAQtS,KAAK6f,SAASwG,YAAYrD,EAAY0gB,EAAKrwB,OAAO,IAG3DrT,KAAK64C,oBAAoBvmC,EAAO+vB,EAAc/jC,EAAI0D,EAAIshC,IAKvDuV,oBAAqB,SAASvmC,EAAO+vB,EAAc/jC,EAAI0D,EAAIshC,GAG1DtjC,KAAKoZ,QAAQ,OAAQ9a,EAAG,GAAI+jC,EAAar8B,MAAOhE,EAAIshC,GAEhDhxB,GACHtS,KAAKoZ,QAAQ,eAAgB,KAAM9G,IAYrCswB,WAAY,SAASP,EAAc1uB,KAMnCmvB,aAAc,aAUdsJ,0BAA2B,SAAS95B,GACnC,MAAOtS,MAAK46B,IAAI,4BAA8B56B,KAAKgiC,iBAAiB1vB,IAKrEg6B,wBAAyB,SAASh6B,GACjC,MAAOtS,MAAKgiC,iBAAiB1vB,IAK9B0vB,iBAAkB,SAAS1vB,GAC1B,GAAII,GAASJ,EAAMI,UAEnB,OAAOhI,IACN4H,EAAMwmC,iBACNpmC,EAAOomC,iBACP94C,KAAK46B,IAAI,yBACTtoB,EAAMorB,SACNhrB,EAAOgrB,SACP19B,KAAK46B,IAAI,cAMX0J,kBAAmB,SAAShyB,EAAOuxB,EAAgB7b,EAAW1pB,EAAI0D,GACjE,GAAI6d,GAAW7f,KAAK6f,SAChB84B,EAAe94B,EAASqG,YAAY5T,EAAOuxB,EAAgB7b,GAC3DQ,EAAW,WACdmwB,EAAa3vB,OACbnJ,EAAS1F,oBAGVna,MAAK+4C,mBAAmBzmC,EAAOqmC,EAAapwB,cAAeC,EAAUlqB,EAAI0D,GACzE6d,EAAS1F,qBAKV4+B,mBAAoB,SAASzmC,EAAOiW,EAAeC,EAAUlqB,EAAI0D,GAChEhC,KAAKoZ,QAAQ,cAAe9a,EAAG,GAAIgU,EAAOiW,EAAeC,EAAUxmB,OAUpE0Y,OAAQ,SAAS2O,EAAMrnB,GACtBhC,KAAK8a,SAAS9Y,GACdhC,KAAK88B,gBAAgBzT,GACrBrpB,KAAKo9B,gBAAgB/T,EAAMrnB,IAK5B86B,gBAAiB,SAASzT,KAM1B+T,gBAAiB,SAAS/T,EAAMrnB,GAC/BhC,KAAKo8B,YAAa,EAClBp8B,KAAKg5C,cAAc3vB,EAAMrnB,IAK1Bg3C,cAAe,SAAS3vB,EAAMrnB,GAC7BhC,KAAKoZ,QACJ,SACA,KACApZ,KAAK6f,SAAS7D,cAAcqN,EAAKrjB,OACjChG,KAAK6f,SAAS7D,cAAcqN,EAAKnjB,KACjClE,IAOF8Y,SAAU,SAAS9Y,GACdhC,KAAKo8B,aACRp8B,KAAKo8B,YAAa,EACdp8B,KAAKi5C,kBACRj5C,KAAKi5C,mBAENj5C,KAAKg9B,oBACLh9B,KAAKoZ,QAAQ,WAAY,KAAMpX,KAMjCg7B,kBAAmB,aASnBsF,YAAa,SAAShwB,GAChBtS,KAAKq8B,eAAiBr8B,KAAKq8B,gBAAkB/pB,IACjDtS,KAAKk5C,gBACLl5C,KAAKw4C,qBAAqB,SAAS7kC,GAClCA,EAAIrV,GAAGlB,SAAS,gBACdkV,GACHtS,KAAKq8B,cAAgB/pB,IAKvB4mC,cAAe,WACVl5C,KAAKq8B,gBACRr8B,KAAKw4C,qBAAqB,SAAS7kC,GAClCA,EAAIrV,GAAGhB,YAAY,gBACjB0C,KAAKq8B,eACRr8B,KAAKq8B,cAAgB,OAKvBwF,gBAAiB,SAASvvB,GAGzB,MAAOtS,MAAKq8B,eAAiBr8B,KAAKq8B,cAAcvpB,MAAQR,EAAMQ,KAU/D8kC,wBAAyB,SAAS51C,GAC7BD,EAAqBC,IACxBhC,KAAK63C,gBAAgB71C,IAKvB61C,gBAAiB,SAAS71C,GACzBhC,KAAKm5C,qBAAqBn3C,GAC1BhC,KAAKo5C,qBAAqBp3C,IAI3Bm3C,qBAAsB,SAASn3C,GAC9B,GAAIq3C,EAGAr5C,MAAKo8B,YAAcp8B,KAAK46B,IAAI,kBAE/Bye,EAASr5C,KAAK46B,IAAI,kBACbye,GAAW/9C,EAAE0G,EAAGmX,QAAQwW,QAAQ0pB,GAAQv7C,QAC5CkC,KAAK8a,SAAS9Y,KAMjBo3C,qBAAsB,SAASp3C,GAC1BhC,KAAKq8B,gBACH/gC,EAAE0G,EAAGmX,QAAQwW,QAAQ,gBAAgB7xB,QACzCkC,KAAKk5C,kBAYR/b,gBAAiB,SAAS9T,EAAMimB,EAAOttC,GACtChC,KAAKoZ,QACJ,WACAk2B,EACAtvC,KAAK6f,SAAS7D,cAAcqN,EAAKrjB,OACjChE,IAUF00C,eAAgB,WACf,GAGIr4C,GAHAi7C,EAAat5C,KAAK46B,IAAI,kBACtBub,KACAoD,EAAS,CAOb,KAJIv5C,KAAK46B,IAAI,eAAgB,GAC5B0e,EAAW56C,KAAK,EAAG,GAGfL,EAAI,EAAGA,EAAI,EAAGA,KAEf83C,EAAgB93C,GAAK/C,EAAEe,QAAQgC,EAAGi7C,UAEpCC,GAIF,KAAKA,EACJ,KAAM,oBAGPv5C,MAAKm2C,gBAAkBA,GAMxBlP,YAAa,SAASnf,GAIrB,MAHIzsB,GAAOgS,SAASya,KACnBA,EAAMA,EAAIA,OAEJ9nB,KAAKm2C,gBAAgBruB,IAQ7BgvB,eAAgB,SAASloC,EAAM4qC,EAAKC,GACnC,GAAI5yB,GAAMjY,EAAKvI,OAEf,KADAmzC,EAAMA,GAAO,EAEZx5C,KAAKm2C,iBAAiBtvB,EAAIiB,OAAS2xB,EAAcD,EAAM,GAAK,GAAK,IAEjE3yB,EAAIpnB,IAAI+5C,EAAK,OAEd,OAAO3yB,IAMRuhB,gBAAiB,SAASxd,GACzB,GAGI8uB,GAHAC,EAAW/uB,EAAM5kB,MAAMK,QAAQI,YAC/BP,EAAM0kB,EAAM1kB,IACZ0zC,EAAS,IAqBb,OAlBI1zC,KACH0zC,EAAS1zC,EAAIG,QAAQI,YACrBizC,GAAaxzC,EAAIS,OAKb+yC,GAAaA,GAAa15C,KAAKk2C,kBAClC0D,EAAOn6C,IAAI,EAAG,WAMXyG,GAAO0zC,GAAUD,KACrBC,EAASD,EAAStzC,QAAQ5G,IAAI,EAAG,UAGzBuG,MAAO2zC,EAAUzzC,IAAK0zC,IAKhC9E,gBAAiB,SAASxiC,GACzB,GAAIsY,GAAQ5qB,KAAKooC,gBAAgB91B,EAEjC,OAAOsY,GAAM1kB,IAAI3G,KAAKqrB,EAAM5kB,MAAO,QAAU,KAU3C6zC,GAAWtrC,GAAGsrC,SAAWxoC,GAAMoC,QAElCnV,GAAI,KACJy0B,SAAU,KACV+mB,UAAW,KACXC,UAAW,KAGXroC,YAAa,SAAS2E,GACrBA,EAAUA,MACVrW,KAAK85C,UAAYzjC,EAAQyjC,WAAazjC,EAAQ9U,UAAY,OAC1DvB,KAAK+5C,UAAY1jC,EAAQ0jC,WAAa1jC,EAAQ9U,UAAY,QAI3D8T,OAAQ,WACPrV,KAAK1B,GAAK0B,KAAKg6C,WACfh6C,KAAKi6C,iBAIND,SAAU,WACT,MAAQh6C,MAAK+yB,SAAWz3B,EAAE,oCAK3B61B,MAAO,WACNnxB,KAAKk4C,UAAU,QACfl4C,KAAKi6C,iBAINpjC,QAAS,WACR7W,KAAK1B,GAAGsD,UAQTq4C,cAAe,WACdj6C,KAAK+yB,SAASn2B,KACbs9C,aAAcl6C,KAAK85C,UACnBK,aAAcn6C,KAAK+5C,aAQrBK,aAAc,SAAS19C,GACtB,GAAIo9C,GAAY95C,KAAK85C,UACjBC,EAAY/5C,KAAK+5C,SAErBr9C,GAAkBA,GAAmBsD,KAAKU,qBAExB,SAAdo5C,IACHA,EACEp9C,EAAgB6D,KAAO7D,EAAgB8D,QAEvCR,KAAK+yB,SAAS,GAAG0E,YAAc,EAAIz3B,KAAK+yB,SAAS,GAAGnyB,YAEjD,SAAW,UAGC,SAAdm5C,IACHA,EACEr9C,EAAgBC,MAAQD,EAAgBK,OAExCiD,KAAK+yB,SAAS,GAAGyE,aAAe,EAAIx3B,KAAK+yB,SAAS,GAAGlyB,aAElD,SAAW,UAGjBb,KAAK+yB,SAASn2B,KAAMs9C,aAAcJ,EAAWK,aAAcJ,KAQ5D7B,UAAW,SAASv5C,GACnBqB,KAAK+yB,SAASp0B,OAAOA,IAItB07C,aAAc,WACb,MAAOr6C,MAAK+yB,SAAS7C,aAItBoqB,aAAc,SAAS/5C,GACtBP,KAAK+yB,SAAS7C,UAAU3vB,IAIzBg6C,eAAgB,WACf,MAAOv6C,MAAK+yB,SAAS,GAAGnyB,aAIzB45C,gBAAiB,WAChB,MAAOx6C,MAAK+yB,SAAS,GAAGlyB,cAIzBH,mBAAoB,WACnB,MAAOA,GAAmBV,KAAK+yB,aAO7BtH,GAAWld,GAAGkd,SAAWpa,GAAMoC,QAElCgnC,YAAa,KACbC,aAAc,KACd5+C,UAAW,KACX2gB,iBAAkB,KAClBpG,QAAS,KACTqG,cAAe,KACfnF,KAAM,KACNrB,OAAQ,KACRykC,aAAc,EAKdjpC,YAAasD,GAIbwK,WAAY,aAMZ7C,oBAAqB,WACpB,GAAI1M,GAAMyqC,EACN3qC,EAAO0qC,CAEXxqC,GAAOvF,GACN1K,KAAKyc,iBAAiBxM,KACtBjQ,KAAKlE,UAAUmU,MAEhByqC,EAAeE,GAAe3qC,GACzByqC,IACJzqC,EAAOwb,GAASovB,SAAS5qC,KACzByqC,EAAeE,GAAe3qC,QAG/BF,EAAQrF,GACP1K,KAAKyc,iBAAiB1M,MACtB/P,KAAKlE,UAAUiU,MACf2qC,EAAa3qC,MACb0b,GAASovB,SAAS9qC,OAEnB0qC,EAAc1qC,EAAQ0b,GAASqvB,eAE/B96C,KAAKy6C,YAAcA,EACnBz6C,KAAK06C,aAAeA,EACpB16C,KAAKqW,QAAU9a,GACdkwB,GAASovB,SACTJ,EACAC,EACA16C,KAAKlE,UACLkE,KAAKyc,mBAENgD,GAAkCzf,KAAKqW,UAKxCwF,YAAa,SAAS3E,GACrB,GAAIqL,GAAQviB,KAAK0c,aAEjB,OAAO6F,GAAMrL,KAAcqL,EAAMrL,GAAYlX,KAAK+6C,cAAc7jC,KAMjE4E,gBAAiB,SAAShV,GACzB,GAAIk0C,GACA38C,EACAud,CAEJ,IAAItgB,EAAEe,QAAQyK,EAAMG,QAQnB,IALA+zC,EAAYh7C,KAAKkW,OAAO+L,sBACxB3mB,EAAEU,KAAKuS,GAAGxS,MAAO,SAASmb,GACzB8jC,EAAUt8C,KAAKwY,KAGX7Y,EAAI,EAAGA,EAAI28C,EAAUl9C,OAAQO,IAEjC,GADAud,EAAO5b,KAAK6b,YAAYm/B,EAAU38C,IAC9Bud,GACCA,EAAKq/B,YAAcn0C,EACtB,MAAO8U,IASZm/B,cAAe,SAASG,GAYvB,IAXA,GAKIt/B,GACA9f,EACAyK,EACAO,EARAq0C,EAAgBn7C,KAAKlE,UAAUC,UAC/Bq/C,KACAC,KACAC,KACApkC,EAAWgkC,EAORhkC,GACN0E,EAAOyP,GAAQnU,GACfpb,EAAYq/C,EAAcjkC,GAC1BA,EAAW,KAES,kBAAT0E,KACVA,GAAS2/B,QAAS3/B,IAGfA,IACHw/B,EAAU7xC,QAAQqS,GAClBy/B,EAAc9xC,QAAQqS,EAAKi/B,cAC3Bt0C,EAAWA,GAAYqV,EAAKrV,SAC5B2Q,EAAWA,GAAY0E,EAAKjZ,MAGzB7G,IACHw/C,EAAe/xC,QAAQzN,GACvByK,EAAWA,GAAYzK,EAAUyK,SACjC2Q,EAAWA,GAAYpb,EAAU6G,KAMnC,OAFAiZ,GAAOngB,EAAW2/C,GAClBx/B,EAAKjZ,KAAOu4C,IACPt/B,EAAK,WAINrV,IACHA,EAAWlL,EAAOkL,SAASA,GACvBA,EAAS4iB,YACZvN,EAAKrV,SAAWA,EAChBO,EAAOE,EAAoBT,GAID,IAAtBA,EAASc,GAAGP,KACf8U,EAAKq/B,WAAan0C,EAClBw0C,EAAe/xC,QAAQ4xC,EAAcr0C,WAKxC8U,EAAKi/B,SAAWt/C,EAAa8/C,GAC7Bz/B,EAAK9f,UAAYP,EAAa+/C,GAE9Bt7C,KAAKw7C,qBAAqB5/B,GAC1B5b,KAAKy7C,wBAAwB7/B,EAAMs/B,GAE5Bt/B,IAKR4/B,qBAAsB,SAAS5/B,GAC9BA,EAAKvF,QAAU9a,GACdkwB,GAASovB,SACTj/B,EAAKi/B,SACL76C,KAAKy6C,YACLz6C,KAAK06C,aACL16C,KAAKlE,UACL8f,EAAK9f,UACLkE,KAAKyc,mBAENgD,GAAkC7D,EAAKvF,UAKxColC,wBAAyB,SAAS7/B,EAAMs/B,GAIvC,QAASQ,GAAgBrlC,GACxB,GAAIkL,GAAalL,EAAQkL,cACzB,OAAOA,GAAW25B,KAChBt/B,EAAKq/B,WAAa15B,EAAW3F,EAAKq/B,YAAc,MAInDr/B,EAAKyF,mBACJq6B,EAAgB17C,KAAKyc,mBACrBi/B,EAAgB17C,KAAKlE,YACrB8f,EAAK9f,UAAUylB,WAGhB3F,EAAK0F,kBACJo6B,EAAgB17C,KAAK06C,eACrBgB,EAAgB17C,KAAKy6C,cACrB7+B,EAAKi/B,SAASt5B,YACdm6B,EAAgBjwB,GAASovB,YACxBj/B,EAAKrV,SAAWvG,KAAKif,iBAAiBrD,EAAKrV,UAAY,OACxD20C,GAKFzjC,gBAAiB,SAASP,GACzB,GAAI0E,GAAO5b,KAAK6b,YAAY3E,EAE5B,OAAO,IAAI0E,GAAK,SAAS5b,KAAMkX,EAAU0E,EAAKvF,QAASuF,EAAKrV,WAK7Do1C,gBAAiB,SAASzkC,GACzB,MAAO9O,SAAQpI,KAAK6b,YAAY3E,KAKjCyM,YAAa,WACN3jB,KAAK26C,gBACV36C,KAAKoZ,QAAQ,UAAW,MAAM,EAAMpZ,KAAKuX,OAM3CqM,WAAY,aACH5jB,KAAK26C,cACZ36C,KAAKoZ,QAAQ,UAAW,MAAM,EAAOpZ,KAAKuX,OAM5CsD,gBAAiB,SAASF,EAAiBC,GAC1C,GACI1U,GADAF,EAAQhG,KAAK3E,OAAOsf,GAAiBnM,WAazC,OATCtI,GADG0U,EACG5a,KAAK3E,OAAOuf,GAAepM,YAEzBxI,EAAMsY,UACRtY,EAAMK,QAAQ5G,IAAIO,KAAKoe,2BAGvBpY,EAAMK,QAAQ5G,IAAIO,KAAKme,6BAGrBnY,MAAOA,EAAOE,IAAKA,KAM9BulB,IAASkC,MAAMC,IAqyBfnC,GAASkC,OAQRvQ,eAAgB,KAIhBxH,WAAY,SAAS2G,EAAYq/B,GAChC57C,KAAKgW,aAAcuG,GAAcq/B,IAKlC5lC,YAAa,SAAS6lC,EAAaD,GAClC,GACIv9C,GADAy9C,GAAen3C,KAAMi3C,EAAa7xC,MAAO8xC,EAG7C,KAAKx9C,EAAI,EAAGA,EAAIw9C,EAAY/9C,OAAQO,IACnC2B,KAAK+7C,yBAAyBF,EAAYx9C,GAAIy9C,EAG/C97C,MAAKg8C,wBAAwBF,IAI9BC,yBAA0B,SAASx/B,EAAYu/B,IAC7C97C,KAAKod,eAAeb,KAAgBvc,KAAKod,eAAeb,QACvD7d,KAAKo9C,IAIRl/B,sBAAuB,SAASL,GAC/B,GACIle,GADA49C,EAAcj8C,KAAKod,eAAeb,MAGtC,KAAKle,EAAI,EAAGA,EAAI49C,EAAYn+C,OAAQO,IACnC2B,KAAKg8C,wBAAwBC,EAAY59C,KAK3C29C,wBAAyB,SAASF,GACjC,GAEIz9C,GAFAw9C,EAAcC,EAAW/xC,MACzBmyC,IAGJ,KAAK79C,EAAI,EAAGA,EAAIw9C,EAAY/9C,OAAQO,IACnC69C,EAAax9C,KAAKsB,KAAKqW,QAAQwlC,EAAYx9C,IAG5Cy9C,GAAWn3C,KAAK8F,MAAMzK,KAAMk8C,MAO9BzwB,GAASovB,UAERsB,oBAAqB,MACrBC,gBAAiB,YAEjBh+B,0BAA2B,WAC3BD,4BAA8B3X,KAAM,GACpCghB,oBAAoB,EACpB0uB,iBAAkB,WAGlB5/B,YAAa,QACb4C,YAAa,KACbhD,QACCvZ,KAAM,QACN0/C,OAAQ,GACRt/C,MAAO,mBAERu/C,UAAU,EACVC,aAAa,EAEbC,gBAAiB,IACjB9+B,sBAAuB,QAMvB++B,WAAY,WAGZ3iC,cAAc,EACdoK,WAAY,QACZC,SAAU,MACVC,cAAe,WAEf/F,UAAU,EAKVtO,OAAO,EACPwR,YACCxG,KAAM,OACNE,KAAM,OACNE,SAAU,YACVC,SAAU,YACV1M,KAAM,OACN2M,MAAO,QACP1M,MAAO,QACPwd,KAAM,OACNrE,IAAK,OAGNpG,aACC3G,KAAM,oBACNE,KAAM,qBACNE,SAAU,oBACVC,SAAU,sBAIXvF,OAAO,EACP2L,kBACCzG,KAAM,oBACNE,KAAM,oBACNE,SAAU,YACVC,SAAU,aAIXshC,YAAa,IACbC,mBAAoB,IACpBC,YAAY,EAGZC,cAAc,EAEdC,WAAY,IAEZC,WAAY,QAEZC,YAAY,EACZC,eAAgB,OAChBC,gBAAiB,UACjBC,iBAAkB,KAElB5mC,oBAAoB,EACpBG,kBAAmB,IAEnB0mC,eAAgB,KAKjB3xB,GAAS4xB,iBACRF,iBAAkB,gBAInB1xB,GAASqvB,aACR5kC,QACCvZ,KAAM,kBACN0/C,OAAQ,GACRt/C,MAAO,SAER2kB,aACC3G,KAAM,qBACNE,KAAM,oBACNE,SAAU,qBACVC,SAAU,qBAEXoG,kBACCzG,KAAM,oBACNE,KAAM,oBACNG,SAAU,YACVD,SAAU,aAMZ,IAAIy/B,IAAiBrsC,GAAG+uC,QASxB/uC,IAAGgvC,eAAiB,SAAS59B,EAAU69B,EAAYC,GAGlD,GAAIC,GAAY9C,GAAej7B,KAAci7B,GAAej7B,MAG5D+9B,GAAU3tC,MAAQ0tC,EAAU1tC,MAC5B2tC,EAAUlB,gBAAkBiB,EAAUE,WAGtCriD,EAAEU,KAAK4hD,GAAqB,SAAS3hD,EAAM0I,GAC1C+4C,EAAUzhD,GAAQ0I,EAAK84C,KAIpBniD,EAAEuiD,aAMLviD,EAAEuiD,WAAWC,SAASN,GACrBliD,EAAEuiD,WAAWC,SAASn+B,GACrB89B,EAGFniD,EAAEuiD,WAAWC,SAASC,GAAKziD,EAAEuiD,WAAWC,SAAS,IAGjDxiD,EAAEuiD,WAAWG,YAAYP,KAM3BlvC,GAAG0B,KAAO,SAAS0P,EAAUs+B,GAC5B,GAAIP,GACAQ,CAGJR,GAAY9C,GAAej7B,KAAci7B,GAAej7B,OAGpDs+B,IACHP,EAAY9C,GAAej7B,GAAYpkB,GAAemiD,EAAWO,KAMlEC,EAAavgC,GAAoBgC,GACjCrkB,EAAEU,KAAKmiD,GAAsB,SAASliD,EAAM0I,GACpB,MAAnB+4C,EAAUzhD,KACbyhD,EAAUzhD,GAAQ0I,EAAKu5C,EAAYR,MAKrCjyB,GAASovB,SAAS5qC,KAAO0P,EAM1B,IAAIi+B,KAEHr8B,WAAY,SAASk8B,GACpB,OAEC1iC,KAAMhQ,GAAkB0yC,EAAUW,UAClCnjC,KAAMlQ,GAAkB0yC,EAAUY,UAClChjC,MAAOtQ,GAAkB0yC,EAAUa,eAKrClC,gBAAiB,SAASqB,GACzB,MAAOA,GAAUc,mBAChB,QAAUd,EAAUe,WAAa,SACjC,aAAef,EAAUe,WAAa,MAKrCL,IAGHM,iBAAkB,SAASP,EAAYR,GACtC,GAAI1uC,GAASkvC,EAAWhuC,eAAe,IAWvC,OARAlB,GAASA,EAAOlE,QAAQ,2BAA4B,IAEhD4yC,EAAU3tC,MACbf,GAAU,OAGVA,EAAS,OAASA,EAEZA,GAIR0vC,iBAAkB,SAASR,GAC1B,MAAOA,GAAWhuC,eAAe,MAC/BpF,QAAQ,SAAU,MAIrB6zC,gBAAiB,SAAST,GACzB,MAAOA,GAAWhuC,eAAe,MAC/BpF,QAAQ,MAAO,SACfA,QAAQ,UAAW,QACnBA,QAAQ,SAAU,MAIrB8zC,qBAAsB,SAASV,GAC9B,MAAOA,GAAWhuC,eAAe,MAC/BpF,QAAQ,MAAO,SACfA,QAAQ,UAAW,QACnBA,QAAQ,SAAU,MAIrB+zC,WAAY,SAASX,GACpB,MAAOA,GAAWhuC,eAAe,MAC/BpF,QAAQ,MAAO,IACfA,QAAQ,UAAW,IACnBA,QAAQ,SAAU,MAIrBg0C,qBAAsB,SAASZ,GAC9B,MAAOA,GAAWhuC,eAAe,MAC/BpF,QAAQ,SAAU,MASlB4U,IAGHq/B,mBAAoB,SAAS1oC,GAC5B,MAAOA,GAAQtG,MACd,OACA,QAIFivC,WAAY,SAAS3oC,GACpB,MAAOA,GAAQtG,MACd,MAAQsG,EAAQmmC,gBAAkB,IAClC,IAAMnmC,EAAQmmC,gBAAkB,OAIlCyC,gBAAiB,SAAS5oC,GACzB,MAAOA,GAAQtG,MACd,KAAOsG,EAAQmmC,gBAAkB,IACjC,IAAMnmC,EAAQmmC,gBAAkB,MAyBnCjuC,IAAG0B,KAAK,KAAMwb,GAAS4xB,iBAiRvB9uC,GAAGoW,qBACHpW,GAAGmV,iBAEH,IAAIY,KACH46B,SAAU,OACV38B,OAAO,GAGJwE,GAAY,CAmqChB0E,IAAS9iB,UAAUye,eAAiB,SAAS9U,KAM7CmZ,GAAS9iB,UAAU4hB,iBAAmB,SAAS40B,EAAWC,GACzD,GAAIv0B,GAAas0B,EAAUn5C,MAAMK,QAAQmI,YACrCsc,EAAW9qB,KAAK6e,YAAYsgC,GAAW3wC,WAE3C,OAAO4wC,GAAUp5C,OAAS6kB,GAAcu0B,EAAUl5C,KAAO4kB,GAM1DW,GAAS9iB,UAAU6hB,cAAgB,SAASnB,EAAM/W,GACjD,GAEIjU,GAAGghD,EAFH98B,EAAQviB,KAAKirB,gBACbd,IAGJ,KAAK9rB,EAAI,EAAGA,EAAIkkB,EAAMzkB,OAAQO,IAC7BghD,EAAa98B,EAAMlkB,GAEjBiU,GACDA,EAAMQ,MAAQusC,EAAWvsC,KAEzBqX,EAAWzrB,KAAK2gD,EAIlB,OAAOl1B,GAeR,IAAI8W,KACHxb,GAAI,mBACJzf,MAAO,QACPE,IAAK,QACL+X,KAAO,EAAG,EAAG,EAAG,EAAG,GACnB1L,UAAW,qBAMZkZ,IAAS9iB,UAAUgiB,6BAA+B,SAASoW,GAC1D,MAAO/gC,MAAKs/C,0BAA0Bve,EAAU/gC,KAAKqW,QAAQ2qB,gBAI9DvV,GAAS9iB,UAAU22C,0BAA4B,SAASve,EAAUnlC,GACjE,MAAIA,MAAU,EACNoE,KAAKu/C,yBAAyBxe,QAE7BzlC,EAAEa,cAAcP,GACjBoE,KAAKu/C,yBAAyBxe,GAAYnlC,IAEzCN,EAAEgJ,QAAQ1I,GACXoE,KAAKu/C,yBAAyBxe,EAAUnlC,GAAO,OASxD6vB,GAAS9iB,UAAU42C,yBAA2B,SAASxe,EAAU9yB,EAAQuxC,GACxE,GAEInhD,GAAGzC,EAFH2b,EAAOvX,KAAKkc,UACZtJ,IAGJ,KAAKvU,EAAI,EAAGA,EAAI4P,EAAOnQ,OAAQO,IAC9BzC,EAAQqS,EAAO5P,GAEXmhD,IAAgB5jD,EAAMqiB,MAK1BriB,EAAQN,EAAEmY,UAAWwtB,GAA8BrlC,GAG/CmlC,IACHnlC,EAAMoK,MAAQ,KACdpK,EAAMsK,IAAM,MAGb0M,EAAOlU,KAAK+L,MAAMmI,EACjB5S,KAAKojB,YACJpjB,KAAKmjB,oBAAoBvnB,GACzB2b,EAAKvR,MACLuR,EAAKrR,MAKR,OAAO0M,GAUR,IAAI6sC,IAAYlxC,GAAGkxC,UAAY3J,GAAKriC,QAEnCisC,SAAU,KAEVC,aAAc/V,GACdgW,QAAS,KAETjV,mBAAmB,EACnBkV,oBAAoB,EAEpBC,gBAAiB,KAEjBC,gBAAiB,KACjBC,UAAW,KAGXxgC,WAAY,WACXxf,KAAK4/C,QAAU5/C,KAAKigD,qBAEpBjgD,KAAK0/C,SAAW,GAAI7F,KACnBC,UAAW,SACXC,UAAW,UAMbkG,mBAAoB,WAGnB,GAAIC,GAAWlgD,KAAK2/C,aAAalsC,OAAO0sC,GAExC,OAAO,IAAID,GAASlgD,OAKrBi7B,SAAU,SAASrQ,GAClBkrB,GAAKntC,UAAUsyB,SAASpyB,KAAK7I,KAAM4qB,GAEnC5qB,KAAK4/C,QAAQpZ,aAAe,kBAAkBpqC,KAAK4D,KAAKi2C,cACxDj2C,KAAK4/C,QAAQ3kB,SAASrQ,IAKvBgsB,aAAc,SAAShoC,GACtB,GAAIgc,GAAQkrB,GAAKntC,UAAUiuC,aAAa/tC,KAAK7I,KAAM4O,EAcnD,OAXI,aAAaxS,KAAKwuB,EAAMqrB,gBAC3BrrB,EAAM5kB,MAAM6wC,QAAQ,QACpBjsB,EAAM5kB,MAAQhG,KAAK82C,eAAelsB,EAAM5kB,OAGpC4kB,EAAM1kB,IAAIk6C,YACbx1B,EAAM1kB,IAAIzG,IAAI,EAAG,QAAQo3C,QAAQ,QACjCjsB,EAAM1kB,IAAMlG,KAAK82C,eAAelsB,EAAM1kB,QAAS,KAI1C0kB,GAKRmR,YAAa,WAEZ/7B,KAAK2qC,kBAAoB3qC,KAAK4/C,QAAQhZ,OAAS,EAC/C5mC,KAAK6/C,mBAAqB7/C,KAAK46B,IAAI,eACnC56B,KAAK4/C,QAAQ/V,eAAiB7pC,KAAK2qC,mBAAqB3qC,KAAK6/C,mBAE7D7/C,KAAK1B,GAAGlB,SAAS,iBAAiBuhC,KAAK3+B,KAAKqgD,sBAC5CrgD,KAAKsgD,aAELtgD,KAAK0/C,SAASrqC,QACd,IAAIkrC,GAAqBvgD,KAAK0/C,SAASphD,GAAGlB,SAAS,yBAC/CojD,EAAYllD,EAAE,+BAA+BmG,SAAS8+C,EAC1DvgD,MAAK1B,GAAGU,KAAK,sBAAsBghB,OAAOugC,GAE1CvgD,KAAK4/C,QAAQloC,WAAW8oC,GACxBxgD,KAAK4/C,QAAQ7jB,YAAY/7B,KAAKygD,iBAK/BH,WAAY,WACXtgD,KAAK+/C,gBACJ//C,KAAK1B,GAAGU,KAAK,sBACX2/B,KAAK3+B,KAAK4/C,QAAQlX,kBACrB1oC,KAAKggD,UAAYhgD,KAAK+/C,gBAAgB/gD,KAAK,YAM5Cg9B,cAAe,WACdh8B,KAAK4/C,QAAQ5jB,gBACbh8B,KAAK4/C,QAAQ7oC,gBACb/W,KAAK0/C,SAAS7oC,WAIfiG,oBAAqB,WACpB9c,KAAK4/C,QAAQ9iC,uBAIdD,sBAAuB,WACtB7c,KAAK4/C,QAAQ/iC,yBAMdwjC,mBAAoB,WACnB,MAAO,kEAI+BrgD,KAAK2oC,kBAAoB,6DAK3C3oC,KAAKwpC,mBAAqB,gCAQ/CkX,oBAAqB,WACpB,MAA6B,QAAzB1gD,KAAK8/C,gBACD,gBAAkB9/C,KAAK8/C,gBAAkB,MAE1C,IAKRW,aAAc,WACb,GAAIzD,GAAah9C,KAAK46B,IAAI,aAC1B,OAAOoiB,IAAoC,gBAAfA,IAS7B/E,YAAa,WACRj4C,KAAK6/C,qBAGR7/C,KAAK8/C,gBAAkBhhD,EACtBkB,KAAK1B,GAAGU,KAAK,sBAOhBk5C,UAAW,SAASyI,EAAaxI,GAChC,GACIyI,GACAlkD,EAFAsgD,EAAah9C,KAAK46B,IAAI,aAK1B56B,MAAK0/C,SAASvuB,QACdj0B,EAAmB8C,KAAKggD,WAExBhgD,KAAK4/C,QAAQtV,mBAGT0S,GAAoC,gBAAfA,IACxBh9C,KAAK4/C,QAAQrS,UAAUyP,GAKxB4D,EAAiB5gD,KAAK6gD,sBAAsBF,GAC5C3gD,KAAK8gD,cAAcF,EAAgBzI,GAG/B6E,GAAoC,gBAAfA,IACxBh9C,KAAK4/C,QAAQrS,UAAUyP,GAGnB7E,IAEJn4C,KAAK0/C,SAASxH,UAAU0I,GACxBlkD,EAAkBsD,KAAK0/C,SAASh/C,sBAE5BhE,EAAgBC,MAAQD,EAAgBK,SAE3CP,EAAiBwD,KAAKggD,UAAWtjD,GAGjCkkD,EAAiB5gD,KAAK6gD,sBAAsBF,GAC5C3gD,KAAK0/C,SAASxH,UAAU0I,IAIzB5gD,KAAK0/C,SAAStF,aAAa19C,KAM7BmkD,sBAAuB,SAASF,GAC/B,MAAOA,GACNthD,EAAsBW,KAAK1B,GAAI0B,KAAK0/C,SAASphD,KAK/CwiD,cAAe,SAASniD,EAAQw5C,GAC3BA,EACH/5C,EAAmB4B,KAAK4/C,QAAQnjD,QAGhCc,EAAiByC,KAAK4/C,QAAQnjD,OAAQkC,GAAQ,IAShD8Z,YAAa,WACZ,MAAOzY,MAAK0/C,SAASrF,gBAItBjD,UAAW,SAAS72C,GACnBP,KAAK0/C,SAASpF,aAAa/5C,IAS5Bg4B,YAAa,WACZv4B,KAAK4/C,QAAQrnB,eAIdK,YAAa,WACZ54B,KAAK4/C,QAAQhnB,eAIdP,SAAU,SAAS17B,EAAM4D,GACxB,MAAOP,MAAK4/C,QAAQvnB,SAAS17B,EAAM4D,IAIpC86B,WAAY,SAASrD,GACpB,MAAOh4B,MAAK4/C,QAAQvkB,WAAWrD,IAIhCsD,SAAU,SAAStD,GAClB,MAAOh4B,MAAK4/C,QAAQtkB,SAAStD,IAS9Bpe,aAAc,SAAShH,GACtB5S,KAAK4/C,QAAQhmC,aAAahH,GAE1B5S,KAAKg4C,gBAKN7X,aAAc,WACb,MAAOngC,MAAK4/C,QAAQzf,gBAKrBJ,eAAgB,WACf//B,KAAK4/C,QAAQ7f,kBAad6C,WAAY,SAASP,EAAc1uB,GAClC,MAAO3T,MAAK4/C,QAAQhd,WAAWP,EAAc1uB,IAI9CmvB,aAAc,WACb9iC,KAAK4/C,QAAQ9c,gBASdhG,gBAAiB,SAASzT,GACzBrpB,KAAK4/C,QAAQ9iB,gBAAgBzT,IAK9B2T,kBAAmB,WAClBh9B,KAAK4/C,QAAQ5iB,uBAOXmjB,IAIHtX,oBAAqB,WACpB,GAAItxB,GAAOvX,KAAKuX,IAEhB,OAAIA,GAAKsoC,mBACD,6BACyBtoC,EAAKoxB,kBAAoB,KAAOpxB,EAAKmpC,sBAAwB,UAE1F91C,GAAW2M,EAAKqjB,IAAI,oBACrB,eAII,IAKR4P,sBAAuB,SAASjD,GAC/B,GAAIhwB,GAAOvX,KAAKuX,IAEhB,OAAIA,GAAKsoC,mBACD,8BAC0BtoC,EAAKmpC,sBAAwB,UAE3D1gD,KAAKsnC,YAAYC,EAAK,GAAGv4B,OAAO,KACjC,eAII,IAKRq6B,kBAAmB,WAClB,GAAI9xB,GAAOvX,KAAKuX,IAEhB,OAAIA,GAAKsoC,mBACD,6BAA+BtoC,EAAKiyB,mBAAqB,KAC/DjyB,EAAKmpC,sBAAwB,SAGxB,IAMR5X,gBAAiB,WAChB,GAAIvxB,GAAOvX,KAAKuX,IAEhB,OAAIA,GAAKsoC,mBACD,8BAAgCtoC,EAAKmpC,sBAAwB,SAG9D,KAULK,GAAYxyC,GAAGwyC,UAAYtB,GAAUhsC,QAGxCmjC,aAAc,SAAShoC,GACtB,GACIg4B,GADAhc,EAAQ60B,GAAU92C,UAAUiuC,aAAa/tC,KAAK7I,KAAM4O,EASxD,OALI5O,MAAKghD,iBACRpa,EAAShpC,KAAKspC,KAAKtc,EAAM1kB,IAAI3G,KAAKqrB,EAAM5kB,MAAO,SAAS,IACxD4kB,EAAM1kB,IAAIzG,IAAI,EAAImnC,EAAQ,UAGpBhc,GAKRk2B,cAAe,SAASniD,EAAQw5C,GAE/BA,EAASA,GAAmC,aAAzBn4C,KAAK46B,IAAI,YAGxBud,IACHx5C,GAAUqB,KAAK4mC,OAAS,GAGzBrpC,EAAiByC,KAAK4/C,QAAQnjD,OAAQkC,GAASw5C,IAIhD6I,aAAc,WACb,GAAIC,GAAWjhD,KAAK46B,IAAI,WACxB,OAAIqmB,GACiB,UAAbA,EAGDjhD,KAAK46B,IAAI,oBAOlBvP,IAAQ61B,OACP3F,QAASkE,IAGVp0B,GAAQ81B,UACPx+C,KAAM,QACN4D,UAAYC,KAAM,IAGnB6kB,GAAQ+1B,WACPz+C,KAAM,QACN4D,UAAY6lB,MAAO,IAGpBf,GAAQ1c,OACP4sC,QAASwF,GACTx6C,UAAYiB,OAAQ,GACpBqzC,UACCwG,gBAAgB,GAUlB,IAAIC,IAAa/yC,GAAG+yC,WAAaxL,GAAKriC,QAErCisC,SAAU,KAEV6B,cAAejR,GACfkR,SAAU,KAEV7B,aAAc/V,GACdgW,QAAS,KAET6B,UAAW,KAEX1B,gBAAiB,KACjB2B,eAAgB,KAGhBC,aAAc,KAGdniC,WAAY,WACXxf,KAAKwhD,SAAWxhD,KAAK4hD,sBAEjB5hD,KAAK46B,IAAI,gBACZ56B,KAAK4/C,QAAU5/C,KAAKigD,sBAGrBjgD,KAAK0/C,SAAW,GAAI7F,KACnBC,UAAW,SACXC,UAAW,UAMb6H,oBAAqB,WACpB,GAAI1B,GAAWlgD,KAAKuhD,cAAc9tC,OAAOouC,GAEzC,OAAO,IAAI3B,GAASlgD,OAKrBigD,mBAAoB,WACnB,GAAIC,GAAWlgD,KAAK2/C,aAAalsC,OAAOquC,GAExC,OAAO,IAAI5B,GAASlgD,OASrBi7B,SAAU,SAASrQ,GAClBkrB,GAAKntC,UAAUsyB,SAASpyB,KAAK7I,KAAM4qB,GAEnC5qB,KAAKwhD,SAASvmB,SAASrQ,GACnB5qB,KAAK4/C,SACR5/C,KAAK4/C,QAAQ3kB,SAASrQ,IAMxBmR,YAAa,WAEZ/7B,KAAK1B,GAAGlB,SAAS,kBAAkBuhC,KAAK3+B,KAAKqgD,sBAC7CrgD,KAAKsgD,aAELtgD,KAAK0/C,SAASrqC,QACd,IAAI0sC,GAAiB/hD,KAAK0/C,SAASphD,GAAGlB,SAAS,0BAC3C4kD,EAAa1mD,EAAE,gCAAgCmG,SAASsgD,EAC5D/hD,MAAK1B,GAAGU,KAAK,sBAAsBghB,OAAO+hC,GAE1C/hD,KAAKwhD,SAAS9pC,WAAWsqC,GACzBhiD,KAAKwhD,SAASzlB,cAGd/7B,KAAK2hD,aAAermD,EAAE,yBAA2B0E,KAAK2oC,kBAAoB,OACxElnC,SAASzB,KAAKwhD,SAASljD,IAErB0B,KAAK4/C,UACR5/C,KAAK4/C,QAAQloC,WAAW1X,KAAK1B,GAAGU,KAAK,iBACrCgB,KAAK4/C,QAAQ7jB,cAGb/7B,KAAK4/C,QAAQ9V,mBAAqB9pC,KAAK4/C,QAAQthD,GAAG2c,KAAK,MAAMxc,eAG9DuB,KAAK0hD,eAAiB1hD,KAAK1B,GAAGU,KAAK,gCAKpCshD,WAAY,WACXtgD,KAAK+/C,gBACJ//C,KAAK1B,GAAGU,KAAK,sBACX2/B,KAAK3+B,KAAKwhD,SAAS9Y,mBAMvB1M,cAAe,WACdh8B,KAAKwhD,SAASxlB,gBACdh8B,KAAKwhD,SAASzqC,gBAEV/W,KAAK4/C,UACR5/C,KAAK4/C,QAAQ5jB,gBACbh8B,KAAK4/C,QAAQ7oC,iBAGd/W,KAAK0/C,SAAS7oC,WAMfwpC,mBAAoB,WACnB,MAAO,kEAI+BrgD,KAAK2oC,kBAAoB,6DAK3C3oC,KAAKwpC,mBAAqB,MACxCxpC,KAAK4/C,QACL,mDAC2B5/C,KAAK2oC,kBAAoB,MACpD,IAEF,8BAQLgJ,cAAe,WACd,MAAuB,QAAnB3xC,KAAKyhD,UACA,gBAAkBzhD,KAAKyhD,UAAY,MAErC,IAQR3kC,oBAAqB,WACpB9c,KAAKwhD,SAAS1kC,sBAEV9c,KAAK4/C,SACR5/C,KAAK4/C,QAAQ9iC,uBAKfD,sBAAuB,WACtB7c,KAAKwhD,SAAS3kC,wBAEV7c,KAAK4/C,SACR5/C,KAAK4/C,QAAQ/iC,yBASfyhB,oBAAqB,WACpB,MAAOt+B,MAAKwhD,SAASljB,uBAItBC,mBAAoB,SAAS3vB,GAC5B5O,KAAKwhD,SAASjjB,mBAAmB3vB,IAIlC4vB,qBAAsB,WACrBx+B,KAAKwhD,SAAShjB,wBAQf9lB,WAAY,SAASi6B,GACpB3yC,KAAKwhD,SAAS9oC,WAAWi6B,GAEzBmD,GAAKntC,UAAU+P,WAAW7P,KAAK7I,KAAM2yC,IAKtCsF,YAAa,WAEZj4C,KAAKyhD,UAAY3iD,EAAgBkB,KAAK1B,GAAGU,KAAK,cAK/Ck5C,UAAW,SAASyI,EAAaxI,GAChC,GAAI6E,GACA4D,EACAlkD,CAGJsD,MAAK2hD,aAAaryB,OAClBtvB,KAAK0/C,SAASvuB,QACdj0B,EAAmB8C,KAAK0hD,gBAGpB1hD,KAAK4/C,UACR5/C,KAAK4/C,QAAQtV,mBAEb0S,EAAah9C,KAAK46B,IAAI,cAClBoiB,GAAoC,gBAAfA,KACxBA,EAAaiF,IAEVjF,GACHh9C,KAAK4/C,QAAQrS,UAAUyP,IAIpB7E,IAEJyI,EAAiB5gD,KAAK6gD,sBAAsBF,GAC5C3gD,KAAK0/C,SAASxH,UAAU0I,GACxBlkD,EAAkBsD,KAAK0/C,SAASh/C,sBAE5BhE,EAAgBC,MAAQD,EAAgBK,SAG3CP,EAAiBwD,KAAK0hD,eAAgBhlD,GAItCkkD,EAAiB5gD,KAAK6gD,sBAAsBF,GAC5C3gD,KAAK0/C,SAASxH,UAAU0I,IAIzB5gD,KAAK0/C,SAAStF,aAAa19C,GAIvBsD,KAAKwhD,SAASxO,qBAAuB4N,GACxC5gD,KAAK2hD,aAAatyB,SAOrBwxB,sBAAuB,SAASF,GAC/B,MAAOA,GACNthD,EAAsBW,KAAK1B,GAAI0B,KAAK0/C,SAASphD,KAS/Cg5C,qBAAsB,WACrB,GAAImF,GAAaphD,EAAOkL,SAASvG,KAAK46B,IAAI,eACtCr6B,EAAMP,KAAKwhD,SAASrO,eAAesJ,EASvC,OANAl8C,GAAM3C,KAAKspC,KAAK3mC,GAEZA,GACHA,IAGMA,GAIRkY,YAAa,WACZ,MAAOzY,MAAK0/C,SAASrF,gBAItBjD,UAAW,SAAS72C,GACnBP,KAAK0/C,SAASpF,aAAa/5C,IAS5Bg4B,YAAa,WACZv4B,KAAKwhD,SAASjpB,cACVv4B,KAAK4/C,SACR5/C,KAAK4/C,QAAQrnB,eAKfK,YAAa,WACZ54B,KAAKwhD,SAAS5oB,cACV54B,KAAK4/C,SACR5/C,KAAK4/C,QAAQhnB,eAKfP,SAAU,SAAS17B,EAAM4D,GACxB,GAAIy3B,GAAMh4B,KAAKwhD,SAASnpB,SAAS17B,EAAM4D,EAMvC,QAJKy3B,GAAOh4B,KAAK4/C,UAChB5nB,EAAMh4B,KAAK4/C,QAAQvnB,SAAS17B,EAAM4D,IAG5By3B,GAIRqD,WAAY,SAASrD,GAEpB,MAAOA,GAAIhmB,UAAUqpB,WAAWrD,IAIjCsD,SAAU,SAAStD,GAElB,MAAOA,GAAIhmB,UAAUspB,SAAStD,IAS/Bpe,aAAc,SAAShH,GACtB,GAGIsvC,GACA7jD,EAJA8jD,KACAC,KACAC,IAKJ,KAAKhkD,EAAI,EAAGA,EAAIuU,EAAO9U,OAAQO,IAC1BuU,EAAOvU,GAAG0gB,OACbojC,EAAUzjD,KAAKkU,EAAOvU,IAGtB+jD,EAAY1jD,KAAKkU,EAAOvU,GAK1B6jD,GAAYliD,KAAKwhD,SAAS5nC,aAAawoC,GACnCpiD,KAAK4/C,UACRyC,EAAUriD,KAAK4/C,QAAQhmC,aAAauoC,IAIrCniD,KAAKg4C,gBAKN7X,aAAc,WACb,MAAOngC,MAAKwhD,SAASrhB,eAAepV,OACnC/qB,KAAK4/C,QAAU5/C,KAAK4/C,QAAQzf,oBAM9BJ,eAAgB,WAGf//B,KAAKwhD,SAASzhB,iBACV//B,KAAK4/C,SACR5/C,KAAK4/C,QAAQ7f,kBAcf6C,WAAY,SAASP,EAAc1uB,GAClC,MAAI0uB,GAAar8B,MAAMsY,UACfte,KAAKwhD,SAAS5e,WAAWP,EAAc1uB,GAEtC3T,KAAK4/C,QACN5/C,KAAK4/C,QAAQhd,WAAWP,EAAc1uB,GADzC,QAMNmvB,aAAc,WACb9iC,KAAKwhD,SAAS1e,eACV9iC,KAAK4/C,SACR5/C,KAAK4/C,QAAQ9c,gBAUfhG,gBAAiB,SAASzT,GACrBA,EAAKrjB,MAAMsY,WAAa+K,EAAKnjB,IAAIoY,UACpCte,KAAKwhD,SAAS1kB,gBAAgBzT,GAEtBrpB,KAAK4/C,SACb5/C,KAAK4/C,QAAQ9iB,gBAAgBzT,IAM/B2T,kBAAmB,WAClBh9B,KAAKwhD,SAASxkB,oBACVh9B,KAAK4/C,SACR5/C,KAAK4/C,QAAQ5iB,uBASZ6kB,IAIHhZ,oBAAqB,WACpB,GACIyZ,GADA/qC,EAAOvX,KAAKuX,IAGhB,OAAIA,GAAKqjB,IAAI,gBACZ0nB,EAAWtiD,KAAKgG,MAAMgJ,OAAOuI,EAAKqjB,IAAI,oBAE/B,qCACiCrjB,EAAKoxB,kBAAoB,KAAOpxB,EAAKo6B,gBAAkB,UAE5F/mC,GAAW03C,GACZ,gBAIK,sBAAwB/qC,EAAKoxB,kBAAoB,KAAOpxB,EAAKo6B,gBAAkB,UAMxFtI,kBAAmB,WAClB,GAAI9xB,GAAOvX,KAAKuX,IAEhB,OAAO,sBAAwBA,EAAKiyB,mBAAqB,KAAOjyB,EAAKo6B,gBAAkB,UAMxF7I,gBAAiB,WAChB,GAAIvxB,GAAOvX,KAAKuX,IAEhB,OAAO,uBAAyBA,EAAKo6B,gBAAkB,WAOrDmQ,IAIHzY,kBAAmB,WAClB,GAAI9xB,GAAOvX,KAAKuX,IAEhB,OAAO,sBACkBA,EAAKiyB,mBAAqB,KAAOjyB,EAAKo6B,gBAAkB,WAE7Ep6B,EAAKqjB,IAAI,eAAiBhwB,GAAW2M,EAAKqjB,IAAI,gBAChD,gBAOHkO,gBAAiB,WAChB,GAAIvxB,GAAOvX,KAAKuX,IAEhB,OAAO,uBAAyBA,EAAKo6B,gBAAkB,WAOrDsQ,GAA6B,EAI7BnQ,KACDzpC,MAAO,IACPC,QAAS,KACTA,QAAS,KACTC,QAAS,KACTA,QAAS,IA0BZ,OAvBA8iB,IAAQk3B,QACPhH,QAAS+F,GACTzG,UACC2H,YAAY,EACZC,WAAY,UACZlS,aAAc,WACdG,QAAS,WACTC,QAAS,WACT+R,kBAAkB,IAIpBr3B,GAAQs3B,WACPhgD,KAAM,SACN4D,UAAYC,KAAM,IAGnB6kB,GAAQu3B,YACPjgD,KAAM,SACN4D,UAAY6lB,MAAO,IAIb7d","file":"libs/fullcalendar.min.js","sourcesContent":["/*!\n * <%= meta.title %> v<%= meta.version %>\n * Docs & License: <%= meta.homepage %>\n * (c) <%= meta.copyright %>\n */\n\n(function(factory) {\n\tif (typeof define === 'function' && define.amd) {\n\t\tdefine([ 'jquery', 'moment' ], factory);\n\t}\n\telse if (typeof exports === 'object') { // Node/CommonJS\n\t\tmodule.exports = factory(require('jquery'), require('moment'));\n\t}\n\telse {\n\t\tfactory(jQuery, moment);\n\t}\n})(function($, moment) {\n\n;;\n\nvar FC = $.fullCalendar = {\n\tversion: \"<%= meta.version %>\",\n\tinternalApiVersion: 5\n};\nvar fcViews = FC.views = {};\n\n\n$.fn.fullCalendar = function(options) {\n\tvar args = Array.prototype.slice.call(arguments, 1); // for a possible method call\n\tvar res = this; // what this function will return (this jQuery object by default)\n\n\tthis.each(function(i, _element) { // loop each DOM element involved\n\t\tvar element = $(_element);\n\t\tvar calendar = element.data('fullCalendar'); // get the existing calendar object (if any)\n\t\tvar singleRes; // the returned value of this single method call\n\n\t\t// a method call\n\t\tif (typeof options === 'string') {\n\t\t\tif (calendar && $.isFunction(calendar[options])) {\n\t\t\t\tsingleRes = calendar[options].apply(calendar, args);\n\t\t\t\tif (!i) {\n\t\t\t\t\tres = singleRes; // record the first method call result\n\t\t\t\t}\n\t\t\t\tif (options === 'destroy') { // for the destroy method, must remove Calendar object data\n\t\t\t\t\telement.removeData('fullCalendar');\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// a new calendar initialization\n\t\telse if (!calendar) { // don't initialize twice\n\t\t\tcalendar = new Calendar(element, options);\n\t\t\telement.data('fullCalendar', calendar);\n\t\t\tcalendar.render();\n\t\t}\n\t});\n\t\n\treturn res;\n};\n\n\nvar complexOptions = [ // names of options that are objects whose properties should be combined\n\t'header',\n\t'buttonText',\n\t'buttonIcons',\n\t'themeButtonIcons'\n];\n\n\n// Merges an array of option objects into a single object\nfunction mergeOptions(optionObjs) {\n\treturn mergeProps(optionObjs, complexOptions);\n}\n\n\n// Given options specified for the calendar's constructor, massages any legacy options into a non-legacy form.\n// Converts View-Option-Hashes into the View-Specific-Options format.\nfunction massageOverrides(input) {\n\tvar overrides = { views: input.views || {} }; // the output. ensure a `views` hash\n\tvar subObj;\n\n\t// iterate through all option override properties (except `views`)\n\t$.each(input, function(name, val) {\n\t\tif (name != 'views') {\n\n\t\t\t// could the value be a legacy View-Option-Hash?\n\t\t\tif (\n\t\t\t\t$.isPlainObject(val) &&\n\t\t\t\t!/(time|duration|interval)$/i.test(name) && // exclude duration options. might be given as objects\n\t\t\t\t$.inArray(name, complexOptions) == -1 // complex options aren't allowed to be View-Option-Hashes\n\t\t\t) {\n\t\t\t\tsubObj = null;\n\n\t\t\t\t// iterate through the properties of this possible View-Option-Hash value\n\t\t\t\t$.each(val, function(subName, subVal) {\n\n\t\t\t\t\t// is the property targeting a view?\n\t\t\t\t\tif (/^(month|week|day|default|basic(Week|Day)?|agenda(Week|Day)?)$/.test(subName)) {\n\t\t\t\t\t\tif (!overrides.views[subName]) { // ensure the view-target entry exists\n\t\t\t\t\t\t\toverrides.views[subName] = {};\n\t\t\t\t\t\t}\n\t\t\t\t\t\toverrides.views[subName][name] = subVal; // record the value in the `views` object\n\t\t\t\t\t}\n\t\t\t\t\telse { // a non-View-Option-Hash property\n\t\t\t\t\t\tif (!subObj) {\n\t\t\t\t\t\t\tsubObj = {};\n\t\t\t\t\t\t}\n\t\t\t\t\t\tsubObj[subName] = subVal; // accumulate these unrelated values for later\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tif (subObj) { // non-View-Option-Hash properties? transfer them as-is\n\t\t\t\t\toverrides[name] = subObj;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\toverrides[name] = val; // transfer normal options as-is\n\t\t\t}\n\t\t}\n\t});\n\n\treturn overrides;\n}\n\n;;\n\n// exports\nFC.intersectRanges = intersectRanges;\nFC.applyAll = applyAll;\nFC.debounce = debounce;\nFC.isInt = isInt;\nFC.htmlEscape = htmlEscape;\nFC.cssToStr = cssToStr;\nFC.proxy = proxy;\nFC.capitaliseFirstLetter = capitaliseFirstLetter;\n\n\n/* FullCalendar-specific DOM Utilities\n----------------------------------------------------------------------------------------------------------------------*/\n\n\n// Given the scrollbar widths of some other container, create borders/margins on rowEls in order to match the left\n// and right space that was offset by the scrollbars. A 1-pixel border first, then margin beyond that.\nfunction compensateScroll(rowEls, scrollbarWidths) {\n\tif (scrollbarWidths.left) {\n\t\trowEls.css({\n\t\t\t'border-left-width': 1,\n\t\t\t'margin-left': scrollbarWidths.left - 1\n\t\t});\n\t}\n\tif (scrollbarWidths.right) {\n\t\trowEls.css({\n\t\t\t'border-right-width': 1,\n\t\t\t'margin-right': scrollbarWidths.right - 1\n\t\t});\n\t}\n}\n\n\n// Undoes compensateScroll and restores all borders/margins\nfunction uncompensateScroll(rowEls) {\n\trowEls.css({\n\t\t'margin-left': '',\n\t\t'margin-right': '',\n\t\t'border-left-width': '',\n\t\t'border-right-width': ''\n\t});\n}\n\n\n// Make the mouse cursor express that an event is not allowed in the current area\nfunction disableCursor() {\n\t$('body').addClass('fc-not-allowed');\n}\n\n\n// Returns the mouse cursor to its original look\nfunction enableCursor() {\n\t$('body').removeClass('fc-not-allowed');\n}\n\n\n// Given a total available height to fill, have `els` (essentially child rows) expand to accomodate.\n// By default, all elements that are shorter than the recommended height are expanded uniformly, not considering\n// any other els that are already too tall. if `shouldRedistribute` is on, it considers these tall rows and \n// reduces the available height.\nfunction distributeHeight(els, availableHeight, shouldRedistribute) {\n\n\t// *FLOORING NOTE*: we floor in certain places because zoom can give inaccurate floating-point dimensions,\n\t// and it is better to be shorter than taller, to avoid creating unnecessary scrollbars.\n\n\tvar minOffset1 = Math.floor(availableHeight / els.length); // for non-last element\n\tvar minOffset2 = Math.floor(availableHeight - minOffset1 * (els.length - 1)); // for last element *FLOORING NOTE*\n\tvar flexEls = []; // elements that are allowed to expand. array of DOM nodes\n\tvar flexOffsets = []; // amount of vertical space it takes up\n\tvar flexHeights = []; // actual css height\n\tvar usedHeight = 0;\n\n\tundistributeHeight(els); // give all elements their natural height\n\n\t// find elements that are below the recommended height (expandable).\n\t// important to query for heights in a single first pass (to avoid reflow oscillation).\n\tels.each(function(i, el) {\n\t\tvar minOffset = i === els.length - 1 ? minOffset2 : minOffset1;\n\t\tvar naturalOffset = $(el).outerHeight(true);\n\n\t\tif (naturalOffset < minOffset) {\n\t\t\tflexEls.push(el);\n\t\t\tflexOffsets.push(naturalOffset);\n\t\t\tflexHeights.push($(el).height());\n\t\t}\n\t\telse {\n\t\t\t// this element stretches past recommended height (non-expandable). mark the space as occupied.\n\t\t\tusedHeight += naturalOffset;\n\t\t}\n\t});\n\n\t// readjust the recommended height to only consider the height available to non-maxed-out rows.\n\tif (shouldRedistribute) {\n\t\tavailableHeight -= usedHeight;\n\t\tminOffset1 = Math.floor(availableHeight / flexEls.length);\n\t\tminOffset2 = Math.floor(availableHeight - minOffset1 * (flexEls.length - 1)); // *FLOORING NOTE*\n\t}\n\n\t// assign heights to all expandable elements\n\t$(flexEls).each(function(i, el) {\n\t\tvar minOffset = i === flexEls.length - 1 ? minOffset2 : minOffset1;\n\t\tvar naturalOffset = flexOffsets[i];\n\t\tvar naturalHeight = flexHeights[i];\n\t\tvar newHeight = minOffset - (naturalOffset - naturalHeight); // subtract the margin/padding\n\n\t\tif (naturalOffset < minOffset) { // we check this again because redistribution might have changed things\n\t\t\t$(el).height(newHeight);\n\t\t}\n\t});\n}\n\n\n// Undoes distrubuteHeight, restoring all els to their natural height\nfunction undistributeHeight(els) {\n\tels.height('');\n}\n\n\n// Given `els`, a jQuery set of cells, find the cell with the largest natural width and set the widths of all the\n// cells to be that width.\n// PREREQUISITE: if you want a cell to take up width, it needs to have a single inner element w/ display:inline\nfunction matchCellWidths(els) {\n\tvar maxInnerWidth = 0;\n\n\tels.find('> span').each(function(i, innerEl) {\n\t\tvar innerWidth = $(innerEl).outerWidth();\n\t\tif (innerWidth > maxInnerWidth) {\n\t\t\tmaxInnerWidth = innerWidth;\n\t\t}\n\t});\n\n\tmaxInnerWidth++; // sometimes not accurate of width the text needs to stay on one line. insurance\n\n\tels.width(maxInnerWidth);\n\n\treturn maxInnerWidth;\n}\n\n\n// Given one element that resides inside another,\n// Subtracts the height of the inner element from the outer element.\nfunction subtractInnerElHeight(outerEl, innerEl) {\n\tvar both = outerEl.add(innerEl);\n\tvar diff;\n\n\t// effin' IE8/9/10/11 sometimes returns 0 for dimensions. this weird hack was the only thing that worked\n\tboth.css({\n\t\tposition: 'relative', // cause a reflow, which will force fresh dimension recalculation\n\t\tleft: -1 // ensure reflow in case the el was already relative. negative is less likely to cause new scroll\n\t});\n\tdiff = outerEl.outerHeight() - innerEl.outerHeight(); // grab the dimensions\n\tboth.css({ position: '', left: '' }); // undo hack\n\n\treturn diff;\n}\n\n\n/* Element Geom Utilities\n----------------------------------------------------------------------------------------------------------------------*/\n\nFC.getOuterRect = getOuterRect;\nFC.getClientRect = getClientRect;\nFC.getContentRect = getContentRect;\nFC.getScrollbarWidths = getScrollbarWidths;\n\n\n// borrowed from https://github.com/jquery/jquery-ui/blob/1.11.0/ui/core.js#L51\nfunction getScrollParent(el) {\n\tvar position = el.css('position'),\n\t\tscrollParent = el.parents().filter(function() {\n\t\t\tvar parent = $(this);\n\t\t\treturn (/(auto|scroll)/).test(\n\t\t\t\tparent.css('overflow') + parent.css('overflow-y') + parent.css('overflow-x')\n\t\t\t);\n\t\t}).eq(0);\n\n\treturn position === 'fixed' || !scrollParent.length ? $(el[0].ownerDocument || document) : scrollParent;\n}\n\n\n// Queries the outer bounding area of a jQuery element.\n// Returns a rectangle with absolute coordinates: left, right (exclusive), top, bottom (exclusive).\n// Origin is optional.\nfunction getOuterRect(el, origin) {\n\tvar offset = el.offset();\n\tvar left = offset.left - (origin ? origin.left : 0);\n\tvar top = offset.top - (origin ? origin.top : 0);\n\n\treturn {\n\t\tleft: left,\n\t\tright: left + el.outerWidth(),\n\t\ttop: top,\n\t\tbottom: top + el.outerHeight()\n\t};\n}\n\n\n// Queries the area within the margin/border/scrollbars of a jQuery element. Does not go within the padding.\n// Returns a rectangle with absolute coordinates: left, right (exclusive), top, bottom (exclusive).\n// Origin is optional.\n// NOTE: should use clientLeft/clientTop, but very unreliable cross-browser.\nfunction getClientRect(el, origin) {\n\tvar offset = el.offset();\n\tvar scrollbarWidths = getScrollbarWidths(el);\n\tvar left = offset.left + getCssFloat(el, 'border-left-width') + scrollbarWidths.left - (origin ? origin.left : 0);\n\tvar top = offset.top + getCssFloat(el, 'border-top-width') + scrollbarWidths.top - (origin ? origin.top : 0);\n\n\treturn {\n\t\tleft: left,\n\t\tright: left + el[0].clientWidth, // clientWidth includes padding but NOT scrollbars\n\t\ttop: top,\n\t\tbottom: top + el[0].clientHeight // clientHeight includes padding but NOT scrollbars\n\t};\n}\n\n\n// Queries the area within the margin/border/padding of a jQuery element. Assumed not to have scrollbars.\n// Returns a rectangle with absolute coordinates: left, right (exclusive), top, bottom (exclusive).\n// Origin is optional.\nfunction getContentRect(el, origin) {\n\tvar offset = el.offset(); // just outside of border, margin not included\n\tvar left = offset.left + getCssFloat(el, 'border-left-width') + getCssFloat(el, 'padding-left') -\n\t\t(origin ? origin.left : 0);\n\tvar top = offset.top + getCssFloat(el, 'border-top-width') + getCssFloat(el, 'padding-top') -\n\t\t(origin ? origin.top : 0);\n\n\treturn {\n\t\tleft: left,\n\t\tright: left + el.width(),\n\t\ttop: top,\n\t\tbottom: top + el.height()\n\t};\n}\n\n\n// Returns the computed left/right/top/bottom scrollbar widths for the given jQuery element.\n// NOTE: should use clientLeft/clientTop, but very unreliable cross-browser.\nfunction getScrollbarWidths(el) {\n\tvar leftRightWidth = el.innerWidth() - el[0].clientWidth; // the paddings cancel out, leaving the scrollbars\n\tvar widths = {\n\t\tleft: 0,\n\t\tright: 0,\n\t\ttop: 0,\n\t\tbottom: el.innerHeight() - el[0].clientHeight // the paddings cancel out, leaving the bottom scrollbar\n\t};\n\n\tif (getIsLeftRtlScrollbars() && el.css('direction') == 'rtl') { // is the scrollbar on the left side?\n\t\twidths.left = leftRightWidth;\n\t}\n\telse {\n\t\twidths.right = leftRightWidth;\n\t}\n\n\treturn widths;\n}\n\n\n// Logic for determining if, when the element is right-to-left, the scrollbar appears on the left side\n\nvar _isLeftRtlScrollbars = null;\n\nfunction getIsLeftRtlScrollbars() { // responsible for caching the computation\n\tif (_isLeftRtlScrollbars === null) {\n\t\t_isLeftRtlScrollbars = computeIsLeftRtlScrollbars();\n\t}\n\treturn _isLeftRtlScrollbars;\n}\n\nfunction computeIsLeftRtlScrollbars() { // creates an offscreen test element, then removes it\n\tvar el = $('
')\n\t\t.css({\n\t\t\tposition: 'absolute',\n\t\t\ttop: -1000,\n\t\t\tleft: 0,\n\t\t\tborder: 0,\n\t\t\tpadding: 0,\n\t\t\toverflow: 'scroll',\n\t\t\tdirection: 'rtl'\n\t\t})\n\t\t.appendTo('body');\n\tvar innerEl = el.children();\n\tvar res = innerEl.offset().left > el.offset().left; // is the inner div shifted to accommodate a left scrollbar?\n\tel.remove();\n\treturn res;\n}\n\n\n// Retrieves a jQuery element's computed CSS value as a floating-point number.\n// If the queried value is non-numeric (ex: IE can return \"medium\" for border width), will just return zero.\nfunction getCssFloat(el, prop) {\n\treturn parseFloat(el.css(prop)) || 0;\n}\n\n\n/* Mouse / Touch Utilities\n----------------------------------------------------------------------------------------------------------------------*/\n\nFC.preventDefault = preventDefault;\n\n\n// Returns a boolean whether this was a left mouse click and no ctrl key (which means right click on Mac)\nfunction isPrimaryMouseButton(ev) {\n\treturn ev.which == 1 && !ev.ctrlKey;\n}\n\n\nfunction getEvX(ev) {\n\tif (ev.pageX !== undefined) {\n\t\treturn ev.pageX;\n\t}\n\tvar touches = ev.originalEvent.touches;\n\tif (touches) {\n\t\treturn touches[0].pageX;\n\t}\n}\n\n\nfunction getEvY(ev) {\n\tif (ev.pageY !== undefined) {\n\t\treturn ev.pageY;\n\t}\n\tvar touches = ev.originalEvent.touches;\n\tif (touches) {\n\t\treturn touches[0].pageY;\n\t}\n}\n\n\nfunction getEvIsTouch(ev) {\n\treturn /^touch/.test(ev.type);\n}\n\n\nfunction preventSelection(el) {\n\tel.addClass('fc-unselectable')\n\t\t.on('selectstart', preventDefault);\n}\n\n\n// Stops a mouse/touch event from doing it's native browser action\nfunction preventDefault(ev) {\n\tev.preventDefault();\n}\n\n\n// attach a handler to get called when ANY scroll action happens on the page.\n// this was impossible to do with normal on/off because 'scroll' doesn't bubble.\n// http://stackoverflow.com/a/32954565/96342\n// returns `true` on success.\nfunction bindAnyScroll(handler) {\n\tif (window.addEventListener) {\n\t\twindow.addEventListener('scroll', handler, true); // useCapture=true\n\t\treturn true;\n\t}\n\treturn false;\n}\n\n\n// undoes bindAnyScroll. must pass in the original function.\n// returns `true` on success.\nfunction unbindAnyScroll(handler) {\n\tif (window.removeEventListener) {\n\t\twindow.removeEventListener('scroll', handler, true); // useCapture=true\n\t\treturn true;\n\t}\n\treturn false;\n}\n\n\n/* General Geometry Utils\n----------------------------------------------------------------------------------------------------------------------*/\n\nFC.intersectRects = intersectRects;\n\n// Returns a new rectangle that is the intersection of the two rectangles. If they don't intersect, returns false\nfunction intersectRects(rect1, rect2) {\n\tvar res = {\n\t\tleft: Math.max(rect1.left, rect2.left),\n\t\tright: Math.min(rect1.right, rect2.right),\n\t\ttop: Math.max(rect1.top, rect2.top),\n\t\tbottom: Math.min(rect1.bottom, rect2.bottom)\n\t};\n\n\tif (res.left < res.right && res.top < res.bottom) {\n\t\treturn res;\n\t}\n\treturn false;\n}\n\n\n// Returns a new point that will have been moved to reside within the given rectangle\nfunction constrainPoint(point, rect) {\n\treturn {\n\t\tleft: Math.min(Math.max(point.left, rect.left), rect.right),\n\t\ttop: Math.min(Math.max(point.top, rect.top), rect.bottom)\n\t};\n}\n\n\n// Returns a point that is the center of the given rectangle\nfunction getRectCenter(rect) {\n\treturn {\n\t\tleft: (rect.left + rect.right) / 2,\n\t\ttop: (rect.top + rect.bottom) / 2\n\t};\n}\n\n\n// Subtracts point2's coordinates from point1's coordinates, returning a delta\nfunction diffPoints(point1, point2) {\n\treturn {\n\t\tleft: point1.left - point2.left,\n\t\ttop: point1.top - point2.top\n\t};\n}\n\n\n/* Object Ordering by Field\n----------------------------------------------------------------------------------------------------------------------*/\n\nFC.parseFieldSpecs = parseFieldSpecs;\nFC.compareByFieldSpecs = compareByFieldSpecs;\nFC.compareByFieldSpec = compareByFieldSpec;\nFC.flexibleCompare = flexibleCompare;\n\n\nfunction parseFieldSpecs(input) {\n\tvar specs = [];\n\tvar tokens = [];\n\tvar i, token;\n\n\tif (typeof input === 'string') {\n\t\ttokens = input.split(/\\s*,\\s*/);\n\t}\n\telse if (typeof input === 'function') {\n\t\ttokens = [ input ];\n\t}\n\telse if ($.isArray(input)) {\n\t\ttokens = input;\n\t}\n\n\tfor (i = 0; i < tokens.length; i++) {\n\t\ttoken = tokens[i];\n\n\t\tif (typeof token === 'string') {\n\t\t\tspecs.push(\n\t\t\t\ttoken.charAt(0) == '-' ?\n\t\t\t\t\t{ field: token.substring(1), order: -1 } :\n\t\t\t\t\t{ field: token, order: 1 }\n\t\t\t);\n\t\t}\n\t\telse if (typeof token === 'function') {\n\t\t\tspecs.push({ func: token });\n\t\t}\n\t}\n\n\treturn specs;\n}\n\n\nfunction compareByFieldSpecs(obj1, obj2, fieldSpecs) {\n\tvar i;\n\tvar cmp;\n\n\tfor (i = 0; i < fieldSpecs.length; i++) {\n\t\tcmp = compareByFieldSpec(obj1, obj2, fieldSpecs[i]);\n\t\tif (cmp) {\n\t\t\treturn cmp;\n\t\t}\n\t}\n\n\treturn 0;\n}\n\n\nfunction compareByFieldSpec(obj1, obj2, fieldSpec) {\n\tif (fieldSpec.func) {\n\t\treturn fieldSpec.func(obj1, obj2);\n\t}\n\treturn flexibleCompare(obj1[fieldSpec.field], obj2[fieldSpec.field]) *\n\t\t(fieldSpec.order || 1);\n}\n\n\nfunction flexibleCompare(a, b) {\n\tif (!a && !b) {\n\t\treturn 0;\n\t}\n\tif (b == null) {\n\t\treturn -1;\n\t}\n\tif (a == null) {\n\t\treturn 1;\n\t}\n\tif ($.type(a) === 'string' || $.type(b) === 'string') {\n\t\treturn String(a).localeCompare(String(b));\n\t}\n\treturn a - b;\n}\n\n\n/* FullCalendar-specific Misc Utilities\n----------------------------------------------------------------------------------------------------------------------*/\n\n\n// Computes the intersection of the two ranges. Returns undefined if no intersection.\n// Expects all dates to be normalized to the same timezone beforehand.\n// TODO: move to date section?\nfunction intersectRanges(subjectRange, constraintRange) {\n\tvar subjectStart = subjectRange.start;\n\tvar subjectEnd = subjectRange.end;\n\tvar constraintStart = constraintRange.start;\n\tvar constraintEnd = constraintRange.end;\n\tvar segStart, segEnd;\n\tvar isStart, isEnd;\n\n\tif (subjectEnd > constraintStart && subjectStart < constraintEnd) { // in bounds at all?\n\n\t\tif (subjectStart >= constraintStart) {\n\t\t\tsegStart = subjectStart.clone();\n\t\t\tisStart = true;\n\t\t}\n\t\telse {\n\t\t\tsegStart = constraintStart.clone();\n\t\t\tisStart = false;\n\t\t}\n\n\t\tif (subjectEnd <= constraintEnd) {\n\t\t\tsegEnd = subjectEnd.clone();\n\t\t\tisEnd = true;\n\t\t}\n\t\telse {\n\t\t\tsegEnd = constraintEnd.clone();\n\t\t\tisEnd = false;\n\t\t}\n\n\t\treturn {\n\t\t\tstart: segStart,\n\t\t\tend: segEnd,\n\t\t\tisStart: isStart,\n\t\t\tisEnd: isEnd\n\t\t};\n\t}\n}\n\n\n/* Date Utilities\n----------------------------------------------------------------------------------------------------------------------*/\n\nFC.computeIntervalUnit = computeIntervalUnit;\nFC.divideRangeByDuration = divideRangeByDuration;\nFC.divideDurationByDuration = divideDurationByDuration;\nFC.multiplyDuration = multiplyDuration;\nFC.durationHasTime = durationHasTime;\n\nvar dayIDs = [ 'sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat' ];\nvar intervalUnits = [ 'year', 'month', 'week', 'day', 'hour', 'minute', 'second', 'millisecond' ];\n\n\n// Diffs the two moments into a Duration where full-days are recorded first, then the remaining time.\n// Moments will have their timezones normalized.\nfunction diffDayTime(a, b) {\n\treturn moment.duration({\n\t\tdays: a.clone().stripTime().diff(b.clone().stripTime(), 'days'),\n\t\tms: a.time() - b.time() // time-of-day from day start. disregards timezone\n\t});\n}\n\n\n// Diffs the two moments via their start-of-day (regardless of timezone). Produces whole-day durations.\nfunction diffDay(a, b) {\n\treturn moment.duration({\n\t\tdays: a.clone().stripTime().diff(b.clone().stripTime(), 'days')\n\t});\n}\n\n\n// Diffs two moments, producing a duration, made of a whole-unit-increment of the given unit. Uses rounding.\nfunction diffByUnit(a, b, unit) {\n\treturn moment.duration(\n\t\tMath.round(a.diff(b, unit, true)), // returnFloat=true\n\t\tunit\n\t);\n}\n\n\n// Computes the unit name of the largest whole-unit period of time.\n// For example, 48 hours will be \"days\" whereas 49 hours will be \"hours\".\n// Accepts start/end, a range object, or an original duration object.\nfunction computeIntervalUnit(start, end) {\n\tvar i, unit;\n\tvar val;\n\n\tfor (i = 0; i < intervalUnits.length; i++) {\n\t\tunit = intervalUnits[i];\n\t\tval = computeRangeAs(unit, start, end);\n\n\t\tif (val >= 1 && isInt(val)) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn unit; // will be \"milliseconds\" if nothing else matches\n}\n\n\n// Computes the number of units (like \"hours\") in the given range.\n// Range can be a {start,end} object, separate start/end args, or a Duration.\n// Results are based on Moment's .as() and .diff() methods, so results can depend on internal handling\n// of month-diffing logic (which tends to vary from version to version).\nfunction computeRangeAs(unit, start, end) {\n\n\tif (end != null) { // given start, end\n\t\treturn end.diff(start, unit, true);\n\t}\n\telse if (moment.isDuration(start)) { // given duration\n\t\treturn start.as(unit);\n\t}\n\telse { // given { start, end } range object\n\t\treturn start.end.diff(start.start, unit, true);\n\t}\n}\n\n\n// Intelligently divides a range (specified by a start/end params) by a duration\nfunction divideRangeByDuration(start, end, dur) {\n\tvar months;\n\n\tif (durationHasTime(dur)) {\n\t\treturn (end - start) / dur;\n\t}\n\tmonths = dur.asMonths();\n\tif (Math.abs(months) >= 1 && isInt(months)) {\n\t\treturn end.diff(start, 'months', true) / months;\n\t}\n\treturn end.diff(start, 'days', true) / dur.asDays();\n}\n\n\n// Intelligently divides one duration by another\nfunction divideDurationByDuration(dur1, dur2) {\n\tvar months1, months2;\n\n\tif (durationHasTime(dur1) || durationHasTime(dur2)) {\n\t\treturn dur1 / dur2;\n\t}\n\tmonths1 = dur1.asMonths();\n\tmonths2 = dur2.asMonths();\n\tif (\n\t\tMath.abs(months1) >= 1 && isInt(months1) &&\n\t\tMath.abs(months2) >= 1 && isInt(months2)\n\t) {\n\t\treturn months1 / months2;\n\t}\n\treturn dur1.asDays() / dur2.asDays();\n}\n\n\n// Intelligently multiplies a duration by a number\nfunction multiplyDuration(dur, n) {\n\tvar months;\n\n\tif (durationHasTime(dur)) {\n\t\treturn moment.duration(dur * n);\n\t}\n\tmonths = dur.asMonths();\n\tif (Math.abs(months) >= 1 && isInt(months)) {\n\t\treturn moment.duration({ months: months * n });\n\t}\n\treturn moment.duration({ days: dur.asDays() * n });\n}\n\n\n// Returns a boolean about whether the given duration has any time parts (hours/minutes/seconds/ms)\nfunction durationHasTime(dur) {\n\treturn Boolean(dur.hours() || dur.minutes() || dur.seconds() || dur.milliseconds());\n}\n\n\nfunction isNativeDate(input) {\n\treturn Object.prototype.toString.call(input) === '[object Date]' || input instanceof Date;\n}\n\n\n// Returns a boolean about whether the given input is a time string, like \"06:40:00\" or \"06:00\"\nfunction isTimeString(str) {\n\treturn /^\\d+\\:\\d+(?:\\:\\d+\\.?(?:\\d{3})?)?$/.test(str);\n}\n\n\n/* Logging and Debug\n----------------------------------------------------------------------------------------------------------------------*/\n\nFC.log = function() {\n\tvar console = window.console;\n\n\tif (console && console.log) {\n\t\treturn console.log.apply(console, arguments);\n\t}\n};\n\nFC.warn = function() {\n\tvar console = window.console;\n\n\tif (console && console.warn) {\n\t\treturn console.warn.apply(console, arguments);\n\t}\n\telse {\n\t\treturn FC.log.apply(FC, arguments);\n\t}\n};\n\n\n/* General Utilities\n----------------------------------------------------------------------------------------------------------------------*/\n\nvar hasOwnPropMethod = {}.hasOwnProperty;\n\n\n// Merges an array of objects into a single object.\n// The second argument allows for an array of property names who's object values will be merged together.\nfunction mergeProps(propObjs, complexProps) {\n\tvar dest = {};\n\tvar i, name;\n\tvar complexObjs;\n\tvar j, val;\n\tvar props;\n\n\tif (complexProps) {\n\t\tfor (i = 0; i < complexProps.length; i++) {\n\t\t\tname = complexProps[i];\n\t\t\tcomplexObjs = [];\n\n\t\t\t// collect the trailing object values, stopping when a non-object is discovered\n\t\t\tfor (j = propObjs.length - 1; j >= 0; j--) {\n\t\t\t\tval = propObjs[j][name];\n\n\t\t\t\tif (typeof val === 'object') {\n\t\t\t\t\tcomplexObjs.unshift(val);\n\t\t\t\t}\n\t\t\t\telse if (val !== undefined) {\n\t\t\t\t\tdest[name] = val; // if there were no objects, this value will be used\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// if the trailing values were objects, use the merged value\n\t\t\tif (complexObjs.length) {\n\t\t\t\tdest[name] = mergeProps(complexObjs);\n\t\t\t}\n\t\t}\n\t}\n\n\t// copy values into the destination, going from last to first\n\tfor (i = propObjs.length - 1; i >= 0; i--) {\n\t\tprops = propObjs[i];\n\n\t\tfor (name in props) {\n\t\t\tif (!(name in dest)) { // if already assigned by previous props or complex props, don't reassign\n\t\t\t\tdest[name] = props[name];\n\t\t\t}\n\t\t}\n\t}\n\n\treturn dest;\n}\n\n\n// Create an object that has the given prototype. Just like Object.create\nfunction createObject(proto) {\n\tvar f = function() {};\n\tf.prototype = proto;\n\treturn new f();\n}\n\n\nfunction copyOwnProps(src, dest) {\n\tfor (var name in src) {\n\t\tif (hasOwnProp(src, name)) {\n\t\t\tdest[name] = src[name];\n\t\t}\n\t}\n}\n\n\n// Copies over certain methods with the same names as Object.prototype methods. Overcomes an IE<=8 bug:\n// https://developer.mozilla.org/en-US/docs/ECMAScript_DontEnum_attribute#JScript_DontEnum_Bug\nfunction copyNativeMethods(src, dest) {\n\tvar names = [ 'constructor', 'toString', 'valueOf' ];\n\tvar i, name;\n\n\tfor (i = 0; i < names.length; i++) {\n\t\tname = names[i];\n\n\t\tif (src[name] !== Object.prototype[name]) {\n\t\t\tdest[name] = src[name];\n\t\t}\n\t}\n}\n\n\nfunction hasOwnProp(obj, name) {\n\treturn hasOwnPropMethod.call(obj, name);\n}\n\n\n// Is the given value a non-object non-function value?\nfunction isAtomic(val) {\n\treturn /undefined|null|boolean|number|string/.test($.type(val));\n}\n\n\nfunction applyAll(functions, thisObj, args) {\n\tif ($.isFunction(functions)) {\n\t\tfunctions = [ functions ];\n\t}\n\tif (functions) {\n\t\tvar i;\n\t\tvar ret;\n\t\tfor (i=0; i/g, '>')\n\t\t.replace(/'/g, ''')\n\t\t.replace(/\"/g, '"')\n\t\t.replace(/\\n/g, '
');\n}\n\n\nfunction stripHtmlEntities(text) {\n\treturn text.replace(/&.*?;/g, '');\n}\n\n\n// Given a hash of CSS properties, returns a string of CSS.\n// Uses property names as-is (no camel-case conversion). Will not make statements for null/undefined values.\nfunction cssToStr(cssProps) {\n\tvar statements = [];\n\n\t$.each(cssProps, function(name, val) {\n\t\tif (val != null) {\n\t\t\tstatements.push(name + ':' + val);\n\t\t}\n\t});\n\n\treturn statements.join(';');\n}\n\n\nfunction capitaliseFirstLetter(str) {\n\treturn str.charAt(0).toUpperCase() + str.slice(1);\n}\n\n\nfunction compareNumbers(a, b) { // for .sort()\n\treturn a - b;\n}\n\n\nfunction isInt(n) {\n\treturn n % 1 === 0;\n}\n\n\n// Returns a method bound to the given object context.\n// Just like one of the jQuery.proxy signatures, but without the undesired behavior of treating the same method with\n// different contexts as identical when binding/unbinding events.\nfunction proxy(obj, methodName) {\n\tvar method = obj[methodName];\n\n\treturn function() {\n\t\treturn method.apply(obj, arguments);\n\t};\n}\n\n\n// Returns a function, that, as long as it continues to be invoked, will not\n// be triggered. The function will be called after it stops being called for\n// N milliseconds. If `immediate` is passed, trigger the function on the\n// leading edge, instead of the trailing.\n// https://github.com/jashkenas/underscore/blob/1.6.0/underscore.js#L714\nfunction debounce(func, wait, immediate) {\n\tvar timeout, args, context, timestamp, result;\n\n\tvar later = function() {\n\t\tvar last = +new Date() - timestamp;\n\t\tif (last < wait) {\n\t\t\ttimeout = setTimeout(later, wait - last);\n\t\t}\n\t\telse {\n\t\t\ttimeout = null;\n\t\t\tif (!immediate) {\n\t\t\t\tresult = func.apply(context, args);\n\t\t\t\tcontext = args = null;\n\t\t\t}\n\t\t}\n\t};\n\n\treturn function() {\n\t\tcontext = this;\n\t\targs = arguments;\n\t\ttimestamp = +new Date();\n\t\tvar callNow = immediate && !timeout;\n\t\tif (!timeout) {\n\t\t\ttimeout = setTimeout(later, wait);\n\t\t}\n\t\tif (callNow) {\n\t\t\tresult = func.apply(context, args);\n\t\t\tcontext = args = null;\n\t\t}\n\t\treturn result;\n\t};\n}\n\n\n// HACK around jQuery's now A+ promises: execute callback synchronously if already resolved.\n// thenFunc shouldn't accept args.\n// similar to whenResources in Scheduler plugin.\nfunction syncThen(promise, thenFunc) {\n\t// not a promise, or an already-resolved promise?\n\tif (!promise || !promise.then || promise.state() === 'resolved') {\n\t\treturn $.when(thenFunc()); // resolve immediately\n\t}\n\telse if (thenFunc) {\n\t\treturn promise.then(thenFunc);\n\t}\n}\n\n;;\n\nvar ambigDateOfMonthRegex = /^\\s*\\d{4}-\\d\\d$/;\nvar ambigTimeOrZoneRegex =\n\t/^\\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+)?)?)?)?)?$/;\nvar newMomentProto = moment.fn; // where we will attach our new methods\nvar oldMomentProto = $.extend({}, newMomentProto); // copy of original moment methods\nvar allowValueOptimization;\nvar setUTCValues; // function defined below\nvar setLocalValues; // function defined below\n\n\n// Creating\n// -------------------------------------------------------------------------------------------------\n\n// Creates a new moment, similar to the vanilla moment(...) constructor, but with\n// extra features (ambiguous time, enhanced formatting). When given an existing moment,\n// it will function as a clone (and retain the zone of the moment). Anything else will\n// result in a moment in the local zone.\nFC.moment = function() {\n\treturn makeMoment(arguments);\n};\n\n// Sames as FC.moment, but forces the resulting moment to be in the UTC timezone.\nFC.moment.utc = function() {\n\tvar mom = makeMoment(arguments, true);\n\n\t// Force it into UTC because makeMoment doesn't guarantee it\n\t// (if given a pre-existing moment for example)\n\tif (mom.hasTime()) { // don't give ambiguously-timed moments a UTC zone\n\t\tmom.utc();\n\t}\n\n\treturn mom;\n};\n\n// Same as FC.moment, but when given an ISO8601 string, the timezone offset is preserved.\n// ISO8601 strings with no timezone offset will become ambiguously zoned.\nFC.moment.parseZone = function() {\n\treturn makeMoment(arguments, true, true);\n};\n\n// Builds an enhanced moment from args. When given an existing moment, it clones. When given a\n// native Date, or called with no arguments (the current time), the resulting moment will be local.\n// Anything else needs to be \"parsed\" (a string or an array), and will be affected by:\n// parseAsUTC - if there is no zone information, should we parse the input in UTC?\n// parseZone - if there is zone information, should we force the zone of the moment?\nfunction makeMoment(args, parseAsUTC, parseZone) {\n\tvar input = args[0];\n\tvar isSingleString = args.length == 1 && typeof input === 'string';\n\tvar isAmbigTime;\n\tvar isAmbigZone;\n\tvar ambigMatch;\n\tvar mom;\n\n\tif (moment.isMoment(input)) {\n\t\tmom = moment.apply(null, args); // clone it\n\t\ttransferAmbigs(input, mom); // the ambig flags weren't transfered with the clone\n\t}\n\telse if (isNativeDate(input) || input === undefined) {\n\t\tmom = moment.apply(null, args); // will be local\n\t}\n\telse { // \"parsing\" is required\n\t\tisAmbigTime = false;\n\t\tisAmbigZone = false;\n\n\t\tif (isSingleString) {\n\t\t\tif (ambigDateOfMonthRegex.test(input)) {\n\t\t\t\t// accept strings like '2014-05', but convert to the first of the month\n\t\t\t\tinput += '-01';\n\t\t\t\targs = [ input ]; // for when we pass it on to moment's constructor\n\t\t\t\tisAmbigTime = true;\n\t\t\t\tisAmbigZone = true;\n\t\t\t}\n\t\t\telse if ((ambigMatch = ambigTimeOrZoneRegex.exec(input))) {\n\t\t\t\tisAmbigTime = !ambigMatch[5]; // no time part?\n\t\t\t\tisAmbigZone = true;\n\t\t\t}\n\t\t}\n\t\telse if ($.isArray(input)) {\n\t\t\t// arrays have no timezone information, so assume ambiguous zone\n\t\t\tisAmbigZone = true;\n\t\t}\n\t\t// otherwise, probably a string with a format\n\n\t\tif (parseAsUTC || isAmbigTime) {\n\t\t\tmom = moment.utc.apply(moment, args);\n\t\t}\n\t\telse {\n\t\t\tmom = moment.apply(null, args);\n\t\t}\n\n\t\tif (isAmbigTime) {\n\t\t\tmom._ambigTime = true;\n\t\t\tmom._ambigZone = true; // ambiguous time always means ambiguous zone\n\t\t}\n\t\telse if (parseZone) { // let's record the inputted zone somehow\n\t\t\tif (isAmbigZone) {\n\t\t\t\tmom._ambigZone = true;\n\t\t\t}\n\t\t\telse if (isSingleString) {\n\t\t\t\tif (mom.utcOffset) {\n\t\t\t\t\tmom.utcOffset(input); // if not a valid zone, will assign UTC\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tmom.zone(input); // for moment-pre-2.9\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tmom._fullCalendar = true; // flag for extended functionality\n\n\treturn mom;\n}\n\n\n// A clone method that works with the flags related to our enhanced functionality.\n// In the future, use moment.momentProperties\nnewMomentProto.clone = function() {\n\tvar mom = oldMomentProto.clone.apply(this, arguments);\n\n\t// these flags weren't transfered with the clone\n\ttransferAmbigs(this, mom);\n\tif (this._fullCalendar) {\n\t\tmom._fullCalendar = true;\n\t}\n\n\treturn mom;\n};\n\n\n// Week Number\n// -------------------------------------------------------------------------------------------------\n\n\n// Returns the week number, considering the locale's custom week number calcuation\n// `weeks` is an alias for `week`\nnewMomentProto.week = newMomentProto.weeks = function(input) {\n\tvar weekCalc = (this._locale || this._lang) // works pre-moment-2.8\n\t\t._fullCalendar_weekCalc;\n\n\tif (input == null && typeof weekCalc === 'function') { // custom function only works for getter\n\t\treturn weekCalc(this);\n\t}\n\telse if (weekCalc === 'ISO') {\n\t\treturn oldMomentProto.isoWeek.apply(this, arguments); // ISO getter/setter\n\t}\n\n\treturn oldMomentProto.week.apply(this, arguments); // local getter/setter\n};\n\n\n// Time-of-day\n// -------------------------------------------------------------------------------------------------\n\n// GETTER\n// Returns a Duration with the hours/minutes/seconds/ms values of the moment.\n// If the moment has an ambiguous time, a duration of 00:00 will be returned.\n//\n// SETTER\n// You can supply a Duration, a Moment, or a Duration-like argument.\n// When setting the time, and the moment has an ambiguous time, it then becomes unambiguous.\nnewMomentProto.time = function(time) {\n\n\t// Fallback to the original method (if there is one) if this moment wasn't created via FullCalendar.\n\t// `time` is a generic enough method name where this precaution is necessary to avoid collisions w/ other plugins.\n\tif (!this._fullCalendar) {\n\t\treturn oldMomentProto.time.apply(this, arguments);\n\t}\n\n\tif (time == null) { // getter\n\t\treturn moment.duration({\n\t\t\thours: this.hours(),\n\t\t\tminutes: this.minutes(),\n\t\t\tseconds: this.seconds(),\n\t\t\tmilliseconds: this.milliseconds()\n\t\t});\n\t}\n\telse { // setter\n\n\t\tthis._ambigTime = false; // mark that the moment now has a time\n\n\t\tif (!moment.isDuration(time) && !moment.isMoment(time)) {\n\t\t\ttime = moment.duration(time);\n\t\t}\n\n\t\t// The day value should cause overflow (so 24 hours becomes 00:00:00 of next day).\n\t\t// Only for Duration times, not Moment times.\n\t\tvar dayHours = 0;\n\t\tif (moment.isDuration(time)) {\n\t\t\tdayHours = Math.floor(time.asDays()) * 24;\n\t\t}\n\n\t\t// We need to set the individual fields.\n\t\t// Can't use startOf('day') then add duration. In case of DST at start of day.\n\t\treturn this.hours(dayHours + time.hours())\n\t\t\t.minutes(time.minutes())\n\t\t\t.seconds(time.seconds())\n\t\t\t.milliseconds(time.milliseconds());\n\t}\n};\n\n// Converts the moment to UTC, stripping out its time-of-day and timezone offset,\n// but preserving its YMD. A moment with a stripped time will display no time\n// nor timezone offset when .format() is called.\nnewMomentProto.stripTime = function() {\n\tvar a;\n\n\tif (!this._ambigTime) {\n\n\t\t// get the values before any conversion happens\n\t\ta = this.toArray(); // array of y/m/d/h/m/s/ms\n\n\t\t// TODO: use keepLocalTime in the future\n\t\tthis.utc(); // set the internal UTC flag (will clear the ambig flags)\n\t\tsetUTCValues(this, a.slice(0, 3)); // set the year/month/date. time will be zero\n\n\t\t// Mark the time as ambiguous. This needs to happen after the .utc() call, which might call .utcOffset(),\n\t\t// which clears all ambig flags. Same with setUTCValues with moment-timezone.\n\t\tthis._ambigTime = true;\n\t\tthis._ambigZone = true; // if ambiguous time, also ambiguous timezone offset\n\t}\n\n\treturn this; // for chaining\n};\n\n// Returns if the moment has a non-ambiguous time (boolean)\nnewMomentProto.hasTime = function() {\n\treturn !this._ambigTime;\n};\n\n\n// Timezone\n// -------------------------------------------------------------------------------------------------\n\n// Converts the moment to UTC, stripping out its timezone offset, but preserving its\n// YMD and time-of-day. A moment with a stripped timezone offset will display no\n// timezone offset when .format() is called.\n// TODO: look into Moment's keepLocalTime functionality\nnewMomentProto.stripZone = function() {\n\tvar a, wasAmbigTime;\n\n\tif (!this._ambigZone) {\n\n\t\t// get the values before any conversion happens\n\t\ta = this.toArray(); // array of y/m/d/h/m/s/ms\n\t\twasAmbigTime = this._ambigTime;\n\n\t\tthis.utc(); // set the internal UTC flag (might clear the ambig flags, depending on Moment internals)\n\t\tsetUTCValues(this, a); // will set the year/month/date/hours/minutes/seconds/ms\n\n\t\t// the above call to .utc()/.utcOffset() unfortunately might clear the ambig flags, so restore\n\t\tthis._ambigTime = wasAmbigTime || false;\n\n\t\t// Mark the zone as ambiguous. This needs to happen after the .utc() call, which might call .utcOffset(),\n\t\t// which clears the ambig flags. Same with setUTCValues with moment-timezone.\n\t\tthis._ambigZone = true;\n\t}\n\n\treturn this; // for chaining\n};\n\n// Returns of the moment has a non-ambiguous timezone offset (boolean)\nnewMomentProto.hasZone = function() {\n\treturn !this._ambigZone;\n};\n\n\n// this method implicitly marks a zone\nnewMomentProto.local = function() {\n\tvar a = this.toArray(); // year,month,date,hours,minutes,seconds,ms as an array\n\tvar wasAmbigZone = this._ambigZone;\n\n\toldMomentProto.local.apply(this, arguments);\n\n\t// ensure non-ambiguous\n\t// this probably already happened via local() -> utcOffset(), but don't rely on Moment's internals\n\tthis._ambigTime = false;\n\tthis._ambigZone = false;\n\n\tif (wasAmbigZone) {\n\t\t// If the moment was ambiguously zoned, the date fields were stored as UTC.\n\t\t// We want to preserve these, but in local time.\n\t\t// TODO: look into Moment's keepLocalTime functionality\n\t\tsetLocalValues(this, a);\n\t}\n\n\treturn this; // for chaining\n};\n\n\n// implicitly marks a zone\nnewMomentProto.utc = function() {\n\toldMomentProto.utc.apply(this, arguments);\n\n\t// ensure non-ambiguous\n\t// this probably already happened via utc() -> utcOffset(), but don't rely on Moment's internals\n\tthis._ambigTime = false;\n\tthis._ambigZone = false;\n\n\treturn this;\n};\n\n\n// methods for arbitrarily manipulating timezone offset.\n// should clear time/zone ambiguity when called.\n$.each([\n\t'zone', // only in moment-pre-2.9. deprecated afterwards\n\t'utcOffset'\n], function(i, name) {\n\tif (oldMomentProto[name]) { // original method exists?\n\n\t\t// this method implicitly marks a zone (will probably get called upon .utc() and .local())\n\t\tnewMomentProto[name] = function(tzo) {\n\n\t\t\tif (tzo != null) { // setter\n\t\t\t\t// these assignments needs to happen before the original zone method is called.\n\t\t\t\t// I forget why, something to do with a browser crash.\n\t\t\t\tthis._ambigTime = false;\n\t\t\t\tthis._ambigZone = false;\n\t\t\t}\n\n\t\t\treturn oldMomentProto[name].apply(this, arguments);\n\t\t};\n\t}\n});\n\n\n// Formatting\n// -------------------------------------------------------------------------------------------------\n\nnewMomentProto.format = function() {\n\tif (this._fullCalendar && arguments[0]) { // an enhanced moment? and a format string provided?\n\t\treturn formatDate(this, arguments[0]); // our extended formatting\n\t}\n\tif (this._ambigTime) {\n\t\treturn oldMomentFormat(this, 'YYYY-MM-DD');\n\t}\n\tif (this._ambigZone) {\n\t\treturn oldMomentFormat(this, 'YYYY-MM-DD[T]HH:mm:ss');\n\t}\n\treturn oldMomentProto.format.apply(this, arguments);\n};\n\nnewMomentProto.toISOString = function() {\n\tif (this._ambigTime) {\n\t\treturn oldMomentFormat(this, 'YYYY-MM-DD');\n\t}\n\tif (this._ambigZone) {\n\t\treturn oldMomentFormat(this, 'YYYY-MM-DD[T]HH:mm:ss');\n\t}\n\treturn oldMomentProto.toISOString.apply(this, arguments);\n};\n\n\n// Querying\n// -------------------------------------------------------------------------------------------------\n\n// Is the moment within the specified range? `end` is exclusive.\n// FYI, this method is not a standard Moment method, so always do our enhanced logic.\nnewMomentProto.isWithin = function(start, end) {\n\tvar a = commonlyAmbiguate([ this, start, end ]);\n\treturn a[0] >= a[1] && a[0] < a[2];\n};\n\n// When isSame is called with units, timezone ambiguity is normalized before the comparison happens.\n// If no units specified, the two moments must be identically the same, with matching ambig flags.\nnewMomentProto.isSame = function(input, units) {\n\tvar a;\n\n\t// only do custom logic if this is an enhanced moment\n\tif (!this._fullCalendar) {\n\t\treturn oldMomentProto.isSame.apply(this, arguments);\n\t}\n\n\tif (units) {\n\t\ta = commonlyAmbiguate([ this, input ], true); // normalize timezones but don't erase times\n\t\treturn oldMomentProto.isSame.call(a[0], a[1], units);\n\t}\n\telse {\n\t\tinput = FC.moment.parseZone(input); // normalize input\n\t\treturn oldMomentProto.isSame.call(this, input) &&\n\t\t\tBoolean(this._ambigTime) === Boolean(input._ambigTime) &&\n\t\t\tBoolean(this._ambigZone) === Boolean(input._ambigZone);\n\t}\n};\n\n// Make these query methods work with ambiguous moments\n$.each([\n\t'isBefore',\n\t'isAfter'\n], function(i, methodName) {\n\tnewMomentProto[methodName] = function(input, units) {\n\t\tvar a;\n\n\t\t// only do custom logic if this is an enhanced moment\n\t\tif (!this._fullCalendar) {\n\t\t\treturn oldMomentProto[methodName].apply(this, arguments);\n\t\t}\n\n\t\ta = commonlyAmbiguate([ this, input ]);\n\t\treturn oldMomentProto[methodName].call(a[0], a[1], units);\n\t};\n});\n\n\n// Misc Internals\n// -------------------------------------------------------------------------------------------------\n\n// given an array of moment-like inputs, return a parallel array w/ moments similarly ambiguated.\n// for example, of one moment has ambig time, but not others, all moments will have their time stripped.\n// set `preserveTime` to `true` to keep times, but only normalize zone ambiguity.\n// returns the original moments if no modifications are necessary.\nfunction commonlyAmbiguate(inputs, preserveTime) {\n\tvar anyAmbigTime = false;\n\tvar anyAmbigZone = false;\n\tvar len = inputs.length;\n\tvar moms = [];\n\tvar i, mom;\n\n\t// parse inputs into real moments and query their ambig flags\n\tfor (i = 0; i < len; i++) {\n\t\tmom = inputs[i];\n\t\tif (!moment.isMoment(mom)) {\n\t\t\tmom = FC.moment.parseZone(mom);\n\t\t}\n\t\tanyAmbigTime = anyAmbigTime || mom._ambigTime;\n\t\tanyAmbigZone = anyAmbigZone || mom._ambigZone;\n\t\tmoms.push(mom);\n\t}\n\n\t// strip each moment down to lowest common ambiguity\n\t// use clones to avoid modifying the original moments\n\tfor (i = 0; i < len; i++) {\n\t\tmom = moms[i];\n\t\tif (!preserveTime && anyAmbigTime && !mom._ambigTime) {\n\t\t\tmoms[i] = mom.clone().stripTime();\n\t\t}\n\t\telse if (anyAmbigZone && !mom._ambigZone) {\n\t\t\tmoms[i] = mom.clone().stripZone();\n\t\t}\n\t}\n\n\treturn moms;\n}\n\n// Transfers all the flags related to ambiguous time/zone from the `src` moment to the `dest` moment\n// TODO: look into moment.momentProperties for this.\nfunction transferAmbigs(src, dest) {\n\tif (src._ambigTime) {\n\t\tdest._ambigTime = true;\n\t}\n\telse if (dest._ambigTime) {\n\t\tdest._ambigTime = false;\n\t}\n\n\tif (src._ambigZone) {\n\t\tdest._ambigZone = true;\n\t}\n\telse if (dest._ambigZone) {\n\t\tdest._ambigZone = false;\n\t}\n}\n\n\n// Sets the year/month/date/etc values of the moment from the given array.\n// Inefficient because it calls each individual setter.\nfunction setMomentValues(mom, a) {\n\tmom.year(a[0] || 0)\n\t\t.month(a[1] || 0)\n\t\t.date(a[2] || 0)\n\t\t.hours(a[3] || 0)\n\t\t.minutes(a[4] || 0)\n\t\t.seconds(a[5] || 0)\n\t\t.milliseconds(a[6] || 0);\n}\n\n// Can we set the moment's internal date directly?\nallowValueOptimization = '_d' in moment() && 'updateOffset' in moment;\n\n// Utility function. Accepts a moment and an array of the UTC year/month/date/etc values to set.\n// Assumes the given moment is already in UTC mode.\nsetUTCValues = allowValueOptimization ? function(mom, a) {\n\t// simlate what moment's accessors do\n\tmom._d.setTime(Date.UTC.apply(Date, a));\n\tmoment.updateOffset(mom, false); // keepTime=false\n} : setMomentValues;\n\n// Utility function. Accepts a moment and an array of the local year/month/date/etc values to set.\n// Assumes the given moment is already in local mode.\nsetLocalValues = allowValueOptimization ? function(mom, a) {\n\t// simlate what moment's accessors do\n\tmom._d.setTime(+new Date( // FYI, there is now way to apply an array of args to a constructor\n\t\ta[0] || 0,\n\t\ta[1] || 0,\n\t\ta[2] || 0,\n\t\ta[3] || 0,\n\t\ta[4] || 0,\n\t\ta[5] || 0,\n\t\ta[6] || 0\n\t));\n\tmoment.updateOffset(mom, false); // keepTime=false\n} : setMomentValues;\n\n;;\n\n// Single Date Formatting\n// -------------------------------------------------------------------------------------------------\n\n\n// call this if you want Moment's original format method to be used\nfunction oldMomentFormat(mom, formatStr) {\n\treturn oldMomentProto.format.call(mom, formatStr); // oldMomentProto defined in moment-ext.js\n}\n\n\n// Formats `date` with a Moment formatting string, but allow our non-zero areas and\n// additional token.\nfunction formatDate(date, formatStr) {\n\treturn formatDateWithChunks(date, getFormatStringChunks(formatStr));\n}\n\n\nfunction formatDateWithChunks(date, chunks) {\n\tvar s = '';\n\tvar i;\n\n\tfor (i=0; i \"MMMM D YYYY\"\n\tformatStr = localeData.longDateFormat(formatStr) || formatStr;\n\t// BTW, this is not important for `formatDate` because it is impossible to put custom tokens\n\t// or non-zero areas in Moment's localized format strings.\n\n\tseparator = separator || ' - ';\n\n\treturn formatRangeWithChunks(\n\t\tdate1,\n\t\tdate2,\n\t\tgetFormatStringChunks(formatStr),\n\t\tseparator,\n\t\tisRTL\n\t);\n}\nFC.formatRange = formatRange; // expose\n\n\nfunction formatRangeWithChunks(date1, date2, chunks, separator, isRTL) {\n\tvar unzonedDate1 = date1.clone().stripZone(); // for formatSimilarChunk\n\tvar unzonedDate2 = date2.clone().stripZone(); // \"\n\tvar chunkStr; // the rendering of the chunk\n\tvar leftI;\n\tvar leftStr = '';\n\tvar rightI;\n\tvar rightStr = '';\n\tvar middleI;\n\tvar middleStr1 = '';\n\tvar middleStr2 = '';\n\tvar middleStr = '';\n\n\t// Start at the leftmost side of the formatting string and continue until you hit a token\n\t// that is not the same between dates.\n\tfor (leftI=0; leftIleftI; rightI--) {\n\t\tchunkStr = formatSimilarChunk(date1, date2, unzonedDate1, unzonedDate2, chunks[rightI]);\n\t\tif (chunkStr === false) {\n\t\t\tbreak;\n\t\t}\n\t\trightStr = chunkStr + rightStr;\n\t}\n\n\t// The area in the middle is different for both of the dates.\n\t// Collect them distinctly so we can jam them together later.\n\tfor (middleI=leftI; middleI<=rightI; middleI++) {\n\t\tmiddleStr1 += formatDateWithChunk(date1, chunks[middleI]);\n\t\tmiddleStr2 += formatDateWithChunk(date2, chunks[middleI]);\n\t}\n\n\tif (middleStr1 || middleStr2) {\n\t\tif (isRTL) {\n\t\t\tmiddleStr = middleStr2 + separator + middleStr1;\n\t\t}\n\t\telse {\n\t\t\tmiddleStr = middleStr1 + separator + middleStr2;\n\t\t}\n\t}\n\n\treturn leftStr + middleStr + rightStr;\n}\n\n\nvar similarUnitMap = {\n\tY: 'year',\n\tM: 'month',\n\tD: 'day', // day of month\n\td: 'day', // day of week\n\t// prevents a separator between anything time-related...\n\tA: 'second', // AM/PM\n\ta: 'second', // am/pm\n\tT: 'second', // A/P\n\tt: 'second', // a/p\n\tH: 'second', // hour (24)\n\th: 'second', // hour (12)\n\tm: 'second', // minute\n\ts: 'second' // second\n};\n// TODO: week maybe?\n\n\n// Given a formatting chunk, and given that both dates are similar in the regard the\n// formatting chunk is concerned, format date1 against `chunk`. Otherwise, return `false`.\nfunction formatSimilarChunk(date1, date2, unzonedDate1, unzonedDate2, chunk) {\n\tvar token;\n\tvar unit;\n\n\tif (typeof chunk === 'string') { // a literal string\n\t\treturn chunk;\n\t}\n\telse if ((token = chunk.token)) {\n\t\tunit = similarUnitMap[token.charAt(0)];\n\n\t\t// are the dates the same for this unit of measurement?\n\t\t// use the unzoned dates for this calculation because unreliable when near DST (bug #2396)\n\t\tif (unit && unzonedDate1.isSame(unzonedDate2, unit)) {\n\t\t\treturn oldMomentFormat(date1, token); // would be the same if we used `date2`\n\t\t\t// BTW, don't support custom tokens\n\t\t}\n\t}\n\n\treturn false; // the chunk is NOT the same for the two dates\n\t// BTW, don't support splitting on non-zero areas\n}\n\n\n// Chunking Utils\n// -------------------------------------------------------------------------------------------------\n\n\nvar formatStringChunkCache = {};\n\n\nfunction getFormatStringChunks(formatStr) {\n\tif (formatStr in formatStringChunkCache) {\n\t\treturn formatStringChunkCache[formatStr];\n\t}\n\treturn (formatStringChunkCache[formatStr] = chunkFormatString(formatStr));\n}\n\n\n// Break the formatting string into an array of chunks\nfunction chunkFormatString(formatStr) {\n\tvar chunks = [];\n\tvar chunker = /\\[([^\\]]*)\\]|\\(([^\\)]*)\\)|(LTS|LT|(\\w)\\4*o?)|([^\\w\\[\\(]+)/g; // TODO: more descrimination\n\tvar match;\n\n\twhile ((match = chunker.exec(formatStr))) {\n\t\tif (match[1]) { // a literal string inside [ ... ]\n\t\t\tchunks.push(match[1]);\n\t\t}\n\t\telse if (match[2]) { // non-zero formatting inside ( ... )\n\t\t\tchunks.push({ maybe: chunkFormatString(match[2]) });\n\t\t}\n\t\telse if (match[3]) { // a formatting token\n\t\t\tchunks.push({ token: match[3] });\n\t\t}\n\t\telse if (match[5]) { // an unenclosed literal string\n\t\t\tchunks.push(match[5]);\n\t\t}\n\t}\n\n\treturn chunks;\n}\n\n;;\n\nFC.Class = Class; // export\n\n// Class that all other classes will inherit from\nfunction Class() { }\n\n\n// Called on a class to create a subclass.\n// Last argument contains instance methods. Any argument before the last are considered mixins.\nClass.extend = function() {\n\tvar len = arguments.length;\n\tvar i;\n\tvar members;\n\n\tfor (i = 0; i < len; i++) {\n\t\tmembers = arguments[i];\n\t\tif (i < len - 1) { // not the last argument?\n\t\t\tmixIntoClass(this, members);\n\t\t}\n\t}\n\n\treturn extendClass(this, members || {}); // members will be undefined if no arguments\n};\n\n\n// Adds new member variables/methods to the class's prototype.\n// Can be called with another class, or a plain object hash containing new members.\nClass.mixin = function(members) {\n\tmixIntoClass(this, members);\n};\n\n\nfunction extendClass(superClass, members) {\n\tvar subClass;\n\n\t// ensure a constructor for the subclass, forwarding all arguments to the super-constructor if it doesn't exist\n\tif (hasOwnProp(members, 'constructor')) {\n\t\tsubClass = members.constructor;\n\t}\n\tif (typeof subClass !== 'function') {\n\t\tsubClass = members.constructor = function() {\n\t\t\tsuperClass.apply(this, arguments);\n\t\t};\n\t}\n\n\t// build the base prototype for the subclass, which is an new object chained to the superclass's prototype\n\tsubClass.prototype = createObject(superClass.prototype);\n\n\t// copy each member variable/method onto the the subclass's prototype\n\tcopyOwnProps(members, subClass.prototype);\n\tcopyNativeMethods(members, subClass.prototype); // hack for IE8\n\n\t// copy over all class variables/methods to the subclass, such as `extend` and `mixin`\n\tcopyOwnProps(superClass, subClass);\n\n\treturn subClass;\n}\n\n\nfunction mixIntoClass(theClass, members) {\n\tcopyOwnProps(members, theClass.prototype); // TODO: copyNativeMethods?\n}\n;;\n\nvar EmitterMixin = FC.EmitterMixin = {\n\n\t// jQuery-ification via $(this) allows a non-DOM object to have\n\t// the same event handling capabilities (including namespaces).\n\n\n\ton: function(types, handler) {\n\n\t\t// handlers are always called with an \"event\" object as their first param.\n\t\t// sneak the `this` context and arguments into the extra parameter object\n\t\t// and forward them on to the original handler.\n\t\tvar intercept = function(ev, extra) {\n\t\t\treturn handler.apply(\n\t\t\t\textra.context || this,\n\t\t\t\textra.args || []\n\t\t\t);\n\t\t};\n\n\t\t// mimick jQuery's internal \"proxy\" system (risky, I know)\n\t\t// causing all functions with the same .guid to appear to be the same.\n\t\t// https://github.com/jquery/jquery/blob/2.2.4/src/core.js#L448\n\t\t// this is needed for calling .off with the original non-intercept handler.\n\t\tif (!handler.guid) {\n\t\t\thandler.guid = $.guid++;\n\t\t}\n\t\tintercept.guid = handler.guid;\n\n\t\t$(this).on(types, intercept);\n\n\t\treturn this; // for chaining\n\t},\n\n\n\toff: function(types, handler) {\n\t\t$(this).off(types, handler);\n\n\t\treturn this; // for chaining\n\t},\n\n\n\ttrigger: function(types) {\n\t\tvar args = Array.prototype.slice.call(arguments, 1); // arguments after the first\n\n\t\t// pass in \"extra\" info to the intercept\n\t\t$(this).triggerHandler(types, { args: args });\n\n\t\treturn this; // for chaining\n\t},\n\n\n\ttriggerWith: function(types, context, args) {\n\n\t\t// `triggerHandler` is less reliant on the DOM compared to `trigger`.\n\t\t// pass in \"extra\" info to the intercept.\n\t\t$(this).triggerHandler(types, { context: context, args: args });\n\n\t\treturn this; // for chaining\n\t}\n\n};\n\n;;\n\n/*\nUtility methods for easily listening to events on another object,\nand more importantly, easily unlistening from them.\n*/\nvar ListenerMixin = FC.ListenerMixin = (function() {\n\tvar guid = 0;\n\tvar ListenerMixin = {\n\n\t\tlistenerId: null,\n\n\t\t/*\n\t\tGiven an `other` object that has on/off methods, bind the given `callback` to an event by the given name.\n\t\tThe `callback` will be called with the `this` context of the object that .listenTo is being called on.\n\t\tCan be called:\n\t\t\t.listenTo(other, eventName, callback)\n\t\tOR\n\t\t\t.listenTo(other, {\n\t\t\t\teventName1: callback1,\n\t\t\t\teventName2: callback2\n\t\t\t})\n\t\t*/\n\t\tlistenTo: function(other, arg, callback) {\n\t\t\tif (typeof arg === 'object') { // given dictionary of callbacks\n\t\t\t\tfor (var eventName in arg) {\n\t\t\t\t\tif (arg.hasOwnProperty(eventName)) {\n\t\t\t\t\t\tthis.listenTo(other, eventName, arg[eventName]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (typeof arg === 'string') {\n\t\t\t\tother.on(\n\t\t\t\t\targ + '.' + this.getListenerNamespace(), // use event namespacing to identify this object\n\t\t\t\t\t$.proxy(callback, this) // always use `this` context\n\t\t\t\t\t\t// the usually-undesired jQuery guid behavior doesn't matter,\n\t\t\t\t\t\t// because we always unbind via namespace\n\t\t\t\t);\n\t\t\t}\n\t\t},\n\n\t\t/*\n\t\tCauses the current object to stop listening to events on the `other` object.\n\t\t`eventName` is optional. If omitted, will stop listening to ALL events on `other`.\n\t\t*/\n\t\tstopListeningTo: function(other, eventName) {\n\t\t\tother.off((eventName || '') + '.' + this.getListenerNamespace());\n\t\t},\n\n\t\t/*\n\t\tReturns a string, unique to this object, to be used for event namespacing\n\t\t*/\n\t\tgetListenerNamespace: function() {\n\t\t\tif (this.listenerId == null) {\n\t\t\t\tthis.listenerId = guid++;\n\t\t\t}\n\t\t\treturn '_listener' + this.listenerId;\n\t\t}\n\n\t};\n\treturn ListenerMixin;\n})();\n;;\n\n// simple class for toggle a `isIgnoringMouse` flag on delay\n// initMouseIgnoring must first be called, with a millisecond delay setting.\nvar MouseIgnorerMixin = {\n\n\tisIgnoringMouse: false, // bool\n\tdelayUnignoreMouse: null, // method\n\n\n\tinitMouseIgnoring: function(delay) {\n\t\tthis.delayUnignoreMouse = debounce(proxy(this, 'unignoreMouse'), delay || 1000);\n\t},\n\n\n\t// temporarily ignore mouse actions on segments\n\ttempIgnoreMouse: function() {\n\t\tthis.isIgnoringMouse = true;\n\t\tthis.delayUnignoreMouse();\n\t},\n\n\n\t// delayUnignoreMouse eventually calls this\n\tunignoreMouse: function() {\n\t\tthis.isIgnoringMouse = false;\n\t}\n\n};\n\n;;\n\n/* A rectangular panel that is absolutely positioned over other content\n------------------------------------------------------------------------------------------------------------------------\nOptions:\n\t- className (string)\n\t- content (HTML string or jQuery element set)\n\t- parentEl\n\t- top\n\t- left\n\t- right (the x coord of where the right edge should be. not a \"CSS\" right)\n\t- autoHide (boolean)\n\t- show (callback)\n\t- hide (callback)\n*/\n\nvar Popover = Class.extend(ListenerMixin, {\n\n\tisHidden: true,\n\toptions: null,\n\tel: null, // the container element for the popover. generated by this object\n\tmargin: 10, // the space required between the popover and the edges of the scroll container\n\n\n\tconstructor: function(options) {\n\t\tthis.options = options || {};\n\t},\n\n\n\t// Shows the popover on the specified position. Renders it if not already\n\tshow: function() {\n\t\tif (this.isHidden) {\n\t\t\tif (!this.el) {\n\t\t\t\tthis.render();\n\t\t\t}\n\t\t\tthis.el.show();\n\t\t\tthis.position();\n\t\t\tthis.isHidden = false;\n\t\t\tthis.trigger('show');\n\t\t}\n\t},\n\n\n\t// Hides the popover, through CSS, but does not remove it from the DOM\n\thide: function() {\n\t\tif (!this.isHidden) {\n\t\t\tthis.el.hide();\n\t\t\tthis.isHidden = true;\n\t\t\tthis.trigger('hide');\n\t\t}\n\t},\n\n\n\t// Creates `this.el` and renders content inside of it\n\trender: function() {\n\t\tvar _this = this;\n\t\tvar options = this.options;\n\n\t\tthis.el = $('
')\n\t\t\t.addClass(options.className || '')\n\t\t\t.css({\n\t\t\t\t// position initially to the top left to avoid creating scrollbars\n\t\t\t\ttop: 0,\n\t\t\t\tleft: 0\n\t\t\t})\n\t\t\t.append(options.content)\n\t\t\t.appendTo(options.parentEl);\n\n\t\t// when a click happens on anything inside with a 'fc-close' className, hide the popover\n\t\tthis.el.on('click', '.fc-close', function() {\n\t\t\t_this.hide();\n\t\t});\n\n\t\tif (options.autoHide) {\n\t\t\tthis.listenTo($(document), 'mousedown', this.documentMousedown);\n\t\t}\n\t},\n\n\n\t// Triggered when the user clicks *anywhere* in the document, for the autoHide feature\n\tdocumentMousedown: function(ev) {\n\t\t// only hide the popover if the click happened outside the popover\n\t\tif (this.el && !$(ev.target).closest(this.el).length) {\n\t\t\tthis.hide();\n\t\t}\n\t},\n\n\n\t// Hides and unregisters any handlers\n\tremoveElement: function() {\n\t\tthis.hide();\n\n\t\tif (this.el) {\n\t\t\tthis.el.remove();\n\t\t\tthis.el = null;\n\t\t}\n\n\t\tthis.stopListeningTo($(document), 'mousedown');\n\t},\n\n\n\t// Positions the popover optimally, using the top/left/right options\n\tposition: function() {\n\t\tvar options = this.options;\n\t\tvar origin = this.el.offsetParent().offset();\n\t\tvar width = this.el.outerWidth();\n\t\tvar height = this.el.outerHeight();\n\t\tvar windowEl = $(window);\n\t\tvar viewportEl = getScrollParent(this.el);\n\t\tvar viewportTop;\n\t\tvar viewportLeft;\n\t\tvar viewportOffset;\n\t\tvar top; // the \"position\" (not \"offset\") values for the popover\n\t\tvar left; //\n\n\t\t// compute top and left\n\t\ttop = options.top || 0;\n\t\tif (options.left !== undefined) {\n\t\t\tleft = options.left;\n\t\t}\n\t\telse if (options.right !== undefined) {\n\t\t\tleft = options.right - width; // derive the left value from the right value\n\t\t}\n\t\telse {\n\t\t\tleft = 0;\n\t\t}\n\n\t\tif (viewportEl.is(window) || viewportEl.is(document)) { // normalize getScrollParent's result\n\t\t\tviewportEl = windowEl;\n\t\t\tviewportTop = 0; // the window is always at the top left\n\t\t\tviewportLeft = 0; // (and .offset() won't work if called here)\n\t\t}\n\t\telse {\n\t\t\tviewportOffset = viewportEl.offset();\n\t\t\tviewportTop = viewportOffset.top;\n\t\t\tviewportLeft = viewportOffset.left;\n\t\t}\n\n\t\t// if the window is scrolled, it causes the visible area to be further down\n\t\tviewportTop += windowEl.scrollTop();\n\t\tviewportLeft += windowEl.scrollLeft();\n\n\t\t// constrain to the view port. if constrained by two edges, give precedence to top/left\n\t\tif (options.viewportConstrain !== false) {\n\t\t\ttop = Math.min(top, viewportTop + viewportEl.outerHeight() - height - this.margin);\n\t\t\ttop = Math.max(top, viewportTop + this.margin);\n\t\t\tleft = Math.min(left, viewportLeft + viewportEl.outerWidth() - width - this.margin);\n\t\t\tleft = Math.max(left, viewportLeft + this.margin);\n\t\t}\n\n\t\tthis.el.css({\n\t\t\ttop: top - origin.top,\n\t\t\tleft: left - origin.left\n\t\t});\n\t},\n\n\n\t// Triggers a callback. Calls a function in the option hash of the same name.\n\t// Arguments beyond the first `name` are forwarded on.\n\t// TODO: better code reuse for this. Repeat code\n\ttrigger: function(name) {\n\t\tif (this.options[name]) {\n\t\t\tthis.options[name].apply(this, Array.prototype.slice.call(arguments, 1));\n\t\t}\n\t}\n\n});\n\n;;\n\n/*\nA cache for the left/right/top/bottom/width/height values for one or more elements.\nWorks with both offset (from topleft document) and position (from offsetParent).\n\noptions:\n- els\n- isHorizontal\n- isVertical\n*/\nvar CoordCache = FC.CoordCache = Class.extend({\n\n\tels: null, // jQuery set (assumed to be siblings)\n\tforcedOffsetParentEl: null, // options can override the natural offsetParent\n\torigin: null, // {left,top} position of offsetParent of els\n\tboundingRect: null, // constrain cordinates to this rectangle. {left,right,top,bottom} or null\n\tisHorizontal: false, // whether to query for left/right/width\n\tisVertical: false, // whether to query for top/bottom/height\n\n\t// arrays of coordinates (offsets from topleft of document)\n\tlefts: null,\n\trights: null,\n\ttops: null,\n\tbottoms: null,\n\n\n\tconstructor: function(options) {\n\t\tthis.els = $(options.els);\n\t\tthis.isHorizontal = options.isHorizontal;\n\t\tthis.isVertical = options.isVertical;\n\t\tthis.forcedOffsetParentEl = options.offsetParent ? $(options.offsetParent) : null;\n\t},\n\n\n\t// Queries the els for coordinates and stores them.\n\t// Call this method before using and of the get* methods below.\n\tbuild: function() {\n\t\tvar offsetParentEl = this.forcedOffsetParentEl || this.els.eq(0).offsetParent();\n\n\t\tthis.origin = offsetParentEl.offset();\n\t\tthis.boundingRect = this.queryBoundingRect();\n\n\t\tif (this.isHorizontal) {\n\t\t\tthis.buildElHorizontals();\n\t\t}\n\t\tif (this.isVertical) {\n\t\t\tthis.buildElVerticals();\n\t\t}\n\t},\n\n\n\t// Destroys all internal data about coordinates, freeing memory\n\tclear: function() {\n\t\tthis.origin = null;\n\t\tthis.boundingRect = null;\n\t\tthis.lefts = null;\n\t\tthis.rights = null;\n\t\tthis.tops = null;\n\t\tthis.bottoms = null;\n\t},\n\n\n\t// When called, if coord caches aren't built, builds them\n\tensureBuilt: function() {\n\t\tif (!this.origin) {\n\t\t\tthis.build();\n\t\t}\n\t},\n\n\n\t// Populates the left/right internal coordinate arrays\n\tbuildElHorizontals: function() {\n\t\tvar lefts = [];\n\t\tvar rights = [];\n\n\t\tthis.els.each(function(i, node) {\n\t\t\tvar el = $(node);\n\t\t\tvar left = el.offset().left;\n\t\t\tvar width = el.outerWidth();\n\n\t\t\tlefts.push(left);\n\t\t\trights.push(left + width);\n\t\t});\n\n\t\tthis.lefts = lefts;\n\t\tthis.rights = rights;\n\t},\n\n\n\t// Populates the top/bottom internal coordinate arrays\n\tbuildElVerticals: function() {\n\t\tvar tops = [];\n\t\tvar bottoms = [];\n\n\t\tthis.els.each(function(i, node) {\n\t\t\tvar el = $(node);\n\t\t\tvar top = el.offset().top;\n\t\t\tvar height = el.outerHeight();\n\n\t\t\ttops.push(top);\n\t\t\tbottoms.push(top + height);\n\t\t});\n\n\t\tthis.tops = tops;\n\t\tthis.bottoms = bottoms;\n\t},\n\n\n\t// Given a left offset (from document left), returns the index of the el that it horizontally intersects.\n\t// If no intersection is made, returns undefined.\n\tgetHorizontalIndex: function(leftOffset) {\n\t\tthis.ensureBuilt();\n\n\t\tvar lefts = this.lefts;\n\t\tvar rights = this.rights;\n\t\tvar len = lefts.length;\n\t\tvar i;\n\n\t\tfor (i = 0; i < len; i++) {\n\t\t\tif (leftOffset >= lefts[i] && leftOffset < rights[i]) {\n\t\t\t\treturn i;\n\t\t\t}\n\t\t}\n\t},\n\n\n\t// Given a top offset (from document top), returns the index of the el that it vertically intersects.\n\t// If no intersection is made, returns undefined.\n\tgetVerticalIndex: function(topOffset) {\n\t\tthis.ensureBuilt();\n\n\t\tvar tops = this.tops;\n\t\tvar bottoms = this.bottoms;\n\t\tvar len = tops.length;\n\t\tvar i;\n\n\t\tfor (i = 0; i < len; i++) {\n\t\t\tif (topOffset >= tops[i] && topOffset < bottoms[i]) {\n\t\t\t\treturn i;\n\t\t\t}\n\t\t}\n\t},\n\n\n\t// Gets the left offset (from document left) of the element at the given index\n\tgetLeftOffset: function(leftIndex) {\n\t\tthis.ensureBuilt();\n\t\treturn this.lefts[leftIndex];\n\t},\n\n\n\t// Gets the left position (from offsetParent left) of the element at the given index\n\tgetLeftPosition: function(leftIndex) {\n\t\tthis.ensureBuilt();\n\t\treturn this.lefts[leftIndex] - this.origin.left;\n\t},\n\n\n\t// Gets the right offset (from document left) of the element at the given index.\n\t// This value is NOT relative to the document's right edge, like the CSS concept of \"right\" would be.\n\tgetRightOffset: function(leftIndex) {\n\t\tthis.ensureBuilt();\n\t\treturn this.rights[leftIndex];\n\t},\n\n\n\t// Gets the right position (from offsetParent left) of the element at the given index.\n\t// This value is NOT relative to the offsetParent's right edge, like the CSS concept of \"right\" would be.\n\tgetRightPosition: function(leftIndex) {\n\t\tthis.ensureBuilt();\n\t\treturn this.rights[leftIndex] - this.origin.left;\n\t},\n\n\n\t// Gets the width of the element at the given index\n\tgetWidth: function(leftIndex) {\n\t\tthis.ensureBuilt();\n\t\treturn this.rights[leftIndex] - this.lefts[leftIndex];\n\t},\n\n\n\t// Gets the top offset (from document top) of the element at the given index\n\tgetTopOffset: function(topIndex) {\n\t\tthis.ensureBuilt();\n\t\treturn this.tops[topIndex];\n\t},\n\n\n\t// Gets the top position (from offsetParent top) of the element at the given position\n\tgetTopPosition: function(topIndex) {\n\t\tthis.ensureBuilt();\n\t\treturn this.tops[topIndex] - this.origin.top;\n\t},\n\n\t// Gets the bottom offset (from the document top) of the element at the given index.\n\t// This value is NOT relative to the offsetParent's bottom edge, like the CSS concept of \"bottom\" would be.\n\tgetBottomOffset: function(topIndex) {\n\t\tthis.ensureBuilt();\n\t\treturn this.bottoms[topIndex];\n\t},\n\n\n\t// Gets the bottom position (from the offsetParent top) of the element at the given index.\n\t// This value is NOT relative to the offsetParent's bottom edge, like the CSS concept of \"bottom\" would be.\n\tgetBottomPosition: function(topIndex) {\n\t\tthis.ensureBuilt();\n\t\treturn this.bottoms[topIndex] - this.origin.top;\n\t},\n\n\n\t// Gets the height of the element at the given index\n\tgetHeight: function(topIndex) {\n\t\tthis.ensureBuilt();\n\t\treturn this.bottoms[topIndex] - this.tops[topIndex];\n\t},\n\n\n\t// Bounding Rect\n\t// TODO: decouple this from CoordCache\n\n\t// Compute and return what the elements' bounding rectangle is, from the user's perspective.\n\t// Right now, only returns a rectangle if constrained by an overflow:scroll element.\n\tqueryBoundingRect: function() {\n\t\tvar scrollParentEl = getScrollParent(this.els.eq(0));\n\n\t\tif (!scrollParentEl.is(document)) {\n\t\t\treturn getClientRect(scrollParentEl);\n\t\t}\n\t},\n\n\tisPointInBounds: function(leftOffset, topOffset) {\n\t\treturn this.isLeftInBounds(leftOffset) && this.isTopInBounds(topOffset);\n\t},\n\n\tisLeftInBounds: function(leftOffset) {\n\t\treturn !this.boundingRect || (leftOffset >= this.boundingRect.left && leftOffset < this.boundingRect.right);\n\t},\n\n\tisTopInBounds: function(topOffset) {\n\t\treturn !this.boundingRect || (topOffset >= this.boundingRect.top && topOffset < this.boundingRect.bottom);\n\t}\n\n});\n\n;;\n\n/* Tracks a drag's mouse movement, firing various handlers\n----------------------------------------------------------------------------------------------------------------------*/\n// TODO: use Emitter\n\nvar DragListener = FC.DragListener = Class.extend(ListenerMixin, MouseIgnorerMixin, {\n\n\toptions: null,\n\n\t// for IE8 bug-fighting behavior\n\tsubjectEl: null,\n\tsubjectHref: null,\n\n\t// coordinates of the initial mousedown\n\toriginX: null,\n\toriginY: null,\n\n\t// the wrapping element that scrolls, or MIGHT scroll if there's overflow.\n\t// TODO: do this for wrappers that have overflow:hidden as well.\n\tscrollEl: null,\n\n\tisInteracting: false,\n\tisDistanceSurpassed: false,\n\tisDelayEnded: false,\n\tisDragging: false,\n\tisTouch: false,\n\n\tdelay: null,\n\tdelayTimeoutId: null,\n\tminDistance: null,\n\n\thandleTouchScrollProxy: null, // calls handleTouchScroll, always bound to `this`\n\n\n\tconstructor: function(options) {\n\t\tthis.options = options || {};\n\t\tthis.handleTouchScrollProxy = proxy(this, 'handleTouchScroll');\n\t\tthis.initMouseIgnoring(500);\n\t},\n\n\n\t// Interaction (high-level)\n\t// -----------------------------------------------------------------------------------------------------------------\n\n\n\tstartInteraction: function(ev, extraOptions) {\n\t\tvar isTouch = getEvIsTouch(ev);\n\n\t\tif (ev.type === 'mousedown') {\n\t\t\tif (this.isIgnoringMouse) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\telse if (!isPrimaryMouseButton(ev)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tev.preventDefault(); // prevents native selection in most browsers\n\t\t\t}\n\t\t}\n\n\t\tif (!this.isInteracting) {\n\n\t\t\t// process options\n\t\t\textraOptions = extraOptions || {};\n\t\t\tthis.delay = firstDefined(extraOptions.delay, this.options.delay, 0);\n\t\t\tthis.minDistance = firstDefined(extraOptions.distance, this.options.distance, 0);\n\t\t\tthis.subjectEl = this.options.subjectEl;\n\n\t\t\tthis.isInteracting = true;\n\t\t\tthis.isTouch = isTouch;\n\t\t\tthis.isDelayEnded = false;\n\t\t\tthis.isDistanceSurpassed = false;\n\n\t\t\tthis.originX = getEvX(ev);\n\t\t\tthis.originY = getEvY(ev);\n\t\t\tthis.scrollEl = getScrollParent($(ev.target));\n\n\t\t\tthis.bindHandlers();\n\t\t\tthis.initAutoScroll();\n\t\t\tthis.handleInteractionStart(ev);\n\t\t\tthis.startDelay(ev);\n\n\t\t\tif (!this.minDistance) {\n\t\t\t\tthis.handleDistanceSurpassed(ev);\n\t\t\t}\n\t\t}\n\t},\n\n\n\thandleInteractionStart: function(ev) {\n\t\tthis.trigger('interactionStart', ev);\n\t},\n\n\n\tendInteraction: function(ev, isCancelled) {\n\t\tif (this.isInteracting) {\n\t\t\tthis.endDrag(ev);\n\n\t\t\tif (this.delayTimeoutId) {\n\t\t\t\tclearTimeout(this.delayTimeoutId);\n\t\t\t\tthis.delayTimeoutId = null;\n\t\t\t}\n\n\t\t\tthis.destroyAutoScroll();\n\t\t\tthis.unbindHandlers();\n\n\t\t\tthis.isInteracting = false;\n\t\t\tthis.handleInteractionEnd(ev, isCancelled);\n\n\t\t\t// a touchstart+touchend on the same element will result in the following addition simulated events:\n\t\t\t// mouseover + mouseout + click\n\t\t\t// let's ignore these bogus events\n\t\t\tif (this.isTouch) {\n\t\t\t\tthis.tempIgnoreMouse();\n\t\t\t}\n\t\t}\n\t},\n\n\n\thandleInteractionEnd: function(ev, isCancelled) {\n\t\tthis.trigger('interactionEnd', ev, isCancelled || false);\n\t},\n\n\n\t// Binding To DOM\n\t// -----------------------------------------------------------------------------------------------------------------\n\n\n\tbindHandlers: function() {\n\t\tvar _this = this;\n\t\tvar touchStartIgnores = 1;\n\n\t\tif (this.isTouch) {\n\t\t\tthis.listenTo($(document), {\n\t\t\t\ttouchmove: this.handleTouchMove,\n\t\t\t\ttouchend: this.endInteraction,\n\t\t\t\ttouchcancel: this.endInteraction,\n\n\t\t\t\t// Sometimes touchend doesn't fire\n\t\t\t\t// (can't figure out why. touchcancel doesn't fire either. has to do with scrolling?)\n\t\t\t\t// If another touchstart happens, we know it's bogus, so cancel the drag.\n\t\t\t\t// touchend will continue to be broken until user does a shorttap/scroll, but this is best we can do.\n\t\t\t\ttouchstart: function(ev) {\n\t\t\t\t\tif (touchStartIgnores) { // bindHandlers is called from within a touchstart,\n\t\t\t\t\t\ttouchStartIgnores--; // and we don't want this to fire immediately, so ignore.\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\t_this.endInteraction(ev, true); // isCancelled=true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// listen to ALL scroll actions on the page\n\t\t\tif (\n\t\t\t\t!bindAnyScroll(this.handleTouchScrollProxy) && // hopefully this works and short-circuits the rest\n\t\t\t\tthis.scrollEl // otherwise, attach a single handler to this\n\t\t\t) {\n\t\t\t\tthis.listenTo(this.scrollEl, 'scroll', this.handleTouchScroll);\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tthis.listenTo($(document), {\n\t\t\t\tmousemove: this.handleMouseMove,\n\t\t\t\tmouseup: this.endInteraction\n\t\t\t});\n\t\t}\n\n\t\tthis.listenTo($(document), {\n\t\t\tselectstart: preventDefault, // don't allow selection while dragging\n\t\t\tcontextmenu: preventDefault // long taps would open menu on Chrome dev tools\n\t\t});\n\t},\n\n\n\tunbindHandlers: function() {\n\t\tthis.stopListeningTo($(document));\n\n\t\t// unbind scroll listening\n\t\tunbindAnyScroll(this.handleTouchScrollProxy);\n\t\tif (this.scrollEl) {\n\t\t\tthis.stopListeningTo(this.scrollEl, 'scroll');\n\t\t}\n\t},\n\n\n\t// Drag (high-level)\n\t// -----------------------------------------------------------------------------------------------------------------\n\n\n\t// extraOptions ignored if drag already started\n\tstartDrag: function(ev, extraOptions) {\n\t\tthis.startInteraction(ev, extraOptions); // ensure interaction began\n\n\t\tif (!this.isDragging) {\n\t\t\tthis.isDragging = true;\n\t\t\tthis.handleDragStart(ev);\n\t\t}\n\t},\n\n\n\thandleDragStart: function(ev) {\n\t\tthis.trigger('dragStart', ev);\n\t\tthis.initHrefHack();\n\t},\n\n\n\thandleMove: function(ev) {\n\t\tvar dx = getEvX(ev) - this.originX;\n\t\tvar dy = getEvY(ev) - this.originY;\n\t\tvar minDistance = this.minDistance;\n\t\tvar distanceSq; // current distance from the origin, squared\n\n\t\tif (!this.isDistanceSurpassed) {\n\t\t\tdistanceSq = dx * dx + dy * dy;\n\t\t\tif (distanceSq >= minDistance * minDistance) { // use pythagorean theorem\n\t\t\t\tthis.handleDistanceSurpassed(ev);\n\t\t\t}\n\t\t}\n\n\t\tif (this.isDragging) {\n\t\t\tthis.handleDrag(dx, dy, ev);\n\t\t}\n\t},\n\n\n\t// Called while the mouse is being moved and when we know a legitimate drag is taking place\n\thandleDrag: function(dx, dy, ev) {\n\t\tthis.trigger('drag', dx, dy, ev);\n\t\tthis.updateAutoScroll(ev); // will possibly cause scrolling\n\t},\n\n\n\tendDrag: function(ev) {\n\t\tif (this.isDragging) {\n\t\t\tthis.isDragging = false;\n\t\t\tthis.handleDragEnd(ev);\n\t\t}\n\t},\n\n\n\thandleDragEnd: function(ev) {\n\t\tthis.trigger('dragEnd', ev);\n\t\tthis.destroyHrefHack();\n\t},\n\n\n\t// Delay\n\t// -----------------------------------------------------------------------------------------------------------------\n\n\n\tstartDelay: function(initialEv) {\n\t\tvar _this = this;\n\n\t\tif (this.delay) {\n\t\t\tthis.delayTimeoutId = setTimeout(function() {\n\t\t\t\t_this.handleDelayEnd(initialEv);\n\t\t\t}, this.delay);\n\t\t}\n\t\telse {\n\t\t\tthis.handleDelayEnd(initialEv);\n\t\t}\n\t},\n\n\n\thandleDelayEnd: function(initialEv) {\n\t\tthis.isDelayEnded = true;\n\n\t\tif (this.isDistanceSurpassed) {\n\t\t\tthis.startDrag(initialEv);\n\t\t}\n\t},\n\n\n\t// Distance\n\t// -----------------------------------------------------------------------------------------------------------------\n\n\n\thandleDistanceSurpassed: function(ev) {\n\t\tthis.isDistanceSurpassed = true;\n\n\t\tif (this.isDelayEnded) {\n\t\t\tthis.startDrag(ev);\n\t\t}\n\t},\n\n\n\t// Mouse / Touch\n\t// -----------------------------------------------------------------------------------------------------------------\n\n\n\thandleTouchMove: function(ev) {\n\t\t// prevent inertia and touchmove-scrolling while dragging\n\t\tif (this.isDragging) {\n\t\t\tev.preventDefault();\n\t\t}\n\n\t\tthis.handleMove(ev);\n\t},\n\n\n\thandleMouseMove: function(ev) {\n\t\tthis.handleMove(ev);\n\t},\n\n\n\t// Scrolling (unrelated to auto-scroll)\n\t// -----------------------------------------------------------------------------------------------------------------\n\n\n\thandleTouchScroll: function(ev) {\n\t\t// if the drag is being initiated by touch, but a scroll happens before\n\t\t// the drag-initiating delay is over, cancel the drag\n\t\tif (!this.isDragging) {\n\t\t\tthis.endInteraction(ev, true); // isCancelled=true\n\t\t}\n\t},\n\n\n\t// HREF Hack\n\t// -----------------------------------------------------------------------------------------------------------------\n\n\n\tinitHrefHack: function() {\n\t\tvar subjectEl = this.subjectEl;\n\n\t\t// remove a mousedown'd 's href so it is not visited (IE8 bug)\n\t\tif ((this.subjectHref = subjectEl ? subjectEl.attr('href') : null)) {\n\t\t\tsubjectEl.removeAttr('href');\n\t\t}\n\t},\n\n\n\tdestroyHrefHack: function() {\n\t\tvar subjectEl = this.subjectEl;\n\t\tvar subjectHref = this.subjectHref;\n\n\t\t// restore a mousedown'd 's href (for IE8 bug)\n\t\tsetTimeout(function() { // must be outside of the click's execution\n\t\t\tif (subjectHref) {\n\t\t\t\tsubjectEl.attr('href', subjectHref);\n\t\t\t}\n\t\t}, 0);\n\t},\n\n\n\t// Utils\n\t// -----------------------------------------------------------------------------------------------------------------\n\n\n\t// Triggers a callback. Calls a function in the option hash of the same name.\n\t// Arguments beyond the first `name` are forwarded on.\n\ttrigger: function(name) {\n\t\tif (this.options[name]) {\n\t\t\tthis.options[name].apply(this, Array.prototype.slice.call(arguments, 1));\n\t\t}\n\t\t// makes _methods callable by event name. TODO: kill this\n\t\tif (this['_' + name]) {\n\t\t\tthis['_' + name].apply(this, Array.prototype.slice.call(arguments, 1));\n\t\t}\n\t}\n\n\n});\n\n;;\n/*\nthis.scrollEl is set in DragListener\n*/\nDragListener.mixin({\n\n\tisAutoScroll: false,\n\n\tscrollBounds: null, // { top, bottom, left, right }\n\tscrollTopVel: null, // pixels per second\n\tscrollLeftVel: null, // pixels per second\n\tscrollIntervalId: null, // ID of setTimeout for scrolling animation loop\n\n\t// defaults\n\tscrollSensitivity: 30, // pixels from edge for scrolling to start\n\tscrollSpeed: 200, // pixels per second, at maximum speed\n\tscrollIntervalMs: 50, // millisecond wait between scroll increment\n\n\n\tinitAutoScroll: function() {\n\t\tvar scrollEl = this.scrollEl;\n\n\t\tthis.isAutoScroll =\n\t\t\tthis.options.scroll &&\n\t\t\tscrollEl &&\n\t\t\t!scrollEl.is(window) &&\n\t\t\t!scrollEl.is(document);\n\n\t\tif (this.isAutoScroll) {\n\t\t\t// debounce makes sure rapid calls don't happen\n\t\t\tthis.listenTo(scrollEl, 'scroll', debounce(this.handleDebouncedScroll, 100));\n\t\t}\n\t},\n\n\n\tdestroyAutoScroll: function() {\n\t\tthis.endAutoScroll(); // kill any animation loop\n\n\t\t// remove the scroll handler if there is a scrollEl\n\t\tif (this.isAutoScroll) {\n\t\t\tthis.stopListeningTo(this.scrollEl, 'scroll'); // will probably get removed by unbindHandlers too :(\n\t\t}\n\t},\n\n\n\t// Computes and stores the bounding rectangle of scrollEl\n\tcomputeScrollBounds: function() {\n\t\tif (this.isAutoScroll) {\n\t\t\tthis.scrollBounds = getOuterRect(this.scrollEl);\n\t\t\t// TODO: use getClientRect in future. but prevents auto scrolling when on top of scrollbars\n\t\t}\n\t},\n\n\n\t// Called when the dragging is in progress and scrolling should be updated\n\tupdateAutoScroll: function(ev) {\n\t\tvar sensitivity = this.scrollSensitivity;\n\t\tvar bounds = this.scrollBounds;\n\t\tvar topCloseness, bottomCloseness;\n\t\tvar leftCloseness, rightCloseness;\n\t\tvar topVel = 0;\n\t\tvar leftVel = 0;\n\n\t\tif (bounds) { // only scroll if scrollEl exists\n\n\t\t\t// compute closeness to edges. valid range is from 0.0 - 1.0\n\t\t\ttopCloseness = (sensitivity - (getEvY(ev) - bounds.top)) / sensitivity;\n\t\t\tbottomCloseness = (sensitivity - (bounds.bottom - getEvY(ev))) / sensitivity;\n\t\t\tleftCloseness = (sensitivity - (getEvX(ev) - bounds.left)) / sensitivity;\n\t\t\trightCloseness = (sensitivity - (bounds.right - getEvX(ev))) / sensitivity;\n\n\t\t\t// translate vertical closeness into velocity.\n\t\t\t// mouse must be completely in bounds for velocity to happen.\n\t\t\tif (topCloseness >= 0 && topCloseness <= 1) {\n\t\t\t\ttopVel = topCloseness * this.scrollSpeed * -1; // negative. for scrolling up\n\t\t\t}\n\t\t\telse if (bottomCloseness >= 0 && bottomCloseness <= 1) {\n\t\t\t\ttopVel = bottomCloseness * this.scrollSpeed;\n\t\t\t}\n\n\t\t\t// translate horizontal closeness into velocity\n\t\t\tif (leftCloseness >= 0 && leftCloseness <= 1) {\n\t\t\t\tleftVel = leftCloseness * this.scrollSpeed * -1; // negative. for scrolling left\n\t\t\t}\n\t\t\telse if (rightCloseness >= 0 && rightCloseness <= 1) {\n\t\t\t\tleftVel = rightCloseness * this.scrollSpeed;\n\t\t\t}\n\t\t}\n\n\t\tthis.setScrollVel(topVel, leftVel);\n\t},\n\n\n\t// Sets the speed-of-scrolling for the scrollEl\n\tsetScrollVel: function(topVel, leftVel) {\n\n\t\tthis.scrollTopVel = topVel;\n\t\tthis.scrollLeftVel = leftVel;\n\n\t\tthis.constrainScrollVel(); // massages into realistic values\n\n\t\t// if there is non-zero velocity, and an animation loop hasn't already started, then START\n\t\tif ((this.scrollTopVel || this.scrollLeftVel) && !this.scrollIntervalId) {\n\t\t\tthis.scrollIntervalId = setInterval(\n\t\t\t\tproxy(this, 'scrollIntervalFunc'), // scope to `this`\n\t\t\t\tthis.scrollIntervalMs\n\t\t\t);\n\t\t}\n\t},\n\n\n\t// Forces scrollTopVel and scrollLeftVel to be zero if scrolling has already gone all the way\n\tconstrainScrollVel: function() {\n\t\tvar el = this.scrollEl;\n\n\t\tif (this.scrollTopVel < 0) { // scrolling up?\n\t\t\tif (el.scrollTop() <= 0) { // already scrolled all the way up?\n\t\t\t\tthis.scrollTopVel = 0;\n\t\t\t}\n\t\t}\n\t\telse if (this.scrollTopVel > 0) { // scrolling down?\n\t\t\tif (el.scrollTop() + el[0].clientHeight >= el[0].scrollHeight) { // already scrolled all the way down?\n\t\t\t\tthis.scrollTopVel = 0;\n\t\t\t}\n\t\t}\n\n\t\tif (this.scrollLeftVel < 0) { // scrolling left?\n\t\t\tif (el.scrollLeft() <= 0) { // already scrolled all the left?\n\t\t\t\tthis.scrollLeftVel = 0;\n\t\t\t}\n\t\t}\n\t\telse if (this.scrollLeftVel > 0) { // scrolling right?\n\t\t\tif (el.scrollLeft() + el[0].clientWidth >= el[0].scrollWidth) { // already scrolled all the way right?\n\t\t\t\tthis.scrollLeftVel = 0;\n\t\t\t}\n\t\t}\n\t},\n\n\n\t// This function gets called during every iteration of the scrolling animation loop\n\tscrollIntervalFunc: function() {\n\t\tvar el = this.scrollEl;\n\t\tvar frac = this.scrollIntervalMs / 1000; // considering animation frequency, what the vel should be mult'd by\n\n\t\t// change the value of scrollEl's scroll\n\t\tif (this.scrollTopVel) {\n\t\t\tel.scrollTop(el.scrollTop() + this.scrollTopVel * frac);\n\t\t}\n\t\tif (this.scrollLeftVel) {\n\t\t\tel.scrollLeft(el.scrollLeft() + this.scrollLeftVel * frac);\n\t\t}\n\n\t\tthis.constrainScrollVel(); // since the scroll values changed, recompute the velocities\n\n\t\t// if scrolled all the way, which causes the vels to be zero, stop the animation loop\n\t\tif (!this.scrollTopVel && !this.scrollLeftVel) {\n\t\t\tthis.endAutoScroll();\n\t\t}\n\t},\n\n\n\t// Kills any existing scrolling animation loop\n\tendAutoScroll: function() {\n\t\tif (this.scrollIntervalId) {\n\t\t\tclearInterval(this.scrollIntervalId);\n\t\t\tthis.scrollIntervalId = null;\n\n\t\t\tthis.handleScrollEnd();\n\t\t}\n\t},\n\n\n\t// Get called when the scrollEl is scrolled (NOTE: this is delayed via debounce)\n\thandleDebouncedScroll: function() {\n\t\t// recompute all coordinates, but *only* if this is *not* part of our scrolling animation\n\t\tif (!this.scrollIntervalId) {\n\t\t\tthis.handleScrollEnd();\n\t\t}\n\t},\n\n\n\t// Called when scrolling has stopped, whether through auto scroll, or the user scrolling\n\thandleScrollEnd: function() {\n\t}\n\n});\n;;\n\n/* Tracks mouse movements over a component and raises events about which hit the mouse is over.\n------------------------------------------------------------------------------------------------------------------------\noptions:\n- subjectEl\n- subjectCenter\n*/\n\nvar HitDragListener = DragListener.extend({\n\n\tcomponent: null, // converts coordinates to hits\n\t\t// methods: prepareHits, releaseHits, queryHit\n\n\torigHit: null, // the hit the mouse was over when listening started\n\thit: null, // the hit the mouse is over\n\tcoordAdjust: null, // delta that will be added to the mouse coordinates when computing collisions\n\n\n\tconstructor: function(component, options) {\n\t\tDragListener.call(this, options); // call the super-constructor\n\n\t\tthis.component = component;\n\t},\n\n\n\t// Called when drag listening starts (but a real drag has not necessarily began).\n\t// ev might be undefined if dragging was started manually.\n\thandleInteractionStart: function(ev) {\n\t\tvar subjectEl = this.subjectEl;\n\t\tvar subjectRect;\n\t\tvar origPoint;\n\t\tvar point;\n\n\t\tthis.computeCoords();\n\n\t\tif (ev) {\n\t\t\torigPoint = { left: getEvX(ev), top: getEvY(ev) };\n\t\t\tpoint = origPoint;\n\n\t\t\t// constrain the point to bounds of the element being dragged\n\t\t\tif (subjectEl) {\n\t\t\t\tsubjectRect = getOuterRect(subjectEl); // used for centering as well\n\t\t\t\tpoint = constrainPoint(point, subjectRect);\n\t\t\t}\n\n\t\t\tthis.origHit = this.queryHit(point.left, point.top);\n\n\t\t\t// treat the center of the subject as the collision point?\n\t\t\tif (subjectEl && this.options.subjectCenter) {\n\n\t\t\t\t// only consider the area the subject overlaps the hit. best for large subjects.\n\t\t\t\t// TODO: skip this if hit didn't supply left/right/top/bottom\n\t\t\t\tif (this.origHit) {\n\t\t\t\t\tsubjectRect = intersectRects(this.origHit, subjectRect) ||\n\t\t\t\t\t\tsubjectRect; // in case there is no intersection\n\t\t\t\t}\n\n\t\t\t\tpoint = getRectCenter(subjectRect);\n\t\t\t}\n\n\t\t\tthis.coordAdjust = diffPoints(point, origPoint); // point - origPoint\n\t\t}\n\t\telse {\n\t\t\tthis.origHit = null;\n\t\t\tthis.coordAdjust = null;\n\t\t}\n\n\t\t// call the super-method. do it after origHit has been computed\n\t\tDragListener.prototype.handleInteractionStart.apply(this, arguments);\n\t},\n\n\n\t// Recomputes the drag-critical positions of elements\n\tcomputeCoords: function() {\n\t\tthis.component.prepareHits();\n\t\tthis.computeScrollBounds(); // why is this here??????\n\t},\n\n\n\t// Called when the actual drag has started\n\thandleDragStart: function(ev) {\n\t\tvar hit;\n\n\t\tDragListener.prototype.handleDragStart.apply(this, arguments); // call the super-method\n\n\t\t// might be different from this.origHit if the min-distance is large\n\t\thit = this.queryHit(getEvX(ev), getEvY(ev));\n\n\t\t// report the initial hit the mouse is over\n\t\t// especially important if no min-distance and drag starts immediately\n\t\tif (hit) {\n\t\t\tthis.handleHitOver(hit);\n\t\t}\n\t},\n\n\n\t// Called when the drag moves\n\thandleDrag: function(dx, dy, ev) {\n\t\tvar hit;\n\n\t\tDragListener.prototype.handleDrag.apply(this, arguments); // call the super-method\n\n\t\thit = this.queryHit(getEvX(ev), getEvY(ev));\n\n\t\tif (!isHitsEqual(hit, this.hit)) { // a different hit than before?\n\t\t\tif (this.hit) {\n\t\t\t\tthis.handleHitOut();\n\t\t\t}\n\t\t\tif (hit) {\n\t\t\t\tthis.handleHitOver(hit);\n\t\t\t}\n\t\t}\n\t},\n\n\n\t// Called when dragging has been stopped\n\thandleDragEnd: function() {\n\t\tthis.handleHitDone();\n\t\tDragListener.prototype.handleDragEnd.apply(this, arguments); // call the super-method\n\t},\n\n\n\t// Called when a the mouse has just moved over a new hit\n\thandleHitOver: function(hit) {\n\t\tvar isOrig = isHitsEqual(hit, this.origHit);\n\n\t\tthis.hit = hit;\n\n\t\tthis.trigger('hitOver', this.hit, isOrig, this.origHit);\n\t},\n\n\n\t// Called when the mouse has just moved out of a hit\n\thandleHitOut: function() {\n\t\tif (this.hit) {\n\t\t\tthis.trigger('hitOut', this.hit);\n\t\t\tthis.handleHitDone();\n\t\t\tthis.hit = null;\n\t\t}\n\t},\n\n\n\t// Called after a hitOut. Also called before a dragStop\n\thandleHitDone: function() {\n\t\tif (this.hit) {\n\t\t\tthis.trigger('hitDone', this.hit);\n\t\t}\n\t},\n\n\n\t// Called when the interaction ends, whether there was a real drag or not\n\thandleInteractionEnd: function() {\n\t\tDragListener.prototype.handleInteractionEnd.apply(this, arguments); // call the super-method\n\n\t\tthis.origHit = null;\n\t\tthis.hit = null;\n\n\t\tthis.component.releaseHits();\n\t},\n\n\n\t// Called when scrolling has stopped, whether through auto scroll, or the user scrolling\n\thandleScrollEnd: function() {\n\t\tDragListener.prototype.handleScrollEnd.apply(this, arguments); // call the super-method\n\n\t\tthis.computeCoords(); // hits' absolute positions will be in new places. recompute\n\t},\n\n\n\t// Gets the hit underneath the coordinates for the given mouse event\n\tqueryHit: function(left, top) {\n\n\t\tif (this.coordAdjust) {\n\t\t\tleft += this.coordAdjust.left;\n\t\t\ttop += this.coordAdjust.top;\n\t\t}\n\n\t\treturn this.component.queryHit(left, top);\n\t}\n\n});\n\n\n// Returns `true` if the hits are identically equal. `false` otherwise. Must be from the same component.\n// Two null values will be considered equal, as two \"out of the component\" states are the same.\nfunction isHitsEqual(hit0, hit1) {\n\n\tif (!hit0 && !hit1) {\n\t\treturn true;\n\t}\n\n\tif (hit0 && hit1) {\n\t\treturn hit0.component === hit1.component &&\n\t\t\tisHitPropsWithin(hit0, hit1) &&\n\t\t\tisHitPropsWithin(hit1, hit0); // ensures all props are identical\n\t}\n\n\treturn false;\n}\n\n\n// Returns true if all of subHit's non-standard properties are within superHit\nfunction isHitPropsWithin(subHit, superHit) {\n\tfor (var propName in subHit) {\n\t\tif (!/^(component|left|right|top|bottom)$/.test(propName)) {\n\t\t\tif (subHit[propName] !== superHit[propName]) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t}\n\treturn true;\n}\n\n;;\n\n/* Creates a clone of an element and lets it track the mouse as it moves\n----------------------------------------------------------------------------------------------------------------------*/\n\nvar MouseFollower = Class.extend(ListenerMixin, {\n\n\toptions: null,\n\n\tsourceEl: null, // the element that will be cloned and made to look like it is dragging\n\tel: null, // the clone of `sourceEl` that will track the mouse\n\tparentEl: null, // the element that `el` (the clone) will be attached to\n\n\t// the initial position of el, relative to the offset parent. made to match the initial offset of sourceEl\n\ttop0: null,\n\tleft0: null,\n\n\t// the absolute coordinates of the initiating touch/mouse action\n\ty0: null,\n\tx0: null,\n\n\t// the number of pixels the mouse has moved from its initial position\n\ttopDelta: null,\n\tleftDelta: null,\n\n\tisFollowing: false,\n\tisHidden: false,\n\tisAnimating: false, // doing the revert animation?\n\n\tconstructor: function(sourceEl, options) {\n\t\tthis.options = options = options || {};\n\t\tthis.sourceEl = sourceEl;\n\t\tthis.parentEl = options.parentEl ? $(options.parentEl) : sourceEl.parent(); // default to sourceEl's parent\n\t},\n\n\n\t// Causes the element to start following the mouse\n\tstart: function(ev) {\n\t\tif (!this.isFollowing) {\n\t\t\tthis.isFollowing = true;\n\n\t\t\tthis.y0 = getEvY(ev);\n\t\t\tthis.x0 = getEvX(ev);\n\t\t\tthis.topDelta = 0;\n\t\t\tthis.leftDelta = 0;\n\n\t\t\tif (!this.isHidden) {\n\t\t\t\tthis.updatePosition();\n\t\t\t}\n\n\t\t\tif (getEvIsTouch(ev)) {\n\t\t\t\tthis.listenTo($(document), 'touchmove', this.handleMove);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthis.listenTo($(document), 'mousemove', this.handleMove);\n\t\t\t}\n\t\t}\n\t},\n\n\n\t// Causes the element to stop following the mouse. If shouldRevert is true, will animate back to original position.\n\t// `callback` gets invoked when the animation is complete. If no animation, it is invoked immediately.\n\tstop: function(shouldRevert, callback) {\n\t\tvar _this = this;\n\t\tvar revertDuration = this.options.revertDuration;\n\n\t\tfunction complete() { // might be called by .animate(), which might change `this` context\n\t\t\t_this.isAnimating = false;\n\t\t\t_this.removeElement();\n\n\t\t\t_this.top0 = _this.left0 = null; // reset state for future updatePosition calls\n\n\t\t\tif (callback) {\n\t\t\t\tcallback();\n\t\t\t}\n\t\t}\n\n\t\tif (this.isFollowing && !this.isAnimating) { // disallow more than one stop animation at a time\n\t\t\tthis.isFollowing = false;\n\n\t\t\tthis.stopListeningTo($(document));\n\n\t\t\tif (shouldRevert && revertDuration && !this.isHidden) { // do a revert animation?\n\t\t\t\tthis.isAnimating = true;\n\t\t\t\tthis.el.animate({\n\t\t\t\t\ttop: this.top0,\n\t\t\t\t\tleft: this.left0\n\t\t\t\t}, {\n\t\t\t\t\tduration: revertDuration,\n\t\t\t\t\tcomplete: complete\n\t\t\t\t});\n\t\t\t}\n\t\t\telse {\n\t\t\t\tcomplete();\n\t\t\t}\n\t\t}\n\t},\n\n\n\t// Gets the tracking element. Create it if necessary\n\tgetEl: function() {\n\t\tvar el = this.el;\n\n\t\tif (!el) {\n\t\t\tthis.sourceEl.width(); // hack to force IE8 to compute correct bounding box\n\t\t\tel = this.el = this.sourceEl.clone()\n\t\t\t\t.addClass(this.options.additionalClass || '')\n\t\t\t\t.css({\n\t\t\t\t\tposition: 'absolute',\n\t\t\t\t\tvisibility: '', // in case original element was hidden (commonly through hideEvents())\n\t\t\t\t\tdisplay: this.isHidden ? 'none' : '', // for when initially hidden\n\t\t\t\t\tmargin: 0,\n\t\t\t\t\tright: 'auto', // erase and set width instead\n\t\t\t\t\tbottom: 'auto', // erase and set height instead\n\t\t\t\t\twidth: this.sourceEl.width(), // explicit height in case there was a 'right' value\n\t\t\t\t\theight: this.sourceEl.height(), // explicit width in case there was a 'bottom' value\n\t\t\t\t\topacity: this.options.opacity || '',\n\t\t\t\t\tzIndex: this.options.zIndex\n\t\t\t\t});\n\n\t\t\t// we don't want long taps or any mouse interaction causing selection/menus.\n\t\t\t// would use preventSelection(), but that prevents selectstart, causing problems.\n\t\t\tel.addClass('fc-unselectable');\n\n\t\t\tel.appendTo(this.parentEl);\n\t\t}\n\n\t\treturn el;\n\t},\n\n\n\t// Removes the tracking element if it has already been created\n\tremoveElement: function() {\n\t\tif (this.el) {\n\t\t\tthis.el.remove();\n\t\t\tthis.el = null;\n\t\t}\n\t},\n\n\n\t// Update the CSS position of the tracking element\n\tupdatePosition: function() {\n\t\tvar sourceOffset;\n\t\tvar origin;\n\n\t\tthis.getEl(); // ensure this.el\n\n\t\t// make sure origin info was computed\n\t\tif (this.top0 === null) {\n\t\t\tthis.sourceEl.width(); // hack to force IE8 to compute correct bounding box\n\t\t\tsourceOffset = this.sourceEl.offset();\n\t\t\torigin = this.el.offsetParent().offset();\n\t\t\tthis.top0 = sourceOffset.top - origin.top;\n\t\t\tthis.left0 = sourceOffset.left - origin.left;\n\t\t}\n\n\t\tthis.el.css({\n\t\t\ttop: this.top0 + this.topDelta,\n\t\t\tleft: this.left0 + this.leftDelta\n\t\t});\n\t},\n\n\n\t// Gets called when the user moves the mouse\n\thandleMove: function(ev) {\n\t\tthis.topDelta = getEvY(ev) - this.y0;\n\t\tthis.leftDelta = getEvX(ev) - this.x0;\n\n\t\tif (!this.isHidden) {\n\t\t\tthis.updatePosition();\n\t\t}\n\t},\n\n\n\t// Temporarily makes the tracking element invisible. Can be called before following starts\n\thide: function() {\n\t\tif (!this.isHidden) {\n\t\t\tthis.isHidden = true;\n\t\t\tif (this.el) {\n\t\t\t\tthis.el.hide();\n\t\t\t}\n\t\t}\n\t},\n\n\n\t// Show the tracking element after it has been temporarily hidden\n\tshow: function() {\n\t\tif (this.isHidden) {\n\t\t\tthis.isHidden = false;\n\t\t\tthis.updatePosition();\n\t\t\tthis.getEl().show();\n\t\t}\n\t}\n\n});\n\n;;\n\n/* An abstract class comprised of a \"grid\" of areas that each represent a specific datetime\n----------------------------------------------------------------------------------------------------------------------*/\n\nvar Grid = FC.Grid = Class.extend(ListenerMixin, MouseIgnorerMixin, {\n\n\tview: null, // a View object\n\tisRTL: null, // shortcut to the view's isRTL option\n\n\tstart: null,\n\tend: null,\n\n\tel: null, // the containing element\n\telsByFill: null, // a hash of jQuery element sets used for rendering each fill. Keyed by fill name.\n\n\t// derived from options\n\teventTimeFormat: null,\n\tdisplayEventTime: null,\n\tdisplayEventEnd: null,\n\n\tminResizeDuration: null, // TODO: hack. set by subclasses. minumum event resize duration\n\n\t// if defined, holds the unit identified (ex: \"year\" or \"month\") that determines the level of granularity\n\t// of the date areas. if not defined, assumes to be day and time granularity.\n\t// TODO: port isTimeScale into same system?\n\tlargeUnit: null,\n\n\tdayDragListener: null,\n\tsegDragListener: null,\n\tsegResizeListener: null,\n\texternalDragListener: null,\n\n\n\tconstructor: function(view) {\n\t\tthis.view = view;\n\t\tthis.isRTL = view.opt('isRTL');\n\t\tthis.elsByFill = {};\n\n\t\tthis.dayDragListener = this.buildDayDragListener();\n\t\tthis.initMouseIgnoring();\n\t},\n\n\n\t/* Options\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// Generates the format string used for event time text, if not explicitly defined by 'timeFormat'\n\tcomputeEventTimeFormat: function() {\n\t\treturn this.view.opt('smallTimeFormat');\n\t},\n\n\n\t// Determines whether events should have their end times displayed, if not explicitly defined by 'displayEventTime'.\n\t// Only applies to non-all-day events.\n\tcomputeDisplayEventTime: function() {\n\t\treturn true;\n\t},\n\n\n\t// Determines whether events should have their end times displayed, if not explicitly defined by 'displayEventEnd'\n\tcomputeDisplayEventEnd: function() {\n\t\treturn true;\n\t},\n\n\n\t/* Dates\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// Tells the grid about what period of time to display.\n\t// Any date-related internal data should be generated.\n\tsetRange: function(range) {\n\t\tthis.start = range.start.clone();\n\t\tthis.end = range.end.clone();\n\n\t\tthis.rangeUpdated();\n\t\tthis.processRangeOptions();\n\t},\n\n\n\t// Called when internal variables that rely on the range should be updated\n\trangeUpdated: function() {\n\t},\n\n\n\t// Updates values that rely on options and also relate to range\n\tprocessRangeOptions: function() {\n\t\tvar view = this.view;\n\t\tvar displayEventTime;\n\t\tvar displayEventEnd;\n\n\t\tthis.eventTimeFormat =\n\t\t\tview.opt('eventTimeFormat') ||\n\t\t\tview.opt('timeFormat') || // deprecated\n\t\t\tthis.computeEventTimeFormat();\n\n\t\tdisplayEventTime = view.opt('displayEventTime');\n\t\tif (displayEventTime == null) {\n\t\t\tdisplayEventTime = this.computeDisplayEventTime(); // might be based off of range\n\t\t}\n\n\t\tdisplayEventEnd = view.opt('displayEventEnd');\n\t\tif (displayEventEnd == null) {\n\t\t\tdisplayEventEnd = this.computeDisplayEventEnd(); // might be based off of range\n\t\t}\n\n\t\tthis.displayEventTime = displayEventTime;\n\t\tthis.displayEventEnd = displayEventEnd;\n\t},\n\n\n\t// Converts a span (has unzoned start/end and any other grid-specific location information)\n\t// into an array of segments (pieces of events whose format is decided by the grid).\n\tspanToSegs: function(span) {\n\t\t// subclasses must implement\n\t},\n\n\n\t// Diffs the two dates, returning a duration, based on granularity of the grid\n\t// TODO: port isTimeScale into this system?\n\tdiffDates: function(a, b) {\n\t\tif (this.largeUnit) {\n\t\t\treturn diffByUnit(a, b, this.largeUnit);\n\t\t}\n\t\telse {\n\t\t\treturn diffDayTime(a, b);\n\t\t}\n\t},\n\n\n\t/* Hit Area\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// Called before one or more queryHit calls might happen. Should prepare any cached coordinates for queryHit\n\tprepareHits: function() {\n\t},\n\n\n\t// Called when queryHit calls have subsided. Good place to clear any coordinate caches.\n\treleaseHits: function() {\n\t},\n\n\n\t// Given coordinates from the topleft of the document, return data about the date-related area underneath.\n\t// Can return an object with arbitrary properties (although top/right/left/bottom are encouraged).\n\t// Must have a `grid` property, a reference to this current grid. TODO: avoid this\n\t// The returned object will be processed by getHitSpan and getHitEl.\n\tqueryHit: function(leftOffset, topOffset) {\n\t},\n\n\n\t// Given position-level information about a date-related area within the grid,\n\t// should return an object with at least a start/end date. Can provide other information as well.\n\tgetHitSpan: function(hit) {\n\t},\n\n\n\t// Given position-level information about a date-related area within the grid,\n\t// should return a jQuery element that best represents it. passed to dayClick callback.\n\tgetHitEl: function(hit) {\n\t},\n\n\n\t/* Rendering\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// Sets the container element that the grid should render inside of.\n\t// Does other DOM-related initializations.\n\tsetElement: function(el) {\n\t\tthis.el = el;\n\t\tpreventSelection(el);\n\n\t\tthis.bindDayHandler('touchstart', this.dayTouchStart);\n\t\tthis.bindDayHandler('mousedown', this.dayMousedown);\n\n\t\t// attach event-element-related handlers. in Grid.events\n\t\t// same garbage collection note as above.\n\t\tthis.bindSegHandlers();\n\n\t\tthis.bindGlobalHandlers();\n\t},\n\n\n\tbindDayHandler: function(name, handler) {\n\t\tvar _this = this;\n\n\t\t// attach a handler to the grid's root element.\n\t\t// jQuery will take care of unregistering them when removeElement gets called.\n\t\tthis.el.on(name, function(ev) {\n\t\t\tif (\n\t\t\t\t!$(ev.target).is('.fc-event-container *, .fc-more') // not an an event element, or \"more..\" link\n\t\t\t) {\n\t\t\t\treturn handler.call(_this, ev);\n\t\t\t}\n\t\t});\n\t},\n\n\n\t// Removes the grid's container element from the DOM. Undoes any other DOM-related attachments.\n\t// DOES NOT remove any content beforehand (doesn't clear events or call unrenderDates), unlike View\n\tremoveElement: function() {\n\t\tthis.unbindGlobalHandlers();\n\t\tthis.clearDragListeners();\n\n\t\tthis.el.remove();\n\n\t\t// NOTE: we don't null-out this.el for the same reasons we don't do it within View::removeElement\n\t},\n\n\n\t// Renders the basic structure of grid view before any content is rendered\n\trenderSkeleton: function() {\n\t\t// subclasses should implement\n\t},\n\n\n\t// Renders the grid's date-related content (like areas that represent days/times).\n\t// Assumes setRange has already been called and the skeleton has already been rendered.\n\trenderDates: function() {\n\t\t// subclasses should implement\n\t},\n\n\n\t// Unrenders the grid's date-related content\n\tunrenderDates: function() {\n\t\t// subclasses should implement\n\t},\n\n\n\t/* Handlers\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// Binds DOM handlers to elements that reside outside the grid, such as the document\n\tbindGlobalHandlers: function() {\n\t\tthis.listenTo($(document), {\n\t\t\tdragstart: this.externalDragStart, // jqui\n\t\t\tsortstart: this.externalDragStart // jqui\n\t\t});\n\t},\n\n\n\t// Unbinds DOM handlers from elements that reside outside the grid\n\tunbindGlobalHandlers: function() {\n\t\tthis.stopListeningTo($(document));\n\t},\n\n\n\t// Process a mousedown on an element that represents a day. For day clicking and selecting.\n\tdayMousedown: function(ev) {\n\t\tif (!this.isIgnoringMouse) {\n\t\t\tthis.dayDragListener.startInteraction(ev, {\n\t\t\t\t//distance: 5, // needs more work if we want dayClick to fire correctly\n\t\t\t});\n\t\t}\n\t},\n\n\n\tdayTouchStart: function(ev) {\n\t\tvar view = this.view;\n\n\t\t// HACK to prevent a user's clickaway for unselecting a range or an event\n\t\t// from causing a dayClick.\n\t\tif (view.isSelected || view.selectedEvent) {\n\t\t\tthis.tempIgnoreMouse();\n\t\t}\n\n\t\tthis.dayDragListener.startInteraction(ev, {\n\t\t\tdelay: this.view.opt('longPressDelay')\n\t\t});\n\t},\n\n\n\t// Creates a listener that tracks the user's drag across day elements.\n\t// For day clicking and selecting.\n\tbuildDayDragListener: function() {\n\t\tvar _this = this;\n\t\tvar view = this.view;\n\t\tvar isSelectable = view.opt('selectable');\n\t\tvar dayClickHit; // null if invalid dayClick\n\t\tvar selectionSpan; // null if invalid selection\n\n\t\t// this listener tracks a mousedown on a day element, and a subsequent drag.\n\t\t// if the drag ends on the same day, it is a 'dayClick'.\n\t\t// if 'selectable' is enabled, this listener also detects selections.\n\t\tvar dragListener = new HitDragListener(this, {\n\t\t\tscroll: view.opt('dragScroll'),\n\t\t\tinteractionStart: function() {\n\t\t\t\tdayClickHit = dragListener.origHit; // for dayClick, where no dragging happens\n\t\t\t\tselectionSpan = null;\n\t\t\t},\n\t\t\tdragStart: function() {\n\t\t\t\tview.unselect(); // since we could be rendering a new selection, we want to clear any old one\n\t\t\t},\n\t\t\thitOver: function(hit, isOrig, origHit) {\n\t\t\t\tif (origHit) { // click needs to have started on a hit\n\n\t\t\t\t\t// if user dragged to another cell at any point, it can no longer be a dayClick\n\t\t\t\t\tif (!isOrig) {\n\t\t\t\t\t\tdayClickHit = null;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (isSelectable) {\n\t\t\t\t\t\tselectionSpan = _this.computeSelection(\n\t\t\t\t\t\t\t_this.getHitSpan(origHit),\n\t\t\t\t\t\t\t_this.getHitSpan(hit)\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif (selectionSpan) {\n\t\t\t\t\t\t\t_this.renderSelection(selectionSpan);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (selectionSpan === false) {\n\t\t\t\t\t\t\tdisableCursor();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\thitOut: function() { // called before mouse moves to a different hit OR moved out of all hits\n\t\t\t\tdayClickHit = null;\n\t\t\t\tselectionSpan = null;\n\t\t\t\t_this.unrenderSelection();\n\t\t\t},\n\t\t\thitDone: function() { // called after a hitOut OR before a dragEnd\n\t\t\t\tenableCursor();\n\t\t\t},\n\t\t\tinteractionEnd: function(ev, isCancelled) {\n\t\t\t\tif (!isCancelled) {\n\t\t\t\t\tif (\n\t\t\t\t\t\tdayClickHit &&\n\t\t\t\t\t\t!_this.isIgnoringMouse // see hack in dayTouchStart\n\t\t\t\t\t) {\n\t\t\t\t\t\tview.triggerDayClick(\n\t\t\t\t\t\t\t_this.getHitSpan(dayClickHit),\n\t\t\t\t\t\t\t_this.getHitEl(dayClickHit),\n\t\t\t\t\t\t\tev\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tif (selectionSpan) {\n\t\t\t\t\t\t// the selection will already have been rendered. just report it\n\t\t\t\t\t\tview.reportSelection(selectionSpan, ev);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\treturn dragListener;\n\t},\n\n\n\t// Kills all in-progress dragging.\n\t// Useful for when public API methods that result in re-rendering are invoked during a drag.\n\t// Also useful for when touch devices misbehave and don't fire their touchend.\n\tclearDragListeners: function() {\n\t\tthis.dayDragListener.endInteraction();\n\n\t\tif (this.segDragListener) {\n\t\t\tthis.segDragListener.endInteraction(); // will clear this.segDragListener\n\t\t}\n\t\tif (this.segResizeListener) {\n\t\t\tthis.segResizeListener.endInteraction(); // will clear this.segResizeListener\n\t\t}\n\t\tif (this.externalDragListener) {\n\t\t\tthis.externalDragListener.endInteraction(); // will clear this.externalDragListener\n\t\t}\n\t},\n\n\n\t/* Event Helper\n\t------------------------------------------------------------------------------------------------------------------*/\n\t// TODO: should probably move this to Grid.events, like we did event dragging / resizing\n\n\n\t// Renders a mock event at the given event location, which contains zoned start/end properties.\n\t// Returns all mock event elements.\n\trenderEventLocationHelper: function(eventLocation, sourceSeg) {\n\t\tvar fakeEvent = this.fabricateHelperEvent(eventLocation, sourceSeg);\n\n\t\treturn this.renderHelper(fakeEvent, sourceSeg); // do the actual rendering\n\t},\n\n\n\t// Builds a fake event given zoned event date properties and a segment is should be inspired from.\n\t// The range's end can be null, in which case the mock event that is rendered will have a null end time.\n\t// `sourceSeg` is the internal segment object involved in the drag. If null, something external is dragging.\n\tfabricateHelperEvent: function(eventLocation, sourceSeg) {\n\t\tvar fakeEvent = sourceSeg ? createObject(sourceSeg.event) : {}; // mask the original event object if possible\n\n\t\tfakeEvent.start = eventLocation.start.clone();\n\t\tfakeEvent.end = eventLocation.end ? eventLocation.end.clone() : null;\n\t\tfakeEvent.allDay = null; // force it to be freshly computed by normalizeEventDates\n\t\tthis.view.calendar.normalizeEventDates(fakeEvent);\n\n\t\t// this extra className will be useful for differentiating real events from mock events in CSS\n\t\tfakeEvent.className = (fakeEvent.className || []).concat('fc-helper');\n\n\t\t// if something external is being dragged in, don't render a resizer\n\t\tif (!sourceSeg) {\n\t\t\tfakeEvent.editable = false;\n\t\t}\n\n\t\treturn fakeEvent;\n\t},\n\n\n\t// Renders a mock event. Given zoned event date properties.\n\t// Must return all mock event elements.\n\trenderHelper: function(eventLocation, sourceSeg) {\n\t\t// subclasses must implement\n\t},\n\n\n\t// Unrenders a mock event\n\tunrenderHelper: function() {\n\t\t// subclasses must implement\n\t},\n\n\n\t/* Selection\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// Renders a visual indication of a selection. Will highlight by default but can be overridden by subclasses.\n\t// Given a span (unzoned start/end and other misc data)\n\trenderSelection: function(span) {\n\t\tthis.renderHighlight(span);\n\t},\n\n\n\t// Unrenders any visual indications of a selection. Will unrender a highlight by default.\n\tunrenderSelection: function() {\n\t\tthis.unrenderHighlight();\n\t},\n\n\n\t// Given the first and last date-spans of a selection, returns another date-span object.\n\t// Subclasses can override and provide additional data in the span object. Will be passed to renderSelection().\n\t// Will return false if the selection is invalid and this should be indicated to the user.\n\t// Will return null/undefined if a selection invalid but no error should be reported.\n\tcomputeSelection: function(span0, span1) {\n\t\tvar span = this.computeSelectionSpan(span0, span1);\n\n\t\tif (span && !this.view.calendar.isSelectionSpanAllowed(span)) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn span;\n\t},\n\n\n\t// Given two spans, must return the combination of the two.\n\t// TODO: do this separation of concerns (combining VS validation) for event dnd/resize too.\n\tcomputeSelectionSpan: function(span0, span1) {\n\t\tvar dates = [ span0.start, span0.end, span1.start, span1.end ];\n\n\t\tdates.sort(compareNumbers); // sorts chronologically. works with Moments\n\n\t\treturn { start: dates[0].clone(), end: dates[3].clone() };\n\t},\n\n\n\t/* Highlight\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// Renders an emphasis on the given date range. Given a span (unzoned start/end and other misc data)\n\trenderHighlight: function(span) {\n\t\tthis.renderFill('highlight', this.spanToSegs(span));\n\t},\n\n\n\t// Unrenders the emphasis on a date range\n\tunrenderHighlight: function() {\n\t\tthis.unrenderFill('highlight');\n\t},\n\n\n\t// Generates an array of classNames for rendering the highlight. Used by the fill system.\n\thighlightSegClasses: function() {\n\t\treturn [ 'fc-highlight' ];\n\t},\n\n\n\t/* Business Hours\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\trenderBusinessHours: function() {\n\t},\n\n\n\tunrenderBusinessHours: function() {\n\t},\n\n\n\t/* Now Indicator\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\tgetNowIndicatorUnit: function() {\n\t},\n\n\n\trenderNowIndicator: function(date) {\n\t},\n\n\n\tunrenderNowIndicator: function() {\n\t},\n\n\n\t/* Fill System (highlight, background events, business hours)\n\t--------------------------------------------------------------------------------------------------------------------\n\tTODO: remove this system. like we did in TimeGrid\n\t*/\n\n\n\t// Renders a set of rectangles over the given segments of time.\n\t// MUST RETURN a subset of segs, the segs that were actually rendered.\n\t// Responsible for populating this.elsByFill. TODO: better API for expressing this requirement\n\trenderFill: function(type, segs) {\n\t\t// subclasses must implement\n\t},\n\n\n\t// Unrenders a specific type of fill that is currently rendered on the grid\n\tunrenderFill: function(type) {\n\t\tvar el = this.elsByFill[type];\n\n\t\tif (el) {\n\t\t\tel.remove();\n\t\t\tdelete this.elsByFill[type];\n\t\t}\n\t},\n\n\n\t// Renders and assigns an `el` property for each fill segment. Generic enough to work with different types.\n\t// Only returns segments that successfully rendered.\n\t// To be harnessed by renderFill (implemented by subclasses).\n\t// Analagous to renderFgSegEls.\n\trenderFillSegEls: function(type, segs) {\n\t\tvar _this = this;\n\t\tvar segElMethod = this[type + 'SegEl'];\n\t\tvar html = '';\n\t\tvar renderedSegs = [];\n\t\tvar i;\n\n\t\tif (segs.length) {\n\n\t\t\t// build a large concatenation of segment HTML\n\t\t\tfor (i = 0; i < segs.length; i++) {\n\t\t\t\thtml += this.fillSegHtml(type, segs[i]);\n\t\t\t}\n\n\t\t\t// Grab individual elements from the combined HTML string. Use each as the default rendering.\n\t\t\t// Then, compute the 'el' for each segment.\n\t\t\t$(html).each(function(i, node) {\n\t\t\t\tvar seg = segs[i];\n\t\t\t\tvar el = $(node);\n\n\t\t\t\t// allow custom filter methods per-type\n\t\t\t\tif (segElMethod) {\n\t\t\t\t\tel = segElMethod.call(_this, seg, el);\n\t\t\t\t}\n\n\t\t\t\tif (el) { // custom filters did not cancel the render\n\t\t\t\t\tel = $(el); // allow custom filter to return raw DOM node\n\n\t\t\t\t\t// correct element type? (would be bad if a non-TD were inserted into a table for example)\n\t\t\t\t\tif (el.is(_this.fillSegTag)) {\n\t\t\t\t\t\tseg.el = el;\n\t\t\t\t\t\trenderedSegs.push(seg);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\treturn renderedSegs;\n\t},\n\n\n\tfillSegTag: 'div', // subclasses can override\n\n\n\t// Builds the HTML needed for one fill segment. Generic enough to work with different types.\n\tfillSegHtml: function(type, seg) {\n\n\t\t// custom hooks per-type\n\t\tvar classesMethod = this[type + 'SegClasses'];\n\t\tvar cssMethod = this[type + 'SegCss'];\n\n\t\tvar classes = classesMethod ? classesMethod.call(this, seg) : [];\n\t\tvar css = cssToStr(cssMethod ? cssMethod.call(this, seg) : {});\n\n\t\treturn '<' + this.fillSegTag +\n\t\t\t(classes.length ? ' class=\"' + classes.join(' ') + '\"' : '') +\n\t\t\t(css ? ' style=\"' + css + '\"' : '') +\n\t\t\t' />';\n\t},\n\n\n\n\t/* Generic rendering utilities for subclasses\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// Computes HTML classNames for a single-day element\n\tgetDayClasses: function(date) {\n\t\tvar view = this.view;\n\t\tvar today = view.calendar.getNow();\n\t\tvar classes = [ 'fc-' + dayIDs[date.day()] ];\n\n\t\tif (\n\t\t\tview.intervalDuration.as('months') == 1 &&\n\t\t\tdate.month() != view.intervalStart.month()\n\t\t) {\n\t\t\tclasses.push('fc-other-month');\n\t\t}\n\n\t\tif (date.isSame(today, 'day')) {\n\t\t\tclasses.push(\n\t\t\t\t'fc-today',\n\t\t\t\tview.highlightStateClass\n\t\t\t);\n\t\t}\n\t\telse if (date < today) {\n\t\t\tclasses.push('fc-past');\n\t\t}\n\t\telse {\n\t\t\tclasses.push('fc-future');\n\t\t}\n\n\t\treturn classes;\n\t}\n\n});\n\n;;\n\n/* Event-rendering and event-interaction methods for the abstract Grid class\n----------------------------------------------------------------------------------------------------------------------*/\n\nGrid.mixin({\n\n\tmousedOverSeg: null, // the segment object the user's mouse is over. null if over nothing\n\tisDraggingSeg: false, // is a segment being dragged? boolean\n\tisResizingSeg: false, // is a segment being resized? boolean\n\tisDraggingExternal: false, // jqui-dragging an external element? boolean\n\tsegs: null, // the *event* segments currently rendered in the grid. TODO: rename to `eventSegs`\n\n\n\t// Renders the given events onto the grid\n\trenderEvents: function(events) {\n\t\tvar bgEvents = [];\n\t\tvar fgEvents = [];\n\t\tvar i;\n\n\t\tfor (i = 0; i < events.length; i++) {\n\t\t\t(isBgEvent(events[i]) ? bgEvents : fgEvents).push(events[i]);\n\t\t}\n\n\t\tthis.segs = [].concat( // record all segs\n\t\t\tthis.renderBgEvents(bgEvents),\n\t\t\tthis.renderFgEvents(fgEvents)\n\t\t);\n\t},\n\n\n\trenderBgEvents: function(events) {\n\t\tvar segs = this.eventsToSegs(events);\n\n\t\t// renderBgSegs might return a subset of segs, segs that were actually rendered\n\t\treturn this.renderBgSegs(segs) || segs;\n\t},\n\n\n\trenderFgEvents: function(events) {\n\t\tvar segs = this.eventsToSegs(events);\n\n\t\t// renderFgSegs might return a subset of segs, segs that were actually rendered\n\t\treturn this.renderFgSegs(segs) || segs;\n\t},\n\n\n\t// Unrenders all events currently rendered on the grid\n\tunrenderEvents: function() {\n\t\tthis.handleSegMouseout(); // trigger an eventMouseout if user's mouse is over an event\n\t\tthis.clearDragListeners();\n\n\t\tthis.unrenderFgSegs();\n\t\tthis.unrenderBgSegs();\n\n\t\tthis.segs = null;\n\t},\n\n\n\t// Retrieves all rendered segment objects currently rendered on the grid\n\tgetEventSegs: function() {\n\t\treturn this.segs || [];\n\t},\n\n\n\t/* Foreground Segment Rendering\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// Renders foreground event segments onto the grid. May return a subset of segs that were rendered.\n\trenderFgSegs: function(segs) {\n\t\t// subclasses must implement\n\t},\n\n\n\t// Unrenders all currently rendered foreground segments\n\tunrenderFgSegs: function() {\n\t\t// subclasses must implement\n\t},\n\n\n\t// Renders and assigns an `el` property for each foreground event segment.\n\t// Only returns segments that successfully rendered.\n\t// A utility that subclasses may use.\n\trenderFgSegEls: function(segs, disableResizing) {\n\t\tvar view = this.view;\n\t\tvar html = '';\n\t\tvar renderedSegs = [];\n\t\tvar i;\n\n\t\tif (segs.length) { // don't build an empty html string\n\n\t\t\t// build a large concatenation of event segment HTML\n\t\t\tfor (i = 0; i < segs.length; i++) {\n\t\t\t\thtml += this.fgSegHtml(segs[i], disableResizing);\n\t\t\t}\n\n\t\t\t// Grab individual elements from the combined HTML string. Use each as the default rendering.\n\t\t\t// Then, compute the 'el' for each segment. An el might be null if the eventRender callback returned false.\n\t\t\t$(html).each(function(i, node) {\n\t\t\t\tvar seg = segs[i];\n\t\t\t\tvar el = view.resolveEventEl(seg.event, $(node));\n\n\t\t\t\tif (el) {\n\t\t\t\t\tel.data('fc-seg', seg); // used by handlers\n\t\t\t\t\tseg.el = el;\n\t\t\t\t\trenderedSegs.push(seg);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\treturn renderedSegs;\n\t},\n\n\n\t// Generates the HTML for the default rendering of a foreground event segment. Used by renderFgSegEls()\n\tfgSegHtml: function(seg, disableResizing) {\n\t\t// subclasses should implement\n\t},\n\n\n\t/* Background Segment Rendering\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// Renders the given background event segments onto the grid.\n\t// Returns a subset of the segs that were actually rendered.\n\trenderBgSegs: function(segs) {\n\t\treturn this.renderFill('bgEvent', segs);\n\t},\n\n\n\t// Unrenders all the currently rendered background event segments\n\tunrenderBgSegs: function() {\n\t\tthis.unrenderFill('bgEvent');\n\t},\n\n\n\t// Renders a background event element, given the default rendering. Called by the fill system.\n\tbgEventSegEl: function(seg, el) {\n\t\treturn this.view.resolveEventEl(seg.event, el); // will filter through eventRender\n\t},\n\n\n\t// Generates an array of classNames to be used for the default rendering of a background event.\n\t// Called by fillSegHtml.\n\tbgEventSegClasses: function(seg) {\n\t\tvar event = seg.event;\n\t\tvar source = event.source || {};\n\n\t\treturn [ 'fc-bgevent' ].concat(\n\t\t\tevent.className,\n\t\t\tsource.className || []\n\t\t);\n\t},\n\n\n\t// Generates a semicolon-separated CSS string to be used for the default rendering of a background event.\n\t// Called by fillSegHtml.\n\tbgEventSegCss: function(seg) {\n\t\treturn {\n\t\t\t'background-color': this.getSegSkinCss(seg)['background-color']\n\t\t};\n\t},\n\n\n\t// Generates an array of classNames to be used for the rendering business hours overlay. Called by the fill system.\n\t// Called by fillSegHtml.\n\tbusinessHoursSegClasses: function(seg) {\n\t\treturn [ 'fc-nonbusiness', 'fc-bgevent' ];\n\t},\n\n\n\t/* Business Hours\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// Compute business hour segs for the grid's current date range.\n\t// Caller must ask if whole-day business hours are needed.\n\tbuildBusinessHourSegs: function(wholeDay) {\n\t\tvar events = this.view.calendar.getCurrentBusinessHourEvents(wholeDay);\n\n\t\t// HACK. Eventually refactor business hours \"events\" system.\n\t\t// If no events are given, but businessHours is activated, this means the entire visible range should be\n\t\t// marked as *not* business-hours, via inverse-background rendering.\n\t\tif (\n\t\t\t!events.length &&\n\t\t\tthis.view.calendar.options.businessHours // don't access view option. doesn't update with dynamic options\n\t\t) {\n\t\t\tevents = [\n\t\t\t\t$.extend({}, BUSINESS_HOUR_EVENT_DEFAULTS, {\n\t\t\t\t\tstart: this.view.end, // guaranteed out-of-range\n\t\t\t\t\tend: this.view.end, // \"\n\t\t\t\t\tdow: null\n\t\t\t\t})\n\t\t\t];\n\t\t}\n\n\t\treturn this.eventsToSegs(events);\n\t},\n\n\n\t/* Handlers\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// Attaches event-element-related handlers for *all* rendered event segments of the view.\n\tbindSegHandlers: function() {\n\t\tthis.bindSegHandlersToEl(this.el);\n\t},\n\n\n\t// Attaches event-element-related handlers to an arbitrary container element. leverages bubbling.\n\tbindSegHandlersToEl: function(el) {\n\t\tthis.bindSegHandlerToEl(el, 'touchstart', this.handleSegTouchStart);\n\t\tthis.bindSegHandlerToEl(el, 'touchend', this.handleSegTouchEnd);\n\t\tthis.bindSegHandlerToEl(el, 'mouseenter', this.handleSegMouseover);\n\t\tthis.bindSegHandlerToEl(el, 'mouseleave', this.handleSegMouseout);\n\t\tthis.bindSegHandlerToEl(el, 'mousedown', this.handleSegMousedown);\n\t\tthis.bindSegHandlerToEl(el, 'click', this.handleSegClick);\n\t},\n\n\n\t// Executes a handler for any a user-interaction on a segment.\n\t// Handler gets called with (seg, ev), and with the `this` context of the Grid\n\tbindSegHandlerToEl: function(el, name, handler) {\n\t\tvar _this = this;\n\n\t\tel.on(name, '.fc-event-container > *', function(ev) {\n\t\t\tvar seg = $(this).data('fc-seg'); // grab segment data. put there by View::renderEvents\n\n\t\t\t// only call the handlers if there is not a drag/resize in progress\n\t\t\tif (seg && !_this.isDraggingSeg && !_this.isResizingSeg) {\n\t\t\t\treturn handler.call(_this, seg, ev); // context will be the Grid\n\t\t\t}\n\t\t});\n\t},\n\n\n\thandleSegClick: function(seg, ev) {\n\t\treturn this.view.trigger('eventClick', seg.el[0], seg.event, ev); // can return `false` to cancel\n\t},\n\n\n\t// Updates internal state and triggers handlers for when an event element is moused over\n\thandleSegMouseover: function(seg, ev) {\n\t\tif (\n\t\t\t!this.isIgnoringMouse &&\n\t\t\t!this.mousedOverSeg\n\t\t) {\n\t\t\tthis.mousedOverSeg = seg;\n\t\t\tseg.el.addClass('fc-allow-mouse-resize');\n\t\t\tthis.view.trigger('eventMouseover', seg.el[0], seg.event, ev);\n\t\t}\n\t},\n\n\n\t// Updates internal state and triggers handlers for when an event element is moused out.\n\t// Can be given no arguments, in which case it will mouseout the segment that was previously moused over.\n\thandleSegMouseout: function(seg, ev) {\n\t\tev = ev || {}; // if given no args, make a mock mouse event\n\n\t\tif (this.mousedOverSeg) {\n\t\t\tseg = seg || this.mousedOverSeg; // if given no args, use the currently moused-over segment\n\t\t\tthis.mousedOverSeg = null;\n\t\t\tseg.el.removeClass('fc-allow-mouse-resize');\n\t\t\tthis.view.trigger('eventMouseout', seg.el[0], seg.event, ev);\n\t\t}\n\t},\n\n\n\thandleSegMousedown: function(seg, ev) {\n\t\tvar isResizing = this.startSegResize(seg, ev, { distance: 5 });\n\n\t\tif (!isResizing && this.view.isEventDraggable(seg.event)) {\n\t\t\tthis.buildSegDragListener(seg)\n\t\t\t\t.startInteraction(ev, {\n\t\t\t\t\tdistance: 5\n\t\t\t\t});\n\t\t}\n\t},\n\n\n\thandleSegTouchStart: function(seg, ev) {\n\t\tvar view = this.view;\n\t\tvar event = seg.event;\n\t\tvar isSelected = view.isEventSelected(event);\n\t\tvar isDraggable = view.isEventDraggable(event);\n\t\tvar isResizable = view.isEventResizable(event);\n\t\tvar isResizing = false;\n\t\tvar dragListener;\n\n\t\tif (isSelected && isResizable) {\n\t\t\t// only allow resizing of the event is selected\n\t\t\tisResizing = this.startSegResize(seg, ev);\n\t\t}\n\n\t\tif (!isResizing && (isDraggable || isResizable)) { // allowed to be selected?\n\n\t\t\tdragListener = isDraggable ?\n\t\t\t\tthis.buildSegDragListener(seg) :\n\t\t\t\tthis.buildSegSelectListener(seg); // seg isn't draggable, but still needs to be selected\n\n\t\t\tdragListener.startInteraction(ev, { // won't start if already started\n\t\t\t\tdelay: isSelected ? 0 : this.view.opt('longPressDelay') // do delay if not already selected\n\t\t\t});\n\t\t}\n\n\t\t// a long tap simulates a mouseover. ignore this bogus mouseover.\n\t\tthis.tempIgnoreMouse();\n\t},\n\n\n\thandleSegTouchEnd: function(seg, ev) {\n\t\t// touchstart+touchend = click, which simulates a mouseover.\n\t\t// ignore this bogus mouseover.\n\t\tthis.tempIgnoreMouse();\n\t},\n\n\n\t// returns boolean whether resizing actually started or not.\n\t// assumes the seg allows resizing.\n\t// `dragOptions` are optional.\n\tstartSegResize: function(seg, ev, dragOptions) {\n\t\tif ($(ev.target).is('.fc-resizer')) {\n\t\t\tthis.buildSegResizeListener(seg, $(ev.target).is('.fc-start-resizer'))\n\t\t\t\t.startInteraction(ev, dragOptions);\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t},\n\n\n\n\t/* Event Dragging\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// Builds a listener that will track user-dragging on an event segment.\n\t// Generic enough to work with any type of Grid.\n\t// Has side effect of setting/unsetting `segDragListener`\n\tbuildSegDragListener: function(seg) {\n\t\tvar _this = this;\n\t\tvar view = this.view;\n\t\tvar calendar = view.calendar;\n\t\tvar el = seg.el;\n\t\tvar event = seg.event;\n\t\tvar isDragging;\n\t\tvar mouseFollower; // A clone of the original element that will move with the mouse\n\t\tvar dropLocation; // zoned event date properties\n\n\t\tif (this.segDragListener) {\n\t\t\treturn this.segDragListener;\n\t\t}\n\n\t\t// Tracks mouse movement over the *view's* coordinate map. Allows dragging and dropping between subcomponents\n\t\t// of the view.\n\t\tvar dragListener = this.segDragListener = new HitDragListener(view, {\n\t\t\tscroll: view.opt('dragScroll'),\n\t\t\tsubjectEl: el,\n\t\t\tsubjectCenter: true,\n\t\t\tinteractionStart: function(ev) {\n\t\t\t\tseg.component = _this; // for renderDrag\n\t\t\t\tisDragging = false;\n\t\t\t\tmouseFollower = new MouseFollower(seg.el, {\n\t\t\t\t\tadditionalClass: 'fc-dragging',\n\t\t\t\t\tparentEl: view.el,\n\t\t\t\t\topacity: dragListener.isTouch ? null : view.opt('dragOpacity'),\n\t\t\t\t\trevertDuration: view.opt('dragRevertDuration'),\n\t\t\t\t\tzIndex: 2 // one above the .fc-view\n\t\t\t\t});\n\t\t\t\tmouseFollower.hide(); // don't show until we know this is a real drag\n\t\t\t\tmouseFollower.start(ev);\n\t\t\t},\n\t\t\tdragStart: function(ev) {\n\t\t\t\tif (dragListener.isTouch && !view.isEventSelected(event)) {\n\t\t\t\t\t// if not previously selected, will fire after a delay. then, select the event\n\t\t\t\t\tview.selectEvent(event);\n\t\t\t\t}\n\t\t\t\tisDragging = true;\n\t\t\t\t_this.handleSegMouseout(seg, ev); // ensure a mouseout on the manipulated event has been reported\n\t\t\t\t_this.segDragStart(seg, ev);\n\t\t\t\tview.hideEvent(event); // hide all event segments. our mouseFollower will take over\n\t\t\t},\n\t\t\thitOver: function(hit, isOrig, origHit) {\n\t\t\t\tvar dragHelperEls;\n\n\t\t\t\t// starting hit could be forced (DayGrid.limit)\n\t\t\t\tif (seg.hit) {\n\t\t\t\t\torigHit = seg.hit;\n\t\t\t\t}\n\n\t\t\t\t// since we are querying the parent view, might not belong to this grid\n\t\t\t\tdropLocation = _this.computeEventDrop(\n\t\t\t\t\torigHit.component.getHitSpan(origHit),\n\t\t\t\t\thit.component.getHitSpan(hit),\n\t\t\t\t\tevent\n\t\t\t\t);\n\n\t\t\t\tif (dropLocation && !calendar.isEventSpanAllowed(_this.eventToSpan(dropLocation), event)) {\n\t\t\t\t\tdisableCursor();\n\t\t\t\t\tdropLocation = null;\n\t\t\t\t}\n\n\t\t\t\t// if a valid drop location, have the subclass render a visual indication\n\t\t\t\tif (dropLocation && (dragHelperEls = view.renderDrag(dropLocation, seg))) {\n\n\t\t\t\t\tdragHelperEls.addClass('fc-dragging');\n\t\t\t\t\tif (!dragListener.isTouch) {\n\t\t\t\t\t\t_this.applyDragOpacity(dragHelperEls);\n\t\t\t\t\t}\n\n\t\t\t\t\tmouseFollower.hide(); // if the subclass is already using a mock event \"helper\", hide our own\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tmouseFollower.show(); // otherwise, have the helper follow the mouse (no snapping)\n\t\t\t\t}\n\n\t\t\t\tif (isOrig) {\n\t\t\t\t\tdropLocation = null; // needs to have moved hits to be a valid drop\n\t\t\t\t}\n\t\t\t},\n\t\t\thitOut: function() { // called before mouse moves to a different hit OR moved out of all hits\n\t\t\t\tview.unrenderDrag(); // unrender whatever was done in renderDrag\n\t\t\t\tmouseFollower.show(); // show in case we are moving out of all hits\n\t\t\t\tdropLocation = null;\n\t\t\t},\n\t\t\thitDone: function() { // Called after a hitOut OR before a dragEnd\n\t\t\t\tenableCursor();\n\t\t\t},\n\t\t\tinteractionEnd: function(ev) {\n\t\t\t\tdelete seg.component; // prevent side effects\n\n\t\t\t\t// do revert animation if hasn't changed. calls a callback when finished (whether animation or not)\n\t\t\t\tmouseFollower.stop(!dropLocation, function() {\n\t\t\t\t\tif (isDragging) {\n\t\t\t\t\t\tview.unrenderDrag();\n\t\t\t\t\t\tview.showEvent(event);\n\t\t\t\t\t\t_this.segDragStop(seg, ev);\n\t\t\t\t\t}\n\t\t\t\t\tif (dropLocation) {\n\t\t\t\t\t\tview.reportEventDrop(event, dropLocation, this.largeUnit, el, ev);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\t_this.segDragListener = null;\n\t\t\t}\n\t\t});\n\n\t\treturn dragListener;\n\t},\n\n\n\t// seg isn't draggable, but let's use a generic DragListener\n\t// simply for the delay, so it can be selected.\n\t// Has side effect of setting/unsetting `segDragListener`\n\tbuildSegSelectListener: function(seg) {\n\t\tvar _this = this;\n\t\tvar view = this.view;\n\t\tvar event = seg.event;\n\n\t\tif (this.segDragListener) {\n\t\t\treturn this.segDragListener;\n\t\t}\n\n\t\tvar dragListener = this.segDragListener = new DragListener({\n\t\t\tdragStart: function(ev) {\n\t\t\t\tif (dragListener.isTouch && !view.isEventSelected(event)) {\n\t\t\t\t\t// if not previously selected, will fire after a delay. then, select the event\n\t\t\t\t\tview.selectEvent(event);\n\t\t\t\t}\n\t\t\t},\n\t\t\tinteractionEnd: function(ev) {\n\t\t\t\t_this.segDragListener = null;\n\t\t\t}\n\t\t});\n\n\t\treturn dragListener;\n\t},\n\n\n\t// Called before event segment dragging starts\n\tsegDragStart: function(seg, ev) {\n\t\tthis.isDraggingSeg = true;\n\t\tthis.view.trigger('eventDragStart', seg.el[0], seg.event, ev, {}); // last argument is jqui dummy\n\t},\n\n\n\t// Called after event segment dragging stops\n\tsegDragStop: function(seg, ev) {\n\t\tthis.isDraggingSeg = false;\n\t\tthis.view.trigger('eventDragStop', seg.el[0], seg.event, ev, {}); // last argument is jqui dummy\n\t},\n\n\n\t// Given the spans an event drag began, and the span event was dropped, calculates the new zoned start/end/allDay\n\t// values for the event. Subclasses may override and set additional properties to be used by renderDrag.\n\t// A falsy returned value indicates an invalid drop.\n\t// DOES NOT consider overlap/constraint.\n\tcomputeEventDrop: function(startSpan, endSpan, event) {\n\t\tvar calendar = this.view.calendar;\n\t\tvar dragStart = startSpan.start;\n\t\tvar dragEnd = endSpan.start;\n\t\tvar delta;\n\t\tvar dropLocation; // zoned event date properties\n\n\t\tif (dragStart.hasTime() === dragEnd.hasTime()) {\n\t\t\tdelta = this.diffDates(dragEnd, dragStart);\n\n\t\t\t// if an all-day event was in a timed area and it was dragged to a different time,\n\t\t\t// guarantee an end and adjust start/end to have times\n\t\t\tif (event.allDay && durationHasTime(delta)) {\n\t\t\t\tdropLocation = {\n\t\t\t\t\tstart: event.start.clone(),\n\t\t\t\t\tend: calendar.getEventEnd(event), // will be an ambig day\n\t\t\t\t\tallDay: false // for normalizeEventTimes\n\t\t\t\t};\n\t\t\t\tcalendar.normalizeEventTimes(dropLocation);\n\t\t\t}\n\t\t\t// othewise, work off existing values\n\t\t\telse {\n\t\t\t\tdropLocation = {\n\t\t\t\t\tstart: event.start.clone(),\n\t\t\t\t\tend: event.end ? event.end.clone() : null,\n\t\t\t\t\tallDay: event.allDay // keep it the same\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tdropLocation.start.add(delta);\n\t\t\tif (dropLocation.end) {\n\t\t\t\tdropLocation.end.add(delta);\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\t// if switching from day <-> timed, start should be reset to the dropped date, and the end cleared\n\t\t\tdropLocation = {\n\t\t\t\tstart: dragEnd.clone(),\n\t\t\t\tend: null, // end should be cleared\n\t\t\t\tallDay: !dragEnd.hasTime()\n\t\t\t};\n\t\t}\n\n\t\treturn dropLocation;\n\t},\n\n\n\t// Utility for apply dragOpacity to a jQuery set\n\tapplyDragOpacity: function(els) {\n\t\tvar opacity = this.view.opt('dragOpacity');\n\n\t\tif (opacity != null) {\n\t\t\tels.each(function(i, node) {\n\t\t\t\t// Don't use jQuery (will set an IE filter), do it the old fashioned way.\n\t\t\t\t// In IE8, a helper element will disappears if there's a filter.\n\t\t\t\tnode.style.opacity = opacity;\n\t\t\t});\n\t\t}\n\t},\n\n\n\t/* External Element Dragging\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// Called when a jQuery UI drag is initiated anywhere in the DOM\n\texternalDragStart: function(ev, ui) {\n\t\tvar view = this.view;\n\t\tvar el;\n\t\tvar accept;\n\n\t\tif (view.opt('droppable')) { // only listen if this setting is on\n\t\t\tel = $((ui ? ui.item : null) || ev.target);\n\n\t\t\t// Test that the dragged element passes the dropAccept selector or filter function.\n\t\t\t// FYI, the default is \"*\" (matches all)\n\t\t\taccept = view.opt('dropAccept');\n\t\t\tif ($.isFunction(accept) ? accept.call(el[0], el) : el.is(accept)) {\n\t\t\t\tif (!this.isDraggingExternal) { // prevent double-listening if fired twice\n\t\t\t\t\tthis.listenToExternalDrag(el, ev, ui);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\n\t// Called when a jQuery UI drag starts and it needs to be monitored for dropping\n\tlistenToExternalDrag: function(el, ev, ui) {\n\t\tvar _this = this;\n\t\tvar calendar = this.view.calendar;\n\t\tvar meta = getDraggedElMeta(el); // extra data about event drop, including possible event to create\n\t\tvar dropLocation; // a null value signals an unsuccessful drag\n\n\t\t// listener that tracks mouse movement over date-associated pixel regions\n\t\tvar dragListener = _this.externalDragListener = new HitDragListener(this, {\n\t\t\tinteractionStart: function() {\n\t\t\t\t_this.isDraggingExternal = true;\n\t\t\t},\n\t\t\thitOver: function(hit) {\n\t\t\t\tdropLocation = _this.computeExternalDrop(\n\t\t\t\t\thit.component.getHitSpan(hit), // since we are querying the parent view, might not belong to this grid\n\t\t\t\t\tmeta\n\t\t\t\t);\n\n\t\t\t\tif ( // invalid hit?\n\t\t\t\t\tdropLocation &&\n\t\t\t\t\t!calendar.isExternalSpanAllowed(_this.eventToSpan(dropLocation), dropLocation, meta.eventProps)\n\t\t\t\t) {\n\t\t\t\t\tdisableCursor();\n\t\t\t\t\tdropLocation = null;\n\t\t\t\t}\n\n\t\t\t\tif (dropLocation) {\n\t\t\t\t\t_this.renderDrag(dropLocation); // called without a seg parameter\n\t\t\t\t}\n\t\t\t},\n\t\t\thitOut: function() {\n\t\t\t\tdropLocation = null; // signal unsuccessful\n\t\t\t},\n\t\t\thitDone: function() { // Called after a hitOut OR before a dragEnd\n\t\t\t\tenableCursor();\n\t\t\t\t_this.unrenderDrag();\n\t\t\t},\n\t\t\tinteractionEnd: function(ev) {\n\t\t\t\tif (dropLocation) { // element was dropped on a valid hit\n\t\t\t\t\t_this.view.reportExternalDrop(meta, dropLocation, el, ev, ui);\n\t\t\t\t}\n\t\t\t\t_this.isDraggingExternal = false;\n\t\t\t\t_this.externalDragListener = null;\n\t\t\t}\n\t\t});\n\n\t\tdragListener.startDrag(ev); // start listening immediately\n\t},\n\n\n\t// Given a hit to be dropped upon, and misc data associated with the jqui drag (guaranteed to be a plain object),\n\t// returns the zoned start/end dates for the event that would result from the hypothetical drop. end might be null.\n\t// Returning a null value signals an invalid drop hit.\n\t// DOES NOT consider overlap/constraint.\n\tcomputeExternalDrop: function(span, meta) {\n\t\tvar calendar = this.view.calendar;\n\t\tvar dropLocation = {\n\t\t\tstart: calendar.applyTimezone(span.start), // simulate a zoned event start date\n\t\t\tend: null\n\t\t};\n\n\t\t// if dropped on an all-day span, and element's metadata specified a time, set it\n\t\tif (meta.startTime && !dropLocation.start.hasTime()) {\n\t\t\tdropLocation.start.time(meta.startTime);\n\t\t}\n\n\t\tif (meta.duration) {\n\t\t\tdropLocation.end = dropLocation.start.clone().add(meta.duration);\n\t\t}\n\n\t\treturn dropLocation;\n\t},\n\n\n\n\t/* Drag Rendering (for both events and an external elements)\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// Renders a visual indication of an event or external element being dragged.\n\t// `dropLocation` contains hypothetical start/end/allDay values the event would have if dropped. end can be null.\n\t// `seg` is the internal segment object that is being dragged. If dragging an external element, `seg` is null.\n\t// A truthy returned value indicates this method has rendered a helper element.\n\t// Must return elements used for any mock events.\n\trenderDrag: function(dropLocation, seg) {\n\t\t// subclasses must implement\n\t},\n\n\n\t// Unrenders a visual indication of an event or external element being dragged\n\tunrenderDrag: function() {\n\t\t// subclasses must implement\n\t},\n\n\n\t/* Resizing\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// Creates a listener that tracks the user as they resize an event segment.\n\t// Generic enough to work with any type of Grid.\n\tbuildSegResizeListener: function(seg, isStart) {\n\t\tvar _this = this;\n\t\tvar view = this.view;\n\t\tvar calendar = view.calendar;\n\t\tvar el = seg.el;\n\t\tvar event = seg.event;\n\t\tvar eventEnd = calendar.getEventEnd(event);\n\t\tvar isDragging;\n\t\tvar resizeLocation; // zoned event date properties. falsy if invalid resize\n\n\t\t// Tracks mouse movement over the *grid's* coordinate map\n\t\tvar dragListener = this.segResizeListener = new HitDragListener(this, {\n\t\t\tscroll: view.opt('dragScroll'),\n\t\t\tsubjectEl: el,\n\t\t\tinteractionStart: function() {\n\t\t\t\tisDragging = false;\n\t\t\t},\n\t\t\tdragStart: function(ev) {\n\t\t\t\tisDragging = true;\n\t\t\t\t_this.handleSegMouseout(seg, ev); // ensure a mouseout on the manipulated event has been reported\n\t\t\t\t_this.segResizeStart(seg, ev);\n\t\t\t},\n\t\t\thitOver: function(hit, isOrig, origHit) {\n\t\t\t\tvar origHitSpan = _this.getHitSpan(origHit);\n\t\t\t\tvar hitSpan = _this.getHitSpan(hit);\n\n\t\t\t\tresizeLocation = isStart ?\n\t\t\t\t\t_this.computeEventStartResize(origHitSpan, hitSpan, event) :\n\t\t\t\t\t_this.computeEventEndResize(origHitSpan, hitSpan, event);\n\n\t\t\t\tif (resizeLocation) {\n\t\t\t\t\tif (!calendar.isEventSpanAllowed(_this.eventToSpan(resizeLocation), event)) {\n\t\t\t\t\t\tdisableCursor();\n\t\t\t\t\t\tresizeLocation = null;\n\t\t\t\t\t}\n\t\t\t\t\t// no change? (TODO: how does this work with timezones?)\n\t\t\t\t\telse if (resizeLocation.start.isSame(event.start) && resizeLocation.end.isSame(eventEnd)) {\n\t\t\t\t\t\tresizeLocation = null;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (resizeLocation) {\n\t\t\t\t\tview.hideEvent(event);\n\t\t\t\t\t_this.renderEventResize(resizeLocation, seg);\n\t\t\t\t}\n\t\t\t},\n\t\t\thitOut: function() { // called before mouse moves to a different hit OR moved out of all hits\n\t\t\t\tresizeLocation = null;\n\t\t\t},\n\t\t\thitDone: function() { // resets the rendering to show the original event\n\t\t\t\t_this.unrenderEventResize();\n\t\t\t\tview.showEvent(event);\n\t\t\t\tenableCursor();\n\t\t\t},\n\t\t\tinteractionEnd: function(ev) {\n\t\t\t\tif (isDragging) {\n\t\t\t\t\t_this.segResizeStop(seg, ev);\n\t\t\t\t}\n\t\t\t\tif (resizeLocation) { // valid date to resize to?\n\t\t\t\t\tview.reportEventResize(event, resizeLocation, this.largeUnit, el, ev);\n\t\t\t\t}\n\t\t\t\t_this.segResizeListener = null;\n\t\t\t}\n\t\t});\n\n\t\treturn dragListener;\n\t},\n\n\n\t// Called before event segment resizing starts\n\tsegResizeStart: function(seg, ev) {\n\t\tthis.isResizingSeg = true;\n\t\tthis.view.trigger('eventResizeStart', seg.el[0], seg.event, ev, {}); // last argument is jqui dummy\n\t},\n\n\n\t// Called after event segment resizing stops\n\tsegResizeStop: function(seg, ev) {\n\t\tthis.isResizingSeg = false;\n\t\tthis.view.trigger('eventResizeStop', seg.el[0], seg.event, ev, {}); // last argument is jqui dummy\n\t},\n\n\n\t// Returns new date-information for an event segment being resized from its start\n\tcomputeEventStartResize: function(startSpan, endSpan, event) {\n\t\treturn this.computeEventResize('start', startSpan, endSpan, event);\n\t},\n\n\n\t// Returns new date-information for an event segment being resized from its end\n\tcomputeEventEndResize: function(startSpan, endSpan, event) {\n\t\treturn this.computeEventResize('end', startSpan, endSpan, event);\n\t},\n\n\n\t// Returns new zoned date information for an event segment being resized from its start OR end\n\t// `type` is either 'start' or 'end'.\n\t// DOES NOT consider overlap/constraint.\n\tcomputeEventResize: function(type, startSpan, endSpan, event) {\n\t\tvar calendar = this.view.calendar;\n\t\tvar delta = this.diffDates(endSpan[type], startSpan[type]);\n\t\tvar resizeLocation; // zoned event date properties\n\t\tvar defaultDuration;\n\n\t\t// build original values to work from, guaranteeing a start and end\n\t\tresizeLocation = {\n\t\t\tstart: event.start.clone(),\n\t\t\tend: calendar.getEventEnd(event),\n\t\t\tallDay: event.allDay\n\t\t};\n\n\t\t// if an all-day event was in a timed area and was resized to a time, adjust start/end to have times\n\t\tif (resizeLocation.allDay && durationHasTime(delta)) {\n\t\t\tresizeLocation.allDay = false;\n\t\t\tcalendar.normalizeEventTimes(resizeLocation);\n\t\t}\n\n\t\tresizeLocation[type].add(delta); // apply delta to start or end\n\n\t\t// if the event was compressed too small, find a new reasonable duration for it\n\t\tif (!resizeLocation.start.isBefore(resizeLocation.end)) {\n\n\t\t\tdefaultDuration =\n\t\t\t\tthis.minResizeDuration || // TODO: hack\n\t\t\t\t(event.allDay ?\n\t\t\t\t\tcalendar.defaultAllDayEventDuration :\n\t\t\t\t\tcalendar.defaultTimedEventDuration);\n\n\t\t\tif (type == 'start') { // resizing the start?\n\t\t\t\tresizeLocation.start = resizeLocation.end.clone().subtract(defaultDuration);\n\t\t\t}\n\t\t\telse { // resizing the end?\n\t\t\t\tresizeLocation.end = resizeLocation.start.clone().add(defaultDuration);\n\t\t\t}\n\t\t}\n\n\t\treturn resizeLocation;\n\t},\n\n\n\t// Renders a visual indication of an event being resized.\n\t// `range` has the updated dates of the event. `seg` is the original segment object involved in the drag.\n\t// Must return elements used for any mock events.\n\trenderEventResize: function(range, seg) {\n\t\t// subclasses must implement\n\t},\n\n\n\t// Unrenders a visual indication of an event being resized.\n\tunrenderEventResize: function() {\n\t\t// subclasses must implement\n\t},\n\n\n\t/* Rendering Utils\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// Compute the text that should be displayed on an event's element.\n\t// `range` can be the Event object itself, or something range-like, with at least a `start`.\n\t// If event times are disabled, or the event has no time, will return a blank string.\n\t// If not specified, formatStr will default to the eventTimeFormat setting,\n\t// and displayEnd will default to the displayEventEnd setting.\n\tgetEventTimeText: function(range, formatStr, displayEnd) {\n\n\t\tif (formatStr == null) {\n\t\t\tformatStr = this.eventTimeFormat;\n\t\t}\n\n\t\tif (displayEnd == null) {\n\t\t\tdisplayEnd = this.displayEventEnd;\n\t\t}\n\n\t\tif (this.displayEventTime && range.start.hasTime()) {\n\t\t\tif (displayEnd && range.end) {\n\t\t\t\treturn this.view.formatRange(range, formatStr);\n\t\t\t}\n\t\t\telse {\n\t\t\t\treturn range.start.format(formatStr);\n\t\t\t}\n\t\t}\n\n\t\treturn '';\n\t},\n\n\n\t// Generic utility for generating the HTML classNames for an event segment's element\n\tgetSegClasses: function(seg, isDraggable, isResizable) {\n\t\tvar view = this.view;\n\t\tvar event = seg.event;\n\t\tvar classes = [\n\t\t\t'fc-event',\n\t\t\tseg.isStart ? 'fc-start' : 'fc-not-start',\n\t\t\tseg.isEnd ? 'fc-end' : 'fc-not-end'\n\t\t].concat(\n\t\t\tevent.className,\n\t\t\tevent.source ? event.source.className : []\n\t\t);\n\n\t\tif (isDraggable) {\n\t\t\tclasses.push('fc-draggable');\n\t\t}\n\t\tif (isResizable) {\n\t\t\tclasses.push('fc-resizable');\n\t\t}\n\n\t\t// event is currently selected? attach a className.\n\t\tif (view.isEventSelected(event)) {\n\t\t\tclasses.push('fc-selected');\n\t\t}\n\n\t\treturn classes;\n\t},\n\n\n\t// Utility for generating event skin-related CSS properties\n\tgetSegSkinCss: function(seg) {\n\t\tvar event = seg.event;\n\t\tvar view = this.view;\n\t\tvar source = event.source || {};\n\t\tvar eventColor = event.color;\n\t\tvar sourceColor = source.color;\n\t\tvar optionColor = view.opt('eventColor');\n\n\t\treturn {\n\t\t\t'background-color':\n\t\t\t\tevent.backgroundColor ||\n\t\t\t\teventColor ||\n\t\t\t\tsource.backgroundColor ||\n\t\t\t\tsourceColor ||\n\t\t\t\tview.opt('eventBackgroundColor') ||\n\t\t\t\toptionColor,\n\t\t\t'border-color':\n\t\t\t\tevent.borderColor ||\n\t\t\t\teventColor ||\n\t\t\t\tsource.borderColor ||\n\t\t\t\tsourceColor ||\n\t\t\t\tview.opt('eventBorderColor') ||\n\t\t\t\toptionColor,\n\t\t\tcolor:\n\t\t\t\tevent.textColor ||\n\t\t\t\tsource.textColor ||\n\t\t\t\tview.opt('eventTextColor')\n\t\t};\n\t},\n\n\n\t/* Converting events -> eventRange -> eventSpan -> eventSegs\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// Generates an array of segments for the given single event\n\t// Can accept an event \"location\" as well (which only has start/end and no allDay)\n\teventToSegs: function(event) {\n\t\treturn this.eventsToSegs([ event ]);\n\t},\n\n\n\teventToSpan: function(event) {\n\t\treturn this.eventToSpans(event)[0];\n\t},\n\n\n\t// Generates spans (always unzoned) for the given event.\n\t// Does not do any inverting for inverse-background events.\n\t// Can accept an event \"location\" as well (which only has start/end and no allDay)\n\teventToSpans: function(event) {\n\t\tvar range = this.eventToRange(event);\n\t\treturn this.eventRangeToSpans(range, event);\n\t},\n\n\n\n\t// Converts an array of event objects into an array of event segment objects.\n\t// A custom `segSliceFunc` may be given for arbitrarily slicing up events.\n\t// Doesn't guarantee an order for the resulting array.\n\teventsToSegs: function(allEvents, segSliceFunc) {\n\t\tvar _this = this;\n\t\tvar eventsById = groupEventsById(allEvents);\n\t\tvar segs = [];\n\n\t\t$.each(eventsById, function(id, events) {\n\t\t\tvar ranges = [];\n\t\t\tvar i;\n\n\t\t\tfor (i = 0; i < events.length; i++) {\n\t\t\t\tranges.push(_this.eventToRange(events[i]));\n\t\t\t}\n\n\t\t\t// inverse-background events (utilize only the first event in calculations)\n\t\t\tif (isInverseBgEvent(events[0])) {\n\t\t\t\tranges = _this.invertRanges(ranges);\n\n\t\t\t\tfor (i = 0; i < ranges.length; i++) {\n\t\t\t\t\tsegs.push.apply(segs, // append to\n\t\t\t\t\t\t_this.eventRangeToSegs(ranges[i], events[0], segSliceFunc));\n\t\t\t\t}\n\t\t\t}\n\t\t\t// normal event ranges\n\t\t\telse {\n\t\t\t\tfor (i = 0; i < ranges.length; i++) {\n\t\t\t\t\tsegs.push.apply(segs, // append to\n\t\t\t\t\t\t_this.eventRangeToSegs(ranges[i], events[i], segSliceFunc));\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\treturn segs;\n\t},\n\n\n\t// Generates the unzoned start/end dates an event appears to occupy\n\t// Can accept an event \"location\" as well (which only has start/end and no allDay)\n\teventToRange: function(event) {\n\t\treturn {\n\t\t\tstart: event.start.clone().stripZone(),\n\t\t\tend: (\n\t\t\t\tevent.end ?\n\t\t\t\t\tevent.end.clone() :\n\t\t\t\t\t// derive the end from the start and allDay. compute allDay if necessary\n\t\t\t\t\tthis.view.calendar.getDefaultEventEnd(\n\t\t\t\t\t\tevent.allDay != null ?\n\t\t\t\t\t\t\tevent.allDay :\n\t\t\t\t\t\t\t!event.start.hasTime(),\n\t\t\t\t\t\tevent.start\n\t\t\t\t\t)\n\t\t\t).stripZone()\n\t\t};\n\t},\n\n\n\t// Given an event's range (unzoned start/end), and the event itself,\n\t// slice into segments (using the segSliceFunc function if specified)\n\teventRangeToSegs: function(range, event, segSliceFunc) {\n\t\tvar spans = this.eventRangeToSpans(range, event);\n\t\tvar segs = [];\n\t\tvar i;\n\n\t\tfor (i = 0; i < spans.length; i++) {\n\t\t\tsegs.push.apply(segs, // append to\n\t\t\t\tthis.eventSpanToSegs(spans[i], event, segSliceFunc));\n\t\t}\n\n\t\treturn segs;\n\t},\n\n\n\t// Given an event's unzoned date range, return an array of \"span\" objects.\n\t// Subclasses can override.\n\teventRangeToSpans: function(range, event) {\n\t\treturn [ $.extend({}, range) ]; // copy into a single-item array\n\t},\n\n\n\t// Given an event's span (unzoned start/end and other misc data), and the event itself,\n\t// slices into segments and attaches event-derived properties to them.\n\teventSpanToSegs: function(span, event, segSliceFunc) {\n\t\tvar segs = segSliceFunc ? segSliceFunc(span) : this.spanToSegs(span);\n\t\tvar i, seg;\n\n\t\tfor (i = 0; i < segs.length; i++) {\n\t\t\tseg = segs[i];\n\t\t\tseg.event = event;\n\t\t\tseg.eventStartMS = +span.start; // TODO: not the best name after making spans unzoned\n\t\t\tseg.eventDurationMS = span.end - span.start;\n\t\t}\n\n\t\treturn segs;\n\t},\n\n\n\t// Produces a new array of range objects that will cover all the time NOT covered by the given ranges.\n\t// SIDE EFFECT: will mutate the given array and will use its date references.\n\tinvertRanges: function(ranges) {\n\t\tvar view = this.view;\n\t\tvar viewStart = view.start.clone(); // need a copy\n\t\tvar viewEnd = view.end.clone(); // need a copy\n\t\tvar inverseRanges = [];\n\t\tvar start = viewStart; // the end of the previous range. the start of the new range\n\t\tvar i, range;\n\n\t\t// ranges need to be in order. required for our date-walking algorithm\n\t\tranges.sort(compareRanges);\n\n\t\tfor (i = 0; i < ranges.length; i++) {\n\t\t\trange = ranges[i];\n\n\t\t\t// add the span of time before the event (if there is any)\n\t\t\tif (range.start > start) { // compare millisecond time (skip any ambig logic)\n\t\t\t\tinverseRanges.push({\n\t\t\t\t\tstart: start,\n\t\t\t\t\tend: range.start\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tstart = range.end;\n\t\t}\n\n\t\t// add the span of time after the last event (if there is any)\n\t\tif (start < viewEnd) { // compare millisecond time (skip any ambig logic)\n\t\t\tinverseRanges.push({\n\t\t\t\tstart: start,\n\t\t\t\tend: viewEnd\n\t\t\t});\n\t\t}\n\n\t\treturn inverseRanges;\n\t},\n\n\n\tsortEventSegs: function(segs) {\n\t\tsegs.sort(proxy(this, 'compareEventSegs'));\n\t},\n\n\n\t// A cmp function for determining which segments should take visual priority\n\tcompareEventSegs: function(seg1, seg2) {\n\t\treturn seg1.eventStartMS - seg2.eventStartMS || // earlier events go first\n\t\t\tseg2.eventDurationMS - seg1.eventDurationMS || // tie? longer events go first\n\t\t\tseg2.event.allDay - seg1.event.allDay || // tie? put all-day events first (booleans cast to 0/1)\n\t\t\tcompareByFieldSpecs(seg1.event, seg2.event, this.view.eventOrderSpecs);\n\t}\n\n});\n\n\n/* Utilities\n----------------------------------------------------------------------------------------------------------------------*/\n\n\nfunction isBgEvent(event) { // returns true if background OR inverse-background\n\tvar rendering = getEventRendering(event);\n\treturn rendering === 'background' || rendering === 'inverse-background';\n}\nFC.isBgEvent = isBgEvent; // export\n\n\nfunction isInverseBgEvent(event) {\n\treturn getEventRendering(event) === 'inverse-background';\n}\n\n\nfunction getEventRendering(event) {\n\treturn firstDefined((event.source || {}).rendering, event.rendering);\n}\n\n\nfunction groupEventsById(events) {\n\tvar eventsById = {};\n\tvar i, event;\n\n\tfor (i = 0; i < events.length; i++) {\n\t\tevent = events[i];\n\t\t(eventsById[event._id] || (eventsById[event._id] = [])).push(event);\n\t}\n\n\treturn eventsById;\n}\n\n\n// A cmp function for determining which non-inverted \"ranges\" (see above) happen earlier\nfunction compareRanges(range1, range2) {\n\treturn range1.start - range2.start; // earlier ranges go first\n}\n\n\n/* External-Dragging-Element Data\n----------------------------------------------------------------------------------------------------------------------*/\n\n// Require all HTML5 data-* attributes used by FullCalendar to have this prefix.\n// A value of '' will query attributes like data-event. A value of 'fc' will query attributes like data-fc-event.\nFC.dataAttrPrefix = '';\n\n// Given a jQuery element that might represent a dragged FullCalendar event, returns an intermediate data structure\n// to be used for Event Object creation.\n// A defined `.eventProps`, even when empty, indicates that an event should be created.\nfunction getDraggedElMeta(el) {\n\tvar prefix = FC.dataAttrPrefix;\n\tvar eventProps; // properties for creating the event, not related to date/time\n\tvar startTime; // a Duration\n\tvar duration;\n\tvar stick;\n\n\tif (prefix) { prefix += '-'; }\n\teventProps = el.data(prefix + 'event') || null;\n\n\tif (eventProps) {\n\t\tif (typeof eventProps === 'object') {\n\t\t\teventProps = $.extend({}, eventProps); // make a copy\n\t\t}\n\t\telse { // something like 1 or true. still signal event creation\n\t\t\teventProps = {};\n\t\t}\n\n\t\t// pluck special-cased date/time properties\n\t\tstartTime = eventProps.start;\n\t\tif (startTime == null) { startTime = eventProps.time; } // accept 'time' as well\n\t\tduration = eventProps.duration;\n\t\tstick = eventProps.stick;\n\t\tdelete eventProps.start;\n\t\tdelete eventProps.time;\n\t\tdelete eventProps.duration;\n\t\tdelete eventProps.stick;\n\t}\n\n\t// fallback to standalone attribute values for each of the date/time properties\n\tif (startTime == null) { startTime = el.data(prefix + 'start'); }\n\tif (startTime == null) { startTime = el.data(prefix + 'time'); } // accept 'time' as well\n\tif (duration == null) { duration = el.data(prefix + 'duration'); }\n\tif (stick == null) { stick = el.data(prefix + 'stick'); }\n\n\t// massage into correct data types\n\tstartTime = startTime != null ? moment.duration(startTime) : null;\n\tduration = duration != null ? moment.duration(duration) : null;\n\tstick = Boolean(stick);\n\n\treturn { eventProps: eventProps, startTime: startTime, duration: duration, stick: stick };\n}\n\n\n;;\n\n/*\nA set of rendering and date-related methods for a visual component comprised of one or more rows of day columns.\nPrerequisite: the object being mixed into needs to be a *Grid*\n*/\nvar DayTableMixin = FC.DayTableMixin = {\n\n\tbreakOnWeeks: false, // should create a new row for each week?\n\tdayDates: null, // whole-day dates for each column. left to right\n\tdayIndices: null, // for each day from start, the offset\n\tdaysPerRow: null,\n\trowCnt: null,\n\tcolCnt: null,\n\tcolHeadFormat: null,\n\n\n\t// Populates internal variables used for date calculation and rendering\n\tupdateDayTable: function() {\n\t\tvar view = this.view;\n\t\tvar date = this.start.clone();\n\t\tvar dayIndex = -1;\n\t\tvar dayIndices = [];\n\t\tvar dayDates = [];\n\t\tvar daysPerRow;\n\t\tvar firstDay;\n\t\tvar rowCnt;\n\n\t\twhile (date.isBefore(this.end)) { // loop each day from start to end\n\t\t\tif (view.isHiddenDay(date)) {\n\t\t\t\tdayIndices.push(dayIndex + 0.5); // mark that it's between indices\n\t\t\t}\n\t\t\telse {\n\t\t\t\tdayIndex++;\n\t\t\t\tdayIndices.push(dayIndex);\n\t\t\t\tdayDates.push(date.clone());\n\t\t\t}\n\t\t\tdate.add(1, 'days');\n\t\t}\n\n\t\tif (this.breakOnWeeks) {\n\t\t\t// count columns until the day-of-week repeats\n\t\t\tfirstDay = dayDates[0].day();\n\t\t\tfor (daysPerRow = 1; daysPerRow < dayDates.length; daysPerRow++) {\n\t\t\t\tif (dayDates[daysPerRow].day() == firstDay) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\trowCnt = Math.ceil(dayDates.length / daysPerRow);\n\t\t}\n\t\telse {\n\t\t\trowCnt = 1;\n\t\t\tdaysPerRow = dayDates.length;\n\t\t}\n\n\t\tthis.dayDates = dayDates;\n\t\tthis.dayIndices = dayIndices;\n\t\tthis.daysPerRow = daysPerRow;\n\t\tthis.rowCnt = rowCnt;\n\t\t\n\t\tthis.updateDayTableCols();\n\t},\n\n\n\t// Computes and assigned the colCnt property and updates any options that may be computed from it\n\tupdateDayTableCols: function() {\n\t\tthis.colCnt = this.computeColCnt();\n\t\tthis.colHeadFormat = this.view.opt('columnFormat') || this.computeColHeadFormat();\n\t},\n\n\n\t// Determines how many columns there should be in the table\n\tcomputeColCnt: function() {\n\t\treturn this.daysPerRow;\n\t},\n\n\n\t// Computes the ambiguously-timed moment for the given cell\n\tgetCellDate: function(row, col) {\n\t\treturn this.dayDates[\n\t\t\t\tthis.getCellDayIndex(row, col)\n\t\t\t].clone();\n\t},\n\n\n\t// Computes the ambiguously-timed date range for the given cell\n\tgetCellRange: function(row, col) {\n\t\tvar start = this.getCellDate(row, col);\n\t\tvar end = start.clone().add(1, 'days');\n\n\t\treturn { start: start, end: end };\n\t},\n\n\n\t// Returns the number of day cells, chronologically, from the first of the grid (0-based)\n\tgetCellDayIndex: function(row, col) {\n\t\treturn row * this.daysPerRow + this.getColDayIndex(col);\n\t},\n\n\n\t// Returns the numner of day cells, chronologically, from the first cell in *any given row*\n\tgetColDayIndex: function(col) {\n\t\tif (this.isRTL) {\n\t\t\treturn this.colCnt - 1 - col;\n\t\t}\n\t\telse {\n\t\t\treturn col;\n\t\t}\n\t},\n\n\n\t// Given a date, returns its chronolocial cell-index from the first cell of the grid.\n\t// If the date lies between cells (because of hiddenDays), returns a floating-point value between offsets.\n\t// If before the first offset, returns a negative number.\n\t// If after the last offset, returns an offset past the last cell offset.\n\t// Only works for *start* dates of cells. Will not work for exclusive end dates for cells.\n\tgetDateDayIndex: function(date) {\n\t\tvar dayIndices = this.dayIndices;\n\t\tvar dayOffset = date.diff(this.start, 'days');\n\n\t\tif (dayOffset < 0) {\n\t\t\treturn dayIndices[0] - 1;\n\t\t}\n\t\telse if (dayOffset >= dayIndices.length) {\n\t\t\treturn dayIndices[dayIndices.length - 1] + 1;\n\t\t}\n\t\telse {\n\t\t\treturn dayIndices[dayOffset];\n\t\t}\n\t},\n\n\n\t/* Options\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// Computes a default column header formatting string if `colFormat` is not explicitly defined\n\tcomputeColHeadFormat: function() {\n\t\t// if more than one week row, or if there are a lot of columns with not much space,\n\t\t// put just the day numbers will be in each cell\n\t\tif (this.rowCnt > 1 || this.colCnt > 10) {\n\t\t\treturn 'ddd'; // \"Sat\"\n\t\t}\n\t\t// multiple days, so full single date string WON'T be in title text\n\t\telse if (this.colCnt > 1) {\n\t\t\treturn this.view.opt('dayOfMonthFormat'); // \"Sat 12/10\"\n\t\t}\n\t\t// single day, so full single date string will probably be in title text\n\t\telse {\n\t\t\treturn 'dddd'; // \"Saturday\"\n\t\t}\n\t},\n\n\n\t/* Slicing\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// Slices up a date range into a segment for every week-row it intersects with\n\tsliceRangeByRow: function(range) {\n\t\tvar daysPerRow = this.daysPerRow;\n\t\tvar normalRange = this.view.computeDayRange(range); // make whole-day range, considering nextDayThreshold\n\t\tvar rangeFirst = this.getDateDayIndex(normalRange.start); // inclusive first index\n\t\tvar rangeLast = this.getDateDayIndex(normalRange.end.clone().subtract(1, 'days')); // inclusive last index\n\t\tvar segs = [];\n\t\tvar row;\n\t\tvar rowFirst, rowLast; // inclusive day-index range for current row\n\t\tvar segFirst, segLast; // inclusive day-index range for segment\n\n\t\tfor (row = 0; row < this.rowCnt; row++) {\n\t\t\trowFirst = row * daysPerRow;\n\t\t\trowLast = rowFirst + daysPerRow - 1;\n\n\t\t\t// intersect segment's offset range with the row's\n\t\t\tsegFirst = Math.max(rangeFirst, rowFirst);\n\t\t\tsegLast = Math.min(rangeLast, rowLast);\n\n\t\t\t// deal with in-between indices\n\t\t\tsegFirst = Math.ceil(segFirst); // in-between starts round to next cell\n\t\t\tsegLast = Math.floor(segLast); // in-between ends round to prev cell\n\n\t\t\tif (segFirst <= segLast) { // was there any intersection with the current row?\n\t\t\t\tsegs.push({\n\t\t\t\t\trow: row,\n\n\t\t\t\t\t// normalize to start of row\n\t\t\t\t\tfirstRowDayIndex: segFirst - rowFirst,\n\t\t\t\t\tlastRowDayIndex: segLast - rowFirst,\n\n\t\t\t\t\t// must be matching integers to be the segment's start/end\n\t\t\t\t\tisStart: segFirst === rangeFirst,\n\t\t\t\t\tisEnd: segLast === rangeLast\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn segs;\n\t},\n\n\n\t// Slices up a date range into a segment for every day-cell it intersects with.\n\t// TODO: make more DRY with sliceRangeByRow somehow.\n\tsliceRangeByDay: function(range) {\n\t\tvar daysPerRow = this.daysPerRow;\n\t\tvar normalRange = this.view.computeDayRange(range); // make whole-day range, considering nextDayThreshold\n\t\tvar rangeFirst = this.getDateDayIndex(normalRange.start); // inclusive first index\n\t\tvar rangeLast = this.getDateDayIndex(normalRange.end.clone().subtract(1, 'days')); // inclusive last index\n\t\tvar segs = [];\n\t\tvar row;\n\t\tvar rowFirst, rowLast; // inclusive day-index range for current row\n\t\tvar i;\n\t\tvar segFirst, segLast; // inclusive day-index range for segment\n\n\t\tfor (row = 0; row < this.rowCnt; row++) {\n\t\t\trowFirst = row * daysPerRow;\n\t\t\trowLast = rowFirst + daysPerRow - 1;\n\n\t\t\tfor (i = rowFirst; i <= rowLast; i++) {\n\n\t\t\t\t// intersect segment's offset range with the row's\n\t\t\t\tsegFirst = Math.max(rangeFirst, i);\n\t\t\t\tsegLast = Math.min(rangeLast, i);\n\n\t\t\t\t// deal with in-between indices\n\t\t\t\tsegFirst = Math.ceil(segFirst); // in-between starts round to next cell\n\t\t\t\tsegLast = Math.floor(segLast); // in-between ends round to prev cell\n\n\t\t\t\tif (segFirst <= segLast) { // was there any intersection with the current row?\n\t\t\t\t\tsegs.push({\n\t\t\t\t\t\trow: row,\n\n\t\t\t\t\t\t// normalize to start of row\n\t\t\t\t\t\tfirstRowDayIndex: segFirst - rowFirst,\n\t\t\t\t\t\tlastRowDayIndex: segLast - rowFirst,\n\n\t\t\t\t\t\t// must be matching integers to be the segment's start/end\n\t\t\t\t\t\tisStart: segFirst === rangeFirst,\n\t\t\t\t\t\tisEnd: segLast === rangeLast\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn segs;\n\t},\n\n\n\t/* Header Rendering\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\trenderHeadHtml: function() {\n\t\tvar view = this.view;\n\n\t\treturn '' +\n\t\t\t'
' +\n\t\t\t\t'' +\n\t\t\t\t\t'' +\n\t\t\t\t\t\tthis.renderHeadTrHtml() +\n\t\t\t\t\t'' +\n\t\t\t\t'
' +\n\t\t\t'
';\n\t},\n\n\n\trenderHeadIntroHtml: function() {\n\t\treturn this.renderIntroHtml(); // fall back to generic\n\t},\n\n\n\trenderHeadTrHtml: function() {\n\t\treturn '' +\n\t\t\t'' +\n\t\t\t\t(this.isRTL ? '' : this.renderHeadIntroHtml()) +\n\t\t\t\tthis.renderHeadDateCellsHtml() +\n\t\t\t\t(this.isRTL ? this.renderHeadIntroHtml() : '') +\n\t\t\t'';\n\t},\n\n\n\trenderHeadDateCellsHtml: function() {\n\t\tvar htmls = [];\n\t\tvar col, date;\n\n\t\tfor (col = 0; col < this.colCnt; col++) {\n\t\t\tdate = this.getCellDate(0, col);\n\t\t\thtmls.push(this.renderHeadDateCellHtml(date));\n\t\t}\n\n\t\treturn htmls.join('');\n\t},\n\n\n\t// TODO: when internalApiVersion, accept an object for HTML attributes\n\t// (colspan should be no different)\n\trenderHeadDateCellHtml: function(date, colspan, otherAttrs) {\n\t\tvar view = this.view;\n\n\t\treturn '' +\n\t\t\t' 1 ?\n\t\t\t\t\t' colspan=\"' + colspan + '\"' :\n\t\t\t\t\t'') +\n\t\t\t\t(otherAttrs ?\n\t\t\t\t\t' ' + otherAttrs :\n\t\t\t\t\t'') +\n\t\t\t'>' +\n\t\t\t\thtmlEscape(date.format(this.colHeadFormat)) +\n\t\t\t'';\n\t},\n\n\n\t/* Background Rendering\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\trenderBgTrHtml: function(row) {\n\t\treturn '' +\n\t\t\t'' +\n\t\t\t\t(this.isRTL ? '' : this.renderBgIntroHtml(row)) +\n\t\t\t\tthis.renderBgCellsHtml(row) +\n\t\t\t\t(this.isRTL ? this.renderBgIntroHtml(row) : '') +\n\t\t\t'';\n\t},\n\n\n\trenderBgIntroHtml: function(row) {\n\t\treturn this.renderIntroHtml(); // fall back to generic\n\t},\n\n\n\trenderBgCellsHtml: function(row) {\n\t\tvar htmls = [];\n\t\tvar col, date;\n\n\t\tfor (col = 0; col < this.colCnt; col++) {\n\t\t\tdate = this.getCellDate(row, col);\n\t\t\thtmls.push(this.renderBgCellHtml(date));\n\t\t}\n\n\t\treturn htmls.join('');\n\t},\n\n\n\trenderBgCellHtml: function(date, otherAttrs) {\n\t\tvar view = this.view;\n\t\tvar classes = this.getDayClasses(date);\n\n\t\tclasses.unshift('fc-day', view.widgetContentClass);\n\n\t\treturn '';\n\t},\n\n\n\t/* Generic\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// Generates the default HTML intro for any row. User classes should override\n\trenderIntroHtml: function() {\n\t},\n\n\n\t// TODO: a generic method for dealing with , RTL, intro\n\t// when increment internalApiVersion\n\t// wrapTr (scheduler)\n\n\n\t/* Utils\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// Applies the generic \"intro\" and \"outro\" HTML to the given cells.\n\t// Intro means the leftmost cell when the calendar is LTR and the rightmost cell when RTL. Vice-versa for outro.\n\tbookendCells: function(trEl) {\n\t\tvar introHtml = this.renderIntroHtml();\n\n\t\tif (introHtml) {\n\t\t\tif (this.isRTL) {\n\t\t\t\ttrEl.append(introHtml);\n\t\t\t}\n\t\t\telse {\n\t\t\t\ttrEl.prepend(introHtml);\n\t\t\t}\n\t\t}\n\t}\n\n};\n\n;;\n\n/* A component that renders a grid of whole-days that runs horizontally. There can be multiple rows, one per week.\n----------------------------------------------------------------------------------------------------------------------*/\n\nvar DayGrid = FC.DayGrid = Grid.extend(DayTableMixin, {\n\n\tnumbersVisible: false, // should render a row for day/week numbers? set by outside view. TODO: make internal\n\tbottomCoordPadding: 0, // hack for extending the hit area for the last row of the coordinate grid\n\n\trowEls: null, // set of fake row elements\n\tcellEls: null, // set of whole-day elements comprising the row's background\n\thelperEls: null, // set of cell skeleton elements for rendering the mock event \"helper\"\n\n\trowCoordCache: null,\n\tcolCoordCache: null,\n\n\n\t// Renders the rows and columns into the component's `this.el`, which should already be assigned.\n\t// isRigid determins whether the individual rows should ignore the contents and be a constant height.\n\t// Relies on the view's colCnt and rowCnt. In the future, this component should probably be self-sufficient.\n\trenderDates: function(isRigid) {\n\t\tvar view = this.view;\n\t\tvar rowCnt = this.rowCnt;\n\t\tvar colCnt = this.colCnt;\n\t\tvar html = '';\n\t\tvar row;\n\t\tvar col;\n\n\t\tfor (row = 0; row < rowCnt; row++) {\n\t\t\thtml += this.renderDayRowHtml(row, isRigid);\n\t\t}\n\t\tthis.el.html(html);\n\n\t\tthis.rowEls = this.el.find('.fc-row');\n\t\tthis.cellEls = this.el.find('.fc-day');\n\n\t\tthis.rowCoordCache = new CoordCache({\n\t\t\tels: this.rowEls,\n\t\t\tisVertical: true\n\t\t});\n\t\tthis.colCoordCache = new CoordCache({\n\t\t\tels: this.cellEls.slice(0, this.colCnt), // only the first row\n\t\t\tisHorizontal: true\n\t\t});\n\n\t\t// trigger dayRender with each cell's element\n\t\tfor (row = 0; row < rowCnt; row++) {\n\t\t\tfor (col = 0; col < colCnt; col++) {\n\t\t\t\tview.trigger(\n\t\t\t\t\t'dayRender',\n\t\t\t\t\tnull,\n\t\t\t\t\tthis.getCellDate(row, col),\n\t\t\t\t\tthis.getCellEl(row, col)\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t},\n\n\n\tunrenderDates: function() {\n\t\tthis.removeSegPopover();\n\t},\n\n\n\trenderBusinessHours: function() {\n\t\tvar segs = this.buildBusinessHourSegs(true); // wholeDay=true\n\t\tthis.renderFill('businessHours', segs, 'bgevent');\n\t},\n\n\n\tunrenderBusinessHours: function() {\n\t\tthis.unrenderFill('businessHours');\n\t},\n\n\n\t// Generates the HTML for a single row, which is a div that wraps a table.\n\t// `row` is the row number.\n\trenderDayRowHtml: function(row, isRigid) {\n\t\tvar view = this.view;\n\t\tvar classes = [ 'fc-row', 'fc-week', view.widgetContentClass ];\n\n\t\tif (isRigid) {\n\t\t\tclasses.push('fc-rigid');\n\t\t}\n\n\t\treturn '' +\n\t\t\t'
' +\n\t\t\t\t'
' +\n\t\t\t\t\t'' +\n\t\t\t\t\t\tthis.renderBgTrHtml(row) +\n\t\t\t\t\t'
' +\n\t\t\t\t'
' +\n\t\t\t\t'
' +\n\t\t\t\t\t'' +\n\t\t\t\t\t\t(this.numbersVisible ?\n\t\t\t\t\t\t\t'' +\n\t\t\t\t\t\t\t\tthis.renderNumberTrHtml(row) +\n\t\t\t\t\t\t\t'' :\n\t\t\t\t\t\t\t''\n\t\t\t\t\t\t\t) +\n\t\t\t\t\t'
' +\n\t\t\t\t'
' +\n\t\t\t'
';\n\t},\n\n\n\t/* Grid Number Rendering\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\trenderNumberTrHtml: function(row) {\n\t\treturn '' +\n\t\t\t'' +\n\t\t\t\t(this.isRTL ? '' : this.renderNumberIntroHtml(row)) +\n\t\t\t\tthis.renderNumberCellsHtml(row) +\n\t\t\t\t(this.isRTL ? this.renderNumberIntroHtml(row) : '') +\n\t\t\t'';\n\t},\n\n\n\trenderNumberIntroHtml: function(row) {\n\t\treturn this.renderIntroHtml();\n\t},\n\n\n\trenderNumberCellsHtml: function(row) {\n\t\tvar htmls = [];\n\t\tvar col, date;\n\n\t\tfor (col = 0; col < this.colCnt; col++) {\n\t\t\tdate = this.getCellDate(row, col);\n\t\t\thtmls.push(this.renderNumberCellHtml(date));\n\t\t}\n\n\t\treturn htmls.join('');\n\t},\n\n\n\t// Generates the HTML for the s of the \"number\" row in the DayGrid's content skeleton.\n\t// The number row will only exist if either day numbers or week numbers are turned on.\n\trenderNumberCellHtml: function(date) {\n\t\tvar classes;\n\n\t\tif (!this.view.dayNumbersVisible) { // if there are week numbers but not day numbers\n\t\t\treturn ''; // will create an empty space above events :(\n\t\t}\n\n\t\tclasses = this.getDayClasses(date);\n\t\tclasses.unshift('fc-day-number');\n\n\t\treturn '' +\n\t\t\t'' +\n\t\t\t\tdate.date() +\n\t\t\t'';\n\t},\n\n\n\t/* Options\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// Computes a default event time formatting string if `timeFormat` is not explicitly defined\n\tcomputeEventTimeFormat: function() {\n\t\treturn this.view.opt('extraSmallTimeFormat'); // like \"6p\" or \"6:30p\"\n\t},\n\n\n\t// Computes a default `displayEventEnd` value if one is not expliclty defined\n\tcomputeDisplayEventEnd: function() {\n\t\treturn this.colCnt == 1; // we'll likely have space if there's only one day\n\t},\n\n\n\t/* Dates\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\trangeUpdated: function() {\n\t\tthis.updateDayTable();\n\t},\n\n\n\t// Slices up the given span (unzoned start/end with other misc data) into an array of segments\n\tspanToSegs: function(span) {\n\t\tvar segs = this.sliceRangeByRow(span);\n\t\tvar i, seg;\n\n\t\tfor (i = 0; i < segs.length; i++) {\n\t\t\tseg = segs[i];\n\t\t\tif (this.isRTL) {\n\t\t\t\tseg.leftCol = this.daysPerRow - 1 - seg.lastRowDayIndex;\n\t\t\t\tseg.rightCol = this.daysPerRow - 1 - seg.firstRowDayIndex;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tseg.leftCol = seg.firstRowDayIndex;\n\t\t\t\tseg.rightCol = seg.lastRowDayIndex;\n\t\t\t}\n\t\t}\n\n\t\treturn segs;\n\t},\n\n\n\t/* Hit System\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\tprepareHits: function() {\n\t\tthis.colCoordCache.build();\n\t\tthis.rowCoordCache.build();\n\t\tthis.rowCoordCache.bottoms[this.rowCnt - 1] += this.bottomCoordPadding; // hack\n\t},\n\n\n\treleaseHits: function() {\n\t\tthis.colCoordCache.clear();\n\t\tthis.rowCoordCache.clear();\n\t},\n\n\n\tqueryHit: function(leftOffset, topOffset) {\n\t\tif (this.colCoordCache.isLeftInBounds(leftOffset) && this.rowCoordCache.isTopInBounds(topOffset)) {\n\t\t\tvar col = this.colCoordCache.getHorizontalIndex(leftOffset);\n\t\t\tvar row = this.rowCoordCache.getVerticalIndex(topOffset);\n\n\t\t\tif (row != null && col != null) {\n\t\t\t\treturn this.getCellHit(row, col);\n\t\t\t}\n\t\t}\n\t},\n\n\n\tgetHitSpan: function(hit) {\n\t\treturn this.getCellRange(hit.row, hit.col);\n\t},\n\n\n\tgetHitEl: function(hit) {\n\t\treturn this.getCellEl(hit.row, hit.col);\n\t},\n\n\n\t/* Cell System\n\t------------------------------------------------------------------------------------------------------------------*/\n\t// FYI: the first column is the leftmost column, regardless of date\n\n\n\tgetCellHit: function(row, col) {\n\t\treturn {\n\t\t\trow: row,\n\t\t\tcol: col,\n\t\t\tcomponent: this, // needed unfortunately :(\n\t\t\tleft: this.colCoordCache.getLeftOffset(col),\n\t\t\tright: this.colCoordCache.getRightOffset(col),\n\t\t\ttop: this.rowCoordCache.getTopOffset(row),\n\t\t\tbottom: this.rowCoordCache.getBottomOffset(row)\n\t\t};\n\t},\n\n\n\tgetCellEl: function(row, col) {\n\t\treturn this.cellEls.eq(row * this.colCnt + col);\n\t},\n\n\n\t/* Event Drag Visualization\n\t------------------------------------------------------------------------------------------------------------------*/\n\t// TODO: move to DayGrid.event, similar to what we did with Grid's drag methods\n\n\n\t// Renders a visual indication of an event or external element being dragged.\n\t// `eventLocation` has zoned start and end (optional)\n\trenderDrag: function(eventLocation, seg) {\n\n\t\t// always render a highlight underneath\n\t\tthis.renderHighlight(this.eventToSpan(eventLocation));\n\n\t\t// if a segment from the same calendar but another component is being dragged, render a helper event\n\t\tif (seg && seg.component !== this) {\n\t\t\treturn this.renderEventLocationHelper(eventLocation, seg); // returns mock event elements\n\t\t}\n\t},\n\n\n\t// Unrenders any visual indication of a hovering event\n\tunrenderDrag: function() {\n\t\tthis.unrenderHighlight();\n\t\tthis.unrenderHelper();\n\t},\n\n\n\t/* Event Resize Visualization\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// Renders a visual indication of an event being resized\n\trenderEventResize: function(eventLocation, seg) {\n\t\tthis.renderHighlight(this.eventToSpan(eventLocation));\n\t\treturn this.renderEventLocationHelper(eventLocation, seg); // returns mock event elements\n\t},\n\n\n\t// Unrenders a visual indication of an event being resized\n\tunrenderEventResize: function() {\n\t\tthis.unrenderHighlight();\n\t\tthis.unrenderHelper();\n\t},\n\n\n\t/* Event Helper\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// Renders a mock \"helper\" event. `sourceSeg` is the associated internal segment object. It can be null.\n\trenderHelper: function(event, sourceSeg) {\n\t\tvar helperNodes = [];\n\t\tvar segs = this.eventToSegs(event);\n\t\tvar rowStructs;\n\n\t\tsegs = this.renderFgSegEls(segs); // assigns each seg's el and returns a subset of segs that were rendered\n\t\trowStructs = this.renderSegRows(segs);\n\n\t\t// inject each new event skeleton into each associated row\n\t\tthis.rowEls.each(function(row, rowNode) {\n\t\t\tvar rowEl = $(rowNode); // the .fc-row\n\t\t\tvar skeletonEl = $('
'); // will be absolutely positioned\n\t\t\tvar skeletonTop;\n\n\t\t\t// If there is an original segment, match the top position. Otherwise, put it at the row's top level\n\t\t\tif (sourceSeg && sourceSeg.row === row) {\n\t\t\t\tskeletonTop = sourceSeg.el.position().top;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tskeletonTop = rowEl.find('.fc-content-skeleton tbody').position().top;\n\t\t\t}\n\n\t\t\tskeletonEl.css('top', skeletonTop)\n\t\t\t\t.find('table')\n\t\t\t\t\t.append(rowStructs[row].tbodyEl);\n\n\t\t\trowEl.append(skeletonEl);\n\t\t\thelperNodes.push(skeletonEl[0]);\n\t\t});\n\n\t\treturn ( // must return the elements rendered\n\t\t\tthis.helperEls = $(helperNodes) // array -> jQuery set\n\t\t);\n\t},\n\n\n\t// Unrenders any visual indication of a mock helper event\n\tunrenderHelper: function() {\n\t\tif (this.helperEls) {\n\t\t\tthis.helperEls.remove();\n\t\t\tthis.helperEls = null;\n\t\t}\n\t},\n\n\n\t/* Fill System (highlight, background events, business hours)\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\tfillSegTag: 'td', // override the default tag name\n\n\n\t// Renders a set of rectangles over the given segments of days.\n\t// Only returns segments that successfully rendered.\n\trenderFill: function(type, segs, className) {\n\t\tvar nodes = [];\n\t\tvar i, seg;\n\t\tvar skeletonEl;\n\n\t\tsegs = this.renderFillSegEls(type, segs); // assignes `.el` to each seg. returns successfully rendered segs\n\n\t\tfor (i = 0; i < segs.length; i++) {\n\t\t\tseg = segs[i];\n\t\t\tskeletonEl = this.renderFillRow(type, seg, className);\n\t\t\tthis.rowEls.eq(seg.row).append(skeletonEl);\n\t\t\tnodes.push(skeletonEl[0]);\n\t\t}\n\n\t\tthis.elsByFill[type] = $(nodes);\n\n\t\treturn segs;\n\t},\n\n\n\t// Generates the HTML needed for one row of a fill. Requires the seg's el to be rendered.\n\trenderFillRow: function(type, seg, className) {\n\t\tvar colCnt = this.colCnt;\n\t\tvar startCol = seg.leftCol;\n\t\tvar endCol = seg.rightCol + 1;\n\t\tvar skeletonEl;\n\t\tvar trEl;\n\n\t\tclassName = className || type.toLowerCase();\n\n\t\tskeletonEl = $(\n\t\t\t'
' +\n\t\t\t\t'
' +\n\t\t\t'
'\n\t\t);\n\t\ttrEl = skeletonEl.find('tr');\n\n\t\tif (startCol > 0) {\n\t\t\ttrEl.append('');\n\t\t}\n\n\t\ttrEl.append(\n\t\t\tseg.el.attr('colspan', endCol - startCol)\n\t\t);\n\n\t\tif (endCol < colCnt) {\n\t\t\ttrEl.append('');\n\t\t}\n\n\t\tthis.bookendCells(trEl);\n\n\t\treturn skeletonEl;\n\t}\n\n});\n\n;;\n\n/* Event-rendering methods for the DayGrid class\n----------------------------------------------------------------------------------------------------------------------*/\n\nDayGrid.mixin({\n\n\trowStructs: null, // an array of objects, each holding information about a row's foreground event-rendering\n\n\n\t// Unrenders all events currently rendered on the grid\n\tunrenderEvents: function() {\n\t\tthis.removeSegPopover(); // removes the \"more..\" events popover\n\t\tGrid.prototype.unrenderEvents.apply(this, arguments); // calls the super-method\n\t},\n\n\n\t// Retrieves all rendered segment objects currently rendered on the grid\n\tgetEventSegs: function() {\n\t\treturn Grid.prototype.getEventSegs.call(this) // get the segments from the super-method\n\t\t\t.concat(this.popoverSegs || []); // append the segments from the \"more...\" popover\n\t},\n\n\n\t// Renders the given background event segments onto the grid\n\trenderBgSegs: function(segs) {\n\n\t\t// don't render timed background events\n\t\tvar allDaySegs = $.grep(segs, function(seg) {\n\t\t\treturn seg.event.allDay;\n\t\t});\n\n\t\treturn Grid.prototype.renderBgSegs.call(this, allDaySegs); // call the super-method\n\t},\n\n\n\t// Renders the given foreground event segments onto the grid\n\trenderFgSegs: function(segs) {\n\t\tvar rowStructs;\n\n\t\t// render an `.el` on each seg\n\t\t// returns a subset of the segs. segs that were actually rendered\n\t\tsegs = this.renderFgSegEls(segs);\n\n\t\trowStructs = this.rowStructs = this.renderSegRows(segs);\n\n\t\t// append to each row's content skeleton\n\t\tthis.rowEls.each(function(i, rowNode) {\n\t\t\t$(rowNode).find('.fc-content-skeleton > table').append(\n\t\t\t\trowStructs[i].tbodyEl\n\t\t\t);\n\t\t});\n\n\t\treturn segs; // return only the segs that were actually rendered\n\t},\n\n\n\t// Unrenders all currently rendered foreground event segments\n\tunrenderFgSegs: function() {\n\t\tvar rowStructs = this.rowStructs || [];\n\t\tvar rowStruct;\n\n\t\twhile ((rowStruct = rowStructs.pop())) {\n\t\t\trowStruct.tbodyEl.remove();\n\t\t}\n\n\t\tthis.rowStructs = null;\n\t},\n\n\n\t// Uses the given events array to generate elements that should be appended to each row's content skeleton.\n\t// Returns an array of rowStruct objects (see the bottom of `renderSegRow`).\n\t// PRECONDITION: each segment shoud already have a rendered and assigned `.el`\n\trenderSegRows: function(segs) {\n\t\tvar rowStructs = [];\n\t\tvar segRows;\n\t\tvar row;\n\n\t\tsegRows = this.groupSegRows(segs); // group into nested arrays\n\n\t\t// iterate each row of segment groupings\n\t\tfor (row = 0; row < segRows.length; row++) {\n\t\t\trowStructs.push(\n\t\t\t\tthis.renderSegRow(row, segRows[row])\n\t\t\t);\n\t\t}\n\n\t\treturn rowStructs;\n\t},\n\n\n\t// Builds the HTML to be used for the default element for an individual segment\n\tfgSegHtml: function(seg, disableResizing) {\n\t\tvar view = this.view;\n\t\tvar event = seg.event;\n\t\tvar isDraggable = view.isEventDraggable(event);\n\t\tvar isResizableFromStart = !disableResizing && event.allDay &&\n\t\t\tseg.isStart && view.isEventResizableFromStart(event);\n\t\tvar isResizableFromEnd = !disableResizing && event.allDay &&\n\t\t\tseg.isEnd && view.isEventResizableFromEnd(event);\n\t\tvar classes = this.getSegClasses(seg, isDraggable, isResizableFromStart || isResizableFromEnd);\n\t\tvar skinCss = cssToStr(this.getSegSkinCss(seg));\n\t\tvar timeHtml = '';\n\t\tvar timeText;\n\t\tvar titleHtml;\n\n\t\tclasses.unshift('fc-day-grid-event', 'fc-h-event');\n\n\t\t// Only display a timed events time if it is the starting segment\n\t\tif (seg.isStart) {\n\t\t\ttimeText = this.getEventTimeText(event);\n\t\t\tif (timeText) {\n\t\t\t\ttimeHtml = '' + htmlEscape(timeText) + '';\n\t\t\t}\n\t\t}\n\n\t\ttitleHtml =\n\t\t\t'' +\n\t\t\t\t(htmlEscape(event.title || '') || ' ') + // we always want one line of height\n\t\t\t'';\n\t\t\n\t\treturn '
' +\n\t\t\t\t'
' +\n\t\t\t\t\t(this.isRTL ?\n\t\t\t\t\t\ttitleHtml + ' ' + timeHtml : // put a natural space in between\n\t\t\t\t\t\ttimeHtml + ' ' + titleHtml //\n\t\t\t\t\t\t) +\n\t\t\t\t'
' +\n\t\t\t\t(isResizableFromStart ?\n\t\t\t\t\t'
' :\n\t\t\t\t\t''\n\t\t\t\t\t) +\n\t\t\t\t(isResizableFromEnd ?\n\t\t\t\t\t'
' :\n\t\t\t\t\t''\n\t\t\t\t\t) +\n\t\t\t'';\n\t},\n\n\n\t// Given a row # and an array of segments all in the same row, render a element, a skeleton that contains\n\t// the segments. Returns object with a bunch of internal data about how the render was calculated.\n\t// NOTE: modifies rowSegs\n\trenderSegRow: function(row, rowSegs) {\n\t\tvar colCnt = this.colCnt;\n\t\tvar segLevels = this.buildSegLevels(rowSegs); // group into sub-arrays of levels\n\t\tvar levelCnt = Math.max(1, segLevels.length); // ensure at least one level\n\t\tvar tbody = $('');\n\t\tvar segMatrix = []; // lookup for which segments are rendered into which level+col cells\n\t\tvar cellMatrix = []; // lookup for all elements of the level+col matrix\n\t\tvar loneCellMatrix = []; // lookup for elements that only take up a single column\n\t\tvar i, levelSegs;\n\t\tvar col;\n\t\tvar tr;\n\t\tvar j, seg;\n\t\tvar td;\n\n\t\t// populates empty cells from the current column (`col`) to `endCol`\n\t\tfunction emptyCellsUntil(endCol) {\n\t\t\twhile (col < endCol) {\n\t\t\t\t// try to grab a cell from the level above and extend its rowspan. otherwise, create a fresh cell\n\t\t\t\ttd = (loneCellMatrix[i - 1] || [])[col];\n\t\t\t\tif (td) {\n\t\t\t\t\ttd.attr(\n\t\t\t\t\t\t'rowspan',\n\t\t\t\t\t\tparseInt(td.attr('rowspan') || 1, 10) + 1\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\ttd = $('');\n\t\t\t\t\ttr.append(td);\n\t\t\t\t}\n\t\t\t\tcellMatrix[i][col] = td;\n\t\t\t\tloneCellMatrix[i][col] = td;\n\t\t\t\tcol++;\n\t\t\t}\n\t\t}\n\n\t\tfor (i = 0; i < levelCnt; i++) { // iterate through all levels\n\t\t\tlevelSegs = segLevels[i];\n\t\t\tcol = 0;\n\t\t\ttr = $('');\n\n\t\t\tsegMatrix.push([]);\n\t\t\tcellMatrix.push([]);\n\t\t\tloneCellMatrix.push([]);\n\n\t\t\t// levelCnt might be 1 even though there are no actual levels. protect against this.\n\t\t\t// this single empty row is useful for styling.\n\t\t\tif (levelSegs) {\n\t\t\t\tfor (j = 0; j < levelSegs.length; j++) { // iterate through segments in level\n\t\t\t\t\tseg = levelSegs[j];\n\n\t\t\t\t\temptyCellsUntil(seg.leftCol);\n\n\t\t\t\t\t// create a container that occupies or more columns. append the event element.\n\t\t\t\t\ttd = $('').append(seg.el);\n\t\t\t\t\tif (seg.leftCol != seg.rightCol) {\n\t\t\t\t\t\ttd.attr('colspan', seg.rightCol - seg.leftCol + 1);\n\t\t\t\t\t}\n\t\t\t\t\telse { // a single-column segment\n\t\t\t\t\t\tloneCellMatrix[i][col] = td;\n\t\t\t\t\t}\n\n\t\t\t\t\twhile (col <= seg.rightCol) {\n\t\t\t\t\t\tcellMatrix[i][col] = td;\n\t\t\t\t\t\tsegMatrix[i][col] = seg;\n\t\t\t\t\t\tcol++;\n\t\t\t\t\t}\n\n\t\t\t\t\ttr.append(td);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\temptyCellsUntil(colCnt); // finish off the row\n\t\t\tthis.bookendCells(tr);\n\t\t\ttbody.append(tr);\n\t\t}\n\n\t\treturn { // a \"rowStruct\"\n\t\t\trow: row, // the row number\n\t\t\ttbodyEl: tbody,\n\t\t\tcellMatrix: cellMatrix,\n\t\t\tsegMatrix: segMatrix,\n\t\t\tsegLevels: segLevels,\n\t\t\tsegs: rowSegs\n\t\t};\n\t},\n\n\n\t// Stacks a flat array of segments, which are all assumed to be in the same row, into subarrays of vertical levels.\n\t// NOTE: modifies segs\n\tbuildSegLevels: function(segs) {\n\t\tvar levels = [];\n\t\tvar i, seg;\n\t\tvar j;\n\n\t\t// Give preference to elements with certain criteria, so they have\n\t\t// a chance to be closer to the top.\n\t\tthis.sortEventSegs(segs);\n\t\t\n\t\tfor (i = 0; i < segs.length; i++) {\n\t\t\tseg = segs[i];\n\n\t\t\t// loop through levels, starting with the topmost, until the segment doesn't collide with other segments\n\t\t\tfor (j = 0; j < levels.length; j++) {\n\t\t\t\tif (!isDaySegCollision(seg, levels[j])) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// `j` now holds the desired subrow index\n\t\t\tseg.level = j;\n\n\t\t\t// create new level array if needed and append segment\n\t\t\t(levels[j] || (levels[j] = [])).push(seg);\n\t\t}\n\n\t\t// order segments left-to-right. very important if calendar is RTL\n\t\tfor (j = 0; j < levels.length; j++) {\n\t\t\tlevels[j].sort(compareDaySegCols);\n\t\t}\n\n\t\treturn levels;\n\t},\n\n\n\t// Given a flat array of segments, return an array of sub-arrays, grouped by each segment's row\n\tgroupSegRows: function(segs) {\n\t\tvar segRows = [];\n\t\tvar i;\n\n\t\tfor (i = 0; i < this.rowCnt; i++) {\n\t\t\tsegRows.push([]);\n\t\t}\n\n\t\tfor (i = 0; i < segs.length; i++) {\n\t\t\tsegRows[segs[i].row].push(segs[i]);\n\t\t}\n\n\t\treturn segRows;\n\t}\n\n});\n\n\n// Computes whether two segments' columns collide. They are assumed to be in the same row.\nfunction isDaySegCollision(seg, otherSegs) {\n\tvar i, otherSeg;\n\n\tfor (i = 0; i < otherSegs.length; i++) {\n\t\totherSeg = otherSegs[i];\n\n\t\tif (\n\t\t\totherSeg.leftCol <= seg.rightCol &&\n\t\t\totherSeg.rightCol >= seg.leftCol\n\t\t) {\n\t\t\treturn true;\n\t\t}\n\t}\n\n\treturn false;\n}\n\n\n// A cmp function for determining the leftmost event\nfunction compareDaySegCols(a, b) {\n\treturn a.leftCol - b.leftCol;\n}\n\n;;\n\n/* Methods relate to limiting the number events for a given day on a DayGrid\n----------------------------------------------------------------------------------------------------------------------*/\n// NOTE: all the segs being passed around in here are foreground segs\n\nDayGrid.mixin({\n\n\tsegPopover: null, // the Popover that holds events that can't fit in a cell. null when not visible\n\tpopoverSegs: null, // an array of segment objects that the segPopover holds. null when not visible\n\n\n\tremoveSegPopover: function() {\n\t\tif (this.segPopover) {\n\t\t\tthis.segPopover.hide(); // in handler, will call segPopover's removeElement\n\t\t}\n\t},\n\n\n\t// Limits the number of \"levels\" (vertically stacking layers of events) for each row of the grid.\n\t// `levelLimit` can be false (don't limit), a number, or true (should be computed).\n\tlimitRows: function(levelLimit) {\n\t\tvar rowStructs = this.rowStructs || [];\n\t\tvar row; // row #\n\t\tvar rowLevelLimit;\n\n\t\tfor (row = 0; row < rowStructs.length; row++) {\n\t\t\tthis.unlimitRow(row);\n\n\t\t\tif (!levelLimit) {\n\t\t\t\trowLevelLimit = false;\n\t\t\t}\n\t\t\telse if (typeof levelLimit === 'number') {\n\t\t\t\trowLevelLimit = levelLimit;\n\t\t\t}\n\t\t\telse {\n\t\t\t\trowLevelLimit = this.computeRowLevelLimit(row);\n\t\t\t}\n\n\t\t\tif (rowLevelLimit !== false) {\n\t\t\t\tthis.limitRow(row, rowLevelLimit);\n\t\t\t}\n\t\t}\n\t},\n\n\n\t// Computes the number of levels a row will accomodate without going outside its bounds.\n\t// Assumes the row is \"rigid\" (maintains a constant height regardless of what is inside).\n\t// `row` is the row number.\n\tcomputeRowLevelLimit: function(row) {\n\t\tvar rowEl = this.rowEls.eq(row); // the containing \"fake\" row div\n\t\tvar rowHeight = rowEl.height(); // TODO: cache somehow?\n\t\tvar trEls = this.rowStructs[row].tbodyEl.children();\n\t\tvar i, trEl;\n\t\tvar trHeight;\n\n\t\tfunction iterInnerHeights(i, childNode) {\n\t\t\ttrHeight = Math.max(trHeight, $(childNode).outerHeight());\n\t\t}\n\n\t\t// Reveal one level at a time and stop when we find one out of bounds\n\t\tfor (i = 0; i < trEls.length; i++) {\n\t\t\ttrEl = trEls.eq(i).removeClass('fc-limited'); // reset to original state (reveal)\n\n\t\t\t// with rowspans>1 and IE8, trEl.outerHeight() would return the height of the largest cell,\n\t\t\t// so instead, find the tallest inner content element.\n\t\t\ttrHeight = 0;\n\t\t\ttrEl.find('> td > :first-child').each(iterInnerHeights);\n\n\t\t\tif (trEl.position().top + trHeight > rowHeight) {\n\t\t\t\treturn i;\n\t\t\t}\n\t\t}\n\n\t\treturn false; // should not limit at all\n\t},\n\n\n\t// Limits the given grid row to the maximum number of levels and injects \"more\" links if necessary.\n\t// `row` is the row number.\n\t// `levelLimit` is a number for the maximum (inclusive) number of levels allowed.\n\tlimitRow: function(row, levelLimit) {\n\t\tvar _this = this;\n\t\tvar rowStruct = this.rowStructs[row];\n\t\tvar moreNodes = []; // array of \"more\" links and DOM nodes\n\t\tvar col = 0; // col #, left-to-right (not chronologically)\n\t\tvar levelSegs; // array of segment objects in the last allowable level, ordered left-to-right\n\t\tvar cellMatrix; // a matrix (by level, then column) of all jQuery elements in the row\n\t\tvar limitedNodes; // array of temporarily hidden level and segment DOM nodes\n\t\tvar i, seg;\n\t\tvar segsBelow; // array of segment objects below `seg` in the current `col`\n\t\tvar totalSegsBelow; // total number of segments below `seg` in any of the columns `seg` occupies\n\t\tvar colSegsBelow; // array of segment arrays, below seg, one for each column (offset from segs's first column)\n\t\tvar td, rowspan;\n\t\tvar segMoreNodes; // array of \"more\" cells that will stand-in for the current seg's cell\n\t\tvar j;\n\t\tvar moreTd, moreWrap, moreLink;\n\n\t\t// Iterates through empty level cells and places \"more\" links inside if need be\n\t\tfunction emptyCellsUntil(endCol) { // goes from current `col` to `endCol`\n\t\t\twhile (col < endCol) {\n\t\t\t\tsegsBelow = _this.getCellSegs(row, col, levelLimit);\n\t\t\t\tif (segsBelow.length) {\n\t\t\t\t\ttd = cellMatrix[levelLimit - 1][col];\n\t\t\t\t\tmoreLink = _this.renderMoreLink(row, col, segsBelow);\n\t\t\t\t\tmoreWrap = $('
').append(moreLink);\n\t\t\t\t\ttd.append(moreWrap);\n\t\t\t\t\tmoreNodes.push(moreWrap[0]);\n\t\t\t\t}\n\t\t\t\tcol++;\n\t\t\t}\n\t\t}\n\n\t\tif (levelLimit && levelLimit < rowStruct.segLevels.length) { // is it actually over the limit?\n\t\t\tlevelSegs = rowStruct.segLevels[levelLimit - 1];\n\t\t\tcellMatrix = rowStruct.cellMatrix;\n\n\t\t\tlimitedNodes = rowStruct.tbodyEl.children().slice(levelLimit) // get level elements past the limit\n\t\t\t\t.addClass('fc-limited').get(); // hide elements and get a simple DOM-nodes array\n\n\t\t\t// iterate though segments in the last allowable level\n\t\t\tfor (i = 0; i < levelSegs.length; i++) {\n\t\t\t\tseg = levelSegs[i];\n\t\t\t\temptyCellsUntil(seg.leftCol); // process empty cells before the segment\n\n\t\t\t\t// determine *all* segments below `seg` that occupy the same columns\n\t\t\t\tcolSegsBelow = [];\n\t\t\t\ttotalSegsBelow = 0;\n\t\t\t\twhile (col <= seg.rightCol) {\n\t\t\t\t\tsegsBelow = this.getCellSegs(row, col, levelLimit);\n\t\t\t\t\tcolSegsBelow.push(segsBelow);\n\t\t\t\t\ttotalSegsBelow += segsBelow.length;\n\t\t\t\t\tcol++;\n\t\t\t\t}\n\n\t\t\t\tif (totalSegsBelow) { // do we need to replace this segment with one or many \"more\" links?\n\t\t\t\t\ttd = cellMatrix[levelLimit - 1][seg.leftCol]; // the segment's parent cell\n\t\t\t\t\trowspan = td.attr('rowspan') || 1;\n\t\t\t\t\tsegMoreNodes = [];\n\n\t\t\t\t\t// make a replacement for each column the segment occupies. will be one for each colspan\n\t\t\t\t\tfor (j = 0; j < colSegsBelow.length; j++) {\n\t\t\t\t\t\tmoreTd = $('').attr('rowspan', rowspan);\n\t\t\t\t\t\tsegsBelow = colSegsBelow[j];\n\t\t\t\t\t\tmoreLink = this.renderMoreLink(\n\t\t\t\t\t\t\trow,\n\t\t\t\t\t\t\tseg.leftCol + j,\n\t\t\t\t\t\t\t[ seg ].concat(segsBelow) // count seg as hidden too\n\t\t\t\t\t\t);\n\t\t\t\t\t\tmoreWrap = $('
').append(moreLink);\n\t\t\t\t\t\tmoreTd.append(moreWrap);\n\t\t\t\t\t\tsegMoreNodes.push(moreTd[0]);\n\t\t\t\t\t\tmoreNodes.push(moreTd[0]);\n\t\t\t\t\t}\n\n\t\t\t\t\ttd.addClass('fc-limited').after($(segMoreNodes)); // hide original and inject replacements\n\t\t\t\t\tlimitedNodes.push(td[0]);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\temptyCellsUntil(this.colCnt); // finish off the level\n\t\t\trowStruct.moreEls = $(moreNodes); // for easy undoing later\n\t\t\trowStruct.limitedEls = $(limitedNodes); // for easy undoing later\n\t\t}\n\t},\n\n\n\t// Reveals all levels and removes all \"more\"-related elements for a grid's row.\n\t// `row` is a row number.\n\tunlimitRow: function(row) {\n\t\tvar rowStruct = this.rowStructs[row];\n\n\t\tif (rowStruct.moreEls) {\n\t\t\trowStruct.moreEls.remove();\n\t\t\trowStruct.moreEls = null;\n\t\t}\n\n\t\tif (rowStruct.limitedEls) {\n\t\t\trowStruct.limitedEls.removeClass('fc-limited');\n\t\t\trowStruct.limitedEls = null;\n\t\t}\n\t},\n\n\n\t// Renders an element that represents hidden event element for a cell.\n\t// Responsible for attaching click handler as well.\n\trenderMoreLink: function(row, col, hiddenSegs) {\n\t\tvar _this = this;\n\t\tvar view = this.view;\n\n\t\treturn $('')\n\t\t\t.text(\n\t\t\t\tthis.getMoreLinkText(hiddenSegs.length)\n\t\t\t)\n\t\t\t.on('click', function(ev) {\n\t\t\t\tvar clickOption = view.opt('eventLimitClick');\n\t\t\t\tvar date = _this.getCellDate(row, col);\n\t\t\t\tvar moreEl = $(this);\n\t\t\t\tvar dayEl = _this.getCellEl(row, col);\n\t\t\t\tvar allSegs = _this.getCellSegs(row, col);\n\n\t\t\t\t// rescope the segments to be within the cell's date\n\t\t\t\tvar reslicedAllSegs = _this.resliceDaySegs(allSegs, date);\n\t\t\t\tvar reslicedHiddenSegs = _this.resliceDaySegs(hiddenSegs, date);\n\n\t\t\t\tif (typeof clickOption === 'function') {\n\t\t\t\t\t// the returned value can be an atomic option\n\t\t\t\t\tclickOption = view.trigger('eventLimitClick', null, {\n\t\t\t\t\t\tdate: date,\n\t\t\t\t\t\tdayEl: dayEl,\n\t\t\t\t\t\tmoreEl: moreEl,\n\t\t\t\t\t\tsegs: reslicedAllSegs,\n\t\t\t\t\t\thiddenSegs: reslicedHiddenSegs\n\t\t\t\t\t}, ev);\n\t\t\t\t}\n\n\t\t\t\tif (clickOption === 'popover') {\n\t\t\t\t\t_this.showSegPopover(row, col, moreEl, reslicedAllSegs);\n\t\t\t\t}\n\t\t\t\telse if (typeof clickOption === 'string') { // a view name\n\t\t\t\t\tview.calendar.zoomTo(date, clickOption);\n\t\t\t\t}\n\t\t\t});\n\t},\n\n\n\t// Reveals the popover that displays all events within a cell\n\tshowSegPopover: function(row, col, moreLink, segs) {\n\t\tvar _this = this;\n\t\tvar view = this.view;\n\t\tvar moreWrap = moreLink.parent(); // the
wrapper around the \n\t\tvar topEl; // the element we want to match the top coordinate of\n\t\tvar options;\n\n\t\tif (this.rowCnt == 1) {\n\t\t\ttopEl = view.el; // will cause the popover to cover any sort of header\n\t\t}\n\t\telse {\n\t\t\ttopEl = this.rowEls.eq(row); // will align with top of row\n\t\t}\n\n\t\toptions = {\n\t\t\tclassName: 'fc-more-popover',\n\t\t\tcontent: this.renderSegPopoverContent(row, col, segs),\n\t\t\tparentEl: this.view.el, // attach to root of view. guarantees outside of scrollbars.\n\t\t\ttop: topEl.offset().top,\n\t\t\tautoHide: true, // when the user clicks elsewhere, hide the popover\n\t\t\tviewportConstrain: view.opt('popoverViewportConstrain'),\n\t\t\thide: function() {\n\t\t\t\t// kill everything when the popover is hidden\n\t\t\t\t_this.segPopover.removeElement();\n\t\t\t\t_this.segPopover = null;\n\t\t\t\t_this.popoverSegs = null;\n\t\t\t}\n\t\t};\n\n\t\t// Determine horizontal coordinate.\n\t\t// We use the moreWrap instead of the to avoid border confusion.\n\t\tif (this.isRTL) {\n\t\t\toptions.right = moreWrap.offset().left + moreWrap.outerWidth() + 1; // +1 to be over cell border\n\t\t}\n\t\telse {\n\t\t\toptions.left = moreWrap.offset().left - 1; // -1 to be over cell border\n\t\t}\n\n\t\tthis.segPopover = new Popover(options);\n\t\tthis.segPopover.show();\n\n\t\t// the popover doesn't live within the grid's container element, and thus won't get the event\n\t\t// delegated-handlers for free. attach event-related handlers to the popover.\n\t\tthis.bindSegHandlersToEl(this.segPopover.el);\n\t},\n\n\n\t// Builds the inner DOM contents of the segment popover\n\trenderSegPopoverContent: function(row, col, segs) {\n\t\tvar view = this.view;\n\t\tvar isTheme = view.opt('theme');\n\t\tvar title = this.getCellDate(row, col).format(view.opt('dayPopoverFormat'));\n\t\tvar content = $(\n\t\t\t'
' +\n\t\t\t\t'' +\n\t\t\t\t'' +\n\t\t\t\t\thtmlEscape(title) +\n\t\t\t\t'' +\n\t\t\t\t'
' +\n\t\t\t'
' +\n\t\t\t'
' +\n\t\t\t\t'
' +\n\t\t\t'
'\n\t\t);\n\t\tvar segContainer = content.find('.fc-event-container');\n\t\tvar i;\n\n\t\t// render each seg's `el` and only return the visible segs\n\t\tsegs = this.renderFgSegEls(segs, true); // disableResizing=true\n\t\tthis.popoverSegs = segs;\n\n\t\tfor (i = 0; i < segs.length; i++) {\n\n\t\t\t// because segments in the popover are not part of a grid coordinate system, provide a hint to any\n\t\t\t// grids that want to do drag-n-drop about which cell it came from\n\t\t\tthis.prepareHits();\n\t\t\tsegs[i].hit = this.getCellHit(row, col);\n\t\t\tthis.releaseHits();\n\n\t\t\tsegContainer.append(segs[i].el);\n\t\t}\n\n\t\treturn content;\n\t},\n\n\n\t// Given the events within an array of segment objects, reslice them to be in a single day\n\tresliceDaySegs: function(segs, dayDate) {\n\n\t\t// build an array of the original events\n\t\tvar events = $.map(segs, function(seg) {\n\t\t\treturn seg.event;\n\t\t});\n\n\t\tvar dayStart = dayDate.clone();\n\t\tvar dayEnd = dayStart.clone().add(1, 'days');\n\t\tvar dayRange = { start: dayStart, end: dayEnd };\n\n\t\t// slice the events with a custom slicing function\n\t\tsegs = this.eventsToSegs(\n\t\t\tevents,\n\t\t\tfunction(range) {\n\t\t\t\tvar seg = intersectRanges(range, dayRange); // undefind if no intersection\n\t\t\t\treturn seg ? [ seg ] : []; // must return an array of segments\n\t\t\t}\n\t\t);\n\n\t\t// force an order because eventsToSegs doesn't guarantee one\n\t\tthis.sortEventSegs(segs);\n\n\t\treturn segs;\n\t},\n\n\n\t// Generates the text that should be inside a \"more\" link, given the number of events it represents\n\tgetMoreLinkText: function(num) {\n\t\tvar opt = this.view.opt('eventLimitText');\n\n\t\tif (typeof opt === 'function') {\n\t\t\treturn opt(num);\n\t\t}\n\t\telse {\n\t\t\treturn '+' + num + ' ' + opt;\n\t\t}\n\t},\n\n\n\t// Returns segments within a given cell.\n\t// If `startLevel` is specified, returns only events including and below that level. Otherwise returns all segs.\n\tgetCellSegs: function(row, col, startLevel) {\n\t\tvar segMatrix = this.rowStructs[row].segMatrix;\n\t\tvar level = startLevel || 0;\n\t\tvar segs = [];\n\t\tvar seg;\n\n\t\twhile (level < segMatrix.length) {\n\t\t\tseg = segMatrix[level][col];\n\t\t\tif (seg) {\n\t\t\t\tsegs.push(seg);\n\t\t\t}\n\t\t\tlevel++;\n\t\t}\n\n\t\treturn segs;\n\t}\n\n});\n\n;;\n\n/* A component that renders one or more columns of vertical time slots\n----------------------------------------------------------------------------------------------------------------------*/\n// We mixin DayTable, even though there is only a single row of days\n\nvar TimeGrid = FC.TimeGrid = Grid.extend(DayTableMixin, {\n\n\tslotDuration: null, // duration of a \"slot\", a distinct time segment on given day, visualized by lines\n\tsnapDuration: null, // granularity of time for dragging and selecting\n\tsnapsPerSlot: null,\n\tminTime: null, // Duration object that denotes the first visible time of any given day\n\tmaxTime: null, // Duration object that denotes the exclusive visible end time of any given day\n\tlabelFormat: null, // formatting string for times running along vertical axis\n\tlabelInterval: null, // duration of how often a label should be displayed for a slot\n\n\tcolEls: null, // cells elements in the day-row background\n\tslatContainerEl: null, // div that wraps all the slat rows\n\tslatEls: null, // elements running horizontally across all columns\n\tnowIndicatorEls: null,\n\n\tcolCoordCache: null,\n\tslatCoordCache: null,\n\n\n\tconstructor: function() {\n\t\tGrid.apply(this, arguments); // call the super-constructor\n\n\t\tthis.processOptions();\n\t},\n\n\n\t// Renders the time grid into `this.el`, which should already be assigned.\n\t// Relies on the view's colCnt. In the future, this component should probably be self-sufficient.\n\trenderDates: function() {\n\t\tthis.el.html(this.renderHtml());\n\t\tthis.colEls = this.el.find('.fc-day');\n\t\tthis.slatContainerEl = this.el.find('.fc-slats');\n\t\tthis.slatEls = this.slatContainerEl.find('tr');\n\n\t\tthis.colCoordCache = new CoordCache({\n\t\t\tels: this.colEls,\n\t\t\tisHorizontal: true\n\t\t});\n\t\tthis.slatCoordCache = new CoordCache({\n\t\t\tels: this.slatEls,\n\t\t\tisVertical: true\n\t\t});\n\n\t\tthis.renderContentSkeleton();\n\t},\n\n\n\t// Renders the basic HTML skeleton for the grid\n\trenderHtml: function() {\n\t\treturn '' +\n\t\t\t'
' +\n\t\t\t\t'' +\n\t\t\t\t\tthis.renderBgTrHtml(0) + // row=0\n\t\t\t\t'
' +\n\t\t\t'
' +\n\t\t\t'
' +\n\t\t\t\t'' +\n\t\t\t\t\tthis.renderSlatRowHtml() +\n\t\t\t\t'
' +\n\t\t\t'
';\n\t},\n\n\n\t// Generates the HTML for the horizontal \"slats\" that run width-wise. Has a time axis on a side. Depends on RTL.\n\trenderSlatRowHtml: function() {\n\t\tvar view = this.view;\n\t\tvar isRTL = this.isRTL;\n\t\tvar html = '';\n\t\tvar slotTime = moment.duration(+this.minTime); // wish there was .clone() for durations\n\t\tvar slotDate; // will be on the view's first day, but we only care about its time\n\t\tvar isLabeled;\n\t\tvar axisHtml;\n\n\t\t// Calculate the time for each slot\n\t\twhile (slotTime < this.maxTime) {\n\t\t\tslotDate = this.start.clone().time(slotTime);\n\t\t\tisLabeled = isInt(divideDurationByDuration(slotTime, this.labelInterval));\n\n\t\t\taxisHtml =\n\t\t\t\t'' +\n\t\t\t\t\t(isLabeled ?\n\t\t\t\t\t\t'' + // for matchCellWidths\n\t\t\t\t\t\t\thtmlEscape(slotDate.format(this.labelFormat)) +\n\t\t\t\t\t\t'' :\n\t\t\t\t\t\t''\n\t\t\t\t\t\t) +\n\t\t\t\t'';\n\n\t\t\thtml +=\n\t\t\t\t'' +\n\t\t\t\t\t(!isRTL ? axisHtml : '') +\n\t\t\t\t\t'' +\n\t\t\t\t\t(isRTL ? axisHtml : '') +\n\t\t\t\t\"\";\n\n\t\t\tslotTime.add(this.slotDuration);\n\t\t}\n\n\t\treturn html;\n\t},\n\n\n\t/* Options\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// Parses various options into properties of this object\n\tprocessOptions: function() {\n\t\tvar view = this.view;\n\t\tvar slotDuration = view.opt('slotDuration');\n\t\tvar snapDuration = view.opt('snapDuration');\n\t\tvar input;\n\n\t\tslotDuration = moment.duration(slotDuration);\n\t\tsnapDuration = snapDuration ? moment.duration(snapDuration) : slotDuration;\n\n\t\tthis.slotDuration = slotDuration;\n\t\tthis.snapDuration = snapDuration;\n\t\tthis.snapsPerSlot = slotDuration / snapDuration; // TODO: ensure an integer multiple?\n\n\t\tthis.minResizeDuration = snapDuration; // hack\n\n\t\tthis.minTime = moment.duration(view.opt('minTime'));\n\t\tthis.maxTime = moment.duration(view.opt('maxTime'));\n\n\t\t// might be an array value (for TimelineView).\n\t\t// if so, getting the most granular entry (the last one probably).\n\t\tinput = view.opt('slotLabelFormat');\n\t\tif ($.isArray(input)) {\n\t\t\tinput = input[input.length - 1];\n\t\t}\n\n\t\tthis.labelFormat =\n\t\t\tinput ||\n\t\t\tview.opt('axisFormat') || // deprecated\n\t\t\tview.opt('smallTimeFormat'); // the computed default\n\n\t\tinput = view.opt('slotLabelInterval');\n\t\tthis.labelInterval = input ?\n\t\t\tmoment.duration(input) :\n\t\t\tthis.computeLabelInterval(slotDuration);\n\t},\n\n\n\t// Computes an automatic value for slotLabelInterval\n\tcomputeLabelInterval: function(slotDuration) {\n\t\tvar i;\n\t\tvar labelInterval;\n\t\tvar slotsPerLabel;\n\n\t\t// find the smallest stock label interval that results in more than one slots-per-label\n\t\tfor (i = AGENDA_STOCK_SUB_DURATIONS.length - 1; i >= 0; i--) {\n\t\t\tlabelInterval = moment.duration(AGENDA_STOCK_SUB_DURATIONS[i]);\n\t\t\tslotsPerLabel = divideDurationByDuration(labelInterval, slotDuration);\n\t\t\tif (isInt(slotsPerLabel) && slotsPerLabel > 1) {\n\t\t\t\treturn labelInterval;\n\t\t\t}\n\t\t}\n\n\t\treturn moment.duration(slotDuration); // fall back. clone\n\t},\n\n\n\t// Computes a default event time formatting string if `timeFormat` is not explicitly defined\n\tcomputeEventTimeFormat: function() {\n\t\treturn this.view.opt('noMeridiemTimeFormat'); // like \"6:30\" (no AM/PM)\n\t},\n\n\n\t// Computes a default `displayEventEnd` value if one is not expliclty defined\n\tcomputeDisplayEventEnd: function() {\n\t\treturn true;\n\t},\n\n\n\t/* Hit System\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\tprepareHits: function() {\n\t\tthis.colCoordCache.build();\n\t\tthis.slatCoordCache.build();\n\t},\n\n\n\treleaseHits: function() {\n\t\tthis.colCoordCache.clear();\n\t\t// NOTE: don't clear slatCoordCache because we rely on it for computeTimeTop\n\t},\n\n\n\tqueryHit: function(leftOffset, topOffset) {\n\t\tvar snapsPerSlot = this.snapsPerSlot;\n\t\tvar colCoordCache = this.colCoordCache;\n\t\tvar slatCoordCache = this.slatCoordCache;\n\n\t\tif (colCoordCache.isLeftInBounds(leftOffset) && slatCoordCache.isTopInBounds(topOffset)) {\n\t\t\tvar colIndex = colCoordCache.getHorizontalIndex(leftOffset);\n\t\t\tvar slatIndex = slatCoordCache.getVerticalIndex(topOffset);\n\n\t\t\tif (colIndex != null && slatIndex != null) {\n\t\t\t\tvar slatTop = slatCoordCache.getTopOffset(slatIndex);\n\t\t\t\tvar slatHeight = slatCoordCache.getHeight(slatIndex);\n\t\t\t\tvar partial = (topOffset - slatTop) / slatHeight; // floating point number between 0 and 1\n\t\t\t\tvar localSnapIndex = Math.floor(partial * snapsPerSlot); // the snap # relative to start of slat\n\t\t\t\tvar snapIndex = slatIndex * snapsPerSlot + localSnapIndex;\n\t\t\t\tvar snapTop = slatTop + (localSnapIndex / snapsPerSlot) * slatHeight;\n\t\t\t\tvar snapBottom = slatTop + ((localSnapIndex + 1) / snapsPerSlot) * slatHeight;\n\n\t\t\t\treturn {\n\t\t\t\t\tcol: colIndex,\n\t\t\t\t\tsnap: snapIndex,\n\t\t\t\t\tcomponent: this, // needed unfortunately :(\n\t\t\t\t\tleft: colCoordCache.getLeftOffset(colIndex),\n\t\t\t\t\tright: colCoordCache.getRightOffset(colIndex),\n\t\t\t\t\ttop: snapTop,\n\t\t\t\t\tbottom: snapBottom\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t},\n\n\n\tgetHitSpan: function(hit) {\n\t\tvar start = this.getCellDate(0, hit.col); // row=0\n\t\tvar time = this.computeSnapTime(hit.snap); // pass in the snap-index\n\t\tvar end;\n\n\t\tstart.time(time);\n\t\tend = start.clone().add(this.snapDuration);\n\n\t\treturn { start: start, end: end };\n\t},\n\n\n\tgetHitEl: function(hit) {\n\t\treturn this.colEls.eq(hit.col);\n\t},\n\n\n\t/* Dates\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\trangeUpdated: function() {\n\t\tthis.updateDayTable();\n\t},\n\n\n\t// Given a row number of the grid, representing a \"snap\", returns a time (Duration) from its start-of-day\n\tcomputeSnapTime: function(snapIndex) {\n\t\treturn moment.duration(this.minTime + this.snapDuration * snapIndex);\n\t},\n\n\n\t// Slices up the given span (unzoned start/end with other misc data) into an array of segments\n\tspanToSegs: function(span) {\n\t\tvar segs = this.sliceRangeByTimes(span);\n\t\tvar i;\n\n\t\tfor (i = 0; i < segs.length; i++) {\n\t\t\tif (this.isRTL) {\n\t\t\t\tsegs[i].col = this.daysPerRow - 1 - segs[i].dayIndex;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tsegs[i].col = segs[i].dayIndex;\n\t\t\t}\n\t\t}\n\n\t\treturn segs;\n\t},\n\n\n\tsliceRangeByTimes: function(range) {\n\t\tvar segs = [];\n\t\tvar seg;\n\t\tvar dayIndex;\n\t\tvar dayDate;\n\t\tvar dayRange;\n\n\t\tfor (dayIndex = 0; dayIndex < this.daysPerRow; dayIndex++) {\n\t\t\tdayDate = this.dayDates[dayIndex].clone(); // TODO: better API for this?\n\t\t\tdayRange = {\n\t\t\t\tstart: dayDate.clone().time(this.minTime),\n\t\t\t\tend: dayDate.clone().time(this.maxTime)\n\t\t\t};\n\t\t\tseg = intersectRanges(range, dayRange); // both will be ambig timezone\n\t\t\tif (seg) {\n\t\t\t\tseg.dayIndex = dayIndex;\n\t\t\t\tsegs.push(seg);\n\t\t\t}\n\t\t}\n\n\t\treturn segs;\n\t},\n\n\n\t/* Coordinates\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\tupdateSize: function(isResize) { // NOT a standard Grid method\n\t\tthis.slatCoordCache.build();\n\n\t\tif (isResize) {\n\t\t\tthis.updateSegVerticals(\n\t\t\t\t[].concat(this.fgSegs || [], this.bgSegs || [], this.businessSegs || [])\n\t\t\t);\n\t\t}\n\t},\n\n\n\tgetTotalSlatHeight: function() {\n\t\treturn this.slatContainerEl.outerHeight();\n\t},\n\n\n\t// Computes the top coordinate, relative to the bounds of the grid, of the given date.\n\t// A `startOfDayDate` must be given for avoiding ambiguity over how to treat midnight.\n\tcomputeDateTop: function(date, startOfDayDate) {\n\t\treturn this.computeTimeTop(\n\t\t\tmoment.duration(\n\t\t\t\tdate - startOfDayDate.clone().stripTime()\n\t\t\t)\n\t\t);\n\t},\n\n\n\t// Computes the top coordinate, relative to the bounds of the grid, of the given time (a Duration).\n\tcomputeTimeTop: function(time) {\n\t\tvar len = this.slatEls.length;\n\t\tvar slatCoverage = (time - this.minTime) / this.slotDuration; // floating-point value of # of slots covered\n\t\tvar slatIndex;\n\t\tvar slatRemainder;\n\n\t\t// compute a floating-point number for how many slats should be progressed through.\n\t\t// from 0 to number of slats (inclusive)\n\t\t// constrained because minTime/maxTime might be customized.\n\t\tslatCoverage = Math.max(0, slatCoverage);\n\t\tslatCoverage = Math.min(len, slatCoverage);\n\n\t\t// an integer index of the furthest whole slat\n\t\t// from 0 to number slats (*exclusive*, so len-1)\n\t\tslatIndex = Math.floor(slatCoverage);\n\t\tslatIndex = Math.min(slatIndex, len - 1);\n\n\t\t// how much further through the slatIndex slat (from 0.0-1.0) must be covered in addition.\n\t\t// could be 1.0 if slatCoverage is covering *all* the slots\n\t\tslatRemainder = slatCoverage - slatIndex;\n\n\t\treturn this.slatCoordCache.getTopPosition(slatIndex) +\n\t\t\tthis.slatCoordCache.getHeight(slatIndex) * slatRemainder;\n\t},\n\n\n\n\t/* Event Drag Visualization\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// Renders a visual indication of an event being dragged over the specified date(s).\n\t// A returned value of `true` signals that a mock \"helper\" event has been rendered.\n\trenderDrag: function(eventLocation, seg) {\n\n\t\tif (seg) { // if there is event information for this drag, render a helper event\n\n\t\t\t// returns mock event elements\n\t\t\t// signal that a helper has been rendered\n\t\t\treturn this.renderEventLocationHelper(eventLocation, seg);\n\t\t}\n\t\telse {\n\t\t\t// otherwise, just render a highlight\n\t\t\tthis.renderHighlight(this.eventToSpan(eventLocation));\n\t\t}\n\t},\n\n\n\t// Unrenders any visual indication of an event being dragged\n\tunrenderDrag: function() {\n\t\tthis.unrenderHelper();\n\t\tthis.unrenderHighlight();\n\t},\n\n\n\t/* Event Resize Visualization\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// Renders a visual indication of an event being resized\n\trenderEventResize: function(eventLocation, seg) {\n\t\treturn this.renderEventLocationHelper(eventLocation, seg); // returns mock event elements\n\t},\n\n\n\t// Unrenders any visual indication of an event being resized\n\tunrenderEventResize: function() {\n\t\tthis.unrenderHelper();\n\t},\n\n\n\t/* Event Helper\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// Renders a mock \"helper\" event. `sourceSeg` is the original segment object and might be null (an external drag)\n\trenderHelper: function(event, sourceSeg) {\n\t\treturn this.renderHelperSegs(this.eventToSegs(event), sourceSeg); // returns mock event elements\n\t},\n\n\n\t// Unrenders any mock helper event\n\tunrenderHelper: function() {\n\t\tthis.unrenderHelperSegs();\n\t},\n\n\n\t/* Business Hours\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\trenderBusinessHours: function() {\n\t\tthis.renderBusinessSegs(\n\t\t\tthis.buildBusinessHourSegs()\n\t\t);\n\t},\n\n\n\tunrenderBusinessHours: function() {\n\t\tthis.unrenderBusinessSegs();\n\t},\n\n\n\t/* Now Indicator\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\tgetNowIndicatorUnit: function() {\n\t\treturn 'minute'; // will refresh on the minute\n\t},\n\n\n\trenderNowIndicator: function(date) {\n\t\t// seg system might be overkill, but it handles scenario where line needs to be rendered\n\t\t// more than once because of columns with the same date (resources columns for example)\n\t\tvar segs = this.spanToSegs({ start: date, end: date });\n\t\tvar top = this.computeDateTop(date, date);\n\t\tvar nodes = [];\n\t\tvar i;\n\n\t\t// render lines within the columns\n\t\tfor (i = 0; i < segs.length; i++) {\n\t\t\tnodes.push($('
')\n\t\t\t\t.css('top', top)\n\t\t\t\t.appendTo(this.colContainerEls.eq(segs[i].col))[0]);\n\t\t}\n\n\t\t// render an arrow over the axis\n\t\tif (segs.length > 0) { // is the current time in view?\n\t\t\tnodes.push($('
')\n\t\t\t\t.css('top', top)\n\t\t\t\t.appendTo(this.el.find('.fc-content-skeleton'))[0]);\n\t\t}\n\n\t\tthis.nowIndicatorEls = $(nodes);\n\t},\n\n\n\tunrenderNowIndicator: function() {\n\t\tif (this.nowIndicatorEls) {\n\t\t\tthis.nowIndicatorEls.remove();\n\t\t\tthis.nowIndicatorEls = null;\n\t\t}\n\t},\n\n\n\t/* Selection\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// Renders a visual indication of a selection. Overrides the default, which was to simply render a highlight.\n\trenderSelection: function(span) {\n\t\tif (this.view.opt('selectHelper')) { // this setting signals that a mock helper event should be rendered\n\n\t\t\t// normally acceps an eventLocation, span has a start/end, which is good enough\n\t\t\tthis.renderEventLocationHelper(span);\n\t\t}\n\t\telse {\n\t\t\tthis.renderHighlight(span);\n\t\t}\n\t},\n\n\n\t// Unrenders any visual indication of a selection\n\tunrenderSelection: function() {\n\t\tthis.unrenderHelper();\n\t\tthis.unrenderHighlight();\n\t},\n\n\n\t/* Highlight\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\trenderHighlight: function(span) {\n\t\tthis.renderHighlightSegs(this.spanToSegs(span));\n\t},\n\n\n\tunrenderHighlight: function() {\n\t\tthis.unrenderHighlightSegs();\n\t}\n\n});\n\n;;\n\n/* Methods for rendering SEGMENTS, pieces of content that live on the view\n ( this file is no longer just for events )\n----------------------------------------------------------------------------------------------------------------------*/\n\nTimeGrid.mixin({\n\n\tcolContainerEls: null, // containers for each column\n\n\t// inner-containers for each column where different types of segs live\n\tfgContainerEls: null,\n\tbgContainerEls: null,\n\thelperContainerEls: null,\n\thighlightContainerEls: null,\n\tbusinessContainerEls: null,\n\n\t// arrays of different types of displayed segments\n\tfgSegs: null,\n\tbgSegs: null,\n\thelperSegs: null,\n\thighlightSegs: null,\n\tbusinessSegs: null,\n\n\n\t// Renders the DOM that the view's content will live in\n\trenderContentSkeleton: function() {\n\t\tvar cellHtml = '';\n\t\tvar i;\n\t\tvar skeletonEl;\n\n\t\tfor (i = 0; i < this.colCnt; i++) {\n\t\t\tcellHtml +=\n\t\t\t\t'' +\n\t\t\t\t\t'
' +\n\t\t\t\t\t\t'
' +\n\t\t\t\t\t\t'
' +\n\t\t\t\t\t\t'
' +\n\t\t\t\t\t\t'
' +\n\t\t\t\t\t\t'
' +\n\t\t\t\t\t'
' +\n\t\t\t\t'';\n\t\t}\n\n\t\tskeletonEl = $(\n\t\t\t'
' +\n\t\t\t\t'' +\n\t\t\t\t\t'' + cellHtml + '' +\n\t\t\t\t'
' +\n\t\t\t'
'\n\t\t);\n\n\t\tthis.colContainerEls = skeletonEl.find('.fc-content-col');\n\t\tthis.helperContainerEls = skeletonEl.find('.fc-helper-container');\n\t\tthis.fgContainerEls = skeletonEl.find('.fc-event-container:not(.fc-helper-container)');\n\t\tthis.bgContainerEls = skeletonEl.find('.fc-bgevent-container');\n\t\tthis.highlightContainerEls = skeletonEl.find('.fc-highlight-container');\n\t\tthis.businessContainerEls = skeletonEl.find('.fc-business-container');\n\n\t\tthis.bookendCells(skeletonEl.find('tr')); // TODO: do this on string level\n\t\tthis.el.append(skeletonEl);\n\t},\n\n\n\t/* Foreground Events\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\trenderFgSegs: function(segs) {\n\t\tsegs = this.renderFgSegsIntoContainers(segs, this.fgContainerEls);\n\t\tthis.fgSegs = segs;\n\t\treturn segs; // needed for Grid::renderEvents\n\t},\n\n\n\tunrenderFgSegs: function() {\n\t\tthis.unrenderNamedSegs('fgSegs');\n\t},\n\n\n\t/* Foreground Helper Events\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\trenderHelperSegs: function(segs, sourceSeg) {\n\t\tvar helperEls = [];\n\t\tvar i, seg;\n\t\tvar sourceEl;\n\n\t\tsegs = this.renderFgSegsIntoContainers(segs, this.helperContainerEls);\n\n\t\t// Try to make the segment that is in the same row as sourceSeg look the same\n\t\tfor (i = 0; i < segs.length; i++) {\n\t\t\tseg = segs[i];\n\t\t\tif (sourceSeg && sourceSeg.col === seg.col) {\n\t\t\t\tsourceEl = sourceSeg.el;\n\t\t\t\tseg.el.css({\n\t\t\t\t\tleft: sourceEl.css('left'),\n\t\t\t\t\tright: sourceEl.css('right'),\n\t\t\t\t\t'margin-left': sourceEl.css('margin-left'),\n\t\t\t\t\t'margin-right': sourceEl.css('margin-right')\n\t\t\t\t});\n\t\t\t}\n\t\t\thelperEls.push(seg.el[0]);\n\t\t}\n\n\t\tthis.helperSegs = segs;\n\n\t\treturn $(helperEls); // must return rendered helpers\n\t},\n\n\n\tunrenderHelperSegs: function() {\n\t\tthis.unrenderNamedSegs('helperSegs');\n\t},\n\n\n\t/* Background Events\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\trenderBgSegs: function(segs) {\n\t\tsegs = this.renderFillSegEls('bgEvent', segs); // TODO: old fill system\n\t\tthis.updateSegVerticals(segs);\n\t\tthis.attachSegsByCol(this.groupSegsByCol(segs), this.bgContainerEls);\n\t\tthis.bgSegs = segs;\n\t\treturn segs; // needed for Grid::renderEvents\n\t},\n\n\n\tunrenderBgSegs: function() {\n\t\tthis.unrenderNamedSegs('bgSegs');\n\t},\n\n\n\t/* Highlight\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\trenderHighlightSegs: function(segs) {\n\t\tsegs = this.renderFillSegEls('highlight', segs); // TODO: old fill system\n\t\tthis.updateSegVerticals(segs);\n\t\tthis.attachSegsByCol(this.groupSegsByCol(segs), this.highlightContainerEls);\n\t\tthis.highlightSegs = segs;\n\t},\n\n\n\tunrenderHighlightSegs: function() {\n\t\tthis.unrenderNamedSegs('highlightSegs');\n\t},\n\n\n\t/* Business Hours\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\trenderBusinessSegs: function(segs) {\n\t\tsegs = this.renderFillSegEls('businessHours', segs); // TODO: old fill system\n\t\tthis.updateSegVerticals(segs);\n\t\tthis.attachSegsByCol(this.groupSegsByCol(segs), this.businessContainerEls);\n\t\tthis.businessSegs = segs;\n\t},\n\n\n\tunrenderBusinessSegs: function() {\n\t\tthis.unrenderNamedSegs('businessSegs');\n\t},\n\n\n\t/* Seg Rendering Utils\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// Given a flat array of segments, return an array of sub-arrays, grouped by each segment's col\n\tgroupSegsByCol: function(segs) {\n\t\tvar segsByCol = [];\n\t\tvar i;\n\n\t\tfor (i = 0; i < this.colCnt; i++) {\n\t\t\tsegsByCol.push([]);\n\t\t}\n\n\t\tfor (i = 0; i < segs.length; i++) {\n\t\t\tsegsByCol[segs[i].col].push(segs[i]);\n\t\t}\n\n\t\treturn segsByCol;\n\t},\n\n\n\t// Given segments grouped by column, insert the segments' elements into a parallel array of container\n\t// elements, each living within a column.\n\tattachSegsByCol: function(segsByCol, containerEls) {\n\t\tvar col;\n\t\tvar segs;\n\t\tvar i;\n\n\t\tfor (col = 0; col < this.colCnt; col++) { // iterate each column grouping\n\t\t\tsegs = segsByCol[col];\n\n\t\t\tfor (i = 0; i < segs.length; i++) {\n\t\t\t\tcontainerEls.eq(col).append(segs[i].el);\n\t\t\t}\n\t\t}\n\t},\n\n\n\t// Given the name of a property of `this` object, assumed to be an array of segments,\n\t// loops through each segment and removes from DOM. Will null-out the property afterwards.\n\tunrenderNamedSegs: function(propName) {\n\t\tvar segs = this[propName];\n\t\tvar i;\n\n\t\tif (segs) {\n\t\t\tfor (i = 0; i < segs.length; i++) {\n\t\t\t\tsegs[i].el.remove();\n\t\t\t}\n\t\t\tthis[propName] = null;\n\t\t}\n\t},\n\n\n\n\t/* Foreground Event Rendering Utils\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// Given an array of foreground segments, render a DOM element for each, computes position,\n\t// and attaches to the column inner-container elements.\n\trenderFgSegsIntoContainers: function(segs, containerEls) {\n\t\tvar segsByCol;\n\t\tvar col;\n\n\t\tsegs = this.renderFgSegEls(segs); // will call fgSegHtml\n\t\tsegsByCol = this.groupSegsByCol(segs);\n\n\t\tfor (col = 0; col < this.colCnt; col++) {\n\t\t\tthis.updateFgSegCoords(segsByCol[col]);\n\t\t}\n\n\t\tthis.attachSegsByCol(segsByCol, containerEls);\n\n\t\treturn segs;\n\t},\n\n\n\t// Renders the HTML for a single event segment's default rendering\n\tfgSegHtml: function(seg, disableResizing) {\n\t\tvar view = this.view;\n\t\tvar event = seg.event;\n\t\tvar isDraggable = view.isEventDraggable(event);\n\t\tvar isResizableFromStart = !disableResizing && seg.isStart && view.isEventResizableFromStart(event);\n\t\tvar isResizableFromEnd = !disableResizing && seg.isEnd && view.isEventResizableFromEnd(event);\n\t\tvar classes = this.getSegClasses(seg, isDraggable, isResizableFromStart || isResizableFromEnd);\n\t\tvar skinCss = cssToStr(this.getSegSkinCss(seg));\n\t\tvar timeText;\n\t\tvar fullTimeText; // more verbose time text. for the print stylesheet\n\t\tvar startTimeText; // just the start time text\n\n\t\tclasses.unshift('fc-time-grid-event', 'fc-v-event');\n\n\t\tif (view.isMultiDayEvent(event)) { // if the event appears to span more than one day...\n\t\t\t// Don't display time text on segments that run entirely through a day.\n\t\t\t// That would appear as midnight-midnight and would look dumb.\n\t\t\t// Otherwise, display the time text for the *segment's* times (like 6pm-midnight or midnight-10am)\n\t\t\tif (seg.isStart || seg.isEnd) {\n\t\t\t\ttimeText = this.getEventTimeText(seg);\n\t\t\t\tfullTimeText = this.getEventTimeText(seg, 'LT');\n\t\t\t\tstartTimeText = this.getEventTimeText(seg, null, false); // displayEnd=false\n\t\t\t}\n\t\t} else {\n\t\t\t// Display the normal time text for the *event's* times\n\t\t\ttimeText = this.getEventTimeText(event);\n\t\t\tfullTimeText = this.getEventTimeText(event, 'LT');\n\t\t\tstartTimeText = this.getEventTimeText(event, null, false); // displayEnd=false\n\t\t}\n\n\t\treturn '
' +\n\t\t\t\t'
' +\n\t\t\t\t\t(timeText ?\n\t\t\t\t\t\t'
' +\n\t\t\t\t\t\t\t'' + htmlEscape(timeText) + '' +\n\t\t\t\t\t\t'
' :\n\t\t\t\t\t\t''\n\t\t\t\t\t\t) +\n\t\t\t\t\t(event.title ?\n\t\t\t\t\t\t'
' +\n\t\t\t\t\t\t\thtmlEscape(event.title) +\n\t\t\t\t\t\t'
' :\n\t\t\t\t\t\t''\n\t\t\t\t\t\t) +\n\t\t\t\t'
' +\n\t\t\t\t'
' +\n\t\t\t\t/* TODO: write CSS for this\n\t\t\t\t(isResizableFromStart ?\n\t\t\t\t\t'
' :\n\t\t\t\t\t''\n\t\t\t\t\t) +\n\t\t\t\t*/\n\t\t\t\t(isResizableFromEnd ?\n\t\t\t\t\t'
' :\n\t\t\t\t\t''\n\t\t\t\t\t) +\n\t\t\t'';\n\t},\n\n\n\t/* Seg Position Utils\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// Refreshes the CSS top/bottom coordinates for each segment element.\n\t// Works when called after initial render, after a window resize/zoom for example.\n\tupdateSegVerticals: function(segs) {\n\t\tthis.computeSegVerticals(segs);\n\t\tthis.assignSegVerticals(segs);\n\t},\n\n\n\t// For each segment in an array, computes and assigns its top and bottom properties\n\tcomputeSegVerticals: function(segs) {\n\t\tvar i, seg;\n\n\t\tfor (i = 0; i < segs.length; i++) {\n\t\t\tseg = segs[i];\n\t\t\tseg.top = this.computeDateTop(seg.start, seg.start);\n\t\t\tseg.bottom = this.computeDateTop(seg.end, seg.start);\n\t\t}\n\t},\n\n\n\t// Given segments that already have their top/bottom properties computed, applies those values to\n\t// the segments' elements.\n\tassignSegVerticals: function(segs) {\n\t\tvar i, seg;\n\n\t\tfor (i = 0; i < segs.length; i++) {\n\t\t\tseg = segs[i];\n\t\t\tseg.el.css(this.generateSegVerticalCss(seg));\n\t\t}\n\t},\n\n\n\t// Generates an object with CSS properties for the top/bottom coordinates of a segment element\n\tgenerateSegVerticalCss: function(seg) {\n\t\treturn {\n\t\t\ttop: seg.top,\n\t\t\tbottom: -seg.bottom // flipped because needs to be space beyond bottom edge of event container\n\t\t};\n\t},\n\n\n\t/* Foreground Event Positioning Utils\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// Given segments that are assumed to all live in the *same column*,\n\t// compute their verical/horizontal coordinates and assign to their elements.\n\tupdateFgSegCoords: function(segs) {\n\t\tthis.computeSegVerticals(segs); // horizontals relies on this\n\t\tthis.computeFgSegHorizontals(segs); // compute horizontal coordinates, z-index's, and reorder the array\n\t\tthis.assignSegVerticals(segs);\n\t\tthis.assignFgSegHorizontals(segs);\n\t},\n\n\n\t// Given an array of segments that are all in the same column, sets the backwardCoord and forwardCoord on each.\n\t// NOTE: Also reorders the given array by date!\n\tcomputeFgSegHorizontals: function(segs) {\n\t\tvar levels;\n\t\tvar level0;\n\t\tvar i;\n\n\t\tthis.sortEventSegs(segs); // order by certain criteria\n\t\tlevels = buildSlotSegLevels(segs);\n\t\tcomputeForwardSlotSegs(levels);\n\n\t\tif ((level0 = levels[0])) {\n\n\t\t\tfor (i = 0; i < level0.length; i++) {\n\t\t\t\tcomputeSlotSegPressures(level0[i]);\n\t\t\t}\n\n\t\t\tfor (i = 0; i < level0.length; i++) {\n\t\t\t\tthis.computeFgSegForwardBack(level0[i], 0, 0);\n\t\t\t}\n\t\t}\n\t},\n\n\n\t// Calculate seg.forwardCoord and seg.backwardCoord for the segment, where both values range\n\t// from 0 to 1. If the calendar is left-to-right, the seg.backwardCoord maps to \"left\" and\n\t// seg.forwardCoord maps to \"right\" (via percentage). Vice-versa if the calendar is right-to-left.\n\t//\n\t// The segment might be part of a \"series\", which means consecutive segments with the same pressure\n\t// who's width is unknown until an edge has been hit. `seriesBackwardPressure` is the number of\n\t// segments behind this one in the current series, and `seriesBackwardCoord` is the starting\n\t// coordinate of the first segment in the series.\n\tcomputeFgSegForwardBack: function(seg, seriesBackwardPressure, seriesBackwardCoord) {\n\t\tvar forwardSegs = seg.forwardSegs;\n\t\tvar i;\n\n\t\tif (seg.forwardCoord === undefined) { // not already computed\n\n\t\t\tif (!forwardSegs.length) {\n\n\t\t\t\t// if there are no forward segments, this segment should butt up against the edge\n\t\t\t\tseg.forwardCoord = 1;\n\t\t\t}\n\t\t\telse {\n\n\t\t\t\t// sort highest pressure first\n\t\t\t\tthis.sortForwardSegs(forwardSegs);\n\n\t\t\t\t// this segment's forwardCoord will be calculated from the backwardCoord of the\n\t\t\t\t// highest-pressure forward segment.\n\t\t\t\tthis.computeFgSegForwardBack(forwardSegs[0], seriesBackwardPressure + 1, seriesBackwardCoord);\n\t\t\t\tseg.forwardCoord = forwardSegs[0].backwardCoord;\n\t\t\t}\n\n\t\t\t// calculate the backwardCoord from the forwardCoord. consider the series\n\t\t\tseg.backwardCoord = seg.forwardCoord -\n\t\t\t\t(seg.forwardCoord - seriesBackwardCoord) / // available width for series\n\t\t\t\t(seriesBackwardPressure + 1); // # of segments in the series\n\n\t\t\t// use this segment's coordinates to computed the coordinates of the less-pressurized\n\t\t\t// forward segments\n\t\t\tfor (i=0; i seg2.top && seg1.top < seg2.bottom;\n}\n\n;;\n\n/* An abstract class from which other views inherit from\n----------------------------------------------------------------------------------------------------------------------*/\n\nvar View = FC.View = Class.extend(EmitterMixin, ListenerMixin, {\n\n\ttype: null, // subclass' view name (string)\n\tname: null, // deprecated. use `type` instead\n\ttitle: null, // the text that will be displayed in the header's title\n\n\tcalendar: null, // owner Calendar object\n\toptions: null, // hash containing all options. already merged with view-specific-options\n\tel: null, // the view's containing element. set by Calendar\n\n\tdisplaying: null, // a promise representing the state of rendering. null if no render requested\n\tisSkeletonRendered: false,\n\tisEventsRendered: false,\n\n\t// range the view is actually displaying (moments)\n\tstart: null,\n\tend: null, // exclusive\n\n\t// range the view is formally responsible for (moments)\n\t// may be different from start/end. for example, a month view might have 1st-31st, excluding padded dates\n\tintervalStart: null,\n\tintervalEnd: null, // exclusive\n\tintervalDuration: null,\n\tintervalUnit: null, // name of largest unit being displayed, like \"month\" or \"week\"\n\n\tisRTL: false,\n\tisSelected: false, // boolean whether a range of time is user-selected or not\n\tselectedEvent: null,\n\n\teventOrderSpecs: null, // criteria for ordering events when they have same date/time\n\n\t// classNames styled by jqui themes\n\twidgetHeaderClass: null,\n\twidgetContentClass: null,\n\thighlightStateClass: null,\n\n\t// for date utils, computed from options\n\tnextDayThreshold: null,\n\tisHiddenDayHash: null,\n\n\t// now indicator\n\tisNowIndicatorRendered: null,\n\tinitialNowDate: null, // result first getNow call\n\tinitialNowQueriedMs: null, // ms time the getNow was called\n\tnowIndicatorTimeoutID: null, // for refresh timing of now indicator\n\tnowIndicatorIntervalID: null, // \"\n\n\n\tconstructor: function(calendar, type, options, intervalDuration) {\n\n\t\tthis.calendar = calendar;\n\t\tthis.type = this.name = type; // .name is deprecated\n\t\tthis.options = options;\n\t\tthis.intervalDuration = intervalDuration || moment.duration(1, 'day');\n\n\t\tthis.nextDayThreshold = moment.duration(this.opt('nextDayThreshold'));\n\t\tthis.initThemingProps();\n\t\tthis.initHiddenDays();\n\t\tthis.isRTL = this.opt('isRTL');\n\n\t\tthis.eventOrderSpecs = parseFieldSpecs(this.opt('eventOrder'));\n\n\t\tthis.initialize();\n\t},\n\n\n\t// A good place for subclasses to initialize member variables\n\tinitialize: function() {\n\t\t// subclasses can implement\n\t},\n\n\n\t// Retrieves an option with the given name\n\topt: function(name) {\n\t\treturn this.options[name];\n\t},\n\n\n\t// Triggers handlers that are view-related. Modifies args before passing to calendar.\n\ttrigger: function(name, thisObj) { // arguments beyond thisObj are passed along\n\t\tvar calendar = this.calendar;\n\n\t\treturn calendar.trigger.apply(\n\t\t\tcalendar,\n\t\t\t[name, thisObj || this].concat(\n\t\t\t\tArray.prototype.slice.call(arguments, 2), // arguments beyond thisObj\n\t\t\t\t[ this ] // always make the last argument a reference to the view. TODO: deprecate\n\t\t\t)\n\t\t);\n\t},\n\n\n\t/* Dates\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// Updates all internal dates to center around the given current unzoned date.\n\tsetDate: function(date) {\n\t\tthis.setRange(this.computeRange(date));\n\t},\n\n\n\t// Updates all internal dates for displaying the given unzoned range.\n\tsetRange: function(range) {\n\t\t$.extend(this, range); // assigns every property to this object's member variables\n\t\tthis.updateTitle();\n\t},\n\n\n\t// Given a single current unzoned date, produce information about what range to display.\n\t// Subclasses can override. Must return all properties.\n\tcomputeRange: function(date) {\n\t\tvar intervalUnit = computeIntervalUnit(this.intervalDuration);\n\t\tvar intervalStart = date.clone().startOf(intervalUnit);\n\t\tvar intervalEnd = intervalStart.clone().add(this.intervalDuration);\n\t\tvar start, end;\n\n\t\t// normalize the range's time-ambiguity\n\t\tif (/year|month|week|day/.test(intervalUnit)) { // whole-days?\n\t\t\tintervalStart.stripTime();\n\t\t\tintervalEnd.stripTime();\n\t\t}\n\t\telse { // needs to have a time?\n\t\t\tif (!intervalStart.hasTime()) {\n\t\t\t\tintervalStart = this.calendar.time(0); // give 00:00 time\n\t\t\t}\n\t\t\tif (!intervalEnd.hasTime()) {\n\t\t\t\tintervalEnd = this.calendar.time(0); // give 00:00 time\n\t\t\t}\n\t\t}\n\n\t\tstart = intervalStart.clone();\n\t\tstart = this.skipHiddenDays(start);\n\t\tend = intervalEnd.clone();\n\t\tend = this.skipHiddenDays(end, -1, true); // exclusively move backwards\n\n\t\treturn {\n\t\t\tintervalUnit: intervalUnit,\n\t\t\tintervalStart: intervalStart,\n\t\t\tintervalEnd: intervalEnd,\n\t\t\tstart: start,\n\t\t\tend: end\n\t\t};\n\t},\n\n\n\t// Computes the new date when the user hits the prev button, given the current date\n\tcomputePrevDate: function(date) {\n\t\treturn this.massageCurrentDate(\n\t\t\tdate.clone().startOf(this.intervalUnit).subtract(this.intervalDuration), -1\n\t\t);\n\t},\n\n\n\t// Computes the new date when the user hits the next button, given the current date\n\tcomputeNextDate: function(date) {\n\t\treturn this.massageCurrentDate(\n\t\t\tdate.clone().startOf(this.intervalUnit).add(this.intervalDuration)\n\t\t);\n\t},\n\n\n\t// Given an arbitrarily calculated current date of the calendar, returns a date that is ensured to be completely\n\t// visible. `direction` is optional and indicates which direction the current date was being\n\t// incremented or decremented (1 or -1).\n\tmassageCurrentDate: function(date, direction) {\n\t\tif (this.intervalDuration.as('days') <= 1) { // if the view displays a single day or smaller\n\t\t\tif (this.isHiddenDay(date)) {\n\t\t\t\tdate = this.skipHiddenDays(date, direction);\n\t\t\t\tdate.startOf('day');\n\t\t\t}\n\t\t}\n\n\t\treturn date;\n\t},\n\n\n\t/* Title and Date Formatting\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// Sets the view's title property to the most updated computed value\n\tupdateTitle: function() {\n\t\tthis.title = this.computeTitle();\n\t},\n\n\n\t// Computes what the title at the top of the calendar should be for this view\n\tcomputeTitle: function() {\n\t\treturn this.formatRange(\n\t\t\t{\n\t\t\t\t// in case intervalStart/End has a time, make sure timezone is correct\n\t\t\t\tstart: this.calendar.applyTimezone(this.intervalStart),\n\t\t\t\tend: this.calendar.applyTimezone(this.intervalEnd)\n\t\t\t},\n\t\t\tthis.opt('titleFormat') || this.computeTitleFormat(),\n\t\t\tthis.opt('titleRangeSeparator')\n\t\t);\n\t},\n\n\n\t// Generates the format string that should be used to generate the title for the current date range.\n\t// Attempts to compute the most appropriate format if not explicitly specified with `titleFormat`.\n\tcomputeTitleFormat: function() {\n\t\tif (this.intervalUnit == 'year') {\n\t\t\treturn 'YYYY';\n\t\t}\n\t\telse if (this.intervalUnit == 'month') {\n\t\t\treturn this.opt('monthYearFormat'); // like \"September 2014\"\n\t\t}\n\t\telse if (this.intervalDuration.as('days') > 1) {\n\t\t\treturn 'll'; // multi-day range. shorter, like \"Sep 9 - 10 2014\"\n\t\t}\n\t\telse {\n\t\t\treturn 'LL'; // one day. longer, like \"September 9 2014\"\n\t\t}\n\t},\n\n\n\t// Utility for formatting a range. Accepts a range object, formatting string, and optional separator.\n\t// Displays all-day ranges naturally, with an inclusive end. Takes the current isRTL into account.\n\t// The timezones of the dates within `range` will be respected.\n\tformatRange: function(range, formatStr, separator) {\n\t\tvar end = range.end;\n\n\t\tif (!end.hasTime()) { // all-day?\n\t\t\tend = end.clone().subtract(1); // convert to inclusive. last ms of previous day\n\t\t}\n\n\t\treturn formatRange(range.start, end, formatStr, separator, this.opt('isRTL'));\n\t},\n\n\n\t/* Rendering\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// Sets the container element that the view should render inside of.\n\t// Does other DOM-related initializations.\n\tsetElement: function(el) {\n\t\tthis.el = el;\n\t\tthis.bindGlobalHandlers();\n\t},\n\n\n\t// Removes the view's container element from the DOM, clearing any content beforehand.\n\t// Undoes any other DOM-related attachments.\n\tremoveElement: function() {\n\t\tthis.clear(); // clears all content\n\n\t\t// clean up the skeleton\n\t\tif (this.isSkeletonRendered) {\n\t\t\tthis.unrenderSkeleton();\n\t\t\tthis.isSkeletonRendered = false;\n\t\t}\n\n\t\tthis.unbindGlobalHandlers();\n\n\t\tthis.el.remove();\n\n\t\t// NOTE: don't null-out this.el in case the View was destroyed within an API callback.\n\t\t// We don't null-out the View's other jQuery element references upon destroy,\n\t\t// so we shouldn't kill this.el either.\n\t},\n\n\n\t// Does everything necessary to display the view centered around the given unzoned date.\n\t// Does every type of rendering EXCEPT rendering events.\n\t// Is asychronous and returns a promise.\n\tdisplay: function(date, explicitScrollState) {\n\t\tvar _this = this;\n\t\tvar prevScrollState = null;\n\n\t\tif (explicitScrollState != null && this.displaying) { // don't need prevScrollState if explicitScrollState\n\t\t\tprevScrollState = this.queryScroll();\n\t\t}\n\n\t\tthis.calendar.freezeContentHeight();\n\n\t\treturn syncThen(this.clear(), function() { // clear the content first\n\t\t\treturn (\n\t\t\t\t_this.displaying =\n\t\t\t\t\tsyncThen(_this.displayView(date), function() { // displayView might return a promise\n\n\t\t\t\t\t\t// caller of display() wants a specific scroll state?\n\t\t\t\t\t\tif (explicitScrollState != null) {\n\t\t\t\t\t\t\t// we make an assumption that this is NOT the initial render,\n\t\t\t\t\t\t\t// and thus don't need forceScroll (is inconveniently asynchronous)\n\t\t\t\t\t\t\t_this.setScroll(explicitScrollState);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t_this.forceScroll(_this.computeInitialScroll(prevScrollState));\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t_this.calendar.unfreezeContentHeight();\n\t\t\t\t\t\t_this.triggerRender();\n\t\t\t\t\t})\n\t\t\t);\n\t\t});\n\t},\n\n\n\t// Does everything necessary to clear the content of the view.\n\t// Clears dates and events. Does not clear the skeleton.\n\t// Is asychronous and returns a promise.\n\tclear: function() {\n\t\tvar _this = this;\n\t\tvar displaying = this.displaying;\n\n\t\tif (displaying) { // previously displayed, or in the process of being displayed?\n\t\t\treturn syncThen(displaying, function() { // wait for the display to finish\n\t\t\t\t_this.displaying = null;\n\t\t\t\t_this.clearEvents();\n\t\t\t\treturn _this.clearView(); // might return a promise. chain it\n\t\t\t});\n\t\t}\n\t\telse {\n\t\t\treturn $.when(); // an immediately-resolved promise\n\t\t}\n\t},\n\n\n\t// Displays the view's non-event content, such as date-related content or anything required by events.\n\t// Renders the view's non-content skeleton if necessary.\n\t// Can be asynchronous and return a promise.\n\tdisplayView: function(date) {\n\t\tif (!this.isSkeletonRendered) {\n\t\t\tthis.renderSkeleton();\n\t\t\tthis.isSkeletonRendered = true;\n\t\t}\n\t\tif (date) {\n\t\t\tthis.setDate(date);\n\t\t}\n\t\tif (this.render) {\n\t\t\tthis.render(); // TODO: deprecate\n\t\t}\n\t\tthis.renderDates();\n\t\tthis.updateSize();\n\t\tthis.renderBusinessHours(); // might need coordinates, so should go after updateSize()\n\t\tthis.startNowIndicator();\n\t},\n\n\n\t// Unrenders the view content that was rendered in displayView.\n\t// Can be asynchronous and return a promise.\n\tclearView: function() {\n\t\tthis.unselect();\n\t\tthis.stopNowIndicator();\n\t\tthis.triggerUnrender();\n\t\tthis.unrenderBusinessHours();\n\t\tthis.unrenderDates();\n\t\tif (this.destroy) {\n\t\t\tthis.destroy(); // TODO: deprecate\n\t\t}\n\t},\n\n\n\t// Renders the basic structure of the view before any content is rendered\n\trenderSkeleton: function() {\n\t\t// subclasses should implement\n\t},\n\n\n\t// Unrenders the basic structure of the view\n\tunrenderSkeleton: function() {\n\t\t// subclasses should implement\n\t},\n\n\n\t// Renders the view's date-related content.\n\t// Assumes setRange has already been called and the skeleton has already been rendered.\n\trenderDates: function() {\n\t\t// subclasses should implement\n\t},\n\n\n\t// Unrenders the view's date-related content\n\tunrenderDates: function() {\n\t\t// subclasses should override\n\t},\n\n\n\t// Signals that the view's content has been rendered\n\ttriggerRender: function() {\n\t\tthis.trigger('viewRender', this, this, this.el);\n\t},\n\n\n\t// Signals that the view's content is about to be unrendered\n\ttriggerUnrender: function() {\n\t\tthis.trigger('viewDestroy', this, this, this.el);\n\t},\n\n\n\t// Binds DOM handlers to elements that reside outside the view container, such as the document\n\tbindGlobalHandlers: function() {\n\t\tthis.listenTo($(document), 'mousedown', this.handleDocumentMousedown);\n\t\tthis.listenTo($(document), 'touchstart', this.processUnselect);\n\t},\n\n\n\t// Unbinds DOM handlers from elements that reside outside the view container\n\tunbindGlobalHandlers: function() {\n\t\tthis.stopListeningTo($(document));\n\t},\n\n\n\t// Initializes internal variables related to theming\n\tinitThemingProps: function() {\n\t\tvar tm = this.opt('theme') ? 'ui' : 'fc';\n\n\t\tthis.widgetHeaderClass = tm + '-widget-header';\n\t\tthis.widgetContentClass = tm + '-widget-content';\n\t\tthis.highlightStateClass = tm + '-state-highlight';\n\t},\n\n\n\t/* Business Hours\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// Renders business-hours onto the view. Assumes updateSize has already been called.\n\trenderBusinessHours: function() {\n\t\t// subclasses should implement\n\t},\n\n\n\t// Unrenders previously-rendered business-hours\n\tunrenderBusinessHours: function() {\n\t\t// subclasses should implement\n\t},\n\n\n\t/* Now Indicator\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// Immediately render the current time indicator and begins re-rendering it at an interval,\n\t// which is defined by this.getNowIndicatorUnit().\n\t// TODO: somehow do this for the current whole day's background too\n\tstartNowIndicator: function() {\n\t\tvar _this = this;\n\t\tvar unit;\n\t\tvar update;\n\t\tvar delay; // ms wait value\n\n\t\tif (this.opt('nowIndicator')) {\n\t\t\tunit = this.getNowIndicatorUnit();\n\t\t\tif (unit) {\n\t\t\t\tupdate = proxy(this, 'updateNowIndicator'); // bind to `this`\n\n\t\t\t\tthis.initialNowDate = this.calendar.getNow();\n\t\t\t\tthis.initialNowQueriedMs = +new Date();\n\t\t\t\tthis.renderNowIndicator(this.initialNowDate);\n\t\t\t\tthis.isNowIndicatorRendered = true;\n\n\t\t\t\t// wait until the beginning of the next interval\n\t\t\t\tdelay = this.initialNowDate.clone().startOf(unit).add(1, unit) - this.initialNowDate;\n\t\t\t\tthis.nowIndicatorTimeoutID = setTimeout(function() {\n\t\t\t\t\t_this.nowIndicatorTimeoutID = null;\n\t\t\t\t\tupdate();\n\t\t\t\t\tdelay = +moment.duration(1, unit);\n\t\t\t\t\tdelay = Math.max(100, delay); // prevent too frequent\n\t\t\t\t\t_this.nowIndicatorIntervalID = setInterval(update, delay); // update every interval\n\t\t\t\t}, delay);\n\t\t\t}\n\t\t}\n\t},\n\n\n\t// rerenders the now indicator, computing the new current time from the amount of time that has passed\n\t// since the initial getNow call.\n\tupdateNowIndicator: function() {\n\t\tif (this.isNowIndicatorRendered) {\n\t\t\tthis.unrenderNowIndicator();\n\t\t\tthis.renderNowIndicator(\n\t\t\t\tthis.initialNowDate.clone().add(new Date() - this.initialNowQueriedMs) // add ms\n\t\t\t);\n\t\t}\n\t},\n\n\n\t// Immediately unrenders the view's current time indicator and stops any re-rendering timers.\n\t// Won't cause side effects if indicator isn't rendered.\n\tstopNowIndicator: function() {\n\t\tif (this.isNowIndicatorRendered) {\n\n\t\t\tif (this.nowIndicatorTimeoutID) {\n\t\t\t\tclearTimeout(this.nowIndicatorTimeoutID);\n\t\t\t\tthis.nowIndicatorTimeoutID = null;\n\t\t\t}\n\t\t\tif (this.nowIndicatorIntervalID) {\n\t\t\t\tclearTimeout(this.nowIndicatorIntervalID);\n\t\t\t\tthis.nowIndicatorIntervalID = null;\n\t\t\t}\n\n\t\t\tthis.unrenderNowIndicator();\n\t\t\tthis.isNowIndicatorRendered = false;\n\t\t}\n\t},\n\n\n\t// Returns a string unit, like 'second' or 'minute' that defined how often the current time indicator\n\t// should be refreshed. If something falsy is returned, no time indicator is rendered at all.\n\tgetNowIndicatorUnit: function() {\n\t\t// subclasses should implement\n\t},\n\n\n\t// Renders a current time indicator at the given datetime\n\trenderNowIndicator: function(date) {\n\t\t// subclasses should implement\n\t},\n\n\n\t// Undoes the rendering actions from renderNowIndicator\n\tunrenderNowIndicator: function() {\n\t\t// subclasses should implement\n\t},\n\n\n\t/* Dimensions\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// Refreshes anything dependant upon sizing of the container element of the grid\n\tupdateSize: function(isResize) {\n\t\tvar scrollState;\n\n\t\tif (isResize) {\n\t\t\tscrollState = this.queryScroll();\n\t\t}\n\n\t\tthis.updateHeight(isResize);\n\t\tthis.updateWidth(isResize);\n\t\tthis.updateNowIndicator();\n\n\t\tif (isResize) {\n\t\t\tthis.setScroll(scrollState);\n\t\t}\n\t},\n\n\n\t// Refreshes the horizontal dimensions of the calendar\n\tupdateWidth: function(isResize) {\n\t\t// subclasses should implement\n\t},\n\n\n\t// Refreshes the vertical dimensions of the calendar\n\tupdateHeight: function(isResize) {\n\t\tvar calendar = this.calendar; // we poll the calendar for height information\n\n\t\tthis.setHeight(\n\t\t\tcalendar.getSuggestedViewHeight(),\n\t\t\tcalendar.isHeightAuto()\n\t\t);\n\t},\n\n\n\t// Updates the vertical dimensions of the calendar to the specified height.\n\t// if `isAuto` is set to true, height becomes merely a suggestion and the view should use its \"natural\" height.\n\tsetHeight: function(height, isAuto) {\n\t\t// subclasses should implement\n\t},\n\n\n\t/* Scroller\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// Computes the initial pre-configured scroll state prior to allowing the user to change it.\n\t// Given the scroll state from the previous rendering. If first time rendering, given null.\n\tcomputeInitialScroll: function(previousScrollState) {\n\t\treturn 0;\n\t},\n\n\n\t// Retrieves the view's current natural scroll state. Can return an arbitrary format.\n\tqueryScroll: function() {\n\t\t// subclasses must implement\n\t},\n\n\n\t// Sets the view's scroll state. Will accept the same format computeInitialScroll and queryScroll produce.\n\tsetScroll: function(scrollState) {\n\t\t// subclasses must implement\n\t},\n\n\n\t// Sets the scroll state, making sure to overcome any predefined scroll value the browser has in mind\n\tforceScroll: function(scrollState) {\n\t\tvar _this = this;\n\n\t\tthis.setScroll(scrollState);\n\t\tsetTimeout(function() {\n\t\t\t_this.setScroll(scrollState);\n\t\t}, 0);\n\t},\n\n\n\t/* Event Elements / Segments\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// Does everything necessary to display the given events onto the current view\n\tdisplayEvents: function(events) {\n\t\tvar scrollState = this.queryScroll();\n\n\t\tthis.clearEvents();\n\t\tthis.renderEvents(events);\n\t\tthis.isEventsRendered = true;\n\t\tthis.setScroll(scrollState);\n\t\tthis.triggerEventRender();\n\t},\n\n\n\t// Does everything necessary to clear the view's currently-rendered events\n\tclearEvents: function() {\n\t\tvar scrollState;\n\n\t\tif (this.isEventsRendered) {\n\n\t\t\t// TODO: optimize: if we know this is part of a displayEvents call, don't queryScroll/setScroll\n\t\t\tscrollState = this.queryScroll();\n\n\t\t\tthis.triggerEventUnrender();\n\t\t\tif (this.destroyEvents) {\n\t\t\t\tthis.destroyEvents(); // TODO: deprecate\n\t\t\t}\n\t\t\tthis.unrenderEvents();\n\t\t\tthis.setScroll(scrollState);\n\t\t\tthis.isEventsRendered = false;\n\t\t}\n\t},\n\n\n\t// Renders the events onto the view.\n\trenderEvents: function(events) {\n\t\t// subclasses should implement\n\t},\n\n\n\t// Removes event elements from the view.\n\tunrenderEvents: function() {\n\t\t// subclasses should implement\n\t},\n\n\n\t// Signals that all events have been rendered\n\ttriggerEventRender: function() {\n\t\tthis.renderedEventSegEach(function(seg) {\n\t\t\tthis.trigger('eventAfterRender', seg.event, seg.event, seg.el);\n\t\t});\n\t\tthis.trigger('eventAfterAllRender');\n\t},\n\n\n\t// Signals that all event elements are about to be removed\n\ttriggerEventUnrender: function() {\n\t\tthis.renderedEventSegEach(function(seg) {\n\t\t\tthis.trigger('eventDestroy', seg.event, seg.event, seg.el);\n\t\t});\n\t},\n\n\n\t// Given an event and the default element used for rendering, returns the element that should actually be used.\n\t// Basically runs events and elements through the eventRender hook.\n\tresolveEventEl: function(event, el) {\n\t\tvar custom = this.trigger('eventRender', event, event, el);\n\n\t\tif (custom === false) { // means don't render at all\n\t\t\tel = null;\n\t\t}\n\t\telse if (custom && custom !== true) {\n\t\t\tel = $(custom);\n\t\t}\n\n\t\treturn el;\n\t},\n\n\n\t// Hides all rendered event segments linked to the given event\n\tshowEvent: function(event) {\n\t\tthis.renderedEventSegEach(function(seg) {\n\t\t\tseg.el.css('visibility', '');\n\t\t}, event);\n\t},\n\n\n\t// Shows all rendered event segments linked to the given event\n\thideEvent: function(event) {\n\t\tthis.renderedEventSegEach(function(seg) {\n\t\t\tseg.el.css('visibility', 'hidden');\n\t\t}, event);\n\t},\n\n\n\t// Iterates through event segments that have been rendered (have an el). Goes through all by default.\n\t// If the optional `event` argument is specified, only iterates through segments linked to that event.\n\t// The `this` value of the callback function will be the view.\n\trenderedEventSegEach: function(func, event) {\n\t\tvar segs = this.getEventSegs();\n\t\tvar i;\n\n\t\tfor (i = 0; i < segs.length; i++) {\n\t\t\tif (!event || segs[i].event._id === event._id) {\n\t\t\t\tif (segs[i].el) {\n\t\t\t\t\tfunc.call(this, segs[i]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\n\t// Retrieves all the rendered segment objects for the view\n\tgetEventSegs: function() {\n\t\t// subclasses must implement\n\t\treturn [];\n\t},\n\n\n\t/* Event Drag-n-Drop\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// Computes if the given event is allowed to be dragged by the user\n\tisEventDraggable: function(event) {\n\t\tvar source = event.source || {};\n\n\t\treturn firstDefined(\n\t\t\tevent.startEditable,\n\t\t\tsource.startEditable,\n\t\t\tthis.opt('eventStartEditable'),\n\t\t\tevent.editable,\n\t\t\tsource.editable,\n\t\t\tthis.opt('editable')\n\t\t);\n\t},\n\n\n\t// Must be called when an event in the view is dropped onto new location.\n\t// `dropLocation` is an object that contains the new zoned start/end/allDay values for the event.\n\treportEventDrop: function(event, dropLocation, largeUnit, el, ev) {\n\t\tvar calendar = this.calendar;\n\t\tvar mutateResult = calendar.mutateEvent(event, dropLocation, largeUnit);\n\t\tvar undoFunc = function() {\n\t\t\tmutateResult.undo();\n\t\t\tcalendar.reportEventChange();\n\t\t};\n\n\t\tthis.triggerEventDrop(event, mutateResult.dateDelta, undoFunc, el, ev);\n\t\tcalendar.reportEventChange(); // will rerender events\n\t},\n\n\n\t// Triggers event-drop handlers that have subscribed via the API\n\ttriggerEventDrop: function(event, dateDelta, undoFunc, el, ev) {\n\t\tthis.trigger('eventDrop', el[0], event, dateDelta, undoFunc, ev, {}); // {} = jqui dummy\n\t},\n\n\n\t/* External Element Drag-n-Drop\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// Must be called when an external element, via jQuery UI, has been dropped onto the calendar.\n\t// `meta` is the parsed data that has been embedded into the dragging event.\n\t// `dropLocation` is an object that contains the new zoned start/end/allDay values for the event.\n\treportExternalDrop: function(meta, dropLocation, el, ev, ui) {\n\t\tvar eventProps = meta.eventProps;\n\t\tvar eventInput;\n\t\tvar event;\n\n\t\t// Try to build an event object and render it. TODO: decouple the two\n\t\tif (eventProps) {\n\t\t\teventInput = $.extend({}, eventProps, dropLocation);\n\t\t\tevent = this.calendar.renderEvent(eventInput, meta.stick)[0]; // renderEvent returns an array\n\t\t}\n\n\t\tthis.triggerExternalDrop(event, dropLocation, el, ev, ui);\n\t},\n\n\n\t// Triggers external-drop handlers that have subscribed via the API\n\ttriggerExternalDrop: function(event, dropLocation, el, ev, ui) {\n\n\t\t// trigger 'drop' regardless of whether element represents an event\n\t\tthis.trigger('drop', el[0], dropLocation.start, ev, ui);\n\n\t\tif (event) {\n\t\t\tthis.trigger('eventReceive', null, event); // signal an external event landed\n\t\t}\n\t},\n\n\n\t/* Drag-n-Drop Rendering (for both events and external elements)\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// Renders a visual indication of a event or external-element drag over the given drop zone.\n\t// If an external-element, seg will be `null`.\n\t// Must return elements used for any mock events.\n\trenderDrag: function(dropLocation, seg) {\n\t\t// subclasses must implement\n\t},\n\n\n\t// Unrenders a visual indication of an event or external-element being dragged.\n\tunrenderDrag: function() {\n\t\t// subclasses must implement\n\t},\n\n\n\t/* Event Resizing\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// Computes if the given event is allowed to be resized from its starting edge\n\tisEventResizableFromStart: function(event) {\n\t\treturn this.opt('eventResizableFromStart') && this.isEventResizable(event);\n\t},\n\n\n\t// Computes if the given event is allowed to be resized from its ending edge\n\tisEventResizableFromEnd: function(event) {\n\t\treturn this.isEventResizable(event);\n\t},\n\n\n\t// Computes if the given event is allowed to be resized by the user at all\n\tisEventResizable: function(event) {\n\t\tvar source = event.source || {};\n\n\t\treturn firstDefined(\n\t\t\tevent.durationEditable,\n\t\t\tsource.durationEditable,\n\t\t\tthis.opt('eventDurationEditable'),\n\t\t\tevent.editable,\n\t\t\tsource.editable,\n\t\t\tthis.opt('editable')\n\t\t);\n\t},\n\n\n\t// Must be called when an event in the view has been resized to a new length\n\treportEventResize: function(event, resizeLocation, largeUnit, el, ev) {\n\t\tvar calendar = this.calendar;\n\t\tvar mutateResult = calendar.mutateEvent(event, resizeLocation, largeUnit);\n\t\tvar undoFunc = function() {\n\t\t\tmutateResult.undo();\n\t\t\tcalendar.reportEventChange();\n\t\t};\n\n\t\tthis.triggerEventResize(event, mutateResult.durationDelta, undoFunc, el, ev);\n\t\tcalendar.reportEventChange(); // will rerender events\n\t},\n\n\n\t// Triggers event-resize handlers that have subscribed via the API\n\ttriggerEventResize: function(event, durationDelta, undoFunc, el, ev) {\n\t\tthis.trigger('eventResize', el[0], event, durationDelta, undoFunc, ev, {}); // {} = jqui dummy\n\t},\n\n\n\t/* Selection (time range)\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// Selects a date span on the view. `start` and `end` are both Moments.\n\t// `ev` is the native mouse event that begin the interaction.\n\tselect: function(span, ev) {\n\t\tthis.unselect(ev);\n\t\tthis.renderSelection(span);\n\t\tthis.reportSelection(span, ev);\n\t},\n\n\n\t// Renders a visual indication of the selection\n\trenderSelection: function(span) {\n\t\t// subclasses should implement\n\t},\n\n\n\t// Called when a new selection is made. Updates internal state and triggers handlers.\n\treportSelection: function(span, ev) {\n\t\tthis.isSelected = true;\n\t\tthis.triggerSelect(span, ev);\n\t},\n\n\n\t// Triggers handlers to 'select'\n\ttriggerSelect: function(span, ev) {\n\t\tthis.trigger(\n\t\t\t'select',\n\t\t\tnull,\n\t\t\tthis.calendar.applyTimezone(span.start), // convert to calendar's tz for external API\n\t\t\tthis.calendar.applyTimezone(span.end), // \"\n\t\t\tev\n\t\t);\n\t},\n\n\n\t// Undoes a selection. updates in the internal state and triggers handlers.\n\t// `ev` is the native mouse event that began the interaction.\n\tunselect: function(ev) {\n\t\tif (this.isSelected) {\n\t\t\tthis.isSelected = false;\n\t\t\tif (this.destroySelection) {\n\t\t\t\tthis.destroySelection(); // TODO: deprecate\n\t\t\t}\n\t\t\tthis.unrenderSelection();\n\t\t\tthis.trigger('unselect', null, ev);\n\t\t}\n\t},\n\n\n\t// Unrenders a visual indication of selection\n\tunrenderSelection: function() {\n\t\t// subclasses should implement\n\t},\n\n\n\t/* Event Selection\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\tselectEvent: function(event) {\n\t\tif (!this.selectedEvent || this.selectedEvent !== event) {\n\t\t\tthis.unselectEvent();\n\t\t\tthis.renderedEventSegEach(function(seg) {\n\t\t\t\tseg.el.addClass('fc-selected');\n\t\t\t}, event);\n\t\t\tthis.selectedEvent = event;\n\t\t}\n\t},\n\n\n\tunselectEvent: function() {\n\t\tif (this.selectedEvent) {\n\t\t\tthis.renderedEventSegEach(function(seg) {\n\t\t\t\tseg.el.removeClass('fc-selected');\n\t\t\t}, this.selectedEvent);\n\t\t\tthis.selectedEvent = null;\n\t\t}\n\t},\n\n\n\tisEventSelected: function(event) {\n\t\t// event references might change on refetchEvents(), while selectedEvent doesn't,\n\t\t// so compare IDs\n\t\treturn this.selectedEvent && this.selectedEvent._id === event._id;\n\t},\n\n\n\t/* Mouse / Touch Unselecting (time range & event unselection)\n\t------------------------------------------------------------------------------------------------------------------*/\n\t// TODO: move consistently to down/start or up/end?\n\t// TODO: don't kill previous selection if touch scrolling\n\n\n\thandleDocumentMousedown: function(ev) {\n\t\tif (isPrimaryMouseButton(ev)) {\n\t\t\tthis.processUnselect(ev);\n\t\t}\n\t},\n\n\n\tprocessUnselect: function(ev) {\n\t\tthis.processRangeUnselect(ev);\n\t\tthis.processEventUnselect(ev);\n\t},\n\n\n\tprocessRangeUnselect: function(ev) {\n\t\tvar ignore;\n\n\t\t// is there a time-range selection?\n\t\tif (this.isSelected && this.opt('unselectAuto')) {\n\t\t\t// only unselect if the clicked element is not identical to or inside of an 'unselectCancel' element\n\t\t\tignore = this.opt('unselectCancel');\n\t\t\tif (!ignore || !$(ev.target).closest(ignore).length) {\n\t\t\t\tthis.unselect(ev);\n\t\t\t}\n\t\t}\n\t},\n\n\n\tprocessEventUnselect: function(ev) {\n\t\tif (this.selectedEvent) {\n\t\t\tif (!$(ev.target).closest('.fc-selected').length) {\n\t\t\t\tthis.unselectEvent();\n\t\t\t}\n\t\t}\n\t},\n\n\n\t/* Day Click\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// Triggers handlers to 'dayClick'\n\t// Span has start/end of the clicked area. Only the start is useful.\n\ttriggerDayClick: function(span, dayEl, ev) {\n\t\tthis.trigger(\n\t\t\t'dayClick',\n\t\t\tdayEl,\n\t\t\tthis.calendar.applyTimezone(span.start), // convert to calendar's timezone for external API\n\t\t\tev\n\t\t);\n\t},\n\n\n\t/* Date Utils\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// Initializes internal variables related to calculating hidden days-of-week\n\tinitHiddenDays: function() {\n\t\tvar hiddenDays = this.opt('hiddenDays') || []; // array of day-of-week indices that are hidden\n\t\tvar isHiddenDayHash = []; // is the day-of-week hidden? (hash with day-of-week-index -> bool)\n\t\tvar dayCnt = 0;\n\t\tvar i;\n\n\t\tif (this.opt('weekends') === false) {\n\t\t\thiddenDays.push(0, 6); // 0=sunday, 6=saturday\n\t\t}\n\n\t\tfor (i = 0; i < 7; i++) {\n\t\t\tif (\n\t\t\t\t!(isHiddenDayHash[i] = $.inArray(i, hiddenDays) !== -1)\n\t\t\t) {\n\t\t\t\tdayCnt++;\n\t\t\t}\n\t\t}\n\n\t\tif (!dayCnt) {\n\t\t\tthrow 'invalid hiddenDays'; // all days were hidden? bad.\n\t\t}\n\n\t\tthis.isHiddenDayHash = isHiddenDayHash;\n\t},\n\n\n\t// Is the current day hidden?\n\t// `day` is a day-of-week index (0-6), or a Moment\n\tisHiddenDay: function(day) {\n\t\tif (moment.isMoment(day)) {\n\t\t\tday = day.day();\n\t\t}\n\t\treturn this.isHiddenDayHash[day];\n\t},\n\n\n\t// Incrementing the current day until it is no longer a hidden day, returning a copy.\n\t// If the initial value of `date` is not a hidden day, don't do anything.\n\t// Pass `isExclusive` as `true` if you are dealing with an end date.\n\t// `inc` defaults to `1` (increment one day forward each time)\n\tskipHiddenDays: function(date, inc, isExclusive) {\n\t\tvar out = date.clone();\n\t\tinc = inc || 1;\n\t\twhile (\n\t\t\tthis.isHiddenDayHash[(out.day() + (isExclusive ? inc : 0) + 7) % 7]\n\t\t) {\n\t\t\tout.add(inc, 'days');\n\t\t}\n\t\treturn out;\n\t},\n\n\n\t// Returns the date range of the full days the given range visually appears to occupy.\n\t// Returns a new range object.\n\tcomputeDayRange: function(range) {\n\t\tvar startDay = range.start.clone().stripTime(); // the beginning of the day the range starts\n\t\tvar end = range.end;\n\t\tvar endDay = null;\n\t\tvar endTimeMS;\n\n\t\tif (end) {\n\t\t\tendDay = end.clone().stripTime(); // the beginning of the day the range exclusively ends\n\t\t\tendTimeMS = +end.time(); // # of milliseconds into `endDay`\n\n\t\t\t// If the end time is actually inclusively part of the next day and is equal to or\n\t\t\t// beyond the next day threshold, adjust the end to be the exclusive end of `endDay`.\n\t\t\t// Otherwise, leaving it as inclusive will cause it to exclude `endDay`.\n\t\t\tif (endTimeMS && endTimeMS >= this.nextDayThreshold) {\n\t\t\t\tendDay.add(1, 'days');\n\t\t\t}\n\t\t}\n\n\t\t// If no end was specified, or if it is within `startDay` but not past nextDayThreshold,\n\t\t// assign the default duration of one day.\n\t\tif (!end || endDay <= startDay) {\n\t\t\tendDay = startDay.clone().add(1, 'days');\n\t\t}\n\n\t\treturn { start: startDay, end: endDay };\n\t},\n\n\n\t// Does the given event visually appear to occupy more than one day?\n\tisMultiDayEvent: function(event) {\n\t\tvar range = this.computeDayRange(event); // event is range-ish\n\n\t\treturn range.end.diff(range.start, 'days') > 1;\n\t}\n\n});\n\n;;\n\n/*\nEmbodies a div that has potential scrollbars\n*/\nvar Scroller = FC.Scroller = Class.extend({\n\n\tel: null, // the guaranteed outer element\n\tscrollEl: null, // the element with the scrollbars\n\toverflowX: null,\n\toverflowY: null,\n\n\n\tconstructor: function(options) {\n\t\toptions = options || {};\n\t\tthis.overflowX = options.overflowX || options.overflow || 'auto';\n\t\tthis.overflowY = options.overflowY || options.overflow || 'auto';\n\t},\n\n\n\trender: function() {\n\t\tthis.el = this.renderEl();\n\t\tthis.applyOverflow();\n\t},\n\n\n\trenderEl: function() {\n\t\treturn (this.scrollEl = $('
'));\n\t},\n\n\n\t// sets to natural height, unlocks overflow\n\tclear: function() {\n\t\tthis.setHeight('auto');\n\t\tthis.applyOverflow();\n\t},\n\n\n\tdestroy: function() {\n\t\tthis.el.remove();\n\t},\n\n\n\t// Overflow\n\t// -----------------------------------------------------------------------------------------------------------------\n\n\n\tapplyOverflow: function() {\n\t\tthis.scrollEl.css({\n\t\t\t'overflow-x': this.overflowX,\n\t\t\t'overflow-y': this.overflowY\n\t\t});\n\t},\n\n\n\t// Causes any 'auto' overflow values to resolves to 'scroll' or 'hidden'.\n\t// Useful for preserving scrollbar widths regardless of future resizes.\n\t// Can pass in scrollbarWidths for optimization.\n\tlockOverflow: function(scrollbarWidths) {\n\t\tvar overflowX = this.overflowX;\n\t\tvar overflowY = this.overflowY;\n\n\t\tscrollbarWidths = scrollbarWidths || this.getScrollbarWidths();\n\n\t\tif (overflowX === 'auto') {\n\t\t\toverflowX = (\n\t\t\t\t\tscrollbarWidths.top || scrollbarWidths.bottom || // horizontal scrollbars?\n\t\t\t\t\t// OR scrolling pane with massless scrollbars?\n\t\t\t\t\tthis.scrollEl[0].scrollWidth - 1 > this.scrollEl[0].clientWidth\n\t\t\t\t\t\t// subtract 1 because of IE off-by-one issue\n\t\t\t\t) ? 'scroll' : 'hidden';\n\t\t}\n\n\t\tif (overflowY === 'auto') {\n\t\t\toverflowY = (\n\t\t\t\t\tscrollbarWidths.left || scrollbarWidths.right || // vertical scrollbars?\n\t\t\t\t\t// OR scrolling pane with massless scrollbars?\n\t\t\t\t\tthis.scrollEl[0].scrollHeight - 1 > this.scrollEl[0].clientHeight\n\t\t\t\t\t\t// subtract 1 because of IE off-by-one issue\n\t\t\t\t) ? 'scroll' : 'hidden';\n\t\t}\n\n\t\tthis.scrollEl.css({ 'overflow-x': overflowX, 'overflow-y': overflowY });\n\t},\n\n\n\t// Getters / Setters\n\t// -----------------------------------------------------------------------------------------------------------------\n\n\n\tsetHeight: function(height) {\n\t\tthis.scrollEl.height(height);\n\t},\n\n\n\tgetScrollTop: function() {\n\t\treturn this.scrollEl.scrollTop();\n\t},\n\n\n\tsetScrollTop: function(top) {\n\t\tthis.scrollEl.scrollTop(top);\n\t},\n\n\n\tgetClientWidth: function() {\n\t\treturn this.scrollEl[0].clientWidth;\n\t},\n\n\n\tgetClientHeight: function() {\n\t\treturn this.scrollEl[0].clientHeight;\n\t},\n\n\n\tgetScrollbarWidths: function() {\n\t\treturn getScrollbarWidths(this.scrollEl);\n\t}\n\n});\n\n;;\n\nvar Calendar = FC.Calendar = Class.extend({\n\n\tdirDefaults: null, // option defaults related to LTR or RTL\n\tlangDefaults: null, // option defaults related to current locale\n\toverrides: null, // option overrides given to the fullCalendar constructor\n\tdynamicOverrides: null, // options set with dynamic setter method. higher precedence than view overrides.\n\toptions: null, // all defaults combined with overrides\n\tviewSpecCache: null, // cache of view definitions\n\tview: null, // current View object\n\theader: null,\n\tloadingLevel: 0, // number of simultaneous loading tasks\n\n\n\t// a lot of this class' OOP logic is scoped within this constructor function,\n\t// but in the future, write individual methods on the prototype.\n\tconstructor: Calendar_constructor,\n\n\n\t// Subclasses can override this for initialization logic after the constructor has been called\n\tinitialize: function() {\n\t},\n\n\n\t// Computes the flattened options hash for the calendar and assigns to `this.options`.\n\t// Assumes this.overrides and this.dynamicOverrides have already been initialized.\n\tpopulateOptionsHash: function() {\n\t\tvar lang, langDefaults;\n\t\tvar isRTL, dirDefaults;\n\n\t\tlang = firstDefined( // explicit lang option given?\n\t\t\tthis.dynamicOverrides.lang,\n\t\t\tthis.overrides.lang\n\t\t);\n\t\tlangDefaults = langOptionHash[lang];\n\t\tif (!langDefaults) { // explicit lang option not given or invalid?\n\t\t\tlang = Calendar.defaults.lang;\n\t\t\tlangDefaults = langOptionHash[lang] || {};\n\t\t}\n\n\t\tisRTL = firstDefined( // based on options computed so far, is direction RTL?\n\t\t\tthis.dynamicOverrides.isRTL,\n\t\t\tthis.overrides.isRTL,\n\t\t\tlangDefaults.isRTL,\n\t\t\tCalendar.defaults.isRTL\n\t\t);\n\t\tdirDefaults = isRTL ? Calendar.rtlDefaults : {};\n\n\t\tthis.dirDefaults = dirDefaults;\n\t\tthis.langDefaults = langDefaults;\n\t\tthis.options = mergeOptions([ // merge defaults and overrides. lowest to highest precedence\n\t\t\tCalendar.defaults, // global defaults\n\t\t\tdirDefaults,\n\t\t\tlangDefaults,\n\t\t\tthis.overrides,\n\t\t\tthis.dynamicOverrides\n\t\t]);\n\t\tpopulateInstanceComputableOptions(this.options); // fill in gaps with computed options\n\t},\n\n\n\t// Gets information about how to create a view. Will use a cache.\n\tgetViewSpec: function(viewType) {\n\t\tvar cache = this.viewSpecCache;\n\n\t\treturn cache[viewType] || (cache[viewType] = this.buildViewSpec(viewType));\n\t},\n\n\n\t// Given a duration singular unit, like \"week\" or \"day\", finds a matching view spec.\n\t// Preference is given to views that have corresponding buttons.\n\tgetUnitViewSpec: function(unit) {\n\t\tvar viewTypes;\n\t\tvar i;\n\t\tvar spec;\n\n\t\tif ($.inArray(unit, intervalUnits) != -1) {\n\n\t\t\t// put views that have buttons first. there will be duplicates, but oh well\n\t\t\tviewTypes = this.header.getViewsWithButtons();\n\t\t\t$.each(FC.views, function(viewType) { // all views\n\t\t\t\tviewTypes.push(viewType);\n\t\t\t});\n\n\t\t\tfor (i = 0; i < viewTypes.length; i++) {\n\t\t\t\tspec = this.getViewSpec(viewTypes[i]);\n\t\t\t\tif (spec) {\n\t\t\t\t\tif (spec.singleUnit == unit) {\n\t\t\t\t\t\treturn spec;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\n\t// Builds an object with information on how to create a given view\n\tbuildViewSpec: function(requestedViewType) {\n\t\tvar viewOverrides = this.overrides.views || {};\n\t\tvar specChain = []; // for the view. lowest to highest priority\n\t\tvar defaultsChain = []; // for the view. lowest to highest priority\n\t\tvar overridesChain = []; // for the view. lowest to highest priority\n\t\tvar viewType = requestedViewType;\n\t\tvar spec; // for the view\n\t\tvar overrides; // for the view\n\t\tvar duration;\n\t\tvar unit;\n\n\t\t// iterate from the specific view definition to a more general one until we hit an actual View class\n\t\twhile (viewType) {\n\t\t\tspec = fcViews[viewType];\n\t\t\toverrides = viewOverrides[viewType];\n\t\t\tviewType = null; // clear. might repopulate for another iteration\n\n\t\t\tif (typeof spec === 'function') { // TODO: deprecate\n\t\t\t\tspec = { 'class': spec };\n\t\t\t}\n\n\t\t\tif (spec) {\n\t\t\t\tspecChain.unshift(spec);\n\t\t\t\tdefaultsChain.unshift(spec.defaults || {});\n\t\t\t\tduration = duration || spec.duration;\n\t\t\t\tviewType = viewType || spec.type;\n\t\t\t}\n\n\t\t\tif (overrides) {\n\t\t\t\toverridesChain.unshift(overrides); // view-specific option hashes have options at zero-level\n\t\t\t\tduration = duration || overrides.duration;\n\t\t\t\tviewType = viewType || overrides.type;\n\t\t\t}\n\t\t}\n\n\t\tspec = mergeProps(specChain);\n\t\tspec.type = requestedViewType;\n\t\tif (!spec['class']) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (duration) {\n\t\t\tduration = moment.duration(duration);\n\t\t\tif (duration.valueOf()) { // valid?\n\t\t\t\tspec.duration = duration;\n\t\t\t\tunit = computeIntervalUnit(duration);\n\n\t\t\t\t// view is a single-unit duration, like \"week\" or \"day\"\n\t\t\t\t// incorporate options for this. lowest priority\n\t\t\t\tif (duration.as(unit) === 1) {\n\t\t\t\t\tspec.singleUnit = unit;\n\t\t\t\t\toverridesChain.unshift(viewOverrides[unit] || {});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tspec.defaults = mergeOptions(defaultsChain);\n\t\tspec.overrides = mergeOptions(overridesChain);\n\n\t\tthis.buildViewSpecOptions(spec);\n\t\tthis.buildViewSpecButtonText(spec, requestedViewType);\n\n\t\treturn spec;\n\t},\n\n\n\t// Builds and assigns a view spec's options object from its already-assigned defaults and overrides\n\tbuildViewSpecOptions: function(spec) {\n\t\tspec.options = mergeOptions([ // lowest to highest priority\n\t\t\tCalendar.defaults, // global defaults\n\t\t\tspec.defaults, // view's defaults (from ViewSubclass.defaults)\n\t\t\tthis.dirDefaults,\n\t\t\tthis.langDefaults, // locale and dir take precedence over view's defaults!\n\t\t\tthis.overrides, // calendar's overrides (options given to constructor)\n\t\t\tspec.overrides, // view's overrides (view-specific options)\n\t\t\tthis.dynamicOverrides // dynamically set via setter. highest precedence\n\t\t]);\n\t\tpopulateInstanceComputableOptions(spec.options);\n\t},\n\n\n\t// Computes and assigns a view spec's buttonText-related options\n\tbuildViewSpecButtonText: function(spec, requestedViewType) {\n\n\t\t// given an options object with a possible `buttonText` hash, lookup the buttonText for the\n\t\t// requested view, falling back to a generic unit entry like \"week\" or \"day\"\n\t\tfunction queryButtonText(options) {\n\t\t\tvar buttonText = options.buttonText || {};\n\t\t\treturn buttonText[requestedViewType] ||\n\t\t\t\t(spec.singleUnit ? buttonText[spec.singleUnit] : null);\n\t\t}\n\n\t\t// highest to lowest priority\n\t\tspec.buttonTextOverride =\n\t\t\tqueryButtonText(this.dynamicOverrides) ||\n\t\t\tqueryButtonText(this.overrides) || // constructor-specified buttonText lookup hash takes precedence\n\t\t\tspec.overrides.buttonText; // `buttonText` for view-specific options is a string\n\n\t\t// highest to lowest priority. mirrors buildViewSpecOptions\n\t\tspec.buttonTextDefault =\n\t\t\tqueryButtonText(this.langDefaults) ||\n\t\t\tqueryButtonText(this.dirDefaults) ||\n\t\t\tspec.defaults.buttonText || // a single string. from ViewSubclass.defaults\n\t\t\tqueryButtonText(Calendar.defaults) ||\n\t\t\t(spec.duration ? this.humanizeDuration(spec.duration) : null) || // like \"3 days\"\n\t\t\trequestedViewType; // fall back to given view name\n\t},\n\n\n\t// Given a view name for a custom view or a standard view, creates a ready-to-go View object\n\tinstantiateView: function(viewType) {\n\t\tvar spec = this.getViewSpec(viewType);\n\n\t\treturn new spec['class'](this, viewType, spec.options, spec.duration);\n\t},\n\n\n\t// Returns a boolean about whether the view is okay to instantiate at some point\n\tisValidViewType: function(viewType) {\n\t\treturn Boolean(this.getViewSpec(viewType));\n\t},\n\n\n\t// Should be called when any type of async data fetching begins\n\tpushLoading: function() {\n\t\tif (!(this.loadingLevel++)) {\n\t\t\tthis.trigger('loading', null, true, this.view);\n\t\t}\n\t},\n\n\n\t// Should be called when any type of async data fetching completes\n\tpopLoading: function() {\n\t\tif (!(--this.loadingLevel)) {\n\t\t\tthis.trigger('loading', null, false, this.view);\n\t\t}\n\t},\n\n\n\t// Given arguments to the select method in the API, returns a span (unzoned start/end and other info)\n\tbuildSelectSpan: function(zonedStartInput, zonedEndInput) {\n\t\tvar start = this.moment(zonedStartInput).stripZone();\n\t\tvar end;\n\n\t\tif (zonedEndInput) {\n\t\t\tend = this.moment(zonedEndInput).stripZone();\n\t\t}\n\t\telse if (start.hasTime()) {\n\t\t\tend = start.clone().add(this.defaultTimedEventDuration);\n\t\t}\n\t\telse {\n\t\t\tend = start.clone().add(this.defaultAllDayEventDuration);\n\t\t}\n\n\t\treturn { start: start, end: end };\n\t}\n\n});\n\n\nCalendar.mixin(EmitterMixin);\n\n\nfunction Calendar_constructor(element, overrides) {\n\tvar t = this;\n\n\n\t// Exports\n\t// -----------------------------------------------------------------------------------\n\n\tt.render = render;\n\tt.destroy = destroy;\n\tt.refetchEvents = refetchEvents;\n\tt.refetchEventSources = refetchEventSources;\n\tt.reportEvents = reportEvents;\n\tt.reportEventChange = reportEventChange;\n\tt.rerenderEvents = renderEvents; // `renderEvents` serves as a rerender. an API method\n\tt.changeView = renderView; // `renderView` will switch to another view\n\tt.select = select;\n\tt.unselect = unselect;\n\tt.prev = prev;\n\tt.next = next;\n\tt.prevYear = prevYear;\n\tt.nextYear = nextYear;\n\tt.today = today;\n\tt.gotoDate = gotoDate;\n\tt.incrementDate = incrementDate;\n\tt.zoomTo = zoomTo;\n\tt.getDate = getDate;\n\tt.getCalendar = getCalendar;\n\tt.getView = getView;\n\tt.option = option; // getter/setter method\n\tt.trigger = trigger;\n\n\n\t// Options\n\t// -----------------------------------------------------------------------------------\n\n\tt.dynamicOverrides = {};\n\tt.viewSpecCache = {};\n\tt.optionHandlers = {}; // for Calendar.options.js\n\n\t// convert legacy options into non-legacy ones.\n\t// in the future, when this is removed, don't use `overrides` reference. make a copy.\n\tt.overrides = massageOverrides(overrides || {});\n\n\tt.populateOptionsHash(); // sets this.options\n\n\n\n\t// Language-data Internals\n\t// -----------------------------------------------------------------------------------\n\t// Apply overrides to the current language's data\n\n\tvar localeData;\n\n\t// Called immediately, and when any of the options change.\n\t// Happens before any internal objects rebuild or rerender, because this is very core.\n\tt.bindOptions([\n\t\t'lang', 'monthNames', 'monthNamesShort', 'dayNames', 'dayNamesShort', 'firstDay', 'weekNumberCalculation'\n\t], function(lang, monthNames, monthNamesShort, dayNames, dayNamesShort, firstDay, weekNumberCalculation) {\n\n\t\tlocaleData = createObject( // make a cheap copy\n\t\t\tgetMomentLocaleData(lang) // will fall back to en\n\t\t);\n\n\t\tif (monthNames) {\n\t\t\tlocaleData._months = monthNames;\n\t\t}\n\t\tif (monthNamesShort) {\n\t\t\tlocaleData._monthsShort = monthNamesShort;\n\t\t}\n\t\tif (dayNames) {\n\t\t\tlocaleData._weekdays = dayNames;\n\t\t}\n\t\tif (dayNamesShort) {\n\t\t\tlocaleData._weekdaysShort = dayNamesShort;\n\t\t}\n\t\tif (firstDay != null) {\n\t\t\tvar _week = createObject(localeData._week); // _week: { dow: # }\n\t\t\t_week.dow = firstDay;\n\t\t\tlocaleData._week = _week;\n\t\t}\n\n\t\tif (weekNumberCalculation === 'iso') {\n\t\t\tweekNumberCalculation = 'ISO'; // normalize\n\t\t}\n\t\tif ( // whitelist certain kinds of input\n\t\t\tweekNumberCalculation === 'ISO' ||\n\t\t\tweekNumberCalculation === 'local' ||\n\t\t\ttypeof weekNumberCalculation === 'function'\n\t\t) {\n\t\t\tlocaleData._fullCalendar_weekCalc = weekNumberCalculation; // moment-ext will know what to do with it\n\t\t}\n\n\t\t// If the internal current date object already exists, move to new locale.\n\t\t// We do NOT need to do this technique for event dates, because this happens when converting to \"segments\".\n\t\tif (date) {\n\t\t\tlocalizeMoment(date); // sets to localeData\n\t\t}\n\t});\n\n\n\n\t// Calendar-specific Date Utilities\n\t// -----------------------------------------------------------------------------------\n\n\n\tt.defaultAllDayEventDuration = moment.duration(t.options.defaultAllDayEventDuration);\n\tt.defaultTimedEventDuration = moment.duration(t.options.defaultTimedEventDuration);\n\n\n\t// Builds a moment using the settings of the current calendar: timezone and language.\n\t// Accepts anything the vanilla moment() constructor accepts.\n\tt.moment = function() {\n\t\tvar mom;\n\n\t\tif (t.options.timezone === 'local') {\n\t\t\tmom = FC.moment.apply(null, arguments);\n\n\t\t\t// Force the moment to be local, because FC.moment doesn't guarantee it.\n\t\t\tif (mom.hasTime()) { // don't give ambiguously-timed moments a local zone\n\t\t\t\tmom.local();\n\t\t\t}\n\t\t}\n\t\telse if (t.options.timezone === 'UTC') {\n\t\t\tmom = FC.moment.utc.apply(null, arguments); // process as UTC\n\t\t}\n\t\telse {\n\t\t\tmom = FC.moment.parseZone.apply(null, arguments); // let the input decide the zone\n\t\t}\n\n\t\tlocalizeMoment(mom);\n\n\t\treturn mom;\n\t};\n\n\n\t// Updates the given moment's locale settings to the current calendar locale settings.\n\tfunction localizeMoment(mom) {\n\t\tif ('_locale' in mom) { // moment 2.8 and above\n\t\t\tmom._locale = localeData;\n\t\t}\n\t\telse { // pre-moment-2.8\n\t\t\tmom._lang = localeData;\n\t\t}\n\t}\n\n\n\t// Returns a boolean about whether or not the calendar knows how to calculate\n\t// the timezone offset of arbitrary dates in the current timezone.\n\tt.getIsAmbigTimezone = function() {\n\t\treturn t.options.timezone !== 'local' && t.options.timezone !== 'UTC';\n\t};\n\n\n\t// Returns a copy of the given date in the current timezone. Has no effect on dates without times.\n\tt.applyTimezone = function(date) {\n\t\tif (!date.hasTime()) {\n\t\t\treturn date.clone();\n\t\t}\n\n\t\tvar zonedDate = t.moment(date.toArray());\n\t\tvar timeAdjust = date.time() - zonedDate.time();\n\t\tvar adjustedZonedDate;\n\n\t\t// Safari sometimes has problems with this coersion when near DST. Adjust if necessary. (bug #2396)\n\t\tif (timeAdjust) { // is the time result different than expected?\n\t\t\tadjustedZonedDate = zonedDate.clone().add(timeAdjust); // add milliseconds\n\t\t\tif (date.time() - adjustedZonedDate.time() === 0) { // does it match perfectly now?\n\t\t\t\tzonedDate = adjustedZonedDate;\n\t\t\t}\n\t\t}\n\n\t\treturn zonedDate;\n\t};\n\n\n\t// Returns a moment for the current date, as defined by the client's computer or from the `now` option.\n\t// Will return an moment with an ambiguous timezone.\n\tt.getNow = function() {\n\t\tvar now = t.options.now;\n\t\tif (typeof now === 'function') {\n\t\t\tnow = now();\n\t\t}\n\t\treturn t.moment(now).stripZone();\n\t};\n\n\n\t// Get an event's normalized end date. If not present, calculate it from the defaults.\n\tt.getEventEnd = function(event) {\n\t\tif (event.end) {\n\t\t\treturn event.end.clone();\n\t\t}\n\t\telse {\n\t\t\treturn t.getDefaultEventEnd(event.allDay, event.start);\n\t\t}\n\t};\n\n\n\t// Given an event's allDay status and start date, return what its fallback end date should be.\n\t// TODO: rename to computeDefaultEventEnd\n\tt.getDefaultEventEnd = function(allDay, zonedStart) {\n\t\tvar end = zonedStart.clone();\n\n\t\tif (allDay) {\n\t\t\tend.stripTime().add(t.defaultAllDayEventDuration);\n\t\t}\n\t\telse {\n\t\t\tend.add(t.defaultTimedEventDuration);\n\t\t}\n\n\t\tif (t.getIsAmbigTimezone()) {\n\t\t\tend.stripZone(); // we don't know what the tzo should be\n\t\t}\n\n\t\treturn end;\n\t};\n\n\n\t// Produces a human-readable string for the given duration.\n\t// Side-effect: changes the locale of the given duration.\n\tt.humanizeDuration = function(duration) {\n\t\treturn (duration.locale || duration.lang).call(duration, t.options.lang) // works moment-pre-2.8\n\t\t\t.humanize();\n\t};\n\n\n\t\n\t// Imports\n\t// -----------------------------------------------------------------------------------\n\n\n\tEventManager.call(t);\n\tvar isFetchNeeded = t.isFetchNeeded;\n\tvar fetchEvents = t.fetchEvents;\n\tvar fetchEventSources = t.fetchEventSources;\n\n\n\n\t// Locals\n\t// -----------------------------------------------------------------------------------\n\n\n\tvar _element = element[0];\n\tvar header;\n\tvar content;\n\tvar tm; // for making theme classes\n\tvar currentView; // NOTE: keep this in sync with this.view\n\tvar viewsByType = {}; // holds all instantiated view instances, current or not\n\tvar suggestedViewHeight;\n\tvar windowResizeProxy; // wraps the windowResize function\n\tvar ignoreWindowResize = 0;\n\tvar events = [];\n\tvar date; // unzoned\n\t\n\t\n\t\n\t// Main Rendering\n\t// -----------------------------------------------------------------------------------\n\n\n\t// compute the initial ambig-timezone date\n\tif (t.options.defaultDate != null) {\n\t\tdate = t.moment(t.options.defaultDate).stripZone();\n\t}\n\telse {\n\t\tdate = t.getNow(); // getNow already returns unzoned\n\t}\n\t\n\t\n\tfunction render() {\n\t\tif (!content) {\n\t\t\tinitialRender();\n\t\t}\n\t\telse if (elementVisible()) {\n\t\t\t// mainly for the public API\n\t\t\tcalcSize();\n\t\t\trenderView();\n\t\t}\n\t}\n\t\n\t\n\tfunction initialRender() {\n\t\telement.addClass('fc');\n\n\t\t// called immediately, and upon option change\n\t\tt.bindOption('theme', function(theme) {\n\t\t\ttm = theme ? 'ui' : 'fc'; // affects a larger scope\n\t\t\telement.toggleClass('ui-widget', theme);\n\t\t\telement.toggleClass('fc-unthemed', !theme);\n\t\t});\n\n\t\t// called immediately, and upon option change.\n\t\t// HACK: lang often affects isRTL, so we explicitly listen to that too.\n\t\tt.bindOptions([ 'isRTL', 'lang' ], function(isRTL) {\n\t\t\telement.toggleClass('fc-ltr', !isRTL);\n\t\t\telement.toggleClass('fc-rtl', isRTL);\n\t\t});\n\n\t\tcontent = $(\"
\").prependTo(element);\n\n\t\theader = t.header = new Header(t);\n\t\trenderHeader();\n\n\t\trenderView(t.options.defaultView);\n\n\t\tif (t.options.handleWindowResize) {\n\t\t\twindowResizeProxy = debounce(windowResize, t.options.windowResizeDelay); // prevents rapid calls\n\t\t\t$(window).resize(windowResizeProxy);\n\t\t}\n\t}\n\n\n\t// can be called repeatedly and Header will rerender\n\tfunction renderHeader() {\n\t\theader.render();\n\t\tif (header.el) {\n\t\t\telement.prepend(header.el);\n\t\t}\n\t}\n\t\n\t\n\tfunction destroy() {\n\n\t\tif (currentView) {\n\t\t\tcurrentView.removeElement();\n\n\t\t\t// NOTE: don't null-out currentView/t.view in case API methods are called after destroy.\n\t\t\t// It is still the \"current\" view, just not rendered.\n\t\t}\n\n\t\theader.removeElement();\n\t\tcontent.remove();\n\t\telement.removeClass('fc fc-ltr fc-rtl fc-unthemed ui-widget');\n\n\t\tif (windowResizeProxy) {\n\t\t\t$(window).unbind('resize', windowResizeProxy);\n\t\t}\n\t}\n\t\n\t\n\tfunction elementVisible() {\n\t\treturn element.is(':visible');\n\t}\n\t\n\t\n\n\t// View Rendering\n\t// -----------------------------------------------------------------------------------\n\n\n\t// Renders a view because of a date change, view-type change, or for the first time.\n\t// If not given a viewType, keep the current view but render different dates.\n\t// Accepts an optional scroll state to restore to.\n\tfunction renderView(viewType, explicitScrollState) {\n\t\tignoreWindowResize++;\n\n\t\t// if viewType is changing, remove the old view's rendering\n\t\tif (currentView && viewType && currentView.type !== viewType) {\n\t\t\tfreezeContentHeight(); // prevent a scroll jump when view element is removed\n\t\t\tclearView();\n\t\t}\n\n\t\t// if viewType changed, or the view was never created, create a fresh view\n\t\tif (!currentView && viewType) {\n\t\t\tcurrentView = t.view =\n\t\t\t\tviewsByType[viewType] ||\n\t\t\t\t(viewsByType[viewType] = t.instantiateView(viewType));\n\n\t\t\tcurrentView.setElement(\n\t\t\t\t$(\"
\").appendTo(content)\n\t\t\t);\n\t\t\theader.activateButton(viewType);\n\t\t}\n\n\t\tif (currentView) {\n\n\t\t\t// in case the view should render a period of time that is completely hidden\n\t\t\tdate = currentView.massageCurrentDate(date);\n\n\t\t\t// render or rerender the view\n\t\t\tif (\n\t\t\t\t!currentView.displaying ||\n\t\t\t\t!date.isWithin(currentView.intervalStart, currentView.intervalEnd) // implicit date window change\n\t\t\t) {\n\t\t\t\tif (elementVisible()) {\n\n\t\t\t\t\tcurrentView.display(date, explicitScrollState); // will call freezeContentHeight\n\t\t\t\t\tunfreezeContentHeight(); // immediately unfreeze regardless of whether display is async\n\n\t\t\t\t\t// need to do this after View::render, so dates are calculated\n\t\t\t\t\tupdateHeaderTitle();\n\t\t\t\t\tupdateTodayButton();\n\n\t\t\t\t\tgetAndRenderEvents();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tunfreezeContentHeight(); // undo any lone freezeContentHeight calls\n\t\tignoreWindowResize--;\n\t}\n\n\n\t// Unrenders the current view and reflects this change in the Header.\n\t// Unregsiters the `currentView`, but does not remove from viewByType hash.\n\tfunction clearView() {\n\t\theader.deactivateButton(currentView.type);\n\t\tcurrentView.removeElement();\n\t\tcurrentView = t.view = null;\n\t}\n\n\n\t// Destroys the view, including the view object. Then, re-instantiates it and renders it.\n\t// Maintains the same scroll state.\n\t// TODO: maintain any other user-manipulated state.\n\tfunction reinitView() {\n\t\tignoreWindowResize++;\n\t\tfreezeContentHeight();\n\n\t\tvar viewType = currentView.type;\n\t\tvar scrollState = currentView.queryScroll();\n\t\tclearView();\n\t\trenderView(viewType, scrollState);\n\n\t\tunfreezeContentHeight();\n\t\tignoreWindowResize--;\n\t}\n\n\t\n\n\t// Resizing\n\t// -----------------------------------------------------------------------------------\n\n\n\tt.getSuggestedViewHeight = function() {\n\t\tif (suggestedViewHeight === undefined) {\n\t\t\tcalcSize();\n\t\t}\n\t\treturn suggestedViewHeight;\n\t};\n\n\n\tt.isHeightAuto = function() {\n\t\treturn t.options.contentHeight === 'auto' || t.options.height === 'auto';\n\t};\n\t\n\t\n\tfunction updateSize(shouldRecalc) {\n\t\tif (elementVisible()) {\n\n\t\t\tif (shouldRecalc) {\n\t\t\t\t_calcSize();\n\t\t\t}\n\n\t\t\tignoreWindowResize++;\n\t\t\tcurrentView.updateSize(true); // isResize=true. will poll getSuggestedViewHeight() and isHeightAuto()\n\t\t\tignoreWindowResize--;\n\n\t\t\treturn true; // signal success\n\t\t}\n\t}\n\n\n\tfunction calcSize() {\n\t\tif (elementVisible()) {\n\t\t\t_calcSize();\n\t\t}\n\t}\n\t\n\t\n\tfunction _calcSize() { // assumes elementVisible\n\t\tvar contentHeightInput = t.options.contentHeight;\n\t\tvar heightInput = t.options.height;\n\n\t\tif (typeof contentHeightInput === 'number') { // exists and not 'auto'\n\t\t\tsuggestedViewHeight = contentHeightInput;\n\t\t}\n\t\telse if (typeof contentHeightInput === 'function') { // exists and is a function\n\t\t\tsuggestedViewHeight = contentHeightInput();\n\t\t}\n\t\telse if (typeof heightInput === 'number') { // exists and not 'auto'\n\t\t\tsuggestedViewHeight = heightInput - queryHeaderHeight();\n\t\t}\n\t\telse if (typeof heightInput === 'function') { // exists and is a function\n\t\t\tsuggestedViewHeight = heightInput() - queryHeaderHeight();\n\t\t}\n\t\telse if (heightInput === 'parent') { // set to height of parent element\n\t\t\tsuggestedViewHeight = element.parent().height() - queryHeaderHeight();\n\t\t}\n\t\telse {\n\t\t\tsuggestedViewHeight = Math.round(content.width() / Math.max(t.options.aspectRatio, .5));\n\t\t}\n\t}\n\n\n\tfunction queryHeaderHeight() {\n\t\treturn header.el ? header.el.outerHeight(true) : 0; // includes margin\n\t}\n\t\n\t\n\tfunction windowResize(ev) {\n\t\tif (\n\t\t\t!ignoreWindowResize &&\n\t\t\tev.target === window && // so we don't process jqui \"resize\" events that have bubbled up\n\t\t\tcurrentView.start // view has already been rendered\n\t\t) {\n\t\t\tif (updateSize(true)) {\n\t\t\t\tcurrentView.trigger('windowResize', _element);\n\t\t\t}\n\t\t}\n\t}\n\t\n\t\n\t\n\t/* Event Fetching/Rendering\n\t-----------------------------------------------------------------------------*/\n\t// TODO: going forward, most of this stuff should be directly handled by the view\n\n\n\tfunction refetchEvents() { // can be called as an API method\n\t\tfetchAndRenderEvents();\n\t}\n\n\n\t// TODO: move this into EventManager?\n\tfunction refetchEventSources(matchInputs) {\n\t\tfetchEventSources(t.getEventSourcesByMatchArray(matchInputs));\n\t}\n\n\n\tfunction renderEvents() { // destroys old events if previously rendered\n\t\tif (elementVisible()) {\n\t\t\tfreezeContentHeight();\n\t\t\tcurrentView.displayEvents(events);\n\t\t\tunfreezeContentHeight();\n\t\t}\n\t}\n\t\n\n\tfunction getAndRenderEvents() {\n\t\tif (!t.options.lazyFetching || isFetchNeeded(currentView.start, currentView.end)) {\n\t\t\tfetchAndRenderEvents();\n\t\t}\n\t\telse {\n\t\t\trenderEvents();\n\t\t}\n\t}\n\n\n\tfunction fetchAndRenderEvents() {\n\t\tfetchEvents(currentView.start, currentView.end);\n\t\t\t// ... will call reportEvents\n\t\t\t// ... which will call renderEvents\n\t}\n\n\t\n\t// called when event data arrives\n\tfunction reportEvents(_events) {\n\t\tevents = _events;\n\t\trenderEvents();\n\t}\n\n\n\t// called when a single event's data has been changed\n\tfunction reportEventChange() {\n\t\trenderEvents();\n\t}\n\n\n\n\t/* Header Updating\n\t-----------------------------------------------------------------------------*/\n\n\n\tfunction updateHeaderTitle() {\n\t\theader.updateTitle(currentView.title);\n\t}\n\n\n\tfunction updateTodayButton() {\n\t\tvar now = t.getNow();\n\t\tif (now.isWithin(currentView.intervalStart, currentView.intervalEnd)) {\n\t\t\theader.disableButton('today');\n\t\t}\n\t\telse {\n\t\t\theader.enableButton('today');\n\t\t}\n\t}\n\t\n\n\n\t/* Selection\n\t-----------------------------------------------------------------------------*/\n\t\n\n\t// this public method receives start/end dates in any format, with any timezone\n\tfunction select(zonedStartInput, zonedEndInput) {\n\t\tcurrentView.select(\n\t\t\tt.buildSelectSpan.apply(t, arguments)\n\t\t);\n\t}\n\t\n\n\tfunction unselect() { // safe to be called before renderView\n\t\tif (currentView) {\n\t\t\tcurrentView.unselect();\n\t\t}\n\t}\n\t\n\t\n\t\n\t/* Date\n\t-----------------------------------------------------------------------------*/\n\t\n\t\n\tfunction prev() {\n\t\tdate = currentView.computePrevDate(date);\n\t\trenderView();\n\t}\n\t\n\t\n\tfunction next() {\n\t\tdate = currentView.computeNextDate(date);\n\t\trenderView();\n\t}\n\t\n\t\n\tfunction prevYear() {\n\t\tdate.add(-1, 'years');\n\t\trenderView();\n\t}\n\t\n\t\n\tfunction nextYear() {\n\t\tdate.add(1, 'years');\n\t\trenderView();\n\t}\n\t\n\t\n\tfunction today() {\n\t\tdate = t.getNow();\n\t\trenderView();\n\t}\n\t\n\t\n\tfunction gotoDate(zonedDateInput) {\n\t\tdate = t.moment(zonedDateInput).stripZone();\n\t\trenderView();\n\t}\n\t\n\t\n\tfunction incrementDate(delta) {\n\t\tdate.add(moment.duration(delta));\n\t\trenderView();\n\t}\n\n\n\t// Forces navigation to a view for the given date.\n\t// `viewType` can be a specific view name or a generic one like \"week\" or \"day\".\n\tfunction zoomTo(newDate, viewType) {\n\t\tvar spec;\n\n\t\tviewType = viewType || 'day'; // day is default zoom\n\t\tspec = t.getViewSpec(viewType) || t.getUnitViewSpec(viewType);\n\n\t\tdate = newDate.clone();\n\t\trenderView(spec ? spec.type : null);\n\t}\n\t\n\t\n\t// for external API\n\tfunction getDate() {\n\t\treturn t.applyTimezone(date); // infuse the calendar's timezone\n\t}\n\n\n\n\t/* Height \"Freezing\"\n\t-----------------------------------------------------------------------------*/\n\t// TODO: move this into the view\n\n\tt.freezeContentHeight = freezeContentHeight;\n\tt.unfreezeContentHeight = unfreezeContentHeight;\n\n\n\tfunction freezeContentHeight() {\n\t\tcontent.css({\n\t\t\twidth: '100%',\n\t\t\theight: content.height(),\n\t\t\toverflow: 'hidden'\n\t\t});\n\t}\n\n\n\tfunction unfreezeContentHeight() {\n\t\tcontent.css({\n\t\t\twidth: '',\n\t\t\theight: '',\n\t\t\toverflow: ''\n\t\t});\n\t}\n\t\n\t\n\t\n\t/* Misc\n\t-----------------------------------------------------------------------------*/\n\t\n\n\tfunction getCalendar() {\n\t\treturn t;\n\t}\n\n\t\n\tfunction getView() {\n\t\treturn currentView;\n\t}\n\t\n\t\n\tfunction option(name, value) {\n\t\tvar newOptionHash;\n\n\t\tif (typeof name === 'string') {\n\t\t\tif (value === undefined) { // getter\n\t\t\t\treturn t.options[name];\n\t\t\t}\n\t\t\telse { // setter for individual option\n\t\t\t\tnewOptionHash = {};\n\t\t\t\tnewOptionHash[name] = value;\n\t\t\t\tsetOptions(newOptionHash);\n\t\t\t}\n\t\t}\n\t\telse if (typeof name === 'object') { // compound setter with object input\n\t\t\tsetOptions(name);\n\t\t}\n\t}\n\n\n\tfunction setOptions(newOptionHash) {\n\t\tvar optionCnt = 0;\n\t\tvar optionName;\n\n\t\tfor (optionName in newOptionHash) {\n\t\t\tt.dynamicOverrides[optionName] = newOptionHash[optionName];\n\t\t}\n\n\t\tt.viewSpecCache = {}; // the dynamic override invalidates the options in this cache, so just clear it\n\t\tt.populateOptionsHash(); // this.options needs to be recomputed after the dynamic override\n\n\t\t// trigger handlers after this.options has been updated\n\t\tfor (optionName in newOptionHash) {\n\t\t\tt.triggerOptionHandlers(optionName); // recall bindOption/bindOptions\n\t\t\toptionCnt++;\n\t\t}\n\n\t\t// special-case handling of single option change.\n\t\t// if only one option change, `optionName` will be its name.\n\t\tif (optionCnt === 1) {\n\t\t\tif (optionName === 'height' || optionName === 'contentHeight' || optionName === 'aspectRatio') {\n\t\t\t\tupdateSize(true); // true = allow recalculation of height\n\t\t\t\treturn;\n\t\t\t}\n\t\t\telse if (optionName === 'defaultDate') {\n\t\t\t\treturn; // can't change date this way. use gotoDate instead\n\t\t\t}\n\t\t\telse if (optionName === 'businessHours') {\n\t\t\t\tif (currentView) {\n\t\t\t\t\tcurrentView.unrenderBusinessHours();\n\t\t\t\t\tcurrentView.renderBusinessHours();\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\telse if (optionName === 'timezone') {\n\t\t\t\tt.rezoneArrayEventSources();\n\t\t\t\trefetchEvents();\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// catch-all. rerender the header and rebuild/rerender the current view\n\t\trenderHeader();\n\t\tviewsByType = {}; // even non-current views will be affected by this option change. do before rerender\n\t\treinitView();\n\t}\n\t\n\t\n\tfunction trigger(name, thisObj) { // overrides the Emitter's trigger method :(\n\t\tvar args = Array.prototype.slice.call(arguments, 2);\n\n\t\tthisObj = thisObj || _element;\n\t\tthis.triggerWith(name, thisObj, args); // Emitter's method\n\n\t\tif (t.options[name]) {\n\t\t\treturn t.options[name].apply(thisObj, args);\n\t\t}\n\t}\n\n\tt.initialize();\n}\n\n;;\n/*\nOptions binding/triggering system.\n*/\nCalendar.mixin({\n\n\t// A map of option names to arrays of handler objects. Initialized to {} in Calendar.\n\t// Format for a handler object:\n\t// {\n\t// func // callback function to be called upon change\n\t// names // option names whose values should be given to func\n\t// }\n\toptionHandlers: null, \n\n\t// Calls handlerFunc immediately, and when the given option has changed.\n\t// handlerFunc will be given the option value.\n\tbindOption: function(optionName, handlerFunc) {\n\t\tthis.bindOptions([ optionName ], handlerFunc);\n\t},\n\n\t// Calls handlerFunc immediately, and when any of the given options change.\n\t// handlerFunc will be given each option value as ordered function arguments.\n\tbindOptions: function(optionNames, handlerFunc) {\n\t\tvar handlerObj = { func: handlerFunc, names: optionNames };\n\t\tvar i;\n\n\t\tfor (i = 0; i < optionNames.length; i++) {\n\t\t\tthis.registerOptionHandlerObj(optionNames[i], handlerObj);\n\t\t}\n\n\t\tthis.triggerOptionHandlerObj(handlerObj);\n\t},\n\n\t// Puts the given handler object into the internal hash\n\tregisterOptionHandlerObj: function(optionName, handlerObj) {\n\t\t(this.optionHandlers[optionName] || (this.optionHandlers[optionName] = []))\n\t\t\t.push(handlerObj);\n\t},\n\n\t// Reports that the given option has changed, and calls all appropriate handlers.\n\ttriggerOptionHandlers: function(optionName) {\n\t\tvar handlerObjs = this.optionHandlers[optionName] || [];\n\t\tvar i;\n\n\t\tfor (i = 0; i < handlerObjs.length; i++) {\n\t\t\tthis.triggerOptionHandlerObj(handlerObjs[i]);\n\t\t}\n\t},\n\n\t// Calls the callback for a specific handler object, passing in the appropriate arguments.\n\ttriggerOptionHandlerObj: function(handlerObj) {\n\t\tvar optionNames = handlerObj.names;\n\t\tvar optionValues = [];\n\t\tvar i;\n\n\t\tfor (i = 0; i < optionNames.length; i++) {\n\t\t\toptionValues.push(this.options[optionNames[i]]);\n\t\t}\n\n\t\thandlerObj.func.apply(this, optionValues); // maintain the Calendar's `this` context\n\t}\n\n});\n\n;;\n\nCalendar.defaults = {\n\n\ttitleRangeSeparator: ' \\u2013 ', // en dash\n\tmonthYearFormat: 'MMMM YYYY', // required for en. other languages rely on datepicker computable option\n\n\tdefaultTimedEventDuration: '02:00:00',\n\tdefaultAllDayEventDuration: { days: 1 },\n\tforceEventDuration: false,\n\tnextDayThreshold: '09:00:00', // 9am\n\n\t// display\n\tdefaultView: 'month',\n\taspectRatio: 1.35,\n\theader: {\n\t\tleft: 'title',\n\t\tcenter: '',\n\t\tright: 'today prev,next'\n\t},\n\tweekends: true,\n\tweekNumbers: false,\n\n\tweekNumberTitle: 'W',\n\tweekNumberCalculation: 'local',\n\t\n\t//editable: false,\n\n\t//nowIndicator: false,\n\n\tscrollTime: '06:00:00',\n\t\n\t// event ajax\n\tlazyFetching: true,\n\tstartParam: 'start',\n\tendParam: 'end',\n\ttimezoneParam: 'timezone',\n\n\ttimezone: false,\n\n\t//allDayDefault: undefined,\n\n\t// locale\n\tisRTL: false,\n\tbuttonText: {\n\t\tprev: \"prev\",\n\t\tnext: \"next\",\n\t\tprevYear: \"prev year\",\n\t\tnextYear: \"next year\",\n\t\tyear: 'year', // TODO: locale files need to specify this\n\t\ttoday: 'today',\n\t\tmonth: 'month',\n\t\tweek: 'week',\n\t\tday: 'day'\n\t},\n\n\tbuttonIcons: {\n\t\tprev: 'left-single-arrow',\n\t\tnext: 'right-single-arrow',\n\t\tprevYear: 'left-double-arrow',\n\t\tnextYear: 'right-double-arrow'\n\t},\n\t\n\t// jquery-ui theming\n\ttheme: false,\n\tthemeButtonIcons: {\n\t\tprev: 'circle-triangle-w',\n\t\tnext: 'circle-triangle-e',\n\t\tprevYear: 'seek-prev',\n\t\tnextYear: 'seek-next'\n\t},\n\n\t//eventResizableFromStart: false,\n\tdragOpacity: .75,\n\tdragRevertDuration: 500,\n\tdragScroll: true,\n\t\n\t//selectable: false,\n\tunselectAuto: true,\n\t\n\tdropAccept: '*',\n\n\teventOrder: 'title',\n\n\teventLimit: false,\n\teventLimitText: 'more',\n\teventLimitClick: 'popover',\n\tdayPopoverFormat: 'LL',\n\t\n\thandleWindowResize: true,\n\twindowResizeDelay: 100, // milliseconds before an updateSize happens\n\n\tlongPressDelay: 1000\n\t\n};\n\n\nCalendar.englishDefaults = { // used by lang.js\n\tdayPopoverFormat: 'dddd, MMMM D'\n};\n\n\nCalendar.rtlDefaults = { // right-to-left defaults\n\theader: { // TODO: smarter solution (first/center/last ?)\n\t\tleft: 'next,prev today',\n\t\tcenter: '',\n\t\tright: 'title'\n\t},\n\tbuttonIcons: {\n\t\tprev: 'right-single-arrow',\n\t\tnext: 'left-single-arrow',\n\t\tprevYear: 'right-double-arrow',\n\t\tnextYear: 'left-double-arrow'\n\t},\n\tthemeButtonIcons: {\n\t\tprev: 'circle-triangle-e',\n\t\tnext: 'circle-triangle-w',\n\t\tnextYear: 'seek-prev',\n\t\tprevYear: 'seek-next'\n\t}\n};\n\n;;\n\nvar langOptionHash = FC.langs = {}; // initialize and expose\n\n\n// TODO: document the structure and ordering of a FullCalendar lang file\n// TODO: rename everything \"lang\" to \"locale\", like what the moment project did\n\n\n// Initialize jQuery UI datepicker translations while using some of the translations\n// Will set this as the default language for datepicker.\nFC.datepickerLang = function(langCode, dpLangCode, dpOptions) {\n\n\t// get the FullCalendar internal option hash for this language. create if necessary\n\tvar fcOptions = langOptionHash[langCode] || (langOptionHash[langCode] = {});\n\n\t// transfer some simple options from datepicker to fc\n\tfcOptions.isRTL = dpOptions.isRTL;\n\tfcOptions.weekNumberTitle = dpOptions.weekHeader;\n\n\t// compute some more complex options from datepicker\n\t$.each(dpComputableOptions, function(name, func) {\n\t\tfcOptions[name] = func(dpOptions);\n\t});\n\n\t// is jQuery UI Datepicker is on the page?\n\tif ($.datepicker) {\n\n\t\t// Register the language data.\n\t\t// FullCalendar and MomentJS use language codes like \"pt-br\" but Datepicker\n\t\t// does it like \"pt-BR\" or if it doesn't have the language, maybe just \"pt\".\n\t\t// Make an alias so the language can be referenced either way.\n\t\t$.datepicker.regional[dpLangCode] =\n\t\t\t$.datepicker.regional[langCode] = // alias\n\t\t\t\tdpOptions;\n\n\t\t// Alias 'en' to the default language data. Do this every time.\n\t\t$.datepicker.regional.en = $.datepicker.regional[''];\n\n\t\t// Set as Datepicker's global defaults.\n\t\t$.datepicker.setDefaults(dpOptions);\n\t}\n};\n\n\n// Sets FullCalendar-specific translations. Will set the language as the global default.\nFC.lang = function(langCode, newFcOptions) {\n\tvar fcOptions;\n\tvar momOptions;\n\n\t// get the FullCalendar internal option hash for this language. create if necessary\n\tfcOptions = langOptionHash[langCode] || (langOptionHash[langCode] = {});\n\n\t// provided new options for this language? merge them in\n\tif (newFcOptions) {\n\t\tfcOptions = langOptionHash[langCode] = mergeOptions([ fcOptions, newFcOptions ]);\n\t}\n\n\t// compute language options that weren't defined.\n\t// always do this. newFcOptions can be undefined when initializing from i18n file,\n\t// so no way to tell if this is an initialization or a default-setting.\n\tmomOptions = getMomentLocaleData(langCode); // will fall back to en\n\t$.each(momComputableOptions, function(name, func) {\n\t\tif (fcOptions[name] == null) {\n\t\t\tfcOptions[name] = func(momOptions, fcOptions);\n\t\t}\n\t});\n\n\t// set it as the default language for FullCalendar\n\tCalendar.defaults.lang = langCode;\n};\n\n\n// NOTE: can't guarantee any of these computations will run because not every language has datepicker\n// configs, so make sure there are English fallbacks for these in the defaults file.\nvar dpComputableOptions = {\n\n\tbuttonText: function(dpOptions) {\n\t\treturn {\n\t\t\t// the translations sometimes wrongly contain HTML entities\n\t\t\tprev: stripHtmlEntities(dpOptions.prevText),\n\t\t\tnext: stripHtmlEntities(dpOptions.nextText),\n\t\t\ttoday: stripHtmlEntities(dpOptions.currentText)\n\t\t};\n\t},\n\n\t// Produces format strings like \"MMMM YYYY\" -> \"September 2014\"\n\tmonthYearFormat: function(dpOptions) {\n\t\treturn dpOptions.showMonthAfterYear ?\n\t\t\t'YYYY[' + dpOptions.yearSuffix + '] MMMM' :\n\t\t\t'MMMM YYYY[' + dpOptions.yearSuffix + ']';\n\t}\n\n};\n\nvar momComputableOptions = {\n\n\t// Produces format strings like \"ddd M/D\" -> \"Fri 9/15\"\n\tdayOfMonthFormat: function(momOptions, fcOptions) {\n\t\tvar format = momOptions.longDateFormat('l'); // for the format like \"M/D/YYYY\"\n\n\t\t// strip the year off the edge, as well as other misc non-whitespace chars\n\t\tformat = format.replace(/^Y+[^\\w\\s]*|[^\\w\\s]*Y+$/g, '');\n\n\t\tif (fcOptions.isRTL) {\n\t\t\tformat += ' ddd'; // for RTL, add day-of-week to end\n\t\t}\n\t\telse {\n\t\t\tformat = 'ddd ' + format; // for LTR, add day-of-week to beginning\n\t\t}\n\t\treturn format;\n\t},\n\n\t// Produces format strings like \"h:mma\" -> \"6:00pm\"\n\tmediumTimeFormat: function(momOptions) { // can't be called `timeFormat` because collides with option\n\t\treturn momOptions.longDateFormat('LT')\n\t\t\t.replace(/\\s*a$/i, 'a'); // convert AM/PM/am/pm to lowercase. remove any spaces beforehand\n\t},\n\n\t// Produces format strings like \"h(:mm)a\" -> \"6pm\" / \"6:30pm\"\n\tsmallTimeFormat: function(momOptions) {\n\t\treturn momOptions.longDateFormat('LT')\n\t\t\t.replace(':mm', '(:mm)')\n\t\t\t.replace(/(\\Wmm)$/, '($1)') // like above, but for foreign langs\n\t\t\t.replace(/\\s*a$/i, 'a'); // convert AM/PM/am/pm to lowercase. remove any spaces beforehand\n\t},\n\n\t// Produces format strings like \"h(:mm)t\" -> \"6p\" / \"6:30p\"\n\textraSmallTimeFormat: function(momOptions) {\n\t\treturn momOptions.longDateFormat('LT')\n\t\t\t.replace(':mm', '(:mm)')\n\t\t\t.replace(/(\\Wmm)$/, '($1)') // like above, but for foreign langs\n\t\t\t.replace(/\\s*a$/i, 't'); // convert to AM/PM/am/pm to lowercase one-letter. remove any spaces beforehand\n\t},\n\n\t// Produces format strings like \"ha\" / \"H\" -> \"6pm\" / \"18\"\n\thourFormat: function(momOptions) {\n\t\treturn momOptions.longDateFormat('LT')\n\t\t\t.replace(':mm', '')\n\t\t\t.replace(/(\\Wmm)$/, '') // like above, but for foreign langs\n\t\t\t.replace(/\\s*a$/i, 'a'); // convert AM/PM/am/pm to lowercase. remove any spaces beforehand\n\t},\n\n\t// Produces format strings like \"h:mm\" -> \"6:30\" (with no AM/PM)\n\tnoMeridiemTimeFormat: function(momOptions) {\n\t\treturn momOptions.longDateFormat('LT')\n\t\t\t.replace(/\\s*a$/i, ''); // remove trailing AM/PM\n\t}\n\n};\n\n\n// options that should be computed off live calendar options (considers override options)\n// TODO: best place for this? related to lang?\n// TODO: flipping text based on isRTL is a bad idea because the CSS `direction` might want to handle it\nvar instanceComputableOptions = {\n\n\t// Produces format strings for results like \"Mo 16\"\n\tsmallDayDateFormat: function(options) {\n\t\treturn options.isRTL ?\n\t\t\t'D dd' :\n\t\t\t'dd D';\n\t},\n\n\t// Produces format strings for results like \"Wk 5\"\n\tweekFormat: function(options) {\n\t\treturn options.isRTL ?\n\t\t\t'w[ ' + options.weekNumberTitle + ']' :\n\t\t\t'[' + options.weekNumberTitle + ' ]w';\n\t},\n\n\t// Produces format strings for results like \"Wk5\"\n\tsmallWeekFormat: function(options) {\n\t\treturn options.isRTL ?\n\t\t\t'w[' + options.weekNumberTitle + ']' :\n\t\t\t'[' + options.weekNumberTitle + ']w';\n\t}\n\n};\n\nfunction populateInstanceComputableOptions(options) {\n\t$.each(instanceComputableOptions, function(name, func) {\n\t\tif (options[name] == null) {\n\t\t\toptions[name] = func(options);\n\t\t}\n\t});\n}\n\n\n// Returns moment's internal locale data. If doesn't exist, returns English.\n// Works with moment-pre-2.8\nfunction getMomentLocaleData(langCode) {\n\tvar func = moment.localeData || moment.langData;\n\treturn func.call(moment, langCode) ||\n\t\tfunc.call(moment, 'en'); // the newer localData could return null, so fall back to en\n}\n\n\n// Initialize English by forcing computation of moment-derived options.\n// Also, sets it as the default.\nFC.lang('en', Calendar.englishDefaults);\n\n;;\n\n/* Top toolbar area with buttons and title\n----------------------------------------------------------------------------------------------------------------------*/\n// TODO: rename all header-related things to \"toolbar\"\n\nfunction Header(calendar) {\n\tvar t = this;\n\t\n\t// exports\n\tt.render = render;\n\tt.removeElement = removeElement;\n\tt.updateTitle = updateTitle;\n\tt.activateButton = activateButton;\n\tt.deactivateButton = deactivateButton;\n\tt.disableButton = disableButton;\n\tt.enableButton = enableButton;\n\tt.getViewsWithButtons = getViewsWithButtons;\n\tt.el = null; // mirrors local `el`\n\t\n\t// locals\n\tvar el;\n\tvar viewsWithButtons = [];\n\tvar tm;\n\n\n\t// can be called repeatedly and will rerender\n\tfunction render() {\n\t\tvar options = calendar.options;\n\t\tvar sections = options.header;\n\n\t\ttm = options.theme ? 'ui' : 'fc';\n\n\t\tif (sections) {\n\t\t\tif (!el) {\n\t\t\t\tel = this.el = $(\"
\");\n\t\t\t}\n\t\t\telse {\n\t\t\t\tel.empty();\n\t\t\t}\n\t\t\tel.append(renderSection('left'))\n\t\t\t\t.append(renderSection('right'))\n\t\t\t\t.append(renderSection('center'))\n\t\t\t\t.append('
');\n\t\t}\n\t\telse {\n\t\t\tremoveElement();\n\t\t}\n\t}\n\t\n\t\n\tfunction removeElement() {\n\t\tif (el) {\n\t\t\tel.remove();\n\t\t\tel = t.el = null;\n\t\t}\n\t}\n\t\n\t\n\tfunction renderSection(position) {\n\t\tvar sectionEl = $('
');\n\t\tvar options = calendar.options;\n\t\tvar buttonStr = options.header[position];\n\n\t\tif (buttonStr) {\n\t\t\t$.each(buttonStr.split(' '), function(i) {\n\t\t\t\tvar groupChildren = $();\n\t\t\t\tvar isOnlyButtons = true;\n\t\t\t\tvar groupEl;\n\n\t\t\t\t$.each(this.split(','), function(j, buttonName) {\n\t\t\t\t\tvar customButtonProps;\n\t\t\t\t\tvar viewSpec;\n\t\t\t\t\tvar buttonClick;\n\t\t\t\t\tvar overrideText; // text explicitly set by calendar's constructor options. overcomes icons\n\t\t\t\t\tvar defaultText;\n\t\t\t\t\tvar themeIcon;\n\t\t\t\t\tvar normalIcon;\n\t\t\t\t\tvar innerHtml;\n\t\t\t\t\tvar classes;\n\t\t\t\t\tvar button; // the element\n\n\t\t\t\t\tif (buttonName == 'title') {\n\t\t\t\t\t\tgroupChildren = groupChildren.add($('

 

')); // we always want it to take up height\n\t\t\t\t\t\tisOnlyButtons = false;\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tif ((customButtonProps = (options.customButtons || {})[buttonName])) {\n\t\t\t\t\t\t\tbuttonClick = function(ev) {\n\t\t\t\t\t\t\t\tif (customButtonProps.click) {\n\t\t\t\t\t\t\t\t\tcustomButtonProps.click.call(button[0], ev);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\toverrideText = ''; // icons will override text\n\t\t\t\t\t\t\tdefaultText = customButtonProps.text;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if ((viewSpec = calendar.getViewSpec(buttonName))) {\n\t\t\t\t\t\t\tbuttonClick = function() {\n\t\t\t\t\t\t\t\tcalendar.changeView(buttonName);\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tviewsWithButtons.push(buttonName);\n\t\t\t\t\t\t\toverrideText = viewSpec.buttonTextOverride;\n\t\t\t\t\t\t\tdefaultText = viewSpec.buttonTextDefault;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (calendar[buttonName]) { // a calendar method\n\t\t\t\t\t\t\tbuttonClick = function() {\n\t\t\t\t\t\t\t\tcalendar[buttonName]();\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\toverrideText = (calendar.overrides.buttonText || {})[buttonName];\n\t\t\t\t\t\t\tdefaultText = options.buttonText[buttonName]; // everything else is considered default\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (buttonClick) {\n\n\t\t\t\t\t\t\tthemeIcon =\n\t\t\t\t\t\t\t\tcustomButtonProps ?\n\t\t\t\t\t\t\t\t\tcustomButtonProps.themeIcon :\n\t\t\t\t\t\t\t\t\toptions.themeButtonIcons[buttonName];\n\n\t\t\t\t\t\t\tnormalIcon =\n\t\t\t\t\t\t\t\tcustomButtonProps ?\n\t\t\t\t\t\t\t\t\tcustomButtonProps.icon :\n\t\t\t\t\t\t\t\t\toptions.buttonIcons[buttonName];\n\n\t\t\t\t\t\t\tif (overrideText) {\n\t\t\t\t\t\t\t\tinnerHtml = htmlEscape(overrideText);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if (themeIcon && options.theme) {\n\t\t\t\t\t\t\t\tinnerHtml = \"\";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if (normalIcon && !options.theme) {\n\t\t\t\t\t\t\t\tinnerHtml = \"\";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tinnerHtml = htmlEscape(defaultText);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tclasses = [\n\t\t\t\t\t\t\t\t'fc-' + buttonName + '-button',\n\t\t\t\t\t\t\t\ttm + '-button',\n\t\t\t\t\t\t\t\ttm + '-state-default'\n\t\t\t\t\t\t\t];\n\n\t\t\t\t\t\t\tbutton = $( // type=\"button\" so that it doesn't submit a form\n\t\t\t\t\t\t\t\t''\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t.click(function(ev) {\n\t\t\t\t\t\t\t\t\t// don't process clicks for disabled buttons\n\t\t\t\t\t\t\t\t\tif (!button.hasClass(tm + '-state-disabled')) {\n\n\t\t\t\t\t\t\t\t\t\tbuttonClick(ev);\n\n\t\t\t\t\t\t\t\t\t\t// after the click action, if the button becomes the \"active\" tab, or disabled,\n\t\t\t\t\t\t\t\t\t\t// it should never have a hover class, so remove it now.\n\t\t\t\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t\t\t\tbutton.hasClass(tm + '-state-active') ||\n\t\t\t\t\t\t\t\t\t\t\tbutton.hasClass(tm + '-state-disabled')\n\t\t\t\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t\t\t\tbutton.removeClass(tm + '-state-hover');\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t.mousedown(function() {\n\t\t\t\t\t\t\t\t\t// the *down* effect (mouse pressed in).\n\t\t\t\t\t\t\t\t\t// only on buttons that are not the \"active\" tab, or disabled\n\t\t\t\t\t\t\t\t\tbutton\n\t\t\t\t\t\t\t\t\t\t.not('.' + tm + '-state-active')\n\t\t\t\t\t\t\t\t\t\t.not('.' + tm + '-state-disabled')\n\t\t\t\t\t\t\t\t\t\t.addClass(tm + '-state-down');\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t.mouseup(function() {\n\t\t\t\t\t\t\t\t\t// undo the *down* effect\n\t\t\t\t\t\t\t\t\tbutton.removeClass(tm + '-state-down');\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t.hover(\n\t\t\t\t\t\t\t\t\tfunction() {\n\t\t\t\t\t\t\t\t\t\t// the *hover* effect.\n\t\t\t\t\t\t\t\t\t\t// only on buttons that are not the \"active\" tab, or disabled\n\t\t\t\t\t\t\t\t\t\tbutton\n\t\t\t\t\t\t\t\t\t\t\t.not('.' + tm + '-state-active')\n\t\t\t\t\t\t\t\t\t\t\t.not('.' + tm + '-state-disabled')\n\t\t\t\t\t\t\t\t\t\t\t.addClass(tm + '-state-hover');\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tfunction() {\n\t\t\t\t\t\t\t\t\t\t// undo the *hover* effect\n\t\t\t\t\t\t\t\t\t\tbutton\n\t\t\t\t\t\t\t\t\t\t\t.removeClass(tm + '-state-hover')\n\t\t\t\t\t\t\t\t\t\t\t.removeClass(tm + '-state-down'); // if mouseleave happens before mouseup\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\tgroupChildren = groupChildren.add(button);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tif (isOnlyButtons) {\n\t\t\t\t\tgroupChildren\n\t\t\t\t\t\t.first().addClass(tm + '-corner-left').end()\n\t\t\t\t\t\t.last().addClass(tm + '-corner-right').end();\n\t\t\t\t}\n\n\t\t\t\tif (groupChildren.length > 1) {\n\t\t\t\t\tgroupEl = $('
');\n\t\t\t\t\tif (isOnlyButtons) {\n\t\t\t\t\t\tgroupEl.addClass('fc-button-group');\n\t\t\t\t\t}\n\t\t\t\t\tgroupEl.append(groupChildren);\n\t\t\t\t\tsectionEl.append(groupEl);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tsectionEl.append(groupChildren); // 1 or 0 children\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\treturn sectionEl;\n\t}\n\t\n\t\n\tfunction updateTitle(text) {\n\t\tif (el) {\n\t\t\tel.find('h2').text(text);\n\t\t}\n\t}\n\t\n\t\n\tfunction activateButton(buttonName) {\n\t\tif (el) {\n\t\t\tel.find('.fc-' + buttonName + '-button')\n\t\t\t\t.addClass(tm + '-state-active');\n\t\t}\n\t}\n\t\n\t\n\tfunction deactivateButton(buttonName) {\n\t\tif (el) {\n\t\t\tel.find('.fc-' + buttonName + '-button')\n\t\t\t\t.removeClass(tm + '-state-active');\n\t\t}\n\t}\n\t\n\t\n\tfunction disableButton(buttonName) {\n\t\tif (el) {\n\t\t\tel.find('.fc-' + buttonName + '-button')\n\t\t\t\t.prop('disabled', true)\n\t\t\t\t.addClass(tm + '-state-disabled');\n\t\t}\n\t}\n\t\n\t\n\tfunction enableButton(buttonName) {\n\t\tif (el) {\n\t\t\tel.find('.fc-' + buttonName + '-button')\n\t\t\t\t.prop('disabled', false)\n\t\t\t\t.removeClass(tm + '-state-disabled');\n\t\t}\n\t}\n\n\n\tfunction getViewsWithButtons() {\n\t\treturn viewsWithButtons;\n\t}\n\n}\n\n;;\n\nFC.sourceNormalizers = [];\nFC.sourceFetchers = [];\n\nvar ajaxDefaults = {\n\tdataType: 'json',\n\tcache: false\n};\n\nvar eventGUID = 1;\n\n\nfunction EventManager() { // assumed to be a calendar\n\tvar t = this;\n\t\n\t\n\t// exports\n\tt.isFetchNeeded = isFetchNeeded;\n\tt.fetchEvents = fetchEvents;\n\tt.fetchEventSources = fetchEventSources;\n\tt.getEventSources = getEventSources;\n\tt.getEventSourceById = getEventSourceById;\n\tt.getEventSourcesByMatchArray = getEventSourcesByMatchArray;\n\tt.getEventSourcesByMatch = getEventSourcesByMatch;\n\tt.addEventSource = addEventSource;\n\tt.removeEventSource = removeEventSource;\n\tt.removeEventSources = removeEventSources;\n\tt.updateEvent = updateEvent;\n\tt.renderEvent = renderEvent;\n\tt.removeEvents = removeEvents;\n\tt.clientEvents = clientEvents;\n\tt.mutateEvent = mutateEvent;\n\tt.normalizeEventDates = normalizeEventDates;\n\tt.normalizeEventTimes = normalizeEventTimes;\n\t\n\t\n\t// imports\n\tvar reportEvents = t.reportEvents;\n\t\n\t\n\t// locals\n\tvar stickySource = { events: [] };\n\tvar sources = [ stickySource ];\n\tvar rangeStart, rangeEnd;\n\tvar pendingSourceCnt = 0; // outstanding fetch requests, max one per source\n\tvar cache = []; // holds events that have already been expanded\n\n\n\t$.each(\n\t\t(t.options.events ? [ t.options.events ] : []).concat(t.options.eventSources || []),\n\t\tfunction(i, sourceInput) {\n\t\t\tvar source = buildEventSource(sourceInput);\n\t\t\tif (source) {\n\t\t\t\tsources.push(source);\n\t\t\t}\n\t\t}\n\t);\n\t\n\t\n\t\n\t/* Fetching\n\t-----------------------------------------------------------------------------*/\n\n\n\t// start and end are assumed to be unzoned\n\tfunction isFetchNeeded(start, end) {\n\t\treturn !rangeStart || // nothing has been fetched yet?\n\t\t\tstart < rangeStart || end > rangeEnd; // is part of the new range outside of the old range?\n\t}\n\t\n\t\n\tfunction fetchEvents(start, end) {\n\t\trangeStart = start;\n\t\trangeEnd = end;\n\t\tfetchEventSources(sources, 'reset');\n\t}\n\n\n\t// expects an array of event source objects (the originals, not copies)\n\t// `specialFetchType` is an optimization parameter that affects purging of the event cache.\n\tfunction fetchEventSources(specificSources, specialFetchType) {\n\t\tvar i, source;\n\n\t\tif (specialFetchType === 'reset') {\n\t\t\tcache = [];\n\t\t}\n\t\telse if (specialFetchType !== 'add') {\n\t\t\tcache = excludeEventsBySources(cache, specificSources);\n\t\t}\n\n\t\tfor (i = 0; i < specificSources.length; i++) {\n\t\t\tsource = specificSources[i];\n\n\t\t\t// already-pending sources have already been accounted for in pendingSourceCnt\n\t\t\tif (source._status !== 'pending') {\n\t\t\t\tpendingSourceCnt++;\n\t\t\t}\n\n\t\t\tsource._fetchId = (source._fetchId || 0) + 1;\n\t\t\tsource._status = 'pending';\n\t\t}\n\n\t\tfor (i = 0; i < specificSources.length; i++) {\n\t\t\tsource = specificSources[i];\n\n\t\t\ttryFetchEventSource(source, source._fetchId);\n\t\t}\n\t}\n\n\n\t// fetches an event source and processes its result ONLY if it is still the current fetch.\n\t// caller is responsible for incrementing pendingSourceCnt first.\n\tfunction tryFetchEventSource(source, fetchId) {\n\t\t_fetchEventSource(source, function(eventInputs) {\n\t\t\tvar isArraySource = $.isArray(source.events);\n\t\t\tvar i, eventInput;\n\t\t\tvar abstractEvent;\n\n\t\t\tif (\n\t\t\t\t// is this the source's most recent fetch?\n\t\t\t\t// if not, rely on an upcoming fetch of this source to decrement pendingSourceCnt\n\t\t\t\tfetchId === source._fetchId &&\n\t\t\t\t// event source no longer valid?\n\t\t\t\tsource._status !== 'rejected'\n\t\t\t) {\n\t\t\t\tsource._status = 'resolved';\n\n\t\t\t\tif (eventInputs) {\n\t\t\t\t\tfor (i = 0; i < eventInputs.length; i++) {\n\t\t\t\t\t\teventInput = eventInputs[i];\n\n\t\t\t\t\t\tif (isArraySource) { // array sources have already been convert to Event Objects\n\t\t\t\t\t\t\tabstractEvent = eventInput;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tabstractEvent = buildEventFromInput(eventInput, source);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (abstractEvent) { // not false (an invalid event)\n\t\t\t\t\t\t\tcache.push.apply(\n\t\t\t\t\t\t\t\tcache,\n\t\t\t\t\t\t\t\texpandEvent(abstractEvent) // add individual expanded events to the cache\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tdecrementPendingSourceCnt();\n\t\t\t}\n\t\t});\n\t}\n\n\n\tfunction rejectEventSource(source) {\n\t\tvar wasPending = source._status === 'pending';\n\n\t\tsource._status = 'rejected';\n\n\t\tif (wasPending) {\n\t\t\tdecrementPendingSourceCnt();\n\t\t}\n\t}\n\n\n\tfunction decrementPendingSourceCnt() {\n\t\tpendingSourceCnt--;\n\t\tif (!pendingSourceCnt) {\n\t\t\treportEvents(cache);\n\t\t}\n\t}\n\t\n\t\n\tfunction _fetchEventSource(source, callback) {\n\t\tvar i;\n\t\tvar fetchers = FC.sourceFetchers;\n\t\tvar res;\n\n\t\tfor (i=0; i eventStart;\n\t}\n\n\n\tt.getEventCache = function() {\n\t\treturn cache;\n\t};\n\n}\n\n\n// hook for external libs to manipulate event properties upon creation.\n// should manipulate the event in-place.\nCalendar.prototype.normalizeEvent = function(event) {\n};\n\n\n// Does the given span (start, end, and other location information)\n// fully contain the other?\nCalendar.prototype.spanContainsSpan = function(outerSpan, innerSpan) {\n\tvar eventStart = outerSpan.start.clone().stripZone();\n\tvar eventEnd = this.getEventEnd(outerSpan).stripZone();\n\n\treturn innerSpan.start >= eventStart && innerSpan.end <= eventEnd;\n};\n\n\n// Returns a list of events that the given event should be compared against when being considered for a move to\n// the specified span. Attached to the Calendar's prototype because EventManager is a mixin for a Calendar.\nCalendar.prototype.getPeerEvents = function(span, event) {\n\tvar cache = this.getEventCache();\n\tvar peerEvents = [];\n\tvar i, otherEvent;\n\n\tfor (i = 0; i < cache.length; i++) {\n\t\totherEvent = cache[i];\n\t\tif (\n\t\t\t!event ||\n\t\t\tevent._id !== otherEvent._id // don't compare the event to itself or other related [repeating] events\n\t\t) {\n\t\t\tpeerEvents.push(otherEvent);\n\t\t}\n\t}\n\n\treturn peerEvents;\n};\n\n\n// updates the \"backup\" properties, which are preserved in order to compute diffs later on.\nfunction backupEventDates(event) {\n\tevent._allDay = event.allDay;\n\tevent._start = event.start.clone();\n\tevent._end = event.end ? event.end.clone() : null;\n}\n\n\n/* Business Hours\n-----------------------------------------------------------------------------------------*/\n\nvar BUSINESS_HOUR_EVENT_DEFAULTS = {\n\tid: '_fcBusinessHours', // will relate events from different calls to expandEvent\n\tstart: '09:00',\n\tend: '17:00',\n\tdow: [ 1, 2, 3, 4, 5 ], // monday - friday\n\trendering: 'inverse-background'\n\t// classNames are defined in businessHoursSegClasses\n};\n\n// Return events objects for business hours within the current view.\n// Abuse of our event system :(\nCalendar.prototype.getCurrentBusinessHourEvents = function(wholeDay) {\n\treturn this.computeBusinessHourEvents(wholeDay, this.options.businessHours);\n};\n\n// Given a raw input value from options, return events objects for business hours within the current view.\nCalendar.prototype.computeBusinessHourEvents = function(wholeDay, input) {\n\tif (input === true) {\n\t\treturn this.expandBusinessHourEvents(wholeDay, [ {} ]);\n\t}\n\telse if ($.isPlainObject(input)) {\n\t\treturn this.expandBusinessHourEvents(wholeDay, [ input ]);\n\t}\n\telse if ($.isArray(input)) {\n\t\treturn this.expandBusinessHourEvents(wholeDay, input, true);\n\t}\n\telse {\n\t\treturn [];\n\t}\n};\n\n// inputs expected to be an array of objects.\n// if ignoreNoDow is true, will ignore entries that don't specify a day-of-week (dow) key.\nCalendar.prototype.expandBusinessHourEvents = function(wholeDay, inputs, ignoreNoDow) {\n\tvar view = this.getView();\n\tvar events = [];\n\tvar i, input;\n\n\tfor (i = 0; i < inputs.length; i++) {\n\t\tinput = inputs[i];\n\n\t\tif (ignoreNoDow && !input.dow) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t// give defaults. will make a copy\n\t\tinput = $.extend({}, BUSINESS_HOUR_EVENT_DEFAULTS, input);\n\n\t\t// if a whole-day series is requested, clear the start/end times\n\t\tif (wholeDay) {\n\t\t\tinput.start = null;\n\t\t\tinput.end = null;\n\t\t}\n\n\t\tevents.push.apply(events, // append\n\t\t\tthis.expandEvent(\n\t\t\t\tthis.buildEventFromInput(input),\n\t\t\t\tview.start,\n\t\t\t\tview.end\n\t\t\t)\n\t\t);\n\t}\n\n\treturn events;\n};\n\n;;\n\n/* An abstract class for the \"basic\" views, as well as month view. Renders one or more rows of day cells.\n----------------------------------------------------------------------------------------------------------------------*/\n// It is a manager for a DayGrid subcomponent, which does most of the heavy lifting.\n// It is responsible for managing width/height.\n\nvar BasicView = FC.BasicView = View.extend({\n\n\tscroller: null,\n\n\tdayGridClass: DayGrid, // class the dayGrid will be instantiated from (overridable by subclasses)\n\tdayGrid: null, // the main subcomponent that does most of the heavy lifting\n\n\tdayNumbersVisible: false, // display day numbers on each day cell?\n\tweekNumbersVisible: false, // display week numbers along the side?\n\n\tweekNumberWidth: null, // width of all the week-number cells running down the side\n\n\theadContainerEl: null, // div that hold's the dayGrid's rendered date header\n\theadRowEl: null, // the fake row element of the day-of-week header\n\n\n\tinitialize: function() {\n\t\tthis.dayGrid = this.instantiateDayGrid();\n\n\t\tthis.scroller = new Scroller({\n\t\t\toverflowX: 'hidden',\n\t\t\toverflowY: 'auto'\n\t\t});\n\t},\n\n\n\t// Generates the DayGrid object this view needs. Draws from this.dayGridClass\n\tinstantiateDayGrid: function() {\n\t\t// generate a subclass on the fly with BasicView-specific behavior\n\t\t// TODO: cache this subclass\n\t\tvar subclass = this.dayGridClass.extend(basicDayGridMethods);\n\n\t\treturn new subclass(this);\n\t},\n\n\n\t// Sets the display range and computes all necessary dates\n\tsetRange: function(range) {\n\t\tView.prototype.setRange.call(this, range); // call the super-method\n\n\t\tthis.dayGrid.breakOnWeeks = /year|month|week/.test(this.intervalUnit); // do before setRange\n\t\tthis.dayGrid.setRange(range);\n\t},\n\n\n\t// Compute the value to feed into setRange. Overrides superclass.\n\tcomputeRange: function(date) {\n\t\tvar range = View.prototype.computeRange.call(this, date); // get value from the super-method\n\n\t\t// year and month views should be aligned with weeks. this is already done for week\n\t\tif (/year|month/.test(range.intervalUnit)) {\n\t\t\trange.start.startOf('week');\n\t\t\trange.start = this.skipHiddenDays(range.start);\n\n\t\t\t// make end-of-week if not already\n\t\t\tif (range.end.weekday()) {\n\t\t\t\trange.end.add(1, 'week').startOf('week');\n\t\t\t\trange.end = this.skipHiddenDays(range.end, -1, true); // exclusively move backwards\n\t\t\t}\n\t\t}\n\n\t\treturn range;\n\t},\n\n\n\t// Renders the view into `this.el`, which should already be assigned\n\trenderDates: function() {\n\n\t\tthis.dayNumbersVisible = this.dayGrid.rowCnt > 1; // TODO: make grid responsible\n\t\tthis.weekNumbersVisible = this.opt('weekNumbers');\n\t\tthis.dayGrid.numbersVisible = this.dayNumbersVisible || this.weekNumbersVisible;\n\n\t\tthis.el.addClass('fc-basic-view').html(this.renderSkeletonHtml());\n\t\tthis.renderHead();\n\n\t\tthis.scroller.render();\n\t\tvar dayGridContainerEl = this.scroller.el.addClass('fc-day-grid-container');\n\t\tvar dayGridEl = $('
').appendTo(dayGridContainerEl);\n\t\tthis.el.find('.fc-body > tr > td').append(dayGridContainerEl);\n\n\t\tthis.dayGrid.setElement(dayGridEl);\n\t\tthis.dayGrid.renderDates(this.hasRigidRows());\n\t},\n\n\n\t// render the day-of-week headers\n\trenderHead: function() {\n\t\tthis.headContainerEl =\n\t\t\tthis.el.find('.fc-head-container')\n\t\t\t\t.html(this.dayGrid.renderHeadHtml());\n\t\tthis.headRowEl = this.headContainerEl.find('.fc-row');\n\t},\n\n\n\t// Unrenders the content of the view. Since we haven't separated skeleton rendering from date rendering,\n\t// always completely kill the dayGrid's rendering.\n\tunrenderDates: function() {\n\t\tthis.dayGrid.unrenderDates();\n\t\tthis.dayGrid.removeElement();\n\t\tthis.scroller.destroy();\n\t},\n\n\n\trenderBusinessHours: function() {\n\t\tthis.dayGrid.renderBusinessHours();\n\t},\n\n\n\tunrenderBusinessHours: function() {\n\t\tthis.dayGrid.unrenderBusinessHours();\n\t},\n\n\n\t// Builds the HTML skeleton for the view.\n\t// The day-grid component will render inside of a container defined by this HTML.\n\trenderSkeletonHtml: function() {\n\t\treturn '' +\n\t\t\t'' +\n\t\t\t\t'' +\n\t\t\t\t\t'' +\n\t\t\t\t\t\t'' +\n\t\t\t\t\t'' +\n\t\t\t\t'' +\n\t\t\t\t'' +\n\t\t\t\t\t'' +\n\t\t\t\t\t\t'' +\n\t\t\t\t\t'' +\n\t\t\t\t'' +\n\t\t\t'
';\n\t},\n\n\n\t// Generates an HTML attribute string for setting the width of the week number column, if it is known\n\tweekNumberStyleAttr: function() {\n\t\tif (this.weekNumberWidth !== null) {\n\t\t\treturn 'style=\"width:' + this.weekNumberWidth + 'px\"';\n\t\t}\n\t\treturn '';\n\t},\n\n\n\t// Determines whether each row should have a constant height\n\thasRigidRows: function() {\n\t\tvar eventLimit = this.opt('eventLimit');\n\t\treturn eventLimit && typeof eventLimit !== 'number';\n\t},\n\n\n\t/* Dimensions\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// Refreshes the horizontal dimensions of the view\n\tupdateWidth: function() {\n\t\tif (this.weekNumbersVisible) {\n\t\t\t// Make sure all week number cells running down the side have the same width.\n\t\t\t// Record the width for cells created later.\n\t\t\tthis.weekNumberWidth = matchCellWidths(\n\t\t\t\tthis.el.find('.fc-week-number')\n\t\t\t);\n\t\t}\n\t},\n\n\n\t// Adjusts the vertical dimensions of the view to the specified values\n\tsetHeight: function(totalHeight, isAuto) {\n\t\tvar eventLimit = this.opt('eventLimit');\n\t\tvar scrollerHeight;\n\t\tvar scrollbarWidths;\n\n\t\t// reset all heights to be natural\n\t\tthis.scroller.clear();\n\t\tuncompensateScroll(this.headRowEl);\n\n\t\tthis.dayGrid.removeSegPopover(); // kill the \"more\" popover if displayed\n\n\t\t// is the event limit a constant level number?\n\t\tif (eventLimit && typeof eventLimit === 'number') {\n\t\t\tthis.dayGrid.limitRows(eventLimit); // limit the levels first so the height can redistribute after\n\t\t}\n\n\t\t// distribute the height to the rows\n\t\t// (totalHeight is a \"recommended\" value if isAuto)\n\t\tscrollerHeight = this.computeScrollerHeight(totalHeight);\n\t\tthis.setGridHeight(scrollerHeight, isAuto);\n\n\t\t// is the event limit dynamically calculated?\n\t\tif (eventLimit && typeof eventLimit !== 'number') {\n\t\t\tthis.dayGrid.limitRows(eventLimit); // limit the levels after the grid's row heights have been set\n\t\t}\n\n\t\tif (!isAuto) { // should we force dimensions of the scroll container?\n\n\t\t\tthis.scroller.setHeight(scrollerHeight);\n\t\t\tscrollbarWidths = this.scroller.getScrollbarWidths();\n\n\t\t\tif (scrollbarWidths.left || scrollbarWidths.right) { // using scrollbars?\n\n\t\t\t\tcompensateScroll(this.headRowEl, scrollbarWidths);\n\n\t\t\t\t// doing the scrollbar compensation might have created text overflow which created more height. redo\n\t\t\t\tscrollerHeight = this.computeScrollerHeight(totalHeight);\n\t\t\t\tthis.scroller.setHeight(scrollerHeight);\n\t\t\t}\n\n\t\t\t// guarantees the same scrollbar widths\n\t\t\tthis.scroller.lockOverflow(scrollbarWidths);\n\t\t}\n\t},\n\n\n\t// given a desired total height of the view, returns what the height of the scroller should be\n\tcomputeScrollerHeight: function(totalHeight) {\n\t\treturn totalHeight -\n\t\t\tsubtractInnerElHeight(this.el, this.scroller.el); // everything that's NOT the scroller\n\t},\n\n\n\t// Sets the height of just the DayGrid component in this view\n\tsetGridHeight: function(height, isAuto) {\n\t\tif (isAuto) {\n\t\t\tundistributeHeight(this.dayGrid.rowEls); // let the rows be their natural height with no expanding\n\t\t}\n\t\telse {\n\t\t\tdistributeHeight(this.dayGrid.rowEls, height, true); // true = compensate for height-hogging rows\n\t\t}\n\t},\n\n\n\t/* Scroll\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\tqueryScroll: function() {\n\t\treturn this.scroller.getScrollTop();\n\t},\n\n\n\tsetScroll: function(top) {\n\t\tthis.scroller.setScrollTop(top);\n\t},\n\n\n\t/* Hit Areas\n\t------------------------------------------------------------------------------------------------------------------*/\n\t// forward all hit-related method calls to dayGrid\n\n\n\tprepareHits: function() {\n\t\tthis.dayGrid.prepareHits();\n\t},\n\n\n\treleaseHits: function() {\n\t\tthis.dayGrid.releaseHits();\n\t},\n\n\n\tqueryHit: function(left, top) {\n\t\treturn this.dayGrid.queryHit(left, top);\n\t},\n\n\n\tgetHitSpan: function(hit) {\n\t\treturn this.dayGrid.getHitSpan(hit);\n\t},\n\n\n\tgetHitEl: function(hit) {\n\t\treturn this.dayGrid.getHitEl(hit);\n\t},\n\n\n\t/* Events\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// Renders the given events onto the view and populates the segments array\n\trenderEvents: function(events) {\n\t\tthis.dayGrid.renderEvents(events);\n\n\t\tthis.updateHeight(); // must compensate for events that overflow the row\n\t},\n\n\n\t// Retrieves all segment objects that are rendered in the view\n\tgetEventSegs: function() {\n\t\treturn this.dayGrid.getEventSegs();\n\t},\n\n\n\t// Unrenders all event elements and clears internal segment data\n\tunrenderEvents: function() {\n\t\tthis.dayGrid.unrenderEvents();\n\n\t\t// we DON'T need to call updateHeight() because:\n\t\t// A) a renderEvents() call always happens after this, which will eventually call updateHeight()\n\t\t// B) in IE8, this causes a flash whenever events are rerendered\n\t},\n\n\n\t/* Dragging (for both events and external elements)\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// A returned value of `true` signals that a mock \"helper\" event has been rendered.\n\trenderDrag: function(dropLocation, seg) {\n\t\treturn this.dayGrid.renderDrag(dropLocation, seg);\n\t},\n\n\n\tunrenderDrag: function() {\n\t\tthis.dayGrid.unrenderDrag();\n\t},\n\n\n\t/* Selection\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// Renders a visual indication of a selection\n\trenderSelection: function(span) {\n\t\tthis.dayGrid.renderSelection(span);\n\t},\n\n\n\t// Unrenders a visual indications of a selection\n\tunrenderSelection: function() {\n\t\tthis.dayGrid.unrenderSelection();\n\t}\n\n});\n\n\n// Methods that will customize the rendering behavior of the BasicView's dayGrid\nvar basicDayGridMethods = {\n\n\n\t// Generates the HTML that will go before the day-of week header cells\n\trenderHeadIntroHtml: function() {\n\t\tvar view = this.view;\n\n\t\tif (view.weekNumbersVisible) {\n\t\t\treturn '' +\n\t\t\t\t'' +\n\t\t\t\t\t'' + // needed for matchCellWidths\n\t\t\t\t\t\thtmlEscape(view.opt('weekNumberTitle')) +\n\t\t\t\t\t'' +\n\t\t\t\t'';\n\t\t}\n\n\t\treturn '';\n\t},\n\n\n\t// Generates the HTML that will go before content-skeleton cells that display the day/week numbers\n\trenderNumberIntroHtml: function(row) {\n\t\tvar view = this.view;\n\n\t\tif (view.weekNumbersVisible) {\n\t\t\treturn '' +\n\t\t\t\t'' +\n\t\t\t\t\t'' + // needed for matchCellWidths\n\t\t\t\t\t\tthis.getCellDate(row, 0).format('w') +\n\t\t\t\t\t'' +\n\t\t\t\t'';\n\t\t}\n\n\t\treturn '';\n\t},\n\n\n\t// Generates the HTML that goes before the day bg cells for each day-row\n\trenderBgIntroHtml: function() {\n\t\tvar view = this.view;\n\n\t\tif (view.weekNumbersVisible) {\n\t\t\treturn '';\n\t\t}\n\n\t\treturn '';\n\t},\n\n\n\t// Generates the HTML that goes before every other type of row generated by DayGrid.\n\t// Affects helper-skeleton and highlight-skeleton rows.\n\trenderIntroHtml: function() {\n\t\tvar view = this.view;\n\n\t\tif (view.weekNumbersVisible) {\n\t\t\treturn '';\n\t\t}\n\n\t\treturn '';\n\t}\n\n};\n\n;;\n\n/* A month view with day cells running in rows (one-per-week) and columns\n----------------------------------------------------------------------------------------------------------------------*/\n\nvar MonthView = FC.MonthView = BasicView.extend({\n\n\t// Produces information about what range to display\n\tcomputeRange: function(date) {\n\t\tvar range = BasicView.prototype.computeRange.call(this, date); // get value from super-method\n\t\tvar rowCnt;\n\n\t\t// ensure 6 weeks\n\t\tif (this.isFixedWeeks()) {\n\t\t\trowCnt = Math.ceil(range.end.diff(range.start, 'weeks', true)); // could be partial weeks due to hiddenDays\n\t\t\trange.end.add(6 - rowCnt, 'weeks');\n\t\t}\n\n\t\treturn range;\n\t},\n\n\n\t// Overrides the default BasicView behavior to have special multi-week auto-height logic\n\tsetGridHeight: function(height, isAuto) {\n\n\t\tisAuto = isAuto || this.opt('weekMode') === 'variable'; // LEGACY: weekMode is deprecated\n\n\t\t// if auto, make the height of each row the height that it would be if there were 6 weeks\n\t\tif (isAuto) {\n\t\t\theight *= this.rowCnt / 6;\n\t\t}\n\n\t\tdistributeHeight(this.dayGrid.rowEls, height, !isAuto); // if auto, don't compensate for height-hogging rows\n\t},\n\n\n\tisFixedWeeks: function() {\n\t\tvar weekMode = this.opt('weekMode'); // LEGACY: weekMode is deprecated\n\t\tif (weekMode) {\n\t\t\treturn weekMode === 'fixed'; // if any other type of weekMode, assume NOT fixed\n\t\t}\n\n\t\treturn this.opt('fixedWeekCount');\n\t}\n\n});\n\n;;\n\nfcViews.basic = {\n\t'class': BasicView\n};\n\nfcViews.basicDay = {\n\ttype: 'basic',\n\tduration: { days: 1 }\n};\n\nfcViews.basicWeek = {\n\ttype: 'basic',\n\tduration: { weeks: 1 }\n};\n\nfcViews.month = {\n\t'class': MonthView,\n\tduration: { months: 1 }, // important for prev/next\n\tdefaults: {\n\t\tfixedWeekCount: true\n\t}\n};\n;;\n\n/* An abstract class for all agenda-related views. Displays one more columns with time slots running vertically.\n----------------------------------------------------------------------------------------------------------------------*/\n// Is a manager for the TimeGrid subcomponent and possibly the DayGrid subcomponent (if allDaySlot is on).\n// Responsible for managing width/height.\n\nvar AgendaView = FC.AgendaView = View.extend({\n\n\tscroller: null,\n\n\ttimeGridClass: TimeGrid, // class used to instantiate the timeGrid. subclasses can override\n\ttimeGrid: null, // the main time-grid subcomponent of this view\n\n\tdayGridClass: DayGrid, // class used to instantiate the dayGrid. subclasses can override\n\tdayGrid: null, // the \"all-day\" subcomponent. if all-day is turned off, this will be null\n\n\taxisWidth: null, // the width of the time axis running down the side\n\n\theadContainerEl: null, // div that hold's the timeGrid's rendered date header\n\tnoScrollRowEls: null, // set of fake row elements that must compensate when scroller has scrollbars\n\n\t// when the time-grid isn't tall enough to occupy the given height, we render an
underneath\n\tbottomRuleEl: null,\n\n\n\tinitialize: function() {\n\t\tthis.timeGrid = this.instantiateTimeGrid();\n\n\t\tif (this.opt('allDaySlot')) { // should we display the \"all-day\" area?\n\t\t\tthis.dayGrid = this.instantiateDayGrid(); // the all-day subcomponent of this view\n\t\t}\n\n\t\tthis.scroller = new Scroller({\n\t\t\toverflowX: 'hidden',\n\t\t\toverflowY: 'auto'\n\t\t});\n\t},\n\n\n\t// Instantiates the TimeGrid object this view needs. Draws from this.timeGridClass\n\tinstantiateTimeGrid: function() {\n\t\tvar subclass = this.timeGridClass.extend(agendaTimeGridMethods);\n\n\t\treturn new subclass(this);\n\t},\n\n\n\t// Instantiates the DayGrid object this view might need. Draws from this.dayGridClass\n\tinstantiateDayGrid: function() {\n\t\tvar subclass = this.dayGridClass.extend(agendaDayGridMethods);\n\n\t\treturn new subclass(this);\n\t},\n\n\n\t/* Rendering\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// Sets the display range and computes all necessary dates\n\tsetRange: function(range) {\n\t\tView.prototype.setRange.call(this, range); // call the super-method\n\n\t\tthis.timeGrid.setRange(range);\n\t\tif (this.dayGrid) {\n\t\t\tthis.dayGrid.setRange(range);\n\t\t}\n\t},\n\n\n\t// Renders the view into `this.el`, which has already been assigned\n\trenderDates: function() {\n\n\t\tthis.el.addClass('fc-agenda-view').html(this.renderSkeletonHtml());\n\t\tthis.renderHead();\n\n\t\tthis.scroller.render();\n\t\tvar timeGridWrapEl = this.scroller.el.addClass('fc-time-grid-container');\n\t\tvar timeGridEl = $('
').appendTo(timeGridWrapEl);\n\t\tthis.el.find('.fc-body > tr > td').append(timeGridWrapEl);\n\n\t\tthis.timeGrid.setElement(timeGridEl);\n\t\tthis.timeGrid.renderDates();\n\n\t\t// the
that sometimes displays under the time-grid\n\t\tthis.bottomRuleEl = $('
')\n\t\t\t.appendTo(this.timeGrid.el); // inject it into the time-grid\n\n\t\tif (this.dayGrid) {\n\t\t\tthis.dayGrid.setElement(this.el.find('.fc-day-grid'));\n\t\t\tthis.dayGrid.renderDates();\n\n\t\t\t// have the day-grid extend it's coordinate area over the
dividing the two grids\n\t\t\tthis.dayGrid.bottomCoordPadding = this.dayGrid.el.next('hr').outerHeight();\n\t\t}\n\n\t\tthis.noScrollRowEls = this.el.find('.fc-row:not(.fc-scroller *)'); // fake rows not within the scroller\n\t},\n\n\n\t// render the day-of-week headers\n\trenderHead: function() {\n\t\tthis.headContainerEl =\n\t\t\tthis.el.find('.fc-head-container')\n\t\t\t\t.html(this.timeGrid.renderHeadHtml());\n\t},\n\n\n\t// Unrenders the content of the view. Since we haven't separated skeleton rendering from date rendering,\n\t// always completely kill each grid's rendering.\n\tunrenderDates: function() {\n\t\tthis.timeGrid.unrenderDates();\n\t\tthis.timeGrid.removeElement();\n\n\t\tif (this.dayGrid) {\n\t\t\tthis.dayGrid.unrenderDates();\n\t\t\tthis.dayGrid.removeElement();\n\t\t}\n\n\t\tthis.scroller.destroy();\n\t},\n\n\n\t// Builds the HTML skeleton for the view.\n\t// The day-grid and time-grid components will render inside containers defined by this HTML.\n\trenderSkeletonHtml: function() {\n\t\treturn '' +\n\t\t\t'' +\n\t\t\t\t'' +\n\t\t\t\t\t'' +\n\t\t\t\t\t\t'' +\n\t\t\t\t\t'' +\n\t\t\t\t'' +\n\t\t\t\t'' +\n\t\t\t\t\t'' +\n\t\t\t\t\t\t'' +\n\t\t\t\t\t'' +\n\t\t\t\t'' +\n\t\t\t'
' +\n\t\t\t\t\t\t\t(this.dayGrid ?\n\t\t\t\t\t\t\t\t'
' +\n\t\t\t\t\t\t\t\t'
' :\n\t\t\t\t\t\t\t\t''\n\t\t\t\t\t\t\t\t) +\n\t\t\t\t\t\t'
';\n\t},\n\n\n\t// Generates an HTML attribute string for setting the width of the axis, if it is known\n\taxisStyleAttr: function() {\n\t\tif (this.axisWidth !== null) {\n\t\t\t return 'style=\"width:' + this.axisWidth + 'px\"';\n\t\t}\n\t\treturn '';\n\t},\n\n\n\t/* Business Hours\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\trenderBusinessHours: function() {\n\t\tthis.timeGrid.renderBusinessHours();\n\n\t\tif (this.dayGrid) {\n\t\t\tthis.dayGrid.renderBusinessHours();\n\t\t}\n\t},\n\n\n\tunrenderBusinessHours: function() {\n\t\tthis.timeGrid.unrenderBusinessHours();\n\n\t\tif (this.dayGrid) {\n\t\t\tthis.dayGrid.unrenderBusinessHours();\n\t\t}\n\t},\n\n\n\t/* Now Indicator\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\tgetNowIndicatorUnit: function() {\n\t\treturn this.timeGrid.getNowIndicatorUnit();\n\t},\n\n\n\trenderNowIndicator: function(date) {\n\t\tthis.timeGrid.renderNowIndicator(date);\n\t},\n\n\n\tunrenderNowIndicator: function() {\n\t\tthis.timeGrid.unrenderNowIndicator();\n\t},\n\n\n\t/* Dimensions\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\tupdateSize: function(isResize) {\n\t\tthis.timeGrid.updateSize(isResize);\n\n\t\tView.prototype.updateSize.call(this, isResize); // call the super-method\n\t},\n\n\n\t// Refreshes the horizontal dimensions of the view\n\tupdateWidth: function() {\n\t\t// make all axis cells line up, and record the width so newly created axis cells will have it\n\t\tthis.axisWidth = matchCellWidths(this.el.find('.fc-axis'));\n\t},\n\n\n\t// Adjusts the vertical dimensions of the view to the specified values\n\tsetHeight: function(totalHeight, isAuto) {\n\t\tvar eventLimit;\n\t\tvar scrollerHeight;\n\t\tvar scrollbarWidths;\n\n\t\t// reset all dimensions back to the original state\n\t\tthis.bottomRuleEl.hide(); // .show() will be called later if this
is necessary\n\t\tthis.scroller.clear(); // sets height to 'auto' and clears overflow\n\t\tuncompensateScroll(this.noScrollRowEls);\n\n\t\t// limit number of events in the all-day area\n\t\tif (this.dayGrid) {\n\t\t\tthis.dayGrid.removeSegPopover(); // kill the \"more\" popover if displayed\n\n\t\t\teventLimit = this.opt('eventLimit');\n\t\t\tif (eventLimit && typeof eventLimit !== 'number') {\n\t\t\t\teventLimit = AGENDA_ALL_DAY_EVENT_LIMIT; // make sure \"auto\" goes to a real number\n\t\t\t}\n\t\t\tif (eventLimit) {\n\t\t\t\tthis.dayGrid.limitRows(eventLimit);\n\t\t\t}\n\t\t}\n\n\t\tif (!isAuto) { // should we force dimensions of the scroll container?\n\n\t\t\tscrollerHeight = this.computeScrollerHeight(totalHeight);\n\t\t\tthis.scroller.setHeight(scrollerHeight);\n\t\t\tscrollbarWidths = this.scroller.getScrollbarWidths();\n\n\t\t\tif (scrollbarWidths.left || scrollbarWidths.right) { // using scrollbars?\n\n\t\t\t\t// make the all-day and header rows lines up\n\t\t\t\tcompensateScroll(this.noScrollRowEls, scrollbarWidths);\n\n\t\t\t\t// the scrollbar compensation might have changed text flow, which might affect height, so recalculate\n\t\t\t\t// and reapply the desired height to the scroller.\n\t\t\t\tscrollerHeight = this.computeScrollerHeight(totalHeight);\n\t\t\t\tthis.scroller.setHeight(scrollerHeight);\n\t\t\t}\n\n\t\t\t// guarantees the same scrollbar widths\n\t\t\tthis.scroller.lockOverflow(scrollbarWidths);\n\n\t\t\t// if there's any space below the slats, show the horizontal rule.\n\t\t\t// this won't cause any new overflow, because lockOverflow already called.\n\t\t\tif (this.timeGrid.getTotalSlatHeight() < scrollerHeight) {\n\t\t\t\tthis.bottomRuleEl.show();\n\t\t\t}\n\t\t}\n\t},\n\n\n\t// given a desired total height of the view, returns what the height of the scroller should be\n\tcomputeScrollerHeight: function(totalHeight) {\n\t\treturn totalHeight -\n\t\t\tsubtractInnerElHeight(this.el, this.scroller.el); // everything that's NOT the scroller\n\t},\n\n\n\t/* Scroll\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// Computes the initial pre-configured scroll state prior to allowing the user to change it\n\tcomputeInitialScroll: function() {\n\t\tvar scrollTime = moment.duration(this.opt('scrollTime'));\n\t\tvar top = this.timeGrid.computeTimeTop(scrollTime);\n\n\t\t// zoom can give weird floating-point values. rather scroll a little bit further\n\t\ttop = Math.ceil(top);\n\n\t\tif (top) {\n\t\t\ttop++; // to overcome top border that slots beyond the first have. looks better\n\t\t}\n\n\t\treturn top;\n\t},\n\n\n\tqueryScroll: function() {\n\t\treturn this.scroller.getScrollTop();\n\t},\n\n\n\tsetScroll: function(top) {\n\t\tthis.scroller.setScrollTop(top);\n\t},\n\n\n\t/* Hit Areas\n\t------------------------------------------------------------------------------------------------------------------*/\n\t// forward all hit-related method calls to the grids (dayGrid might not be defined)\n\n\n\tprepareHits: function() {\n\t\tthis.timeGrid.prepareHits();\n\t\tif (this.dayGrid) {\n\t\t\tthis.dayGrid.prepareHits();\n\t\t}\n\t},\n\n\n\treleaseHits: function() {\n\t\tthis.timeGrid.releaseHits();\n\t\tif (this.dayGrid) {\n\t\t\tthis.dayGrid.releaseHits();\n\t\t}\n\t},\n\n\n\tqueryHit: function(left, top) {\n\t\tvar hit = this.timeGrid.queryHit(left, top);\n\n\t\tif (!hit && this.dayGrid) {\n\t\t\thit = this.dayGrid.queryHit(left, top);\n\t\t}\n\n\t\treturn hit;\n\t},\n\n\n\tgetHitSpan: function(hit) {\n\t\t// TODO: hit.component is set as a hack to identify where the hit came from\n\t\treturn hit.component.getHitSpan(hit);\n\t},\n\n\n\tgetHitEl: function(hit) {\n\t\t// TODO: hit.component is set as a hack to identify where the hit came from\n\t\treturn hit.component.getHitEl(hit);\n\t},\n\n\n\t/* Events\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// Renders events onto the view and populates the View's segment array\n\trenderEvents: function(events) {\n\t\tvar dayEvents = [];\n\t\tvar timedEvents = [];\n\t\tvar daySegs = [];\n\t\tvar timedSegs;\n\t\tvar i;\n\n\t\t// separate the events into all-day and timed\n\t\tfor (i = 0; i < events.length; i++) {\n\t\t\tif (events[i].allDay) {\n\t\t\t\tdayEvents.push(events[i]);\n\t\t\t}\n\t\t\telse {\n\t\t\t\ttimedEvents.push(events[i]);\n\t\t\t}\n\t\t}\n\n\t\t// render the events in the subcomponents\n\t\ttimedSegs = this.timeGrid.renderEvents(timedEvents);\n\t\tif (this.dayGrid) {\n\t\t\tdaySegs = this.dayGrid.renderEvents(dayEvents);\n\t\t}\n\n\t\t// the all-day area is flexible and might have a lot of events, so shift the height\n\t\tthis.updateHeight();\n\t},\n\n\n\t// Retrieves all segment objects that are rendered in the view\n\tgetEventSegs: function() {\n\t\treturn this.timeGrid.getEventSegs().concat(\n\t\t\tthis.dayGrid ? this.dayGrid.getEventSegs() : []\n\t\t);\n\t},\n\n\n\t// Unrenders all event elements and clears internal segment data\n\tunrenderEvents: function() {\n\n\t\t// unrender the events in the subcomponents\n\t\tthis.timeGrid.unrenderEvents();\n\t\tif (this.dayGrid) {\n\t\t\tthis.dayGrid.unrenderEvents();\n\t\t}\n\n\t\t// we DON'T need to call updateHeight() because:\n\t\t// A) a renderEvents() call always happens after this, which will eventually call updateHeight()\n\t\t// B) in IE8, this causes a flash whenever events are rerendered\n\t},\n\n\n\t/* Dragging (for events and external elements)\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// A returned value of `true` signals that a mock \"helper\" event has been rendered.\n\trenderDrag: function(dropLocation, seg) {\n\t\tif (dropLocation.start.hasTime()) {\n\t\t\treturn this.timeGrid.renderDrag(dropLocation, seg);\n\t\t}\n\t\telse if (this.dayGrid) {\n\t\t\treturn this.dayGrid.renderDrag(dropLocation, seg);\n\t\t}\n\t},\n\n\n\tunrenderDrag: function() {\n\t\tthis.timeGrid.unrenderDrag();\n\t\tif (this.dayGrid) {\n\t\t\tthis.dayGrid.unrenderDrag();\n\t\t}\n\t},\n\n\n\t/* Selection\n\t------------------------------------------------------------------------------------------------------------------*/\n\n\n\t// Renders a visual indication of a selection\n\trenderSelection: function(span) {\n\t\tif (span.start.hasTime() || span.end.hasTime()) {\n\t\t\tthis.timeGrid.renderSelection(span);\n\t\t}\n\t\telse if (this.dayGrid) {\n\t\t\tthis.dayGrid.renderSelection(span);\n\t\t}\n\t},\n\n\n\t// Unrenders a visual indications of a selection\n\tunrenderSelection: function() {\n\t\tthis.timeGrid.unrenderSelection();\n\t\tif (this.dayGrid) {\n\t\t\tthis.dayGrid.unrenderSelection();\n\t\t}\n\t}\n\n});\n\n\n// Methods that will customize the rendering behavior of the AgendaView's timeGrid\n// TODO: move into TimeGrid\nvar agendaTimeGridMethods = {\n\n\n\t// Generates the HTML that will go before the day-of week header cells\n\trenderHeadIntroHtml: function() {\n\t\tvar view = this.view;\n\t\tvar weekText;\n\n\t\tif (view.opt('weekNumbers')) {\n\t\t\tweekText = this.start.format(view.opt('smallWeekFormat'));\n\n\t\t\treturn '' +\n\t\t\t\t'' +\n\t\t\t\t\t'' + // needed for matchCellWidths\n\t\t\t\t\t\thtmlEscape(weekText) +\n\t\t\t\t\t'' +\n\t\t\t\t'';\n\t\t}\n\t\telse {\n\t\t\treturn '';\n\t\t}\n\t},\n\n\n\t// Generates the HTML that goes before the bg of the TimeGrid slot area. Long vertical column.\n\trenderBgIntroHtml: function() {\n\t\tvar view = this.view;\n\n\t\treturn '';\n\t},\n\n\n\t// Generates the HTML that goes before all other types of cells.\n\t// Affects content-skeleton, helper-skeleton, highlight-skeleton for both the time-grid and day-grid.\n\trenderIntroHtml: function() {\n\t\tvar view = this.view;\n\n\t\treturn '';\n\t}\n\n};\n\n\n// Methods that will customize the rendering behavior of the AgendaView's dayGrid\nvar agendaDayGridMethods = {\n\n\n\t// Generates the HTML that goes before the all-day cells\n\trenderBgIntroHtml: function() {\n\t\tvar view = this.view;\n\n\t\treturn '' +\n\t\t\t'' +\n\t\t\t\t'' + // needed for matchCellWidths\n\t\t\t\t\t(view.opt('allDayHtml') || htmlEscape(view.opt('allDayText'))) +\n\t\t\t\t'' +\n\t\t\t'';\n\t},\n\n\n\t// Generates the HTML that goes before all other types of cells.\n\t// Affects content-skeleton, helper-skeleton, highlight-skeleton for both the time-grid and day-grid.\n\trenderIntroHtml: function() {\n\t\tvar view = this.view;\n\n\t\treturn '';\n\t}\n\n};\n\n;;\n\nvar AGENDA_ALL_DAY_EVENT_LIMIT = 5;\n\n// potential nice values for the slot-duration and interval-duration\n// from largest to smallest\nvar AGENDA_STOCK_SUB_DURATIONS = [\n\t{ hours: 1 },\n\t{ minutes: 30 },\n\t{ minutes: 15 },\n\t{ seconds: 30 },\n\t{ seconds: 15 }\n];\n\nfcViews.agenda = {\n\t'class': AgendaView,\n\tdefaults: {\n\t\tallDaySlot: true,\n\t\tallDayText: 'all-day',\n\t\tslotDuration: '00:30:00',\n\t\tminTime: '00:00:00',\n\t\tmaxTime: '24:00:00',\n\t\tslotEventOverlap: true // a bad name. confused with overlap/constraint system\n\t}\n};\n\nfcViews.agendaDay = {\n\ttype: 'agenda',\n\tduration: { days: 1 }\n};\n\nfcViews.agendaWeek = {\n\ttype: 'agenda',\n\tduration: { weeks: 1 }\n};\n;;\n\r\nreturn FC; // export for Node/CommonJS\r\n});"],"sourceRoot":"/source/"}