| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423 |
- /* An abstract class for the "basic" views, as well as month view. Renders one or more rows of day cells.
- ----------------------------------------------------------------------------------------------------------------------*/
- // It is a manager for a DayGrid subcomponent, which does most of the heavy lifting.
- // It is responsible for managing width/height.
- var BasicView = FC.BasicView = View.extend({
- scroller: null,
- dayGridClass: DayGrid, // class the dayGrid will be instantiated from (overridable by subclasses)
- dayGrid: null, // the main subcomponent that does most of the heavy lifting
- dayNumbersVisible: false, // display day numbers on each day cell?
- colWeekNumbersVisible: false, // display week numbers along the side?
- cellWeekNumbersVisible: false, // display week numbers in day cell?
- weekNumberWidth: null, // width of all the week-number cells running down the side
- headContainerEl: null, // div that hold's the dayGrid's rendered date header
- headRowEl: null, // the fake row element of the day-of-week header
- initialize: function() {
- this.dayGrid = this.instantiateDayGrid();
- this.scroller = new Scroller({
- overflowX: 'hidden',
- overflowY: 'auto'
- });
- },
- // Generates the DayGrid object this view needs. Draws from this.dayGridClass
- instantiateDayGrid: function() {
- // generate a subclass on the fly with BasicView-specific behavior
- // TODO: cache this subclass
- var subclass = this.dayGridClass.extend(basicDayGridMethods);
- return new subclass(this);
- },
- // Computes the date range that will be rendered.
- buildRenderRange: function(currentRange, unit) {
- var renderRange = View.prototype.buildRenderRange.apply(this, arguments);
- // year and month views should be aligned with weeks. this is already done for week
- if (/^(year|month)$/.test(unit)) {
- renderRange.start.startOf('week');
- // make end-of-week if not already
- if (renderRange.end.weekday()) {
- renderRange.end.add(1, 'week').startOf('week'); // exclusively move backwards
- }
- }
- return this.trimHiddenDays(renderRange);
- },
- // Renders the view into `this.el`, which should already be assigned
- renderDates: function() {
- this.dayGrid.breakOnWeeks = /year|month|week/.test(this.currentRangeUnit); // do before Grid::setRange
- this.dayGrid.setRange(this.renderRange);
- this.dayNumbersVisible = this.dayGrid.rowCnt > 1; // TODO: make grid responsible
- if (this.opt('weekNumbers')) {
- if (this.opt('weekNumbersWithinDays')) {
- this.cellWeekNumbersVisible = true;
- this.colWeekNumbersVisible = false;
- }
- else {
- this.cellWeekNumbersVisible = false;
- this.colWeekNumbersVisible = true;
- };
- }
- this.dayGrid.numbersVisible = this.dayNumbersVisible ||
- this.cellWeekNumbersVisible || this.colWeekNumbersVisible;
- this.el.addClass('fc-basic-view').html(this.renderSkeletonHtml());
- this.renderHead();
- this.scroller.render();
- var dayGridContainerEl = this.scroller.el.addClass('fc-day-grid-container');
- var dayGridEl = $('<div class="fc-day-grid" />').appendTo(dayGridContainerEl);
- this.el.find('.fc-body > tr > td').append(dayGridContainerEl);
- this.dayGrid.setElement(dayGridEl);
- this.dayGrid.renderDates(this.hasRigidRows());
- },
- // render the day-of-week headers
- renderHead: function() {
- this.headContainerEl =
- this.el.find('.fc-head-container')
- .html(this.dayGrid.renderHeadHtml());
- this.headRowEl = this.headContainerEl.find('.fc-row');
- },
- // Unrenders the content of the view. Since we haven't separated skeleton rendering from date rendering,
- // always completely kill the dayGrid's rendering.
- unrenderDates: function() {
- this.dayGrid.unrenderDates();
- this.dayGrid.removeElement();
- this.scroller.destroy();
- },
- renderBusinessHours: function() {
- this.dayGrid.renderBusinessHours();
- },
- unrenderBusinessHours: function() {
- this.dayGrid.unrenderBusinessHours();
- },
- // Builds the HTML skeleton for the view.
- // The day-grid component will render inside of a container defined by this HTML.
- renderSkeletonHtml: function() {
- return '' +
- '<table>' +
- '<thead class="fc-head">' +
- '<tr>' +
- '<td class="fc-head-container ' + this.widgetHeaderClass + '"></td>' +
- '</tr>' +
- '</thead>' +
- '<tbody class="fc-body">' +
- '<tr>' +
- '<td class="' + this.widgetContentClass + '"></td>' +
- '</tr>' +
- '</tbody>' +
- '</table>';
- },
- // Generates an HTML attribute string for setting the width of the week number column, if it is known
- weekNumberStyleAttr: function() {
- if (this.weekNumberWidth !== null) {
- return 'style="width:' + this.weekNumberWidth + 'px"';
- }
- return '';
- },
- // Determines whether each row should have a constant height
- hasRigidRows: function() {
- var eventLimit = this.opt('eventLimit');
- return eventLimit && typeof eventLimit !== 'number';
- },
- /* Dimensions
- ------------------------------------------------------------------------------------------------------------------*/
- // Refreshes the horizontal dimensions of the view
- updateWidth: function() {
- if (this.colWeekNumbersVisible) {
- // Make sure all week number cells running down the side have the same width.
- // Record the width for cells created later.
- this.weekNumberWidth = matchCellWidths(
- this.el.find('.fc-week-number')
- );
- }
- },
- // Adjusts the vertical dimensions of the view to the specified values
- setHeight: function(totalHeight, isAuto) {
- var eventLimit = this.opt('eventLimit');
- var scrollerHeight;
- var scrollbarWidths;
- // reset all heights to be natural
- this.scroller.clear();
- uncompensateScroll(this.headRowEl);
- this.dayGrid.removeSegPopover(); // kill the "more" popover if displayed
- // is the event limit a constant level number?
- if (eventLimit && typeof eventLimit === 'number') {
- this.dayGrid.limitRows(eventLimit); // limit the levels first so the height can redistribute after
- }
- // distribute the height to the rows
- // (totalHeight is a "recommended" value if isAuto)
- scrollerHeight = this.computeScrollerHeight(totalHeight);
- this.setGridHeight(scrollerHeight, isAuto);
- // is the event limit dynamically calculated?
- if (eventLimit && typeof eventLimit !== 'number') {
- this.dayGrid.limitRows(eventLimit); // limit the levels after the grid's row heights have been set
- }
- if (!isAuto) { // should we force dimensions of the scroll container?
- this.scroller.setHeight(scrollerHeight);
- scrollbarWidths = this.scroller.getScrollbarWidths();
- if (scrollbarWidths.left || scrollbarWidths.right) { // using scrollbars?
- compensateScroll(this.headRowEl, scrollbarWidths);
- // doing the scrollbar compensation might have created text overflow which created more height. redo
- scrollerHeight = this.computeScrollerHeight(totalHeight);
- this.scroller.setHeight(scrollerHeight);
- }
- // guarantees the same scrollbar widths
- this.scroller.lockOverflow(scrollbarWidths);
- }
- },
- // given a desired total height of the view, returns what the height of the scroller should be
- computeScrollerHeight: function(totalHeight) {
- return totalHeight -
- subtractInnerElHeight(this.el, this.scroller.el); // everything that's NOT the scroller
- },
- // Sets the height of just the DayGrid component in this view
- setGridHeight: function(height, isAuto) {
- if (isAuto) {
- undistributeHeight(this.dayGrid.rowEls); // let the rows be their natural height with no expanding
- }
- else {
- distributeHeight(this.dayGrid.rowEls, height, true); // true = compensate for height-hogging rows
- }
- },
- /* Scroll
- ------------------------------------------------------------------------------------------------------------------*/
- computeInitialScroll: function() {
- return { top: 0 };
- },
- queryScroll: function() {
- return { top: this.scroller.getScrollTop() };
- },
- setScroll: function(scroll) {
- this.scroller.setScrollTop(scroll.top);
- },
- /* Hit Areas
- ------------------------------------------------------------------------------------------------------------------*/
- // forward all hit-related method calls to dayGrid
- hitsNeeded: function() {
- this.dayGrid.hitsNeeded();
- },
- hitsNotNeeded: function() {
- this.dayGrid.hitsNotNeeded();
- },
- prepareHits: function() {
- this.dayGrid.prepareHits();
- },
- releaseHits: function() {
- this.dayGrid.releaseHits();
- },
- queryHit: function(left, top) {
- return this.dayGrid.queryHit(left, top);
- },
- getHitSpan: function(hit) {
- return this.dayGrid.getHitSpan(hit);
- },
- getHitEl: function(hit) {
- return this.dayGrid.getHitEl(hit);
- },
- /* Events
- ------------------------------------------------------------------------------------------------------------------*/
- // Renders the given events onto the view and populates the segments array
- renderEvents: function(events) {
- this.dayGrid.renderEvents(events);
- this.updateHeight(); // must compensate for events that overflow the row
- },
- // Retrieves all segment objects that are rendered in the view
- getEventSegs: function() {
- return this.dayGrid.getEventSegs();
- },
- // Unrenders all event elements and clears internal segment data
- unrenderEvents: function() {
- this.dayGrid.unrenderEvents();
- // we DON'T need to call updateHeight() because
- // a renderEvents() call always happens after this, which will eventually call updateHeight()
- },
- /* Dragging (for both events and external elements)
- ------------------------------------------------------------------------------------------------------------------*/
- // A returned value of `true` signals that a mock "helper" event has been rendered.
- renderDrag: function(dropLocation, seg) {
- return this.dayGrid.renderDrag(dropLocation, seg);
- },
- unrenderDrag: function() {
- this.dayGrid.unrenderDrag();
- },
- /* Selection
- ------------------------------------------------------------------------------------------------------------------*/
- // Renders a visual indication of a selection
- renderSelection: function(span) {
- this.dayGrid.renderSelection(span);
- },
- // Unrenders a visual indications of a selection
- unrenderSelection: function() {
- this.dayGrid.unrenderSelection();
- }
- });
- // Methods that will customize the rendering behavior of the BasicView's dayGrid
- var basicDayGridMethods = {
- // Generates the HTML that will go before the day-of week header cells
- renderHeadIntroHtml: function() {
- var view = this.view;
- if (view.colWeekNumbersVisible) {
- return '' +
- '<th class="fc-week-number ' + view.widgetHeaderClass + '" ' + view.weekNumberStyleAttr() + '>' +
- '<span>' + // needed for matchCellWidths
- htmlEscape(view.opt('weekNumberTitle')) +
- '</span>' +
- '</th>';
- }
- return '';
- },
- // Generates the HTML that will go before content-skeleton cells that display the day/week numbers
- renderNumberIntroHtml: function(row) {
- var view = this.view;
- var weekStart = this.getCellDate(row, 0);
- if (view.colWeekNumbersVisible) {
- return '' +
- '<td class="fc-week-number" ' + view.weekNumberStyleAttr() + '>' +
- view.buildGotoAnchorHtml( // aside from link, important for matchCellWidths
- { date: weekStart, type: 'week', forceOff: this.colCnt === 1 },
- weekStart.format('w') // inner HTML
- ) +
- '</td>';
- }
- return '';
- },
- // Generates the HTML that goes before the day bg cells for each day-row
- renderBgIntroHtml: function() {
- var view = this.view;
- if (view.colWeekNumbersVisible) {
- return '<td class="fc-week-number ' + view.widgetContentClass + '" ' +
- view.weekNumberStyleAttr() + '></td>';
- }
- return '';
- },
- // Generates the HTML that goes before every other type of row generated by DayGrid.
- // Affects helper-skeleton and highlight-skeleton rows.
- renderIntroHtml: function() {
- var view = this.view;
- if (view.colWeekNumbersVisible) {
- return '<td class="fc-week-number" ' + view.weekNumberStyleAttr() + '></td>';
- }
- return '';
- }
- };
|