Changeset 144254 in webkit


Ignore:
Timestamp:
Feb 27, 2013 6:24:16 PM (11 years ago)
Author:
keishi@webkit.org
Message:

Add month popup for new calendar picker
https://bugs.webkit.org/show_bug.cgi?id=110830

Reviewed by Kent Tamura.

Adding month popup view for use in the new calendar picker (Bug 109439).
YearListCell will grow in height when selected to reveal the buttons for
selecting the month.

No new tests. Code is not used yet.

  • Resources/pagepopups/calendarPicker.js:

(YearListCell): A row inside the month popup. Contains buttons for choosing a month.
(YearListCell.prototype._recycleBin):
(YearListCell.prototype.reset): Resets a thrown away cell for reuse at the given row.
(YearListCell.prototype.height):
(YearListCell.prototype.setHeight):
(YearListView): List view showing YearListCells.
(YearListView.prototype.onMouseOver): If the mouse is over a month button, highlights it.
(YearListView.prototype.onMouseOut): De-highlights the month button.
(YearListView.prototype.setWidth): Set scroll view width to leave space for the scroll bar.
(YearListView.prototype.setHeight): Sets the scroll bar height as well.
(YearListView.prototype._animateRow): Animates the row height to open/close the YearListCell.
(YearListView.prototype.onCellHeightAnimatorDidStop): Keep this._runningAnimators and this._animatingRows up to date.
(YearListView.prototype.onCellHeightAnimatorStep): Update the cell height and position.
(YearListView.prototype.onClick): If this is a click on a month button, select the month.
(YearListView.prototype.rowAtScrollOffset): Calculates the row currently at the given offset.
(YearListView.prototype.scrollOffsetForRow): Calculates the current scroll offset of the given row.
(YearListView.prototype.prepareNewCell): Prepares a new or recycled YearListCell.
(YearListView.prototype.updateCells): Updates the position of the visible cells.
(YearListView.prototype.deselect): Deselects a row.
(YearListView.prototype.deselectWithoutAnimating): Deselects a row without the closing animation.
(YearListView.prototype.select): Selects a row.
(YearListView.prototype.selectWithoutAnimating): Deselects a row without the opening animation.
(YearListView.prototype.buttonForMonth): Returns the month button for a given month. Returns null if the cell is not visible.
(YearListView.prototype.dehighlightMonth): Dehighlights the month button.
(YearListView.prototype.highlightMonth): Highlights the month button.
(YearListView.prototype.show): Call when showing the year list view. Shows the given month as highlighted.
(YearListView.prototype.hide): Dispatches a did hide event which will be picked up by the CalendarPicker and the MonthPopupView will close.
(YearListView.prototype._moveHighlightTo): Used to move the month highlight in response to a key event.
(YearListView.prototype.onKeyDown): Arrow keys and PageUp/PageDown keys work.
(MonthPopupView): The popup view to be overlayed over the calendar picker.
(MonthPopupView.prototype.show): Takes the initialMonth to show and the calendarTableRect so we can overlay the year list view right on top of it.
(MonthPopupView.prototype.hide):
(MonthPopupView.prototype.onClick): Hides itself if the use clicks outside the year list view.

Location:
trunk/Source/WebCore
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r144250 r144254  
     12013-02-27  Keishi Hattori  <keishi@webkit.org>
     2
     3        Add month popup for new calendar picker
     4        https://bugs.webkit.org/show_bug.cgi?id=110830
     5
     6        Reviewed by Kent Tamura.
     7
     8        Adding month popup view for use in the new calendar picker (Bug 109439).
     9        YearListCell will grow in height when selected to reveal the buttons for
     10        selecting the month.
     11
     12        No new tests. Code is not used yet.
     13
     14        * Resources/pagepopups/calendarPicker.js:
     15        (YearListCell): A row inside the month popup. Contains buttons for choosing a month.
     16        (YearListCell.prototype._recycleBin):
     17        (YearListCell.prototype.reset): Resets a thrown away cell for reuse at the given row.
     18        (YearListCell.prototype.height):
     19        (YearListCell.prototype.setHeight):
     20        (YearListView): List view showing YearListCells.
     21        (YearListView.prototype.onMouseOver): If the mouse is over a month button, highlights it.
     22        (YearListView.prototype.onMouseOut): De-highlights the month button.
     23        (YearListView.prototype.setWidth): Set scroll view width to leave space for the scroll bar.
     24        (YearListView.prototype.setHeight): Sets the scroll bar height as well.
     25        (YearListView.prototype._animateRow): Animates the row height to open/close the YearListCell.
     26        (YearListView.prototype.onCellHeightAnimatorDidStop): Keep this._runningAnimators and this._animatingRows up to date.
     27        (YearListView.prototype.onCellHeightAnimatorStep): Update the cell height and position.
     28        (YearListView.prototype.onClick): If this is a click on a month button, select the month.
     29        (YearListView.prototype.rowAtScrollOffset): Calculates the row currently at the given offset.
     30        (YearListView.prototype.scrollOffsetForRow): Calculates the current scroll offset of the given row.
     31        (YearListView.prototype.prepareNewCell): Prepares a new or recycled YearListCell.
     32        (YearListView.prototype.updateCells): Updates the position of the visible cells.
     33        (YearListView.prototype.deselect): Deselects a row.
     34        (YearListView.prototype.deselectWithoutAnimating): Deselects a row without the closing animation.
     35        (YearListView.prototype.select): Selects a row.
     36        (YearListView.prototype.selectWithoutAnimating): Deselects a row without the opening animation.
     37        (YearListView.prototype.buttonForMonth): Returns the month button for a given month. Returns null if the cell is not visible.
     38        (YearListView.prototype.dehighlightMonth): Dehighlights the month button.
     39        (YearListView.prototype.highlightMonth): Highlights the month button.
     40        (YearListView.prototype.show): Call when showing the year list view. Shows the given month as highlighted.
     41        (YearListView.prototype.hide): Dispatches a did hide event which will be picked up by the CalendarPicker and the MonthPopupView will close.
     42        (YearListView.prototype._moveHighlightTo): Used to move the month highlight in response to a key event.
     43        (YearListView.prototype.onKeyDown): Arrow keys and PageUp/PageDown keys work.
     44        (MonthPopupView): The popup view to be overlayed over the calendar picker.
     45        (MonthPopupView.prototype.show): Takes the initialMonth to show and the calendarTableRect so we can overlay the year list view right on top of it.
     46        (MonthPopupView.prototype.hide):
     47        (MonthPopupView.prototype.onClick): Hides itself if the use clicks outside the year list view.
     48
    1492013-02-27  Adam Barth  <abarth@webkit.org>
    250
  • trunk/Source/WebCore/Resources/pagepopups/calendarPicker.js

    r143911 r144254  
    18781878        scrollAmount = -scrollAmount;
    18791879    this.scrollView.scrollBy(scrollAmount, false);
     1880};
     1881
     1882/**
     1883 * @constructor
     1884 * @extends ListCell
     1885 * @param {!Array} shortMonthLabels
     1886 */
     1887function YearListCell(shortMonthLabels) {
     1888    ListCell.call(this);
     1889    this.element.classList.add(YearListCell.ClassNameYearListCell);
     1890    this.element.style.height = YearListCell.Height + "px";
     1891
     1892    /**
     1893     * @type {!Element}
     1894     * @const
     1895     */
     1896    this.label = createElement("div", YearListCell.ClassNameLabel, "----");
     1897    this.element.appendChild(this.label);
     1898
     1899    /**
     1900     * @type {!Array} Array of the 12 month button elements.
     1901     * @const
     1902     */
     1903    this.monthButtons = [];
     1904    var monthChooserElement = createElement("div", YearListCell.ClassNameMonthChooser);
     1905    for (var r = 0; r < YearListCell.ButtonRows; ++r) {
     1906        var buttonsRow = createElement("div", YearListCell.ClassNameMonthButtonsRow);
     1907        for (var c = 0; c < YearListCell.ButtonColumns; ++c) {
     1908            var month = c + r * YearListCell.ButtonColumns;
     1909            var button = createElement("button", YearListCell.ClassNameMonthButton, shortMonthLabels[month]);
     1910            button.dataset.month = month;
     1911            buttonsRow.appendChild(button);
     1912            this.monthButtons.push(button);
     1913        }
     1914        monthChooserElement.appendChild(buttonsRow);
     1915    }
     1916    this.element.appendChild(monthChooserElement);
     1917
     1918    /**
     1919     * @type {!boolean}
     1920     * @private
     1921     */
     1922    this._selected = false;
     1923    /**
     1924     * @type {!number}
     1925     * @private
     1926     */
     1927    this._height = 0;
     1928}
     1929
     1930YearListCell.prototype = Object.create(ListCell.prototype);
     1931
     1932YearListCell.Height = 25;
     1933YearListCell.ButtonRows = 3;
     1934YearListCell.ButtonColumns = 4;
     1935YearListCell.SelectedHeight = 121;
     1936YearListCell.ClassNameYearListCell = "year-list-cell";
     1937YearListCell.ClassNameLabel = "label";
     1938YearListCell.ClassNameMonthChooser = "month-chooser";
     1939YearListCell.ClassNameMonthButtonsRow = "month-buttons-row";
     1940YearListCell.ClassNameMonthButton = "month-button";
     1941YearListCell.ClassNameHighlighted = "highlighted";
     1942
     1943YearListCell._recycleBin = [];
     1944
     1945/**
     1946 * @return {!Array}
     1947 * @override
     1948 */
     1949YearListCell.prototype._recycleBin = function() {
     1950    return YearListCell._recycleBin;
     1951};
     1952
     1953/**
     1954 * @param {!number} row
     1955 */
     1956YearListCell.prototype.reset = function(row) {
     1957    this.row = row;
     1958    this.label.textContent = row + 1;
     1959    for (var i = 0; i < this.monthButtons.length; ++i) {
     1960        this.monthButtons[i].classList.remove(YearListCell.ClassNameHighlighted);
     1961    }
     1962    this.show();
     1963};
     1964
     1965/**
     1966 * @return {!number} The height in pixels.
     1967 */
     1968YearListCell.prototype.height = function() {
     1969    return this._height;
     1970};
     1971
     1972/**
     1973 * @param {!number} height Height in pixels.
     1974 */
     1975YearListCell.prototype.setHeight = function(height) {
     1976    if (this._height === height)
     1977        return;
     1978    this._height = height;
     1979    this.element.style.height = this._height + "px";
     1980};
     1981
     1982/**
     1983 * @constructor
     1984 * @extends ListView
     1985 * @param {!Month} minimumMonth
     1986 * @param {!Month} maximumMonth
     1987 */
     1988function YearListView(minimumMonth, maximumMonth) {
     1989    ListView.call(this);
     1990    this.element.classList.add("year-list-view");
     1991
     1992    /**
     1993     * @type {?Month}
     1994     */
     1995    this.highlightedMonth = null;
     1996    /**
     1997     * @type {!Month}
     1998     * @const
     1999     * @protected
     2000     */
     2001    this._minimumMonth = minimumMonth;
     2002    /**
     2003     * @type {!Month}
     2004     * @const
     2005     * @protected
     2006     */
     2007    this._maximumMonth = maximumMonth;
     2008
     2009    this.scrollView.minimumContentOffset = (this._minimumMonth.year - 1) * YearListCell.Height;
     2010    this.scrollView.maximumContentOffset = (this._maximumMonth.year - 1) * YearListCell.Height + YearListCell.SelectedHeight;
     2011   
     2012    /**
     2013     * @type {!Object}
     2014     * @const
     2015     * @protected
     2016     */
     2017    this._runningAnimators = {};
     2018    /**
     2019     * @type {!Array}
     2020     * @const
     2021     * @protected
     2022     */
     2023    this._animatingRows = [];
     2024    /**
     2025     * @type {!boolean}
     2026     * @protected
     2027     */
     2028    this._ignoreMouseOutUntillNextMouseOver = false;
     2029   
     2030    /**
     2031     * @type {!ScrubbyScrollBar}
     2032     * @const
     2033     */
     2034    this.scrubbyScrollBar = new ScrubbyScrollBar(this.scrollView);
     2035    this.scrubbyScrollBar.attachTo(this);
     2036   
     2037    this.element.addEventListener("mouseover", this.onMouseOver, false);
     2038    this.element.addEventListener("mouseout", this.onMouseOut, false);
     2039    this.element.addEventListener("keydown", this.onKeyDown, false);
     2040}
     2041
     2042YearListView.prototype = Object.create(ListView.prototype);
     2043
     2044YearListView.Height = YearListCell.SelectedHeight - 1;
     2045YearListView.EventTypeYearListViewDidHide = "yearListViewDidHide";
     2046YearListView.EventTypeYearListViewDidSelectMonth = "yearListViewDidSelectMonth";
     2047
     2048/**
     2049 * @param {?Event} event
     2050 */
     2051YearListView.prototype.onMouseOver = function(event) {
     2052    var monthButtonElement = enclosingNodeOrSelfWithClass(event.target, YearListCell.ClassNameMonthButton);
     2053    if (!monthButtonElement)
     2054        return;
     2055    var cellElement = enclosingNodeOrSelfWithClass(monthButtonElement, YearListCell.ClassNameYearListCell);
     2056    var cell = cellElement.$view;
     2057    this.highlightMonth(new Month(cell.row + 1, parseInt(monthButtonElement.dataset.month, 10)));
     2058    this._ignoreMouseOutUntillNextMouseOver = false;
     2059};
     2060
     2061/**
     2062 * @param {?Event} event
     2063 */
     2064YearListView.prototype.onMouseOut = function(event) {
     2065    if (this._ignoreMouseOutUntillNextMouseOver)
     2066        return;
     2067    var monthButtonElement = enclosingNodeOrSelfWithClass(event.target, YearListCell.ClassNameMonthButton);
     2068    if (!monthButtonElement) {
     2069        this.dehighlightMonth();
     2070    }
     2071};
     2072
     2073/**
     2074 * @param {!number} width Width in pixels.
     2075 * @override
     2076 */
     2077YearListView.prototype.setWidth = function(width) {
     2078    ListView.prototype.setWidth.call(this, width - this.scrubbyScrollBar.element.offsetWidth);
     2079    this.element.style.width = width + "px";
     2080};
     2081
     2082/**
     2083 * @param {!number} height Height in pixels.
     2084 * @override
     2085 */
     2086YearListView.prototype.setHeight = function(height) {
     2087    ListView.prototype.setHeight.call(this, height);
     2088    this.scrubbyScrollBar.setHeight(height);
     2089};
     2090
     2091/**
     2092 * @enum {number}
     2093 */
     2094YearListView.RowAnimationDirection = {
     2095    Opening: 0,
     2096    Closing: 1
     2097};
     2098
     2099/**
     2100 * @param {!number} row
     2101 * @param {!YearListView.RowAnimationDirection} direction
     2102 */
     2103YearListView.prototype._animateRow = function(row, direction) {
     2104    var fromValue = direction === YearListView.RowAnimationDirection.Closing ? YearListCell.SelectedHeight : YearListCell.Height;
     2105    var oldAnimator = this._runningAnimators[row];
     2106    if (oldAnimator) {
     2107        oldAnimator.stop();
     2108        fromValue = oldAnimator.currentValue;
     2109    }
     2110    var cell = this.cellAtRow(row);
     2111    var animator = new Animator();
     2112    animator.step = this.onCellHeightAnimatorStep;
     2113    animator.setFrom(fromValue);
     2114    animator.setTo(direction === YearListView.RowAnimationDirection.Opening ? YearListCell.SelectedHeight : YearListCell.Height);
     2115    animator.timingFunction = AnimationTimingFunction.EaseInOut;
     2116    animator.duration = 300;
     2117    animator.row = row;
     2118    animator.on(Animator.EventTypeDidAnimationStop, this.onCellHeightAnimatorDidStop);
     2119    this._runningAnimators[row] = animator;
     2120    this._animatingRows.push(row);
     2121    this._animatingRows.sort();
     2122    animator.start();
     2123};
     2124
     2125/**
     2126 * @param {?Animator} animator
     2127 */
     2128YearListView.prototype.onCellHeightAnimatorDidStop = function(animator) {
     2129    delete this._runningAnimators[animator.row];
     2130    var index = this._animatingRows.indexOf(animator.row);
     2131    this._animatingRows.splice(index, 1);
     2132};
     2133
     2134/**
     2135 * @param {!Animator} animator
     2136 */
     2137YearListView.prototype.onCellHeightAnimatorStep = function(animator) {
     2138    var cell = this.cellAtRow(animator.row);
     2139    if (cell)
     2140        cell.setHeight(animator.currentValue);
     2141    this.updateCells();
     2142};
     2143
     2144/**
     2145 * @param {?Event} event
     2146 */
     2147YearListView.prototype.onClick = function(event) {
     2148    var oldSelectedRow = this.selectedRow;
     2149    ListView.prototype.onClick.call(this, event);
     2150    var year = this.selectedRow + 1;
     2151    if (this.selectedRow !== oldSelectedRow) {
     2152        var month = this.highlightedMonth ? this.highlightedMonth.month : 0;
     2153        this.dispatchEvent(YearListView.EventTypeYearListViewDidSelectMonth, this, new Month(year, month));
     2154        this.scrollView.scrollTo(this.selectedRow * YearListCell.Height, true);
     2155    } else {
     2156        var monthButton = enclosingNodeOrSelfWithClass(event.target, YearListCell.ClassNameMonthButton);
     2157        if (!monthButton)
     2158            return;
     2159        var month = parseInt(monthButton.dataset.month, 10);
     2160        this.dispatchEvent(YearListView.EventTypeYearListViewDidSelectMonth, this, new Month(year, month));
     2161        this.hide();
     2162    }
     2163};
     2164
     2165/**
     2166 * @param {!number} scrollOffset
     2167 * @return {!number}
     2168 * @override
     2169 */
     2170YearListView.prototype.rowAtScrollOffset = function(scrollOffset) {
     2171    var remainingOffset = scrollOffset;
     2172    var lastAnimatingRow = 0;
     2173    var rowsWithIrregularHeight = this._animatingRows.slice();
     2174    if (this.selectedRow > -1 && !this._runningAnimators[this.selectedRow]) {
     2175        rowsWithIrregularHeight.push(this.selectedRow);
     2176        rowsWithIrregularHeight.sort();
     2177    }
     2178    for (var i = 0; i < rowsWithIrregularHeight.length; ++i) {
     2179        var row = rowsWithIrregularHeight[i];
     2180        var animator = this._runningAnimators[row];
     2181        var rowHeight = animator ? animator.currentValue : YearListCell.SelectedHeight;
     2182        if (remainingOffset <= (row - lastAnimatingRow) * YearListCell.Height) {
     2183            return lastAnimatingRow + Math.floor(remainingOffset / YearListCell.Height);
     2184        }
     2185        remainingOffset -= (row - lastAnimatingRow) * YearListCell.Height;
     2186        if (remainingOffset <= (rowHeight - YearListCell.Height))
     2187            return row;
     2188        remainingOffset -= rowHeight - YearListCell.Height;
     2189        lastAnimatingRow = row;
     2190    }
     2191    return lastAnimatingRow + Math.floor(remainingOffset / YearListCell.Height);
     2192};
     2193
     2194/**
     2195 * @param {!number} row
     2196 * @return {!number}
     2197 * @override
     2198 */
     2199YearListView.prototype.scrollOffsetForRow = function(row) {
     2200    var scrollOffset = row * YearListCell.Height;
     2201    for (var i = 0; i < this._animatingRows.length; ++i) {
     2202        var animatingRow = this._animatingRows[i];
     2203        if (animatingRow >= row)
     2204            break;
     2205        var animator = this._runningAnimators[animatingRow];
     2206        scrollOffset += animator.currentValue - YearListCell.Height;
     2207    }
     2208    if (this.selectedRow > -1 && this.selectedRow < row && !this._runningAnimators[this.selectedRow]) {
     2209        scrollOffset += YearListCell.SelectedHeight - YearListCell.Height;
     2210    }
     2211    return scrollOffset;
     2212};
     2213
     2214/**
     2215 * @param {!number} row
     2216 * @return {!YearListCell}
     2217 * @override
     2218 */
     2219YearListView.prototype.prepareNewCell = function(row) {
     2220    var cell = YearListCell._recycleBin.pop() || new YearListCell(global.params.shortMonthLabels);
     2221    cell.reset(row);
     2222    cell.setSelected(this.selectedRow === row);
     2223    if (this.highlightedMonth && row === this.highlightedMonth.year - 1) {
     2224        cell.monthButtons[this.highlightedMonth.month].classList.add(YearListCell.ClassNameHighlighted);
     2225    }
     2226    for (var i = 0; i < cell.monthButtons.length; ++i) {
     2227        var month = new Month(row + 1, i);
     2228        cell.monthButtons[i].disabled = this._minimumMonth > month || this._maximumMonth < month;
     2229    }
     2230    var animator = this._runningAnimators[row];
     2231    if (animator)
     2232        cell.setHeight(animator.currentValue);
     2233    else if (row === this.selectedRow)
     2234        cell.setHeight(YearListCell.SelectedHeight);
     2235    else
     2236        cell.setHeight(YearListCell.Height);
     2237    return cell;
     2238};
     2239
     2240/**
     2241 * @override
     2242 */
     2243YearListView.prototype.updateCells = function() {
     2244    var firstVisibleRow = this.firstVisibleRow();
     2245    var lastVisibleRow = this.lastVisibleRow();
     2246    console.assert(firstVisibleRow <= lastVisibleRow);
     2247    for (var c in this._cells) {
     2248        var cell = this._cells[c];
     2249        if (cell.row < firstVisibleRow || cell.row > lastVisibleRow)
     2250            this.throwAwayCell(cell);
     2251    }
     2252    for (var i = firstVisibleRow; i <= lastVisibleRow; ++i) {
     2253        var cell = this._cells[i];
     2254        if (cell)
     2255            cell.setPosition(this.scrollView.contentPositionForContentOffset(this.scrollOffsetForRow(cell.row)));
     2256        else
     2257            this.addCellIfNecessary(i);
     2258    }
     2259    this.setNeedsUpdateCells(false);
     2260};
     2261
     2262/**
     2263 * @override
     2264 */
     2265YearListView.prototype.deselect = function() {
     2266    if (this.selectedRow === ListView.NoSelection)
     2267        return;
     2268    var selectedCell = this._cells[this.selectedRow];
     2269    if (selectedCell)
     2270        selectedCell.setSelected(false);
     2271    this._animateRow(this.selectedRow, YearListView.RowAnimationDirection.Closing);
     2272    this.selectedRow = ListView.NoSelection;
     2273    this.setNeedsUpdateCells(true);
     2274};
     2275
     2276YearListView.prototype.deselectWithoutAnimating = function() {
     2277    if (this.selectedRow === ListView.NoSelection)
     2278        return;
     2279    var selectedCell = this._cells[this.selectedRow];
     2280    if (selectedCell) {
     2281        selectedCell.setSelected(false);
     2282        selectedCell.setHeight(YearListCell.Height);
     2283    }
     2284    this.selectedRow = ListView.NoSelection;
     2285    this.setNeedsUpdateCells(true);
     2286};
     2287
     2288/**
     2289 * @param {!number} row
     2290 * @override
     2291 */
     2292YearListView.prototype.select = function(row) {
     2293    if (this.selectedRow === row)
     2294        return;
     2295    this.deselect();
     2296    if (row === ListView.NoSelection)
     2297        return;
     2298    this.selectedRow = row;
     2299    if (this.selectedRow !== ListView.NoSelection) {
     2300        var selectedCell = this._cells[this.selectedRow];
     2301        this._animateRow(this.selectedRow, YearListView.RowAnimationDirection.Opening);
     2302        if (selectedCell)
     2303            selectedCell.setSelected(true);
     2304        var month = this.highlightedMonth ? this.highlightedMonth.month : 0;
     2305        this.highlightMonth(new Month(this.selectedRow + 1, month));
     2306    }
     2307    this.setNeedsUpdateCells(true);
     2308};
     2309
     2310/**
     2311 * @param {!number} row
     2312 */
     2313YearListView.prototype.selectWithoutAnimating = function(row) {
     2314    if (this.selectedRow === row)
     2315        return;
     2316    this.deselectWithoutAnimating();
     2317    if (row === ListView.NoSelection)
     2318        return;
     2319    this.selectedRow = row;
     2320    if (this.selectedRow !== ListView.NoSelection) {
     2321        var selectedCell = this._cells[this.selectedRow];
     2322        if (selectedCell) {
     2323            selectedCell.setSelected(true);
     2324            selectedCell.setHeight(YearListCell.SelectedHeight);
     2325        }
     2326        var month = this.highlightedMonth ? this.highlightedMonth.month : 0;
     2327        this.highlightMonth(new Month(this.selectedRow + 1, month));
     2328    }
     2329    this.setNeedsUpdateCells(true);
     2330};
     2331
     2332/**
     2333 * @param {!Month} month
     2334 * @return {?HTMLButtonElement}
     2335 */
     2336YearListView.prototype.buttonForMonth = function(month) {
     2337    if (!month)
     2338        return null;
     2339    var row = month.year - 1;
     2340    var cell = this.cellAtRow(row);
     2341    if (!cell)
     2342        return null;
     2343    return cell.monthButtons[month.month];
     2344};
     2345
     2346YearListView.prototype.dehighlightMonth = function() {
     2347    if (!this.highlightedMonth)
     2348        return;
     2349    var monthButton = this.buttonForMonth(this.highlightedMonth);
     2350    if (monthButton) {
     2351        monthButton.classList.remove(YearListCell.ClassNameHighlighted);
     2352    }
     2353    this.highlightedMonth = null;
     2354};
     2355
     2356/**
     2357 * @param {!Month} month
     2358 */
     2359YearListView.prototype.highlightMonth = function(month) {
     2360    if (this.highlightedMonth && this.highlightedMonth.equals(month))
     2361        return;
     2362    this.dehighlightMonth();
     2363    this.highlightedMonth = month;
     2364    if (!this.highlightedMonth)
     2365        return;
     2366    var monthButton = this.buttonForMonth(this.highlightedMonth);
     2367    if (monthButton) {
     2368        monthButton.classList.add(YearListCell.ClassNameHighlighted);
     2369    }
     2370};
     2371
     2372/**
     2373 * @param {!Month} month
     2374 */
     2375YearListView.prototype.show = function(month) {
     2376    this._ignoreMouseOutUntillNextMouseOver = true;
     2377   
     2378    this.scrollToRow(month.year - 1, false);
     2379    this.selectWithoutAnimating(month.year - 1);
     2380    this.highlightMonth(month);
     2381};
     2382
     2383YearListView.prototype.hide = function() {
     2384    this.dispatchEvent(YearListView.EventTypeYearListViewDidHide, this);
     2385};
     2386
     2387/**
     2388 * @param {!Month} month
     2389 */
     2390YearListView.prototype._moveHighlightTo = function(month) {
     2391    this.highlightMonth(month);
     2392    this.select(this.highlightedMonth.year - 1);
     2393
     2394    this.dispatchEvent(YearListView.EventTypeYearListViewDidSelectMonth, this, month);
     2395    this.scrollView.scrollTo(this.selectedRow * YearListCell.Height, true);
     2396    return true;
     2397};
     2398
     2399/**
     2400 * @param {?Event} event
     2401 */
     2402YearListView.prototype.onKeyDown = function(event) {
     2403    var key = event.keyIdentifier;
     2404    var eventHandled = false;
     2405    if (key == "U+0054") // 't' key.
     2406        eventHandled = this._moveHighlightTo(Month.createFromToday());
     2407    else if (this.highlightedMonth) {
     2408        if (global.params.isLocaleRTL ? key == "Right" : key == "Left")
     2409            eventHandled = this._moveHighlightTo(this.highlightedMonth.previous());
     2410        else if (key == "Up")
     2411            eventHandled = this._moveHighlightTo(this.highlightedMonth.previous(YearListCell.ButtonColumns));
     2412        else if (global.params.isLocaleRTL ? key == "Left" : key == "Right")
     2413            eventHandled = this._moveHighlightTo(this.highlightedMonth.next());
     2414        else if (key == "Down")
     2415            eventHandled = this._moveHighlightTo(this.highlightedMonth.next(YearListCell.ButtonColumns));
     2416        else if (key == "PageUp")
     2417            eventHandled = this._moveHighlightTo(this.highlightedMonth.previous(MonthsPerYear));
     2418        else if (key == "PageDown")
     2419            eventHandled = this._moveHighlightTo(this.highlightedMonth.next(MonthsPerYear));
     2420        else if (key == "Enter") {
     2421            this.dispatchEvent(YearListView.EventTypeYearListViewDidSelectMonth, this, this.highlightedMonth);
     2422            this.hide();
     2423            eventHandled = true;
     2424        }
     2425    } else if (key == "Up") {
     2426        this.scrollView.scrollBy(-YearListCell.Height, true);
     2427        eventHandled = true;
     2428    } else if (key == "Down") {
     2429        this.scrollView.scrollBy(YearListCell.Height, true);
     2430        eventHandled = true;
     2431    } else if (key == "PageUp") {
     2432        this.scrollView.scrollBy(-this.scrollView.height(), true);
     2433        eventHandled = true;
     2434    } else if (key == "PageDown") {
     2435        this.scrollView.scrollBy(this.scrollView.height(), true);
     2436        eventHandled = true;
     2437    }
     2438
     2439    if (eventHandled) {
     2440        event.stopPropagation();
     2441        event.preventDefault();
     2442    }
     2443};
     2444
     2445/**
     2446 * @constructor
     2447 * @extends View
     2448 * @param {!Month} minimumMonth
     2449 * @param {!Month} maximumMonth
     2450 */
     2451function MonthPopupView(minimumMonth, maximumMonth) {
     2452    View.call(this, createElement("div", MonthPopupView.ClassNameMonthPopupView));
     2453
     2454    /**
     2455     * @type {!YearListView}
     2456     * @const
     2457     */
     2458    this.yearListView = new YearListView(minimumMonth, maximumMonth);
     2459    this.yearListView.attachTo(this);
     2460
     2461    /**
     2462     * @type {!boolean}
     2463     */
     2464    this.isVisible = false;
     2465
     2466    this.element.addEventListener("click", this.onClick, false);
     2467}
     2468
     2469MonthPopupView.prototype = Object.create(View.prototype);
     2470
     2471MonthPopupView.ClassNameMonthPopupView = "month-popup-view";
     2472
     2473MonthPopupView.prototype.show = function(initialMonth, calendarTableRect) {
     2474    this.isVisible = true;
     2475    document.body.appendChild(this.element);
     2476    this.yearListView.setWidth(calendarTableRect.width - 2);
     2477    this.yearListView.setHeight(YearListView.Height);
     2478    if (global.params.isLocaleRTL)
     2479        this.yearListView.element.style.right = calendarTableRect.x + "px";
     2480    else
     2481        this.yearListView.element.style.left = calendarTableRect.x + "px";
     2482    this.yearListView.element.style.top = calendarTableRect.y + "px";
     2483    this.yearListView.show(initialMonth);
     2484    this.yearListView.element.focus();
     2485};
     2486
     2487MonthPopupView.prototype.hide = function() {
     2488    if (!this.isVisible)
     2489        return;
     2490    this.isVisible = false;
     2491    this.element.parentNode.removeChild(this.element);
     2492    this.yearListView.hide();
     2493};
     2494
     2495/**
     2496 * @param {?Event} event
     2497 */
     2498MonthPopupView.prototype.onClick = function(event) {
     2499    if (event.target !== this.element)
     2500        return;
     2501    this.hide();
    18802502};
    18812503
Note: See TracChangeset for help on using the changeset viewer.