/* A utility class for rendering rows. ----------------------------------------------------------------------------------------------------------------------*/ // It leverages methods of the subclass and the View to determine custom rendering behavior for each row "type" // (such as highlight rows, day rows, helper rows, etc). function RowRenderer(view) { this.view = view; } RowRenderer.prototype = { view: null, // a View object cellHtml: '', // plain default HTML used for a cell when no other is available // Renders the HTML for a row, leveraging custom cell-HTML-renderers based on the `rowType`. // Also applies the "intro" and "outro" cells, which are specified by the subclass and views. // `row` is an optional row number. rowHtml: function(rowType, row) { var view = this.view; var renderCell = this.getHtmlRenderer('cell', rowType); var cellHtml = ''; var col; var date; row = row || 0; for (col = 0; col < view.colCnt; col++) { date = view.cellToDate(row, col); cellHtml += renderCell(row, col, date); } cellHtml = this.bookendCells(cellHtml, rowType, row); // apply intro and outro return '' + cellHtml + ''; }, // Applies the "intro" and "outro" HTML to the given cells. // Intro means the leftmost cell when the calendar is LTR and the rightmost cell when RTL. Vice-versa for outro. // `cells` can be an HTML string of 's or a jQuery element // `row` is an optional row number. bookendCells: function(cells, rowType, row) { var view = this.view; var intro = this.getHtmlRenderer('intro', rowType)(row || 0); var outro = this.getHtmlRenderer('outro', rowType)(row || 0); var isRTL = view.opt('isRTL'); var prependHtml = isRTL ? outro : intro; var appendHtml = isRTL ? intro : outro; if (typeof cells === 'string') { return prependHtml + cells + appendHtml; } else { // a jQuery element return cells.prepend(prependHtml).append(appendHtml); } }, // Returns an HTML-rendering function given a specific `rendererName` (like cell, intro, or outro) and a specific // `rowType` (like day, eventSkeleton, helperSkeleton), which is optional. // If a renderer for the specific rowType doesn't exist, it will fall back to a generic renderer. // We will query the View object first for any custom rendering functions, then the methods of the subclass. getHtmlRenderer: function(rendererName, rowType) { var view = this.view; var generalName; // like "cellHtml" var specificName; // like "dayCellHtml". based on rowType var provider; // either the View or the RowRenderer subclass, whichever provided the method var renderer; generalName = rendererName + 'Html'; if (rowType) { specificName = rowType + capitaliseFirstLetter(rendererName) + 'Html'; } if (specificName && (renderer = view[specificName])) { provider = view; } else if (specificName && (renderer = this[specificName])) { provider = this; } else if ((renderer = view[generalName])) { provider = view; } else if ((renderer = this[generalName])) { provider = this; } if (typeof renderer === 'function') { return function(row) { return renderer.apply(provider, arguments) || ''; // use correct `this` and always return a string }; } // the rendered can be a plain string as well. if not specified, always an empty string. return function() { return renderer || ''; }; } };