15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)"use strict";
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2012 Google Inc. All rights reserved.
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions are
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * met:
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Redistributions of source code must retain the above copyright
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * notice, this list of conditions and the following disclaimer.
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Redistributions in binary form must reproduce the above
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * copyright notice, this list of conditions and the following disclaimer
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * in the documentation and/or other materials provided with the
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * distribution.
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Neither the name of Google Inc. nor the names of its
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * contributors may be used to endorse or promote products derived from
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * this software without specific prior written permission.
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
34926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @enum {number}
35926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
36926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)var WeekDay = {
37926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    Sunday: 0,
38926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    Monday: 1,
39926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    Tuesday: 2,
40926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    Wednesday: 3,
41926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    Thursday: 4,
42926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    Friday: 5,
43926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    Saturday: 6
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @type {Object}
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)var global = {
50926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    picker: null,
51926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    params: {
52926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        locale: "en_US",
53926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        weekStartDay: WeekDay.Sunday,
54926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        dayLabels: ["S", "M", "T", "W", "T", "F", "S"],
55926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        shortMonthLabels: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec"],
56926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        isLocaleRTL: false,
57926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        mode: "date",
58926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        weekLabel: "Week",
59926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        anchorRectInScreen: new Rectangle(0, 0, 0, 0),
60926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        currentValue: null
61926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// ----------------------------------------------------------------
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Utility functions
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
68a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch * @return {!boolean}
69926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
70926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)function hasInaccuratePointingDevice() {
71926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return matchMedia("(pointer: coarse)").matches;
72926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
73926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
74926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @return {!string} lowercase locale name. e.g. "en-us"
765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function getLocale() {
787242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    return (global.params.locale || "en-us").toLowerCase().replace(/_/g, '-');
795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @return {!string} lowercase language code. e.g. "en"
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function getLanguage() {
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var locale = getLocale();
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var result = locale.match(/^([a-z]+)/);
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!result)
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return "en";
895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return result[1];
905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @param {!number} number
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @return {!string}
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function localizeNumber(number) {
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return window.pagePopupController.localizeNumberString(number);
985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @const
1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @type {number}
1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)var ImperialEraLimit = 2087;
1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @param {!number} year
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @param {!number} month
1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @return {!string}
1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function formatJapaneseImperialEra(year, month) {
1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // We don't show an imperial era if it is greater than 99 becase of space
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // limitation.
1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (year > ImperialEraLimit)
1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return "";
1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (year > 1989)
1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return "(平成" + localizeNumber(year - 1988) + "年)";
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (year == 1989)
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return "(平成元年)";
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (year >= 1927)
1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return "(昭和" + localizeNumber(year - 1925) + "年)";
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (year > 1912)
1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return "(大正" + localizeNumber(year - 1911) + "年)";
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (year == 1912 && month >= 7)
1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return "(大正元年)";
1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (year > 1868)
1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return "(明治" + localizeNumber(year - 1867) + "年)";
1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (year == 1868)
1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return "(明治元年)";
1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return "";
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function createUTCDate(year, month, date) {
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var newDate = new Date(0);
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    newDate.setUTCFullYear(year);
1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    newDate.setUTCMonth(month);
1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    newDate.setUTCDate(date);
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return newDate;
139926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @param {string} dateString
1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @return {?Day|Week|Month}
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function parseDateString(dateString) {
1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var month = Month.parse(dateString);
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (month)
1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return month;
1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var week = Week.parse(dateString);
1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (week)
1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return week;
1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return Day.parse(dateString);
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
156926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @const
157926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @type {number}
158926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
159926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)var DaysPerWeek = 7;
160926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
161926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
162926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @const
163926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @type {number}
164926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
165926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)var MonthsPerYear = 12;
166926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
167926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
168926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @const
169926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @type {number}
170926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
171926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)var MillisecondsPerDay = 24 * 60 * 60 * 1000;
172926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
173926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
174926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @const
175926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @type {number}
176926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
177926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)var MillisecondsPerWeek = DaysPerWeek * MillisecondsPerDay;
178926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
179926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
180926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @constructor
181926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
182926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)function DateType() {
183926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
184926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
185926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @constructor
187926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @extends DateType
188926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} year
189926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} month
190926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} date
191926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
192926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)function Day(year, month, date) {
193926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var dateObject = createUTCDate(year, month, date);
194926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (isNaN(dateObject.valueOf()))
195926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        throw "Invalid date";
196926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
197926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {number}
198926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @const
199926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
200926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.year = dateObject.getUTCFullYear();
201926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     /**
202926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {number}
203926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @const
204926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this.month = dateObject.getUTCMonth();
206926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
207926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {number}
208926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @const
209926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this.date = dateObject.getUTCDate();
2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
213926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)Day.prototype = Object.create(DateType.prototype);
214926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
215926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)Day.ISOStringRegExp = /^(\d+)-(\d+)-(\d+)/;
2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @param {!string} str
219926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {?Day}
2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Day.parse = function(str) {
2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var match = Day.ISOStringRegExp.exec(str);
2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!match)
2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return null;
2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var year = parseInt(match[1], 10);
2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var month = parseInt(match[2], 10) - 1;
2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var date = parseInt(match[3], 10);
2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return new Day(year, month, date);
2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
232926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} value
233926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!Day}
234926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
235926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)Day.createFromValue = function(millisecondsSinceEpoch) {
236926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return Day.createFromDate(new Date(millisecondsSinceEpoch))
237926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
238926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
239926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @param {!Date} date
2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @return {!Day}
2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
2435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Day.createFromDate = function(date) {
244926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (isNaN(date.valueOf()))
245926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        throw "Invalid date";
2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return new Day(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate());
2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
250926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!Day} day
251926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!Day}
252926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
253926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)Day.createFromDay = function(day) {
254926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return day;
255926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
256926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
257926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @return {!Day}
2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Day.createFromToday = function() {
2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var now = new Date();
2625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return new Day(now.getFullYear(), now.getMonth(), now.getDate());
2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
2645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
266926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!DateType} other
267926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!boolean}
2685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Day.prototype.equals = function(other) {
270926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return other instanceof Day && this.year === other.year && this.month === other.month && this.date === other.date;
2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
274926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number=} offset
2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @return {!Day}
2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
277926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)Day.prototype.previous = function(offset) {
278926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (typeof offset === "undefined")
279926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        offset = 1;
280926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return new Day(this.year, this.month, this.date - offset);
2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
2825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
284926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number=} offset
2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @return {!Day}
2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
287926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)Day.prototype.next = function(offset) {
288926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (typeof offset === "undefined")
289926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     offset = 1;
290926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return new Day(this.year, this.month, this.date + offset);
2915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
2945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @return {!Date}
2955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Day.prototype.startDate = function() {
2975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return createUTCDate(this.year, this.month, this.date);
2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
2995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
3015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @return {!Date}
3025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
3035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Day.prototype.endDate = function() {
3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return createUTCDate(this.year, this.month, this.date + 1);
3055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
3065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
308926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!Day}
309926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
310926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)Day.prototype.firstDay = function() {
311926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return this;
312926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
313926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
314926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
315926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!Day}
316926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
317926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)Day.prototype.middleDay = function() {
318926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return this;
319926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
320926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
321926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
322926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!Day}
323926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
324926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)Day.prototype.lastDay = function() {
325926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return this;
326926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
327926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
328926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @return {!number}
3305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
3315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Day.prototype.valueOf = function() {
332926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return createUTCDate(this.year, this.month, this.date).getTime();
333926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
334926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
335926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
336926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!WeekDay}
337926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
338926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)Day.prototype.weekDay = function() {
339926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return createUTCDate(this.year, this.month, this.date).getUTCDay();
3405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
3415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
3435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @return {!string}
3445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
3455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Day.prototype.toString = function() {
3465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var yearString = String(this.year);
3475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (yearString.length < 4)
3485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        yearString = ("000" + yearString).substr(-4, 4);
3495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return yearString + "-" + ("0" + (this.month + 1)).substr(-2, 2) + "-" + ("0" + this.date).substr(-2, 2);
3505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
3515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3527242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci/**
3537242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci * @return {!string}
3547242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci */
3557242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano TucciDay.prototype.format = function() {
3567242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if (!Day.formatter) {
3577242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        Day.formatter = new Intl.DateTimeFormat(getLocale(), {
3587242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            weekday: "long", year: "numeric", month: "long", day: "numeric", timeZone: "UTC"
3597242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        });
3607242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    }
3617242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    return Day.formatter.format(this.startDate());
3627242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci};
3637242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
3645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// See WebCore/platform/DateComponents.h.
365926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)Day.Minimum = Day.createFromValue(-62135596800000.0);
366926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)Day.Maximum = Day.createFromValue(8640000000000000.0);
367926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// See WebCore/html/DayInputType.cpp.
3695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Day.DefaultStep = 86400000;
3705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Day.DefaultStepBase = 0;
3715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
3735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @constructor
374926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @extends DateType
375926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} year
376926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} week
377926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
378926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)function Week(year, week) {
379926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
380926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {number}
381926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @const
382926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
383926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.year = year;
384926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
385926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {number}
386926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @const
387926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
388926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.week = week;
389926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // Number of years per year is either 52 or 53.
390926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this.week < 1 || (this.week > 52 && this.week > Week.numberOfWeeksInYear(this.year))) {
391926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var normalizedWeek = Week.createFromDay(this.firstDay());
392926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.year = normalizedWeek.year;
393926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.week = normalizedWeek.week;
3945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Week.ISOStringRegExp = /^(\d+)-[wW](\d+)$/;
398926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// See WebCore/platform/DateComponents.h.
4005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Week.Minimum = new Week(1, 1);
4015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Week.Maximum = new Week(275760, 37);
402926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// See WebCore/html/WeekInputType.cpp.
4045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Week.DefaultStep = 604800000;
4055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Week.DefaultStepBase = -259200000;
4065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
407926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)Week.EpochWeekDay = createUTCDate(1970, 0, 0).getUTCDay();
408926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
4105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @param {!string} str
4115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @return {?Week}
4125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
4135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Week.parse = function(str) {
4145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var match = Week.ISOStringRegExp.exec(str);
4155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!match)
4165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return null;
4175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var year = parseInt(match[1], 10);
4185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var week = parseInt(match[2], 10);
4195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return new Week(year, week);
4205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
4215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
423926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} millisecondsSinceEpoch
424926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!Week}
425926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
426926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)Week.createFromValue = function(millisecondsSinceEpoch) {
427926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return Week.createFromDate(new Date(millisecondsSinceEpoch))
428926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
429926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
430926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
4315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @param {!Date} date
4325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @return {!Week}
4335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
4345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Week.createFromDate = function(date) {
435926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (isNaN(date.valueOf()))
436926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        throw "Invalid date";
4375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var year = date.getUTCFullYear();
4385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (year <= Week.Maximum.year && Week.weekOneStartDateForYear(year + 1).getTime() <= date.getTime())
4395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        year++;
4405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (year > 1 && Week.weekOneStartDateForYear(year).getTime() > date.getTime())
4415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        year--;
4425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var week = 1 + Week._numberOfWeeksSinceDate(Week.weekOneStartDateForYear(year), date);
4435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return new Week(year, week);
4445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
4455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
447926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!Day} day
448926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!Week}
449926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
450926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)Week.createFromDay = function(day) {
451926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var year = day.year;
452926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (year <= Week.Maximum.year && Week.weekOneStartDayForYear(year + 1) <= day)
453926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        year++;
454926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    else if (year > 1 && Week.weekOneStartDayForYear(year) > day)
455926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        year--;
456926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var week = Math.floor(1 + (day.valueOf() - Week.weekOneStartDayForYear(year).valueOf()) / MillisecondsPerWeek);
457926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return new Week(year, week);
458926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
459926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
460926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
4615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @return {!Week}
4625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
4635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Week.createFromToday = function() {
4645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var now = new Date();
4655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return Week.createFromDate(createUTCDate(now.getFullYear(), now.getMonth(), now.getDate()));
4665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
4675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
4695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @param {!number} year
4705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @return {!Date}
4715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
4725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Week.weekOneStartDateForYear = function(year) {
4735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (year < 1)
4745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return createUTCDate(1, 0, 1);
4755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // The week containing January 4th is week one.
4765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var yearStartDay = createUTCDate(year, 0, 4).getUTCDay();
477926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return createUTCDate(year, 0, 4 - (yearStartDay + 6) % DaysPerWeek);
478926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
479926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
480926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
481926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} year
482926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!Day}
483926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
484926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)Week.weekOneStartDayForYear = function(year) {
485926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (year < 1)
486926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return Day.Minimum;
487926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // The week containing January 4th is week one.
488926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var yearStartDay = createUTCDate(year, 0, 4).getUTCDay();
489926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return new Day(year, 0, 4 - (yearStartDay + 6) % DaysPerWeek);
4905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
4915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
4935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @param {!number} year
4945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @return {!number}
4955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
4965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Week.numberOfWeeksInYear = function(year) {
4975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (year < 1 || year > Week.Maximum.year)
4985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
4995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (year === Week.Maximum.year)
5005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return Week.Maximum.week;
5015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return Week._numberOfWeeksSinceDate(Week.weekOneStartDateForYear(year), Week.weekOneStartDateForYear(year + 1));
5025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
5035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
5055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @param {!Date} baseDate
5065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @param {!Date} date
5075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @return {!number}
5085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
5095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Week._numberOfWeeksSinceDate = function(baseDate, date) {
510926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return Math.floor((date.getTime() - baseDate.getTime()) / MillisecondsPerWeek);
5115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
5125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
514926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!DateType} other
515926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!boolean}
5165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
5175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Week.prototype.equals = function(other) {
518926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return other instanceof Week && this.year === other.year && this.week === other.week;
5195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
5205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
522926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number=} offset
5235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @return {!Week}
5245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
525926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)Week.prototype.previous = function(offset) {
526926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (typeof offset === "undefined")
527926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        offset = 1;
528926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return new Week(this.year, this.week - offset);
5295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
5305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
532926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number=} offset
5335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @return {!Week}
5345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
535926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)Week.prototype.next = function(offset) {
536926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (typeof offset === "undefined")
537926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        offset = 1;
538926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return new Week(this.year, this.week + offset);
5395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
5405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
5425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @return {!Date}
5435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
5445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Week.prototype.startDate = function() {
5455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var weekStartDate = Week.weekOneStartDateForYear(this.year);
5465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    weekStartDate.setUTCDate(weekStartDate.getUTCDate() + (this.week - 1) * 7);
5475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return weekStartDate;
5485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
5495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
5515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @return {!Date}
5525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
5535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Week.prototype.endDate = function() {
5545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (this.equals(Week.Maximum))
5555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return Day.Maximum.startDate();
5565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return this.next().startDate();
5575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
5585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
560926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!Day}
561926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
562926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)Week.prototype.firstDay = function() {
563926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var weekOneStartDay = Week.weekOneStartDayForYear(this.year);
564926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return weekOneStartDay.next((this.week - 1) * DaysPerWeek);
565926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
566926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
567926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
568926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!Day}
569926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
570926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)Week.prototype.middleDay = function() {
571926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return this.firstDay().next(3);
572926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
573926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
574926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
575926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!Day}
576926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
577926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)Week.prototype.lastDay = function() {
578926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this.equals(Week.Maximum))
579926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return Day.Maximum;
580926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return this.next().firstDay().previous();
581926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
582926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
583926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
5845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @return {!number}
5855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
5865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Week.prototype.valueOf = function() {
587926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return this.firstDay().valueOf() - createUTCDate(1970, 0, 1).getTime();
5885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
5895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
5915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @return {!string}
5925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
5935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Week.prototype.toString = function() {
5945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var yearString = String(this.year);
5955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (yearString.length < 4)
5965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        yearString = ("000" + yearString).substr(-4, 4);
5975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return yearString + "-W" + ("0" + this.week).substr(-2, 2);
5985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
5995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
6015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @constructor
602926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @extends DateType
603926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} year
604926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} month
605926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
606926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)function Month(year, month) {
607926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
608926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {number}
609926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @const
610926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
611926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.year = year + Math.floor(month / MonthsPerYear);
612926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
613926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {number}
614926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @const
615926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
616926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.month = month % MonthsPerYear < 0 ? month % MonthsPerYear + MonthsPerYear : month % MonthsPerYear;
6175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
6185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Month.ISOStringRegExp = /^(\d+)-(\d+)$/;
6205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// See WebCore/platform/DateComponents.h.
6225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Month.Minimum = new Month(1, 0);
6235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Month.Maximum = new Month(275760, 8);
624926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
6255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// See WebCore/html/MonthInputType.cpp.
6265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Month.DefaultStep = 1;
6275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Month.DefaultStepBase = 0;
6285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
6305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @param {!string} str
6315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @return {?Month}
6325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
6335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Month.parse = function(str) {
6345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var match = Month.ISOStringRegExp.exec(str);
6355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!match)
6365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return null;
6375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var year = parseInt(match[1], 10);
6385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var month = parseInt(match[2], 10) - 1;
6395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return new Month(year, month);
6405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
6415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
643926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} value
644926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!Month}
645926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
646926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)Month.createFromValue = function(monthsSinceEpoch) {
647926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return new Month(1970, monthsSinceEpoch)
648926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
649926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
650926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
6515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @param {!Date} date
6525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @return {!Month}
6535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
6545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Month.createFromDate = function(date) {
655926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (isNaN(date.valueOf()))
656926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        throw "Invalid date";
6575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return new Month(date.getUTCFullYear(), date.getUTCMonth());
6585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
6595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
661926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!Day} day
662926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!Month}
663926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
664926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)Month.createFromDay = function(day) {
665926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return new Month(day.year, day.month);
666926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
667926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
668926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
6695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @return {!Month}
6705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
6715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Month.createFromToday = function() {
6725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var now = new Date();
6735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return new Month(now.getFullYear(), now.getMonth());
6745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
6755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
677926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!boolean}
678926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
679926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)Month.prototype.containsDay = function(day) {
680926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return this.year === day.year && this.month === day.month;
681926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
682926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
683926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
6845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @param {!Month} other
685926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!boolean}
6865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
6875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Month.prototype.equals = function(other) {
688926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return other instanceof Month && this.year === other.year && this.month === other.month;
6895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
6905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
692926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number=} offset
6935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @return {!Month}
6945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
695926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)Month.prototype.previous = function(offset) {
696926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (typeof offset === "undefined")
697926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        offset = 1;
698926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return new Month(this.year, this.month - offset);
6995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
7005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
702926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number=} offset
7035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @return {!Month}
7045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
705926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)Month.prototype.next = function(offset) {
706926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (typeof offset === "undefined")
707926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        offset = 1;
708926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return new Month(this.year, this.month + offset);
7095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
7105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
7125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @return {!Date}
7135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
7145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Month.prototype.startDate = function() {
7155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return createUTCDate(this.year, this.month, 1);
7165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
7175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
7195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @return {!Date}
7205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
7215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Month.prototype.endDate = function() {
7225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (this.equals(Month.Maximum))
7235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return Day.Maximum.startDate();
7245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return this.next().startDate();
7255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
7265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
728926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!Day}
729926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
730926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)Month.prototype.firstDay = function() {
731926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return new Day(this.year, this.month, 1);
732926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
733926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
734926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
735926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!Day}
736926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
737926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)Month.prototype.middleDay = function() {
738926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return new Day(this.year, this.month, this.month === 2 ? 14 : 15);
739926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
740926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
741926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
742926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!Day}
743926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
744926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)Month.prototype.lastDay = function() {
745926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this.equals(Month.Maximum))
746926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return Day.Maximum;
747926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return this.next().firstDay().previous();
748926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
749926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
750926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
7515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @return {!number}
7525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
7535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Month.prototype.valueOf = function() {
754926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return (this.year - 1970) * MonthsPerYear + this.month;
7555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
7565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
7585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @return {!string}
7595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
7605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Month.prototype.toString = function() {
7615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var yearString = String(this.year);
7625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (yearString.length < 4)
7635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        yearString = ("000" + yearString).substr(-4, 4);
7645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return yearString + "-" + ("0" + (this.month + 1)).substr(-2, 2);
7655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
7665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
767926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
768926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!string}
769926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
770926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)Month.prototype.toLocaleString = function() {
771926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (global.params.locale === "ja")
772926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return "" + this.year + "年" + formatJapaneseImperialEra(this.year, this.month) + " " + (this.month + 1) + "月";
773926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return window.pagePopupController.formatMonth(this.year, this.month);
774926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
775926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
776926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
777926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!string}
778926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
779926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)Month.prototype.toShortLocaleString = function() {
780926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return window.pagePopupController.formatShortMonth(this.year, this.month);
781926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
782926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
7835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// ----------------------------------------------------------------
7845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Initialization
7855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
7875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @param {Event} event
7885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
7895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function handleMessage(event) {
7905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (global.argumentsReceived)
7915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
7925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    global.argumentsReceived = true;
7935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    initialize(JSON.parse(event.data));
7945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
7955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
797926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!Object} params
798926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
799926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)function setGlobalParams(params) {
800926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var name;
801926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    for (name in global.params) {
802926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (typeof params[name] === "undefined")
803926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            console.warn("Missing argument: " + name);
8045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
805926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    for (name in params) {
806926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        global.params[name] = params[name];
807926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
808926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
8095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
8115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @param {!Object} args
8125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
8135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function initialize(args) {
814926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    setGlobalParams(args);
815926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (global.params.suggestionValues && global.params.suggestionValues.length)
816926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        openSuggestionPicker();
817926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    else
818926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        openCalendarPicker();
8195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
8205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function closePicker() {
8225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (global.picker)
8235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        global.picker.cleanup();
8245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var main = $("main");
8255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    main.innerHTML = "";
8265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    main.className = "";
8275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
8285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function openSuggestionPicker() {
8305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    closePicker();
8315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    global.picker = new SuggestionPicker($("main"), global.params);
8325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
8335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function openCalendarPicker() {
8355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    closePicker();
836926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    global.picker = new CalendarPicker(global.params.mode, global.params);
837926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    global.picker.attachTo($("main"));
8385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
8395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
8415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @constructor
8425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
843926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)function EventEmitter() {
8445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
8455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
846926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
847926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!string} type
848926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!function({...*})} callback
849926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
850926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)EventEmitter.prototype.on = function(type, callback) {
851926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    console.assert(callback instanceof Function);
852926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!this._callbacks)
853926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this._callbacks = {};
854926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!this._callbacks[type])
855926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this._callbacks[type] = [];
856926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._callbacks[type].push(callback);
8575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
8585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
859926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)EventEmitter.prototype.hasListener = function(type) {
860926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!this._callbacks)
861926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return false;
862926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var callbacksForType = this._callbacks[type];
863926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!callbacksForType)
864926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return false;
865926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return callbacksForType.length > 0;
8665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
8675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
868926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
869926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!string} type
870926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!function(Object)} callback
871926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
872926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)EventEmitter.prototype.removeListener = function(type, callback) {
873926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!this._callbacks)
874926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
875926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var callbacksForType = this._callbacks[type];
876926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!callbacksForType)
877926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
878926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    callbacksForType.splice(callbacksForType.indexOf(callback), 1);
879926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (callbacksForType.length === 0)
880926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        delete this._callbacks[type];
8815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
8825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
883926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
884926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!string} type
885926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {...*} var_args
886926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
887926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)EventEmitter.prototype.dispatchEvent = function(type) {
888926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!this._callbacks)
889926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
890926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var callbacksForType = this._callbacks[type];
891926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!callbacksForType)
892926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
89309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    callbacksForType = callbacksForType.slice(0);
894926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    for (var i = 0; i < callbacksForType.length; ++i) {
895926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        callbacksForType[i].apply(this, Array.prototype.slice.call(arguments, 1));
896926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
8975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
8985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
899926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)// Parameter t should be a number between 0 and 1.
900926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)var AnimationTimingFunction = {
901926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    Linear: function(t){
902926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return t;
903926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
904926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    EaseInOut: function(t){
905926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        t *= 2;
906926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (t < 1)
907926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            return Math.pow(t, 3) / 2;
908926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        t -= 2;
909926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return Math.pow(t, 3) / 2 + 1;
9105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
9115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
9125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
914926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @constructor
915926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @extends EventEmitter
9165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
917926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)function AnimationManager() {
918926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    EventEmitter.call(this);
919926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
920926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._isRunning = false;
921926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._runningAnimatorCount = 0;
922926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._runningAnimators = {};
923926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._animationFrameCallbackBound = this._animationFrameCallback.bind(this);
924926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
925926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
926926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)AnimationManager.prototype = Object.create(EventEmitter.prototype);
927926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
928926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)AnimationManager.EventTypeAnimationFrameWillFinish = "animationFrameWillFinish";
929926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
930926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)AnimationManager.prototype._startAnimation = function() {
931926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this._isRunning)
932926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
933926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._isRunning = true;
93407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    window.requestAnimationFrame(this._animationFrameCallbackBound);
9355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
9365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
937926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)AnimationManager.prototype._stopAnimation = function() {
938926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!this._isRunning)
9395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
940926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._isRunning = false;
9415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
9425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
944926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!Animator} animator
9455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
946926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)AnimationManager.prototype.add = function(animator) {
947926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this._runningAnimators[animator.id])
948926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
949926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._runningAnimators[animator.id] = animator;
950926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._runningAnimatorCount++;
951926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this._needsTimer())
952926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this._startAnimation();
9535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
9545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
956926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!Animator} animator
9575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
958926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)AnimationManager.prototype.remove = function(animator) {
959926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!this._runningAnimators[animator.id])
960926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
961926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    delete this._runningAnimators[animator.id];
962926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._runningAnimatorCount--;
963926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!this._needsTimer())
964926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this._stopAnimation();
965926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
9665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
967926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)AnimationManager.prototype._animationFrameCallback = function(now) {
968926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this._runningAnimatorCount > 0) {
969926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        for (var id in this._runningAnimators) {
970926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            this._runningAnimators[id].onAnimationFrame(now);
9715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
9725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
973926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.dispatchEvent(AnimationManager.EventTypeAnimationFrameWillFinish);
974926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this._isRunning)
97507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        window.requestAnimationFrame(this._animationFrameCallbackBound);
9765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
9775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
979926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!boolean}
9805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
981926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)AnimationManager.prototype._needsTimer = function() {
982926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return this._runningAnimatorCount > 0 || this.hasListener(AnimationManager.EventTypeAnimationFrameWillFinish);
983926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
9845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
985926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
986926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!string} type
987926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!Function} callback
988926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @override
989926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
990926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)AnimationManager.prototype.on = function(type, callback) {
991926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    EventEmitter.prototype.on.call(this, type, callback);
992926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this._needsTimer())
993926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this._startAnimation();
9945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
9955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
997926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!string} type
998926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!Function} callback
999926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @override
10005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1001926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)AnimationManager.prototype.removeListener = function(type, callback) {
1002926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    EventEmitter.prototype.removeListener.call(this, type, callback);
1003926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!this._needsTimer())
1004926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this._stopAnimation();
10055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
10065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1007926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)AnimationManager.shared = new AnimationManager();
10085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1009926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
1010926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @constructor
1011926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @extends EventEmitter
1012926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
1013926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)function Animator() {
1014926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    EventEmitter.call(this);
1015926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1016926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
1017926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!number}
1018926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @const
1019926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
1020926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.id = Animator._lastId++;
1021926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
1022926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!number}
1023926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
1024926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.duration = 100;
1025926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
1026926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {?function}
1027926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
1028926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.step = null;
1029926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
1030926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!boolean}
1031926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @protected
1032926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
1033926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._isRunning = false;
1034926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
1035926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!number}
1036926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
1037926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.currentValue = 0;
1038926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
1039926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!number}
1040926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @protected
1041926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
1042926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._lastStepTime = 0;
1043926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
10445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1045926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)Animator.prototype = Object.create(EventEmitter.prototype);
1046926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1047926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)Animator._lastId = 0;
1048926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1049926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)Animator.EventTypeDidAnimationStop = "didAnimationStop";
1050926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1051926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
1052926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!boolean}
1053926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
1054926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)Animator.prototype.isRunning = function() {
1055926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return this._isRunning;
1056926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
1057926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1058926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)Animator.prototype.start = function() {
105907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    this._lastStepTime = performance.now();
1060926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._isRunning = true;
1061926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    AnimationManager.shared.add(this);
10625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
10635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1064926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)Animator.prototype.stop = function() {
1065926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!this._isRunning)
1066926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
1067926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._isRunning = false;
1068926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    AnimationManager.shared.remove(this);
1069926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.dispatchEvent(Animator.EventTypeDidAnimationStop, this);
10705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
10715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
1073926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} now
10745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1075926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)Animator.prototype.onAnimationFrame = function(now) {
1076926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._lastStepTime = now;
1077926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.step(this);
1078926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
10795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
1081926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @constructor
1082926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @extends Animator
1083926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
1084926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)function TransitionAnimator() {
1085926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    Animator.call(this);
1086926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
1087926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!number}
1088926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @protected
1089926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
1090926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._from = 0;
1091926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
1092926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!number}
1093926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @protected
1094926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
1095926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._to = 0;
1096926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
1097926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!number}
1098926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @protected
1099926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
1100926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._delta = 0;
1101926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
1102926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!number}
1103926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
1104926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.progress = 0.0;
1105926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
1106926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!function}
1107926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
1108926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.timingFunction = AnimationTimingFunction.Linear;
11095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
11105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1111926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)TransitionAnimator.prototype = Object.create(Animator.prototype);
1112926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
11135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
1114926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} value
11155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1116926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)TransitionAnimator.prototype.setFrom = function(value) {
1117926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._from = value;
1118926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._delta = this._to - this._from;
1119926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
11205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1121926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)TransitionAnimator.prototype.start = function() {
1122926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    console.assert(isFinite(this.duration));
1123926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.progress = 0.0;
1124926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.currentValue = this._from;
1125926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    Animator.prototype.start.call(this);
11265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
11275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
1129926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} value
11305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1131926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)TransitionAnimator.prototype.setTo = function(value) {
1132926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._to = value;
1133926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._delta = this._to - this._from;
1134926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
1135926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
11365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
1137926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} now
11385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1139926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)TransitionAnimator.prototype.onAnimationFrame = function(now) {
1140926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.progress += (now - this._lastStepTime) / this.duration;
1141926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.progress = Math.min(1.0, this.progress);
1142926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._lastStepTime = now;
1143926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.currentValue = this.timingFunction(this.progress) * this._delta + this._from;
1144926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.step(this);
1145926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this.progress === 1.0) {
1146926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.stop();
1147926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
1148926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
1149926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
1150926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
11515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
1152926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @constructor
1153926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @extends Animator
1154926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} initialVelocity
1155926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} initialValue
1156926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
1157926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)function FlingGestureAnimator(initialVelocity, initialValue) {
1158926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    Animator.call(this);
1159926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
1160926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!number}
1161926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
1162926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.initialVelocity = initialVelocity;
1163926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
1164926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!number}
1165926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
1166926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.initialValue = initialValue;
1167926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
1168926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!number}
1169926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @protected
1170926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
1171926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._elapsedTime = 0;
1172926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var startVelocity = Math.abs(this.initialVelocity);
1173926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (startVelocity > this._velocityAtTime(0))
1174926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        startVelocity = this._velocityAtTime(0);
1175926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (startVelocity < 0)
1176926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        startVelocity = 0;
1177926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
1178926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!number}
1179926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @protected
1180926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
1181926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._timeOffset = this._timeAtVelocity(startVelocity);
1182926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
1183926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!number}
1184926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @protected
1185926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
1186926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._positionOffset = this._valueAtTime(this._timeOffset);
1187926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
1188926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!number}
1189926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
1190926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.duration = this._timeAtVelocity(0);
1191926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
1192926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1193926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)FlingGestureAnimator.prototype = Object.create(Animator.prototype);
1194926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1195926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)// Velocity is subject to exponential decay. These parameters are coefficients
1196926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)// that determine the curve.
1197926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)FlingGestureAnimator._P0 = -5707.62;
1198926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)FlingGestureAnimator._P1 = 0.172;
1199926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)FlingGestureAnimator._P2 = 0.0037;
1200926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
12015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
1202926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} t
12035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1204926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)FlingGestureAnimator.prototype._valueAtTime = function(t) {
1205926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return FlingGestureAnimator._P0 * Math.exp(-FlingGestureAnimator._P2 * t) - FlingGestureAnimator._P1 * t - FlingGestureAnimator._P0;
1206926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
1207926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
12085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
1209926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} t
12105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1211926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)FlingGestureAnimator.prototype._velocityAtTime = function(t) {
1212926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return -FlingGestureAnimator._P0 * FlingGestureAnimator._P2 * Math.exp(-FlingGestureAnimator._P2 * t) - FlingGestureAnimator._P1;
1213926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
12145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
1216926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} v
12175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1218926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)FlingGestureAnimator.prototype._timeAtVelocity = function(v) {
1219926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return -Math.log((v + FlingGestureAnimator._P1) / (-FlingGestureAnimator._P0 * FlingGestureAnimator._P2)) / FlingGestureAnimator._P2;
1220926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
1221926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1222926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)FlingGestureAnimator.prototype.start = function() {
122307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    this._lastStepTime = performance.now();
1224926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    Animator.prototype.start.call(this);
12255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
12265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
1228926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} now
12295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1230926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)FlingGestureAnimator.prototype.onAnimationFrame = function(now) {
1231926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._elapsedTime += now - this._lastStepTime;
1232926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._lastStepTime = now;
1233926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this._elapsedTime + this._timeOffset >= this.duration) {
1234926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.stop();
1235926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
1236926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
1237926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var position = this._valueAtTime(this._elapsedTime + this._timeOffset) - this._positionOffset;
1238926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this.initialVelocity < 0)
1239926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        position = -position;
1240926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.currentValue = position + this.initialValue;
1241926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.step(this);
12425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
12435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
12455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @constructor
1246926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @extends EventEmitter
1247926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {?Element} element
1248926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * View adds itself as a property on the element so we can access it from Event.target.
1249926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
1250926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)function View(element) {
1251926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    EventEmitter.call(this);
1252926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
1253926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {Element}
1254926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @const
1255926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
1256926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element = element || createElement("div");
1257926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.$view = this;
1258926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.bindCallbackMethods();
12595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
12605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1261926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)View.prototype = Object.create(EventEmitter.prototype);
1262926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
12635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
1264926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!Element} ancestorElement
1265926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {?Object}
12665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1267926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)View.prototype.offsetRelativeTo = function(ancestorElement) {
1268926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var x = 0;
1269926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var y = 0;
1270926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var element = this.element;
1271926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    while (element) {
1272926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        x += element.offsetLeft  || 0;
1273926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        y += element.offsetTop || 0;
1274926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        element = element.offsetParent;
1275926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (element === ancestorElement)
1276926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            return {x: x, y: y};
1277926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
1278926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return null;
1279926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
12805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
1282926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!View|Node} parent
1283926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {?View|Node=} before
12845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1285926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)View.prototype.attachTo = function(parent, before) {
1286926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (parent instanceof View)
1287926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return this.attachTo(parent.element, before);
1288926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (typeof before === "undefined")
1289926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        before = null;
1290926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (before instanceof View)
1291926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        before = before.element;
1292926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    parent.insertBefore(this.element, before);
1293926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
12945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1295926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)View.prototype.bindCallbackMethods = function() {
1296926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    for (var methodName in this) {
1297926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (!/^on[A-Z]/.test(methodName))
1298926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            continue;
1299926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (this.hasOwnProperty(methodName))
1300926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            continue;
1301926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var method = this[methodName];
1302926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (!(method instanceof Function))
1303926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            continue;
1304926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this[methodName] = method.bind(this);
1305926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
13065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
13075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
1309926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @constructor
1310926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @extends View
1311926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
1312926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)function ScrollView() {
1313926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    View.call(this, createElement("div", ScrollView.ClassNameScrollView));
1314926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
1315926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {Element}
1316926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @const
1317926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
1318926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.contentElement = createElement("div", ScrollView.ClassNameScrollViewContent);
1319926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.appendChild(this.contentElement);
1320926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
1321926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {number}
1322926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
1323926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.minimumContentOffset = -Infinity;
1324926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
1325926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {number}
1326926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
1327926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.maximumContentOffset = Infinity;
1328926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
1329926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {number}
1330926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @protected
1331926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
1332926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._contentOffset = 0;
1333926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
1334926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {number}
1335926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @protected
1336926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
1337926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._width = 0;
1338926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
1339926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {number}
1340926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @protected
1341926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
1342926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._height = 0;
1343926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
1344926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {Animator}
1345926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @protected
1346926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
1347926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._scrollAnimator = null;
1348926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
1349926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {?Object}
1350926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
1351926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.delegate = null;
1352926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
1353926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!number}
1354926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
1355926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._lastTouchPosition = 0;
1356926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
1357926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!number}
1358926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
1359926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._lastTouchVelocity = 0;
1360926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
1361926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!number}
1362926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
1363926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._lastTouchTimeStamp = 0;
1364926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1365926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.addEventListener("mousewheel", this.onMouseWheel, false);
1366926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.addEventListener("touchstart", this.onTouchStart, false);
1367926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1368926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
1369926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * The content offset is partitioned so the it can go beyond the CSS limit
1370926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * of 33554433px.
1371926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {number}
1372926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @protected
1373926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
1374926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._partitionNumber = 0;
13755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
13765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1377926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ScrollView.prototype = Object.create(View.prototype);
1378926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1379926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ScrollView.PartitionHeight = 100000;
1380926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ScrollView.ClassNameScrollView = "scroll-view";
1381926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ScrollView.ClassNameScrollViewContent = "scroll-view-content";
1382926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
13835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
1384926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!Event} event
13855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1386926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ScrollView.prototype.onTouchStart = function(event) {
1387926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var touch = event.touches[0];
1388926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._lastTouchPosition = touch.clientY;
1389926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._lastTouchVelocity = 0;
1390926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._lastTouchTimeStamp = event.timeStamp;
1391926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this._scrollAnimator)
1392926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this._scrollAnimator.stop();
1393926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    window.addEventListener("touchmove", this.onWindowTouchMove, false);
1394926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    window.addEventListener("touchend", this.onWindowTouchEnd, false);
1395926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
13965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
1398926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!Event} event
13995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1400926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ScrollView.prototype.onWindowTouchMove = function(event) {
1401926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var touch = event.touches[0];
1402926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var deltaTime = event.timeStamp - this._lastTouchTimeStamp;
1403926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var deltaY = this._lastTouchPosition - touch.clientY;
1404926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.scrollBy(deltaY, false);
1405926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._lastTouchVelocity = deltaY / deltaTime;
1406926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._lastTouchPosition = touch.clientY;
1407926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._lastTouchTimeStamp = event.timeStamp;
1408926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    event.stopPropagation();
1409926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    event.preventDefault();
1410926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
14115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
1413926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!Event} event
14145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1415926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ScrollView.prototype.onWindowTouchEnd = function(event) {
1416926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (Math.abs(this._lastTouchVelocity) > 0.01) {
1417926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this._scrollAnimator = new FlingGestureAnimator(this._lastTouchVelocity, this._contentOffset);
1418926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this._scrollAnimator.step = this.onFlingGestureAnimatorStep;
1419926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this._scrollAnimator.start();
14205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1421926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    window.removeEventListener("touchmove", this.onWindowTouchMove, false);
1422926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    window.removeEventListener("touchend", this.onWindowTouchEnd, false);
14235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
14245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
1426926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!Animator} animator
1427926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
1428926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ScrollView.prototype.onFlingGestureAnimatorStep = function(animator) {
1429926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.scrollTo(animator.currentValue, false);
14305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
14315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
1433926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!Animator}
14345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1435926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ScrollView.prototype.scrollAnimator = function() {
1436926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return this._scrollAnimator;
14375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
14385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1439926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
1440926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} width
1441926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
1442926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ScrollView.prototype.setWidth = function(width) {
1443926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    console.assert(isFinite(width));
1444926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this._width === width)
14455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1446926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._width = width;
1447926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.style.width = this._width + "px";
14485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
14495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
1451926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!number}
14525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1453926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ScrollView.prototype.width = function() {
1454926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return this._width;
14555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
14565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
1458926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} height
14595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1460926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ScrollView.prototype.setHeight = function(height) {
1461926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    console.assert(isFinite(height));
1462926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this._height === height)
1463926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
1464926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._height = height;
1465926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.style.height = height + "px";
1466926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this.delegate)
1467926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.delegate.scrollViewDidChangeHeight(this);
14685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
14695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
1471926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!number}
14725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1473926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ScrollView.prototype.height = function() {
1474926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return this._height;
14755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
14765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
1478926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!Animator} animator
14795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1480926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ScrollView.prototype.onScrollAnimatorStep = function(animator) {
1481926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.setContentOffset(animator.currentValue);
14825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
14835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
1485926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} offset
1486926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {?boolean} animate
14875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1488926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ScrollView.prototype.scrollTo = function(offset, animate) {
1489926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    console.assert(isFinite(offset));
1490926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!animate) {
1491926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.setContentOffset(offset);
1492926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
1493926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
1494926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this._scrollAnimator)
1495926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this._scrollAnimator.stop();
1496926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._scrollAnimator = new TransitionAnimator();
1497926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._scrollAnimator.step = this.onScrollAnimatorStep;
1498926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._scrollAnimator.setFrom(this._contentOffset);
1499926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._scrollAnimator.setTo(offset);
1500926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._scrollAnimator.duration = 300;
1501926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._scrollAnimator.start();
15025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
15035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
1505926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} offset
1506926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {?boolean} animate
15075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1508926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ScrollView.prototype.scrollBy = function(offset, animate) {
1509926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.scrollTo(this._contentOffset + offset, animate);
15105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
15115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
1513926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!number}
15145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1515926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ScrollView.prototype.contentOffset = function() {
1516926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return this._contentOffset;
15175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
15185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
1520926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {?Event} event
15215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1522926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ScrollView.prototype.onMouseWheel = function(event) {
1523926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.setContentOffset(this._contentOffset - event.wheelDelta / 30);
1524926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    event.stopPropagation();
1525926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    event.preventDefault();
15265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
15275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1528926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
15295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
1530926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} value
15315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1532926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ScrollView.prototype.setContentOffset = function(value) {
1533926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    console.assert(isFinite(value));
1534926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    value = Math.min(this.maximumContentOffset - this._height, Math.max(this.minimumContentOffset, Math.floor(value)));
1535926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this._contentOffset === value)
1536926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
1537d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    this._contentOffset = value;
1538d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    this._updateScrollContent();
1539d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (this.delegate)
1540d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        this.delegate.scrollViewDidChangeContentOffset(this);
1541d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)};
1542d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
1543d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)ScrollView.prototype._updateScrollContent = function() {
1544d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    var newPartitionNumber = Math.floor(this._contentOffset / ScrollView.PartitionHeight);
1545926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var partitionChanged = this._partitionNumber !== newPartitionNumber;
1546926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._partitionNumber = newPartitionNumber;
1547926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.contentElement.style.webkitTransform = "translate(0, " + (-this.contentPositionForContentOffset(this._contentOffset)) + "px)";
1548d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (this.delegate && partitionChanged)
1549d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        this.delegate.scrollViewDidChangePartition(this);
1550d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)};
1551d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
1552d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)/**
1553d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) * @param {!View|Node} parent
1554d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) * @param {?View|Node=} before
1555d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) * @override
1556d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) */
1557d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)ScrollView.prototype.attachTo = function(parent, before) {
1558d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    View.prototype.attachTo.call(this, parent, before);
1559d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    this._updateScrollContent();
15605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
15615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
1563926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} offset
15645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1565926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ScrollView.prototype.contentPositionForContentOffset = function(offset) {
1566926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return offset - this._partitionNumber * ScrollView.PartitionHeight;
15675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
15685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
1570926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @constructor
1571926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @extends View
1572926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
1573926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)function ListCell() {
1574926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    View.call(this, createElement("div", ListCell.ClassNameListCell));
1575926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1576926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
1577926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!number}
1578926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
1579926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.row = NaN;
1580926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
1581926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!number}
1582926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
1583926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._width = 0;
1584926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
1585926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!number}
1586926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
1587926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._position = 0;
1588926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
1589926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1590926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ListCell.prototype = Object.create(View.prototype);
1591926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1592926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ListCell.DefaultRecycleBinLimit = 64;
1593926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ListCell.ClassNameListCell = "list-cell";
1594926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ListCell.ClassNameHidden = "hidden";
1595926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1596926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
1597926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!Array} An array to keep thrown away cells.
15985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1599926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ListCell.prototype._recycleBin = function() {
1600926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    console.assert(false, "NOT REACHED: ListCell.prototype._recycleBin needs to be overridden.");
1601926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return [];
1602926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
1603926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1604926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ListCell.prototype.throwAway = function() {
1605926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.hide();
1606926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var limit = typeof this.constructor.RecycleBinLimit === "undefined" ? ListCell.DefaultRecycleBinLimit : this.constructor.RecycleBinLimit;
1607926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var recycleBin = this._recycleBin();
1608926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (recycleBin.length < limit)
1609926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        recycleBin.push(this);
1610926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
1611926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1612926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ListCell.prototype.show = function() {
1613926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.classList.remove(ListCell.ClassNameHidden);
1614926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
1615926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1616926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ListCell.prototype.hide = function() {
1617926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.classList.add(ListCell.ClassNameHidden);
16185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
16195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
16205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
1621926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!number} Width in pixels.
16225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1623926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ListCell.prototype.width = function(){
1624926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return this._width;
16255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
16265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
16275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
1628926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} width Width in pixels.
16295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1630926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ListCell.prototype.setWidth = function(width){
1631926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this._width === width)
16325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1633926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._width = width;
1634926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.style.width = this._width + "px";
16355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
16365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
16375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
1638926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!number} Position in pixels.
16395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1640926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ListCell.prototype.position = function(){
1641926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return this._position;
16425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
16435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
16445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
1645926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} y Position in pixels.
16465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1647926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ListCell.prototype.setPosition = function(y) {
1648926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this._position === y)
16495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1650926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._position = y;
1651926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.style.webkitTransform = "translate(0, " + this._position + "px)";
16525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
16535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
16545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
1655926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!boolean} selected
16565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1657926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ListCell.prototype.setSelected = function(selected) {
1658926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this._selected === selected)
1659926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
1660926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._selected = selected;
1661926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this._selected)
1662926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.element.classList.add("selected");
1663926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    else
1664926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.element.classList.remove("selected");
16655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
16665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
16675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
16685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @constructor
1669926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @extends View
1670926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
1671926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)function ListView() {
1672926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    View.call(this, createElement("div", ListView.ClassNameListView));
1673926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.tabIndex = 0;
16747242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    this.element.setAttribute("role", "grid");
1675926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1676926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
1677926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!number}
1678926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @private
1679926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
1680926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._width = 0;
1681926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
1682926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!Object}
1683926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @private
1684926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
1685926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._cells = {};
1686926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1687926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
1688926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!number}
1689926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
1690926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.selectedRow = ListView.NoSelection;
1691926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1692926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
1693926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!ScrollView}
1694926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
1695926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.scrollView = new ScrollView();
1696926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.scrollView.delegate = this;
1697926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.scrollView.minimumContentOffset = 0;
1698926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.scrollView.setWidth(0);
1699926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.scrollView.setHeight(0);
1700926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.scrollView.attachTo(this);
1701926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1702926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.addEventListener("click", this.onClick, false);
1703926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1704926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
1705926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!boolean}
1706926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @private
1707926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
1708926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._needsUpdateCells = false;
17095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1710926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1711926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ListView.prototype = Object.create(View.prototype);
1712926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1713926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ListView.NoSelection = -1;
1714926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ListView.ClassNameListView = "list-view";
1715926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1716926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ListView.prototype.onAnimationFrameWillFinish = function() {
1717926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this._needsUpdateCells)
1718926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.updateCells();
1719926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
17205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
1722926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!boolean} needsUpdateCells
17235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1724926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ListView.prototype.setNeedsUpdateCells = function(needsUpdateCells) {
1725926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this._needsUpdateCells === needsUpdateCells)
1726926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
1727926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._needsUpdateCells = needsUpdateCells;
1728926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this._needsUpdateCells)
1729926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        AnimationManager.shared.on(AnimationManager.EventTypeAnimationFrameWillFinish, this.onAnimationFrameWillFinish);
1730926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    else
1731926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        AnimationManager.shared.removeListener(AnimationManager.EventTypeAnimationFrameWillFinish, this.onAnimationFrameWillFinish);
17325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
17335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
1735926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} row
1736926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {?ListCell}
17375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1738926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ListView.prototype.cellAtRow = function(row) {
1739926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return this._cells[row];
17405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
17415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
1743926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} offset Scroll offset in pixels.
1744926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!number}
17455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1746926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ListView.prototype.rowAtScrollOffset = function(offset) {
1747926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    console.assert(false, "NOT REACHED: ListView.prototype.rowAtScrollOffset needs to be overridden.");
1748926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return 0;
17495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
17505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
1752926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} row
1753926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!number} Scroll offset in pixels.
17545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1755926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ListView.prototype.scrollOffsetForRow = function(row) {
1756926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    console.assert(false, "NOT REACHED: ListView.prototype.scrollOffsetForRow needs to be overridden.");
1757926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return 0;
17585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
17595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
1761926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} row
1762926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!ListCell}
17635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1764926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ListView.prototype.addCellIfNecessary = function(row) {
1765926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var cell = this._cells[row];
1766926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (cell)
1767926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return cell;
1768926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    cell = this.prepareNewCell(row);
1769926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    cell.attachTo(this.scrollView.contentElement);
1770926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    cell.setWidth(this._width);
1771926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    cell.setPosition(this.scrollView.contentPositionForContentOffset(this.scrollOffsetForRow(row)));
1772926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._cells[row] = cell;
1773926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return cell;
17745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
17755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
1777926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} row
1778926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!ListCell}
17795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1780926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ListView.prototype.prepareNewCell = function(row) {
1781926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    console.assert(false, "NOT REACHED: ListView.prototype.prepareNewCell should be overridden.");
1782926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return new ListCell();
17835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
17845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
1786926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!ListCell} cell
17875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1788926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ListView.prototype.throwAwayCell = function(cell) {
1789926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    delete this._cells[cell.row];
1790926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    cell.throwAway();
1791926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
17925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
1794926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!number}
17955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1796926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ListView.prototype.firstVisibleRow = function() {
1797926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return this.rowAtScrollOffset(this.scrollView.contentOffset());
17985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
17995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
18005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
1801926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!number}
18025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1803926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ListView.prototype.lastVisibleRow = function() {
1804926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return this.rowAtScrollOffset(this.scrollView.contentOffset() + this.scrollView.height() - 1);
18055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
18065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
18075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
1808926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!ScrollView} scrollView
18095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1810926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ListView.prototype.scrollViewDidChangeContentOffset = function(scrollView) {
1811926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.setNeedsUpdateCells(true);
18125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
18135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
18145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
1815926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!ScrollView} scrollView
18165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1817926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ListView.prototype.scrollViewDidChangeHeight = function(scrollView) {
1818926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.setNeedsUpdateCells(true);
18195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
18205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
18215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
1822926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!ScrollView} scrollView
18235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1824926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ListView.prototype.scrollViewDidChangePartition = function(scrollView) {
1825926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.setNeedsUpdateCells(true);
1826926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
1827926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1828926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ListView.prototype.updateCells = function() {
1829926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var firstVisibleRow = this.firstVisibleRow();
1830926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var lastVisibleRow = this.lastVisibleRow();
1831926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    console.assert(firstVisibleRow <= lastVisibleRow);
1832926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    for (var c in this._cells) {
1833926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var cell = this._cells[c];
1834926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (cell.row < firstVisibleRow || cell.row > lastVisibleRow)
1835926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            this.throwAwayCell(cell);
1836926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
1837926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    for (var i = firstVisibleRow; i <= lastVisibleRow; ++i) {
1838926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var cell = this._cells[i];
1839926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (cell)
1840926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            cell.setPosition(this.scrollView.contentPositionForContentOffset(this.scrollOffsetForRow(cell.row)));
1841926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        else
1842926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            this.addCellIfNecessary(i);
1843926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
1844926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.setNeedsUpdateCells(false);
1845926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
1846926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1847926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
1848926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!number} Width in pixels.
1849926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
1850926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ListView.prototype.width = function() {
1851926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return this._width;
1852926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
1853926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1854926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
1855926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} width Width in pixels.
1856926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
1857926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ListView.prototype.setWidth = function(width) {
1858926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this._width === width)
1859926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
1860926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._width = width;
1861926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.scrollView.setWidth(this._width);
1862926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    for (var c in this._cells) {
1863926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this._cells[c].setWidth(this._width);
1864926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
1865926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.style.width = this._width + "px";
1866926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.setNeedsUpdateCells(true);
1867926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
1868926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1869926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
1870926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!number} Height in pixels.
1871926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
1872926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ListView.prototype.height = function() {
1873926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return this.scrollView.height();
1874926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
1875926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1876926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
1877926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} height Height in pixels.
1878926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
1879926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ListView.prototype.setHeight = function(height) {
1880926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.scrollView.setHeight(height);
1881926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
1882926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1883926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
1884926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {?Event} event
1885926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
1886926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ListView.prototype.onClick = function(event) {
1887926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var clickedCellElement = enclosingNodeOrSelfWithClass(event.target, ListCell.ClassNameListCell);
1888926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!clickedCellElement)
1889926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
1890926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var clickedCell = clickedCellElement.$view;
1891926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (clickedCell.row !== this.selectedRow)
1892926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.select(clickedCell.row);
1893926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
1894926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1895926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
1896926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} row
1897926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
1898926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ListView.prototype.select = function(row) {
1899926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this.selectedRow === row)
1900926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
1901926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.deselect();
1902926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (row === ListView.NoSelection)
1903926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
1904926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.selectedRow = row;
1905926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var selectedCell = this._cells[this.selectedRow];
1906926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (selectedCell)
1907926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        selectedCell.setSelected(true);
1908926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
1909926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1910926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ListView.prototype.deselect = function() {
1911926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this.selectedRow === ListView.NoSelection)
1912926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
1913926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var selectedCell = this._cells[this.selectedRow];
1914926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (selectedCell)
1915926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        selectedCell.setSelected(false);
1916926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.selectedRow = ListView.NoSelection;
1917926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
1918926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1919926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
1920926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} row
1921926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!boolean} animate
1922926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
1923926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ListView.prototype.scrollToRow = function(row, animate) {
1924926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.scrollView.scrollTo(this.scrollOffsetForRow(row), animate);
1925926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
1926926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1927926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
1928926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @constructor
1929926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @extends View
1930926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!ScrollView} scrollView
1931926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
1932926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)function ScrubbyScrollBar(scrollView) {
1933926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    View.call(this, createElement("div", ScrubbyScrollBar.ClassNameScrubbyScrollBar));
1934926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1935926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
1936926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!Element}
1937926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @const
1938926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
1939926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.thumb = createElement("div", ScrubbyScrollBar.ClassNameScrubbyScrollThumb);
1940926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.appendChild(this.thumb);
1941926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1942926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
1943926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!ScrollView}
1944926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @const
1945926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
1946926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.scrollView = scrollView;
1947926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1948926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
1949926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!number}
1950926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @protected
1951926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
1952926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._height = 0;
1953926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
1954926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!number}
1955926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @protected
1956926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
1957926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._thumbHeight = 0;
1958926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
1959926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!number}
1960926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @protected
1961926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
1962926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._thumbPosition = 0;
1963926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1964926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.setHeight(0);
1965926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.setThumbHeight(ScrubbyScrollBar.ThumbHeight);
1966926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1967926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
1968926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {?Animator}
1969926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @protected
1970926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
1971926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._thumbStyleTopAnimator = null;
1972926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1973926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
1974926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {?number}
1975926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @protected
1976926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
1977926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._timer = null;
1978926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1979926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.addEventListener("mousedown", this.onMouseDown, false);
1980926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.addEventListener("touchstart", this.onTouchStart, false);
1981926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
1982926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1983926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ScrubbyScrollBar.prototype = Object.create(View.prototype);
1984926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1985926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ScrubbyScrollBar.ScrollInterval = 16;
1986926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ScrubbyScrollBar.ThumbMargin = 2;
1987926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ScrubbyScrollBar.ThumbHeight = 30;
1988926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ScrubbyScrollBar.ClassNameScrubbyScrollBar = "scrubby-scroll-bar";
1989926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ScrubbyScrollBar.ClassNameScrubbyScrollThumb = "scrubby-scroll-thumb";
1990926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1991926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
1992926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {?Event} event
1993926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
1994926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ScrubbyScrollBar.prototype.onTouchStart = function(event) {
1995926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var touch = event.touches[0];
1996926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._setThumbPositionFromEventPosition(touch.clientY);
1997926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this._thumbStyleTopAnimator)
1998926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this._thumbStyleTopAnimator.stop();
1999926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._timer = setInterval(this.onScrollTimer, ScrubbyScrollBar.ScrollInterval);
2000926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    window.addEventListener("touchmove", this.onWindowTouchMove, false);
2001926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    window.addEventListener("touchend", this.onWindowTouchEnd, false);
2002926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    event.stopPropagation();
2003926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    event.preventDefault();
2004926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
2005926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2006926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
2007926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {?Event} event
2008926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
2009926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ScrubbyScrollBar.prototype.onWindowTouchMove = function(event) {
2010926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var touch = event.touches[0];
2011926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._setThumbPositionFromEventPosition(touch.clientY);
2012926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    event.stopPropagation();
2013926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    event.preventDefault();
2014926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
2015926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2016926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
2017926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {?Event} event
2018926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
2019926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ScrubbyScrollBar.prototype.onWindowTouchEnd = function(event) {
2020926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._thumbStyleTopAnimator = new TransitionAnimator();
2021926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._thumbStyleTopAnimator.step = this.onThumbStyleTopAnimationStep;
2022926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._thumbStyleTopAnimator.setFrom(this.thumb.offsetTop);
2023926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._thumbStyleTopAnimator.setTo((this._height - this._thumbHeight) / 2);
2024926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._thumbStyleTopAnimator.timingFunction = AnimationTimingFunction.EaseInOut;
2025926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._thumbStyleTopAnimator.duration = 100;
2026926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._thumbStyleTopAnimator.start();
2027926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2028926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    window.removeEventListener("touchmove", this.onWindowTouchMove, false);
2029926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    window.removeEventListener("touchend", this.onWindowTouchEnd, false);
2030926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    clearInterval(this._timer);
2031926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
2032926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2033926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
2034926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!number} Height of the view in pixels.
2035926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
2036926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ScrubbyScrollBar.prototype.height = function() {
2037926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return this._height;
2038926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
2039926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2040926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
2041926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} height Height of the view in pixels.
2042926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
2043926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ScrubbyScrollBar.prototype.setHeight = function(height) {
2044926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this._height === height)
2045926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
2046926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._height = height;
2047926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.style.height = this._height + "px";
2048926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.thumb.style.top = ((this._height - this._thumbHeight) / 2) + "px";
2049926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._thumbPosition = 0;
2050926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
2051926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2052926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
2053926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} height Height of the scroll bar thumb in pixels.
2054926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
2055926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ScrubbyScrollBar.prototype.setThumbHeight = function(height) {
2056926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this._thumbHeight === height)
2057926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
2058926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._thumbHeight = height;
2059926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.thumb.style.height = this._thumbHeight + "px";
2060926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.thumb.style.top = ((this._height - this._thumbHeight) / 2) + "px";
2061926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._thumbPosition = 0;
2062926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
2063926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2064926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
2065926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {number} position
2066926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
2067926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ScrubbyScrollBar.prototype._setThumbPositionFromEventPosition = function(position) {
2068926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var thumbMin = ScrubbyScrollBar.ThumbMargin;
2069926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var thumbMax = this._height - this._thumbHeight - ScrubbyScrollBar.ThumbMargin * 2;
2070926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var y = position - this.element.getBoundingClientRect().top - this.element.clientTop + this.element.scrollTop;
2071926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var thumbPosition = y - this._thumbHeight / 2;
2072926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    thumbPosition = Math.max(thumbPosition, thumbMin);
2073926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    thumbPosition = Math.min(thumbPosition, thumbMax);
2074926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.thumb.style.top = thumbPosition + "px";
2075926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._thumbPosition = 1.0 - (thumbPosition - thumbMin) / (thumbMax - thumbMin) * 2;
2076926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
2077926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2078926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
2079926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {?Event} event
2080926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
2081926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ScrubbyScrollBar.prototype.onMouseDown = function(event) {
2082926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._setThumbPositionFromEventPosition(event.clientY);
2083926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2084926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    window.addEventListener("mousemove", this.onWindowMouseMove, false);
2085926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    window.addEventListener("mouseup", this.onWindowMouseUp, false);
2086926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this._thumbStyleTopAnimator)
2087926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this._thumbStyleTopAnimator.stop();
2088926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._timer = setInterval(this.onScrollTimer, ScrubbyScrollBar.ScrollInterval);
2089926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    event.stopPropagation();
2090926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    event.preventDefault();
2091926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
2092926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2093926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
2094926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {?Event} event
2095926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
2096926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ScrubbyScrollBar.prototype.onWindowMouseMove = function(event) {
2097926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._setThumbPositionFromEventPosition(event.clientY);
2098926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
2099926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2100926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
2101926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {?Event} event
2102926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
2103926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ScrubbyScrollBar.prototype.onWindowMouseUp = function(event) {
2104926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._thumbStyleTopAnimator = new TransitionAnimator();
2105926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._thumbStyleTopAnimator.step = this.onThumbStyleTopAnimationStep;
2106926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._thumbStyleTopAnimator.setFrom(this.thumb.offsetTop);
2107926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._thumbStyleTopAnimator.setTo((this._height - this._thumbHeight) / 2);
2108926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._thumbStyleTopAnimator.timingFunction = AnimationTimingFunction.EaseInOut;
2109926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._thumbStyleTopAnimator.duration = 100;
2110926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._thumbStyleTopAnimator.start();
2111926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2112926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    window.removeEventListener("mousemove", this.onWindowMouseMove, false);
2113926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    window.removeEventListener("mouseup", this.onWindowMouseUp, false);
2114926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    clearInterval(this._timer);
2115926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
2116926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2117926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
2118926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!Animator} animator
2119926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
2120926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ScrubbyScrollBar.prototype.onThumbStyleTopAnimationStep = function(animator) {
2121926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.thumb.style.top = animator.currentValue + "px";
2122926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
2123926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2124926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ScrubbyScrollBar.prototype.onScrollTimer = function() {
2125926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var scrollAmount = Math.pow(this._thumbPosition, 2) * 10;
2126926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this._thumbPosition > 0)
2127926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        scrollAmount = -scrollAmount;
2128926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.scrollView.scrollBy(scrollAmount, false);
2129926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
2130926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2131926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
2132926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @constructor
2133926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @extends ListCell
2134926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!Array} shortMonthLabels
2135926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
2136926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)function YearListCell(shortMonthLabels) {
2137926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ListCell.call(this);
2138926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.classList.add(YearListCell.ClassNameYearListCell);
2139926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.style.height = YearListCell.Height + "px";
2140926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2141926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
2142926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!Element}
2143926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @const
2144926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
2145926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.label = createElement("div", YearListCell.ClassNameLabel, "----");
2146926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.appendChild(this.label);
2147926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.label.style.height = (YearListCell.Height - YearListCell.BorderBottomWidth) + "px";
2148926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.label.style.lineHeight = (YearListCell.Height - YearListCell.BorderBottomWidth) + "px";
2149926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2150926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
2151926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!Array} Array of the 12 month button elements.
2152926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @const
2153926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
2154926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.monthButtons = [];
2155926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var monthChooserElement = createElement("div", YearListCell.ClassNameMonthChooser);
2156926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    for (var r = 0; r < YearListCell.ButtonRows; ++r) {
2157926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var buttonsRow = createElement("div", YearListCell.ClassNameMonthButtonsRow);
21587242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        buttonsRow.setAttribute("role", "row");
2159926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        for (var c = 0; c < YearListCell.ButtonColumns; ++c) {
2160926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            var month = c + r * YearListCell.ButtonColumns;
21617242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            var button = createElement("div", YearListCell.ClassNameMonthButton, shortMonthLabels[month]);
21627242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            button.setAttribute("role", "gridcell");
2163926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            button.dataset.month = month;
2164926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            buttonsRow.appendChild(button);
2165926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            this.monthButtons.push(button);
2166926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
2167926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        monthChooserElement.appendChild(buttonsRow);
2168926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
2169926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.appendChild(monthChooserElement);
2170926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2171926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
2172926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!boolean}
2173926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @private
2174926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
2175926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._selected = false;
2176926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
2177926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!number}
2178926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @private
2179926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
2180926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._height = 0;
2181926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
2182926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2183926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)YearListCell.prototype = Object.create(ListCell.prototype);
2184926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2185926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)YearListCell.Height = hasInaccuratePointingDevice() ? 31 : 25;
2186926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)YearListCell.BorderBottomWidth = 1;
2187926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)YearListCell.ButtonRows = 3;
2188926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)YearListCell.ButtonColumns = 4;
2189926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)YearListCell.SelectedHeight = hasInaccuratePointingDevice() ? 127 : 121;
2190926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)YearListCell.ClassNameYearListCell = "year-list-cell";
2191926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)YearListCell.ClassNameLabel = "label";
2192926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)YearListCell.ClassNameMonthChooser = "month-chooser";
2193926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)YearListCell.ClassNameMonthButtonsRow = "month-buttons-row";
2194926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)YearListCell.ClassNameMonthButton = "month-button";
2195926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)YearListCell.ClassNameHighlighted = "highlighted";
2196926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2197926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)YearListCell._recycleBin = [];
2198926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2199926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
2200926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!Array}
2201926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @override
2202926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
2203926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)YearListCell.prototype._recycleBin = function() {
2204926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return YearListCell._recycleBin;
2205926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
2206926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2207926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
2208926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} row
2209926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
2210926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)YearListCell.prototype.reset = function(row) {
2211926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.row = row;
2212926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.label.textContent = row + 1;
2213926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    for (var i = 0; i < this.monthButtons.length; ++i) {
2214926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.monthButtons[i].classList.remove(YearListCell.ClassNameHighlighted);
2215926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
2216926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.show();
2217926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
2218926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2219926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
2220926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!number} The height in pixels.
2221926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
2222926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)YearListCell.prototype.height = function() {
2223926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return this._height;
2224926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
2225926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2226926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
2227926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} height Height in pixels.
2228926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
2229926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)YearListCell.prototype.setHeight = function(height) {
2230926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this._height === height)
2231926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
2232926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._height = height;
2233926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.style.height = this._height + "px";
2234926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
2235926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2236926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
2237926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @constructor
2238926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @extends ListView
2239926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!Month} minimumMonth
2240926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!Month} maximumMonth
2241926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
2242926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)function YearListView(minimumMonth, maximumMonth) {
2243926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ListView.call(this);
2244926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.classList.add("year-list-view");
2245926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2246926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
2247926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {?Month}
2248926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
2249926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.highlightedMonth = null;
2250926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
2251926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!Month}
2252926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @const
2253926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @protected
2254926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
2255926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._minimumMonth = minimumMonth;
2256926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
2257926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!Month}
2258926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @const
2259926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @protected
2260926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
2261926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._maximumMonth = maximumMonth;
2262926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2263926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.scrollView.minimumContentOffset = (this._minimumMonth.year - 1) * YearListCell.Height;
2264926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.scrollView.maximumContentOffset = (this._maximumMonth.year - 1) * YearListCell.Height + YearListCell.SelectedHeight;
2265926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2266926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
2267926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!Object}
2268926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @const
2269926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @protected
2270926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
2271926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._runningAnimators = {};
2272926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
2273926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!Array}
2274926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @const
2275926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @protected
2276926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
2277926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._animatingRows = [];
2278926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
2279926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!boolean}
2280926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @protected
2281926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
2282926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._ignoreMouseOutUntillNextMouseOver = false;
2283926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2284926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
2285926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!ScrubbyScrollBar}
2286926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @const
2287926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
2288926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.scrubbyScrollBar = new ScrubbyScrollBar(this.scrollView);
2289926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.scrubbyScrollBar.attachTo(this);
2290926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2291926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.addEventListener("mouseover", this.onMouseOver, false);
2292926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.addEventListener("mouseout", this.onMouseOut, false);
2293926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.addEventListener("keydown", this.onKeyDown, false);
2294926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.addEventListener("touchstart", this.onTouchStart, false);
2295926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
2296926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2297926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)YearListView.prototype = Object.create(ListView.prototype);
2298926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2299926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)YearListView.Height = YearListCell.SelectedHeight - 1;
2300926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)YearListView.EventTypeYearListViewDidHide = "yearListViewDidHide";
2301926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)YearListView.EventTypeYearListViewDidSelectMonth = "yearListViewDidSelectMonth";
2302926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2303926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
2304926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {?Event} event
2305926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
2306926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)YearListView.prototype.onTouchStart = function(event) {
2307926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var touch = event.touches[0];
2308926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var monthButtonElement = enclosingNodeOrSelfWithClass(touch.target, YearListCell.ClassNameMonthButton);
2309926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!monthButtonElement)
2310926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
2311926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var cellElement = enclosingNodeOrSelfWithClass(monthButtonElement, YearListCell.ClassNameYearListCell);
2312926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var cell = cellElement.$view;
2313926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.highlightMonth(new Month(cell.row + 1, parseInt(monthButtonElement.dataset.month, 10)));
2314926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
2315926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2316926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
2317926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {?Event} event
2318926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
2319926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)YearListView.prototype.onMouseOver = function(event) {
2320926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var monthButtonElement = enclosingNodeOrSelfWithClass(event.target, YearListCell.ClassNameMonthButton);
2321926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!monthButtonElement)
2322926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
2323926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var cellElement = enclosingNodeOrSelfWithClass(monthButtonElement, YearListCell.ClassNameYearListCell);
2324926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var cell = cellElement.$view;
2325926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.highlightMonth(new Month(cell.row + 1, parseInt(monthButtonElement.dataset.month, 10)));
2326926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._ignoreMouseOutUntillNextMouseOver = false;
2327926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
2328926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2329926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
2330926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {?Event} event
2331926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
2332926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)YearListView.prototype.onMouseOut = function(event) {
2333926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this._ignoreMouseOutUntillNextMouseOver)
2334926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
2335926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var monthButtonElement = enclosingNodeOrSelfWithClass(event.target, YearListCell.ClassNameMonthButton);
2336926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!monthButtonElement) {
2337926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.dehighlightMonth();
2338926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
2339926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
2340926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2341926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
2342926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} width Width in pixels.
2343926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @override
2344926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
2345926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)YearListView.prototype.setWidth = function(width) {
2346926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ListView.prototype.setWidth.call(this, width - this.scrubbyScrollBar.element.offsetWidth);
2347926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.style.width = width + "px";
2348926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
2349926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2350926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
2351926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} height Height in pixels.
2352926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @override
2353926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
2354926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)YearListView.prototype.setHeight = function(height) {
2355926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ListView.prototype.setHeight.call(this, height);
2356926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.scrubbyScrollBar.setHeight(height);
2357926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
2358926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2359926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
2360926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @enum {number}
2361926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
2362926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)YearListView.RowAnimationDirection = {
2363926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    Opening: 0,
2364926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    Closing: 1
2365926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
2366926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2367926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
2368926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} row
2369926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!YearListView.RowAnimationDirection} direction
2370926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
2371926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)YearListView.prototype._animateRow = function(row, direction) {
2372926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var fromValue = direction === YearListView.RowAnimationDirection.Closing ? YearListCell.SelectedHeight : YearListCell.Height;
2373926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var oldAnimator = this._runningAnimators[row];
2374926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (oldAnimator) {
2375926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        oldAnimator.stop();
2376926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        fromValue = oldAnimator.currentValue;
2377926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
2378926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var cell = this.cellAtRow(row);
2379926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var animator = new TransitionAnimator();
2380926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    animator.step = this.onCellHeightAnimatorStep;
2381926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    animator.setFrom(fromValue);
2382926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    animator.setTo(direction === YearListView.RowAnimationDirection.Opening ? YearListCell.SelectedHeight : YearListCell.Height);
2383926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    animator.timingFunction = AnimationTimingFunction.EaseInOut;
2384926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    animator.duration = 300;
2385926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    animator.row = row;
2386926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    animator.on(Animator.EventTypeDidAnimationStop, this.onCellHeightAnimatorDidStop);
2387926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._runningAnimators[row] = animator;
2388926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._animatingRows.push(row);
2389926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._animatingRows.sort();
2390926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    animator.start();
2391926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
2392926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2393926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
2394926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {?Animator} animator
2395926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
2396926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)YearListView.prototype.onCellHeightAnimatorDidStop = function(animator) {
2397926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    delete this._runningAnimators[animator.row];
2398926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var index = this._animatingRows.indexOf(animator.row);
2399926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._animatingRows.splice(index, 1);
2400926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
2401926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2402926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
2403926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!Animator} animator
2404926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
2405926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)YearListView.prototype.onCellHeightAnimatorStep = function(animator) {
2406926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var cell = this.cellAtRow(animator.row);
2407926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (cell)
2408926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        cell.setHeight(animator.currentValue);
2409926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.updateCells();
2410926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
2411926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2412926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
2413926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {?Event} event
2414926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
2415926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)YearListView.prototype.onClick = function(event) {
2416926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var oldSelectedRow = this.selectedRow;
2417926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ListView.prototype.onClick.call(this, event);
2418926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var year = this.selectedRow + 1;
2419926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this.selectedRow !== oldSelectedRow) {
2420926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var month = this.highlightedMonth ? this.highlightedMonth.month : 0;
2421926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.dispatchEvent(YearListView.EventTypeYearListViewDidSelectMonth, this, new Month(year, month));
2422926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.scrollView.scrollTo(this.selectedRow * YearListCell.Height, true);
2423926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    } else {
2424926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var monthButton = enclosingNodeOrSelfWithClass(event.target, YearListCell.ClassNameMonthButton);
24257242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        if (!monthButton || monthButton.getAttribute("aria-disabled") == "true")
2426926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            return;
2427926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var month = parseInt(monthButton.dataset.month, 10);
2428926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.dispatchEvent(YearListView.EventTypeYearListViewDidSelectMonth, this, new Month(year, month));
2429926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.hide();
2430926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
2431926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
2432926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2433926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
2434926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} scrollOffset
2435926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!number}
2436926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @override
2437926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
2438926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)YearListView.prototype.rowAtScrollOffset = function(scrollOffset) {
2439926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var remainingOffset = scrollOffset;
2440926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var lastAnimatingRow = 0;
2441926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var rowsWithIrregularHeight = this._animatingRows.slice();
2442926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this.selectedRow > -1 && !this._runningAnimators[this.selectedRow]) {
2443926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        rowsWithIrregularHeight.push(this.selectedRow);
2444926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        rowsWithIrregularHeight.sort();
2445926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
2446926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    for (var i = 0; i < rowsWithIrregularHeight.length; ++i) {
2447926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var row = rowsWithIrregularHeight[i];
2448926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var animator = this._runningAnimators[row];
2449926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var rowHeight = animator ? animator.currentValue : YearListCell.SelectedHeight;
2450926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (remainingOffset <= (row - lastAnimatingRow) * YearListCell.Height) {
2451926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            return lastAnimatingRow + Math.floor(remainingOffset / YearListCell.Height);
2452926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
2453926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        remainingOffset -= (row - lastAnimatingRow) * YearListCell.Height;
2454926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (remainingOffset <= (rowHeight - YearListCell.Height))
2455926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            return row;
2456926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        remainingOffset -= rowHeight - YearListCell.Height;
2457926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        lastAnimatingRow = row;
2458926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
2459926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return lastAnimatingRow + Math.floor(remainingOffset / YearListCell.Height);
2460926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
2461926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2462926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
2463926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} row
2464926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!number}
2465926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @override
2466926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
2467926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)YearListView.prototype.scrollOffsetForRow = function(row) {
2468926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var scrollOffset = row * YearListCell.Height;
2469926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    for (var i = 0; i < this._animatingRows.length; ++i) {
2470926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var animatingRow = this._animatingRows[i];
2471926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (animatingRow >= row)
2472926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            break;
2473926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var animator = this._runningAnimators[animatingRow];
2474926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        scrollOffset += animator.currentValue - YearListCell.Height;
2475926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
2476926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this.selectedRow > -1 && this.selectedRow < row && !this._runningAnimators[this.selectedRow]) {
2477926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        scrollOffset += YearListCell.SelectedHeight - YearListCell.Height;
2478926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
2479926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return scrollOffset;
2480926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
2481926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2482926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
2483926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} row
2484926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!YearListCell}
2485926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @override
2486926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
2487926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)YearListView.prototype.prepareNewCell = function(row) {
2488926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var cell = YearListCell._recycleBin.pop() || new YearListCell(global.params.shortMonthLabels);
2489926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    cell.reset(row);
2490926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    cell.setSelected(this.selectedRow === row);
2491926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    for (var i = 0; i < cell.monthButtons.length; ++i) {
2492926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var month = new Month(row + 1, i);
24937242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        cell.monthButtons[i].id = month.toString();
24947242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        cell.monthButtons[i].setAttribute("aria-disabled", this._minimumMonth > month || this._maximumMonth < month ? "true" : "false");
24957242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        cell.monthButtons[i].setAttribute("aria-label", month.toLocaleString());
24967242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    }
24977242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if (this.highlightedMonth && row === this.highlightedMonth.year - 1) {
24987242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        var monthButton = cell.monthButtons[this.highlightedMonth.month];
24997242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        monthButton.classList.add(YearListCell.ClassNameHighlighted);
25007242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        // aira-activedescendant assumes both elements have renderers, and
25017242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        // |monthButton| might have no renderer yet.
25027242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        var element = this.element;
25037242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        setTimeout(function() {
25047242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            element.setAttribute("aria-activedescendant", monthButton.id);
25057242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        }, 0);
2506926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
2507926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var animator = this._runningAnimators[row];
2508926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (animator)
2509926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        cell.setHeight(animator.currentValue);
2510926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    else if (row === this.selectedRow)
2511926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        cell.setHeight(YearListCell.SelectedHeight);
2512926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    else
2513926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        cell.setHeight(YearListCell.Height);
2514926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return cell;
2515926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
2516926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2517926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
2518926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @override
2519926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
2520926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)YearListView.prototype.updateCells = function() {
2521926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var firstVisibleRow = this.firstVisibleRow();
2522926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var lastVisibleRow = this.lastVisibleRow();
2523926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    console.assert(firstVisibleRow <= lastVisibleRow);
2524926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    for (var c in this._cells) {
2525926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var cell = this._cells[c];
2526926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (cell.row < firstVisibleRow || cell.row > lastVisibleRow)
2527926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            this.throwAwayCell(cell);
2528926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
2529926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    for (var i = firstVisibleRow; i <= lastVisibleRow; ++i) {
2530926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var cell = this._cells[i];
2531926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (cell)
2532926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            cell.setPosition(this.scrollView.contentPositionForContentOffset(this.scrollOffsetForRow(cell.row)));
2533926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        else
2534926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            this.addCellIfNecessary(i);
2535926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
2536926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.setNeedsUpdateCells(false);
2537926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
2538926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2539926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
2540926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @override
2541926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
2542926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)YearListView.prototype.deselect = function() {
2543926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this.selectedRow === ListView.NoSelection)
2544926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
2545926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var selectedCell = this._cells[this.selectedRow];
2546926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (selectedCell)
2547926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        selectedCell.setSelected(false);
2548926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._animateRow(this.selectedRow, YearListView.RowAnimationDirection.Closing);
2549926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.selectedRow = ListView.NoSelection;
2550926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.setNeedsUpdateCells(true);
2551926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
2552926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2553926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)YearListView.prototype.deselectWithoutAnimating = function() {
2554926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this.selectedRow === ListView.NoSelection)
2555926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
2556926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var selectedCell = this._cells[this.selectedRow];
2557926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (selectedCell) {
2558926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        selectedCell.setSelected(false);
2559926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        selectedCell.setHeight(YearListCell.Height);
2560926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
2561926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.selectedRow = ListView.NoSelection;
2562926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.setNeedsUpdateCells(true);
2563926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
2564926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2565926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
2566926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} row
2567926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @override
2568926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
2569926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)YearListView.prototype.select = function(row) {
2570926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this.selectedRow === row)
2571926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
2572926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.deselect();
2573926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (row === ListView.NoSelection)
2574926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
2575926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.selectedRow = row;
2576926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this.selectedRow !== ListView.NoSelection) {
2577926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var selectedCell = this._cells[this.selectedRow];
2578926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this._animateRow(this.selectedRow, YearListView.RowAnimationDirection.Opening);
2579926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (selectedCell)
2580926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            selectedCell.setSelected(true);
2581926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var month = this.highlightedMonth ? this.highlightedMonth.month : 0;
2582926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.highlightMonth(new Month(this.selectedRow + 1, month));
2583926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
2584926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.setNeedsUpdateCells(true);
2585926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
2586926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2587926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
2588926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} row
2589926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
2590926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)YearListView.prototype.selectWithoutAnimating = function(row) {
2591926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this.selectedRow === row)
2592926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
2593926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.deselectWithoutAnimating();
2594926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (row === ListView.NoSelection)
2595926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
2596926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.selectedRow = row;
2597926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this.selectedRow !== ListView.NoSelection) {
2598926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var selectedCell = this._cells[this.selectedRow];
2599926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (selectedCell) {
2600926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            selectedCell.setSelected(true);
2601926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            selectedCell.setHeight(YearListCell.SelectedHeight);
2602926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
2603926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var month = this.highlightedMonth ? this.highlightedMonth.month : 0;
2604926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.highlightMonth(new Month(this.selectedRow + 1, month));
2605926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
2606926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.setNeedsUpdateCells(true);
2607926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
2608926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2609926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
2610926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!Month} month
26117242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci * @return {?HTMLDivElement}
2612926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
2613926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)YearListView.prototype.buttonForMonth = function(month) {
2614926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!month)
2615926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return null;
2616926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var row = month.year - 1;
2617926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var cell = this.cellAtRow(row);
2618926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!cell)
2619926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return null;
2620926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return cell.monthButtons[month.month];
2621926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
2622926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2623926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)YearListView.prototype.dehighlightMonth = function() {
2624926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!this.highlightedMonth)
2625926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
2626926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var monthButton = this.buttonForMonth(this.highlightedMonth);
2627926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (monthButton) {
2628926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        monthButton.classList.remove(YearListCell.ClassNameHighlighted);
2629926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
2630926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.highlightedMonth = null;
26317242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    this.element.removeAttribute("aria-activedescendant");
2632926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
2633926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2634926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
2635926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!Month} month
2636926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
2637926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)YearListView.prototype.highlightMonth = function(month) {
2638926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this.highlightedMonth && this.highlightedMonth.equals(month))
2639926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
2640926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.dehighlightMonth();
2641926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.highlightedMonth = month;
2642926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!this.highlightedMonth)
2643926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
2644926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var monthButton = this.buttonForMonth(this.highlightedMonth);
2645926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (monthButton) {
2646926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        monthButton.classList.add(YearListCell.ClassNameHighlighted);
26477242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        this.element.setAttribute("aria-activedescendant", monthButton.id);
2648926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
2649926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
2650926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2651926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
2652926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!Month} month
2653926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
2654926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)YearListView.prototype.show = function(month) {
2655926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._ignoreMouseOutUntillNextMouseOver = true;
2656926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2657926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.scrollToRow(month.year - 1, false);
2658926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.selectWithoutAnimating(month.year - 1);
2659926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.highlightMonth(month);
2660926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
2661926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2662926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)YearListView.prototype.hide = function() {
2663926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.dispatchEvent(YearListView.EventTypeYearListViewDidHide, this);
2664926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
2665926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2666926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
2667926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!Month} month
2668926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
2669926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)YearListView.prototype._moveHighlightTo = function(month) {
2670926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.highlightMonth(month);
2671926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.select(this.highlightedMonth.year - 1);
2672926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2673926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.dispatchEvent(YearListView.EventTypeYearListViewDidSelectMonth, this, month);
2674926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.scrollView.scrollTo(this.selectedRow * YearListCell.Height, true);
2675926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return true;
2676926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
2677926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2678926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
2679926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {?Event} event
2680926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
2681926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)YearListView.prototype.onKeyDown = function(event) {
2682926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var key = event.keyIdentifier;
2683926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var eventHandled = false;
2684926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (key == "U+0054") // 't' key.
2685926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        eventHandled = this._moveHighlightTo(Month.createFromToday());
2686926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    else if (this.highlightedMonth) {
2687926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (global.params.isLocaleRTL ? key == "Right" : key == "Left")
2688926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            eventHandled = this._moveHighlightTo(this.highlightedMonth.previous());
2689926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        else if (key == "Up")
2690926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            eventHandled = this._moveHighlightTo(this.highlightedMonth.previous(YearListCell.ButtonColumns));
2691926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        else if (global.params.isLocaleRTL ? key == "Left" : key == "Right")
2692926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            eventHandled = this._moveHighlightTo(this.highlightedMonth.next());
2693926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        else if (key == "Down")
2694926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            eventHandled = this._moveHighlightTo(this.highlightedMonth.next(YearListCell.ButtonColumns));
2695926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        else if (key == "PageUp")
2696926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            eventHandled = this._moveHighlightTo(this.highlightedMonth.previous(MonthsPerYear));
2697926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        else if (key == "PageDown")
2698926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            eventHandled = this._moveHighlightTo(this.highlightedMonth.next(MonthsPerYear));
2699926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        else if (key == "Enter") {
2700926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            this.dispatchEvent(YearListView.EventTypeYearListViewDidSelectMonth, this, this.highlightedMonth);
2701926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            this.hide();
2702926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            eventHandled = true;
2703926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
2704926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    } else if (key == "Up") {
2705926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.scrollView.scrollBy(-YearListCell.Height, true);
2706926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        eventHandled = true;
2707926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    } else if (key == "Down") {
2708926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.scrollView.scrollBy(YearListCell.Height, true);
27095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        eventHandled = true;
27105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else if (key == "PageUp") {
2711926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.scrollView.scrollBy(-this.scrollView.height(), true);
2712926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        eventHandled = true;
2713926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    } else if (key == "PageDown") {
2714926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.scrollView.scrollBy(this.scrollView.height(), true);
2715926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        eventHandled = true;
2716926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
2717926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2718926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (eventHandled) {
2719926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        event.stopPropagation();
2720926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        event.preventDefault();
2721926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
2722926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
2723926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2724926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
2725926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @constructor
2726926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @extends View
2727926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!Month} minimumMonth
2728926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!Month} maximumMonth
2729926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
2730926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)function MonthPopupView(minimumMonth, maximumMonth) {
2731926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    View.call(this, createElement("div", MonthPopupView.ClassNameMonthPopupView));
2732926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2733926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
2734926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!YearListView}
2735926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @const
2736926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
2737926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.yearListView = new YearListView(minimumMonth, maximumMonth);
2738926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.yearListView.attachTo(this);
2739926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2740926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
2741926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!boolean}
2742926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
2743926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.isVisible = false;
2744926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2745926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.addEventListener("click", this.onClick, false);
2746926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
2747926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2748926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)MonthPopupView.prototype = Object.create(View.prototype);
2749926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2750926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)MonthPopupView.ClassNameMonthPopupView = "month-popup-view";
2751926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2752926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)MonthPopupView.prototype.show = function(initialMonth, calendarTableRect) {
2753926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.isVisible = true;
2754926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    document.body.appendChild(this.element);
2755926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.yearListView.setWidth(calendarTableRect.width - 2);
2756926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.yearListView.setHeight(YearListView.Height);
2757926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (global.params.isLocaleRTL)
2758926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.yearListView.element.style.right = calendarTableRect.x + "px";
2759926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    else
2760926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.yearListView.element.style.left = calendarTableRect.x + "px";
2761926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.yearListView.element.style.top = calendarTableRect.y + "px";
2762926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.yearListView.show(initialMonth);
2763926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.yearListView.element.focus();
2764926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
2765926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2766926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)MonthPopupView.prototype.hide = function() {
2767926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!this.isVisible)
2768926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
2769926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.isVisible = false;
2770926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.parentNode.removeChild(this.element);
2771926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.yearListView.hide();
2772926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
2773926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2774926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
2775926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {?Event} event
2776926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
2777926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)MonthPopupView.prototype.onClick = function(event) {
2778926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (event.target !== this.element)
2779926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
2780926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.hide();
2781926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
2782926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2783926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
2784926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @constructor
2785926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @extends View
2786926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} maxWidth Maximum width in pixels.
2787926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
2788926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)function MonthPopupButton(maxWidth) {
2789926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    View.call(this, createElement("button", MonthPopupButton.ClassNameMonthPopupButton));
27907242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    this.element.setAttribute("aria-label", global.params.axShowMonthSelector);
2791926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2792926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
2793926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!Element}
2794926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @const
2795926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
2796926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.labelElement = createElement("span", MonthPopupButton.ClassNameMonthPopupButtonLabel, "-----");
2797926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.appendChild(this.labelElement);
2798926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2799926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
2800926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!Element}
2801926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @const
2802926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
2803926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.disclosureTriangleIcon = createElement("span", MonthPopupButton.ClassNameDisclosureTriangle);
2804926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.disclosureTriangleIcon.innerHTML = "<svg width='7' height='5'><polygon points='0,1 7,1 3.5,5' style='fill:#000000;' /></svg>";
2805926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.appendChild(this.disclosureTriangleIcon);
2806926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2807926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
2808926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!boolean}
2809926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @protected
2810926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
2811926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._useShortMonth = this._shouldUseShortMonth(maxWidth);
2812926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.style.maxWidth = maxWidth + "px";
2813926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2814926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.addEventListener("click", this.onClick, false);
2815926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
2816926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2817926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)MonthPopupButton.prototype = Object.create(View.prototype);
2818926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2819926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)MonthPopupButton.ClassNameMonthPopupButton = "month-popup-button";
2820926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)MonthPopupButton.ClassNameMonthPopupButtonLabel = "month-popup-button-label";
2821926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)MonthPopupButton.ClassNameDisclosureTriangle = "disclosure-triangle";
2822926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)MonthPopupButton.EventTypeButtonClick = "buttonClick";
2823926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2824926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
2825926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} maxWidth Maximum available width in pixels.
2826926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!boolean}
2827926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
2828926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)MonthPopupButton.prototype._shouldUseShortMonth = function(maxWidth) {
2829926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    document.body.appendChild(this.element);
2830926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var month = Month.Maximum;
2831926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    for (var i = 0; i < MonthsPerYear; ++i) {
2832926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.labelElement.textContent = month.toLocaleString();
2833926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (this.element.offsetWidth > maxWidth)
2834926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            return true;
2835926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        month = month.previous();
2836926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
2837926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    document.body.removeChild(this.element);
2838926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return false;
2839926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
2840926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2841926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
2842926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!Month} month
2843926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
2844926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)MonthPopupButton.prototype.setCurrentMonth = function(month) {
2845926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.labelElement.textContent = this._useShortMonth ? month.toShortLocaleString() : month.toLocaleString();
2846926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
2847926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2848926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
2849926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {?Event} event
2850926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
2851926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)MonthPopupButton.prototype.onClick = function(event) {
2852926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.dispatchEvent(MonthPopupButton.EventTypeButtonClick, this);
2853926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
2854926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2855926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
2856926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @constructor
2857926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @extends View
2858926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
2859926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)function CalendarNavigationButton() {
2860926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    View.call(this, createElement("button", CalendarNavigationButton.ClassNameCalendarNavigationButton));
2861926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
2862926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {number} Threshold for starting repeating clicks in milliseconds.
2863926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
2864926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.repeatingClicksStartingThreshold = CalendarNavigationButton.DefaultRepeatingClicksStartingThreshold;
2865926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
2866926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {number} Interval between reapeating clicks in milliseconds.
2867926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
2868926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.reapeatingClicksInterval = CalendarNavigationButton.DefaultRepeatingClicksInterval;
2869926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
2870926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {?number} The ID for the timeout that triggers the repeating clicks.
2871926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
2872926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._timer = null;
2873926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.addEventListener("click", this.onClick, false);
2874926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.addEventListener("mousedown", this.onMouseDown, false);
2875926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.addEventListener("touchstart", this.onTouchStart, false);
2876926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
2877926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2878926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarNavigationButton.prototype = Object.create(View.prototype);
2879926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2880926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarNavigationButton.DefaultRepeatingClicksStartingThreshold = 600;
2881926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarNavigationButton.DefaultRepeatingClicksInterval = 300;
2882926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarNavigationButton.LeftMargin = 4;
2883926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarNavigationButton.Width = 24;
2884926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarNavigationButton.ClassNameCalendarNavigationButton = "calendar-navigation-button";
2885926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarNavigationButton.EventTypeButtonClick = "buttonClick";
2886926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarNavigationButton.EventTypeRepeatingButtonClick = "repeatingButtonClick";
2887926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2888926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
2889926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!boolean} disabled
2890926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
2891926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarNavigationButton.prototype.setDisabled = function(disabled) {
2892926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.disabled = disabled;
2893926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
2894926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2895926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
2896926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {?Event} event
2897926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
2898926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarNavigationButton.prototype.onClick = function(event) {
2899926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.dispatchEvent(CalendarNavigationButton.EventTypeButtonClick, this);
2900926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
2901926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2902926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
2903926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {?Event} event
2904926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
2905926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarNavigationButton.prototype.onTouchStart = function(event) {
2906926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this._timer !== null)
2907926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
2908926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._timer = setTimeout(this.onRepeatingClick, this.repeatingClicksStartingThreshold);
2909926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    window.addEventListener("touchend", this.onWindowTouchEnd, false);
2910926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
2911926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2912926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
2913926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {?Event} event
2914926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
2915926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarNavigationButton.prototype.onWindowTouchEnd = function(event) {
2916926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this._timer === null)
2917926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
2918926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    clearTimeout(this._timer);
2919926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._timer = null;
2920926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    window.removeEventListener("touchend", this.onWindowMouseUp, false);
2921926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
2922926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2923926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
2924926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {?Event} event
2925926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
2926926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarNavigationButton.prototype.onMouseDown = function(event) {
2927926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this._timer !== null)
2928926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
2929926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._timer = setTimeout(this.onRepeatingClick, this.repeatingClicksStartingThreshold);
2930926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    window.addEventListener("mouseup", this.onWindowMouseUp, false);
2931926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
2932926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2933926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
2934926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {?Event} event
2935926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
2936926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarNavigationButton.prototype.onWindowMouseUp = function(event) {
2937926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this._timer === null)
2938926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
2939926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    clearTimeout(this._timer);
2940926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._timer = null;
2941926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    window.removeEventListener("mouseup", this.onWindowMouseUp, false);
2942926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
2943926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2944926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
2945926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {?Event} event
2946926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
2947926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarNavigationButton.prototype.onRepeatingClick = function(event) {
2948926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.dispatchEvent(CalendarNavigationButton.EventTypeRepeatingButtonClick, this);
2949926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._timer = setTimeout(this.onRepeatingClick, this.reapeatingClicksInterval);
2950926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
2951926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2952926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
2953926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @constructor
2954926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @extends View
2955926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!CalendarPicker} calendarPicker
2956926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
2957926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)function CalendarHeaderView(calendarPicker) {
2958926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    View.call(this, createElement("div", CalendarHeaderView.ClassNameCalendarHeaderView));
2959926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.calendarPicker = calendarPicker;
2960926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.calendarPicker.on(CalendarPicker.EventTypeCurrentMonthChanged, this.onCurrentMonthChanged);
2961926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2962926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var titleElement = createElement("div", CalendarHeaderView.ClassNameCalendarTitle);
2963926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.appendChild(titleElement);
2964926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2965926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
2966926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!MonthPopupButton}
2967926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
2968926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.monthPopupButton = new MonthPopupButton(this.calendarPicker.calendarTableView.width() - CalendarTableView.BorderWidth * 2 - CalendarNavigationButton.Width * 3 - CalendarNavigationButton.LeftMargin * 2);
2969926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.monthPopupButton.attachTo(titleElement);
2970926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2971926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
2972926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!CalendarNavigationButton}
2973926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @const
2974926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
2975926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._previousMonthButton = new CalendarNavigationButton();
2976926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._previousMonthButton.attachTo(this);
2977926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._previousMonthButton.on(CalendarNavigationButton.EventTypeButtonClick, this.onNavigationButtonClick);
2978926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._previousMonthButton.on(CalendarNavigationButton.EventTypeRepeatingButtonClick, this.onNavigationButtonClick);
29797242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    this._previousMonthButton.element.setAttribute("aria-label", global.params.axShowPreviousMonth);
2980926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2981926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
2982926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!CalendarNavigationButton}
2983926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @const
2984926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
2985926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._todayButton = new CalendarNavigationButton();
2986926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._todayButton.attachTo(this);
2987926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._todayButton.on(CalendarNavigationButton.EventTypeButtonClick, this.onNavigationButtonClick);
2988926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._todayButton.element.classList.add(CalendarHeaderView.ClassNameTodayButton);
2989926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var monthContainingToday = Month.createFromToday();
2990926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._todayButton.setDisabled(monthContainingToday < this.calendarPicker.minimumMonth || monthContainingToday > this.calendarPicker.maximumMonth);
29917242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    this._todayButton.element.setAttribute("aria-label", global.params.todayLabel);
2992926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2993926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
2994926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!CalendarNavigationButton}
2995926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @const
2996926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
2997926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._nextMonthButton = new CalendarNavigationButton();
2998926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._nextMonthButton.attachTo(this);
2999926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._nextMonthButton.on(CalendarNavigationButton.EventTypeButtonClick, this.onNavigationButtonClick);
3000926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._nextMonthButton.on(CalendarNavigationButton.EventTypeRepeatingButtonClick, this.onNavigationButtonClick);
30017242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    this._nextMonthButton.element.setAttribute("aria-label", global.params.axShowNextMonth);
3002926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3003926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (global.params.isLocaleRTL) {
3004926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this._nextMonthButton.element.innerHTML = CalendarHeaderView._BackwardTriangle;
3005926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this._previousMonthButton.element.innerHTML = CalendarHeaderView._ForwardTriangle;
3006926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    } else {
3007926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this._nextMonthButton.element.innerHTML = CalendarHeaderView._ForwardTriangle;
3008926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this._previousMonthButton.element.innerHTML = CalendarHeaderView._BackwardTriangle;
3009926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
3010926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
3011926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3012926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarHeaderView.prototype = Object.create(View.prototype);
3013926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3014926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarHeaderView.Height = 24;
3015926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarHeaderView.BottomMargin = 10;
3016926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarHeaderView._ForwardTriangle = "<svg width='4' height='7'><polygon points='0,7 0,0, 4,3.5' style='fill:#6e6e6e;' /></svg>";
3017926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarHeaderView._BackwardTriangle = "<svg width='4' height='7'><polygon points='0,3.5 4,7 4,0' style='fill:#6e6e6e;' /></svg>";
3018926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarHeaderView.ClassNameCalendarHeaderView = "calendar-header-view";
3019926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarHeaderView.ClassNameCalendarTitle = "calendar-title";
3020926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarHeaderView.ClassNameTodayButton = "today-button";
3021926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3022926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarHeaderView.prototype.onCurrentMonthChanged = function() {
3023926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.monthPopupButton.setCurrentMonth(this.calendarPicker.currentMonth());
3024926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._previousMonthButton.setDisabled(this.disabled || this.calendarPicker.currentMonth() <= this.calendarPicker.minimumMonth);
3025926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._nextMonthButton.setDisabled(this.disabled || this.calendarPicker.currentMonth() >= this.calendarPicker.maximumMonth);
3026926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3027926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3028926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarHeaderView.prototype.onNavigationButtonClick = function(sender) {
3029926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (sender === this._previousMonthButton)
3030926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.calendarPicker.setCurrentMonth(this.calendarPicker.currentMonth().previous(), CalendarPicker.NavigationBehavior.WithAnimation);
3031926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    else if (sender === this._nextMonthButton)
3032926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.calendarPicker.setCurrentMonth(this.calendarPicker.currentMonth().next(), CalendarPicker.NavigationBehavior.WithAnimation);
3033926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    else
3034926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.calendarPicker.selectRangeContainingDay(Day.createFromToday());
3035926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3036926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3037926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3038926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!boolean} disabled
3039926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3040926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarHeaderView.prototype.setDisabled = function(disabled) {
3041926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.disabled = disabled;
3042926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.monthPopupButton.element.disabled = this.disabled;
3043926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._previousMonthButton.setDisabled(this.disabled || this.calendarPicker.currentMonth() <= this.calendarPicker.minimumMonth);
3044926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._nextMonthButton.setDisabled(this.disabled || this.calendarPicker.currentMonth() >= this.calendarPicker.maximumMonth);
3045926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var monthContainingToday = Month.createFromToday();
3046926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._todayButton.setDisabled(this.disabled || monthContainingToday < this.calendarPicker.minimumMonth || monthContainingToday > this.calendarPicker.maximumMonth);
3047926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3048926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3049926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3050926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @constructor
3051926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @extends ListCell
3052926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3053926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)function DayCell() {
3054926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ListCell.call(this);
3055926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.classList.add(DayCell.ClassNameDayCell);
3056926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.style.width = DayCell.Width + "px";
3057926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.style.height = DayCell.Height + "px";
3058591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    this.element.style.lineHeight = (DayCell.Height - DayCell.PaddingSize * 2) + "px";
30597242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    this.element.setAttribute("role", "gridcell");
3060926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
3061926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {?Day}
3062926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
3063926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.day = null;
3064926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3065926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3066926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)DayCell.prototype = Object.create(ListCell.prototype);
3067926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3068926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)DayCell.Width = 34;
3069926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)DayCell.Height = hasInaccuratePointingDevice() ? 34 : 20;
3070591b958dee2cf159d33a0b931e6231072eaf38d5Ben MurdochDayCell.PaddingSize = 1;
3071926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)DayCell.ClassNameDayCell = "day-cell";
3072926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)DayCell.ClassNameHighlighted = "highlighted";
3073926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)DayCell.ClassNameDisabled = "disabled";
3074926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)DayCell.ClassNameCurrentMonth = "current-month";
3075926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)DayCell.ClassNameToday = "today";
3076926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3077926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)DayCell._recycleBin = [];
3078926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3079926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)DayCell.recycleOrCreate = function() {
3080926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return DayCell._recycleBin.pop() || new DayCell();
3081926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3082926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3083926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3084926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!Array}
3085926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @override
3086926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3087926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)DayCell.prototype._recycleBin = function() {
3088926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return DayCell._recycleBin;
3089926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3090926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3091926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3092926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @override
3093926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3094926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)DayCell.prototype.throwAway = function() {
3095926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ListCell.prototype.throwAway.call(this);
3096926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.day = null;
3097926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3098926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3099926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3100926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!boolean} highlighted
3101926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3102926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)DayCell.prototype.setHighlighted = function(highlighted) {
31037242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if (highlighted) {
3104926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.element.classList.add(DayCell.ClassNameHighlighted);
31057242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        this.element.setAttribute("aria-selected", "true");
31067242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    } else {
3107926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.element.classList.remove(DayCell.ClassNameHighlighted);
31087242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        this.element.setAttribute("aria-selected", "false");
31097242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    }
3110926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3111926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3112926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3113926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!boolean} disabled
3114926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3115926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)DayCell.prototype.setDisabled = function(disabled) {
3116926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (disabled)
3117926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.element.classList.add(DayCell.ClassNameDisabled);
3118926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    else
3119926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.element.classList.remove(DayCell.ClassNameDisabled);
3120926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3121926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3122926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3123926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!boolean} selected
3124926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3125926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)DayCell.prototype.setIsInCurrentMonth = function(selected) {
3126926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (selected)
3127926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.element.classList.add(DayCell.ClassNameCurrentMonth);
3128926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    else
3129926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.element.classList.remove(DayCell.ClassNameCurrentMonth);
3130926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3131926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3132926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3133926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!boolean} selected
3134926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3135926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)DayCell.prototype.setIsToday = function(selected) {
3136926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (selected)
3137926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.element.classList.add(DayCell.ClassNameToday);
3138926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    else
3139926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.element.classList.remove(DayCell.ClassNameToday);
3140926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3141926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3142926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3143926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!Day} day
3144926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3145926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)DayCell.prototype.reset = function(day) {
3146926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.day = day;
3147926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.textContent = localizeNumber(this.day.date.toString());
31487242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    this.element.setAttribute("aria-label", this.day.format());
31497242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    this.element.id = this.day.toString();
3150926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.show();
3151926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3152926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3153926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3154926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @constructor
3155926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @extends ListCell
3156926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3157926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)function WeekNumberCell() {
3158926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ListCell.call(this);
3159926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.classList.add(WeekNumberCell.ClassNameWeekNumberCell);
3160591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    this.element.style.width = (WeekNumberCell.Width - WeekNumberCell.SeparatorWidth) + "px";
3161926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.style.height = WeekNumberCell.Height + "px";
3162591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    this.element.style.lineHeight = (WeekNumberCell.Height - WeekNumberCell.PaddingSize * 2) + "px";
3163926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
3164926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {?Week}
3165926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
3166926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.week = null;
3167926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3168926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3169926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)WeekNumberCell.prototype = Object.create(ListCell.prototype);
3170926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3171926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)WeekNumberCell.Width = 48;
3172926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)WeekNumberCell.Height = DayCell.Height;
3173591b958dee2cf159d33a0b931e6231072eaf38d5Ben MurdochWeekNumberCell.SeparatorWidth = 1;
3174591b958dee2cf159d33a0b931e6231072eaf38d5Ben MurdochWeekNumberCell.PaddingSize = 1;
3175926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)WeekNumberCell.ClassNameWeekNumberCell = "week-number-cell";
3176926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)WeekNumberCell.ClassNameHighlighted = "highlighted";
3177926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)WeekNumberCell.ClassNameDisabled = "disabled";
3178926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3179926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)WeekNumberCell._recycleBin = [];
3180926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3181926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3182926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!Array}
3183926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @override
3184926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3185926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)WeekNumberCell.prototype._recycleBin = function() {
3186926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return WeekNumberCell._recycleBin;
3187926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3188926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3189926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3190926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!WeekNumberCell}
3191926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3192926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)WeekNumberCell.recycleOrCreate = function() {
3193926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return WeekNumberCell._recycleBin.pop() || new WeekNumberCell();
3194926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3195926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3196926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3197926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!Week} week
3198926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3199926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)WeekNumberCell.prototype.reset = function(week) {
3200926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.week = week;
32017242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    this.element.id = week.toString();
32027242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    this.element.setAttribute("role", "gridcell");
32037242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    this.element.setAttribute("aria-label", window.pagePopupController.formatWeek(week.year, week.week, week.firstDay().format()));
3204926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.textContent = localizeNumber(this.week.week.toString());
3205926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.show();
3206926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3207926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3208926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3209926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @override
3210926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3211926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)WeekNumberCell.prototype.throwAway = function() {
3212926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ListCell.prototype.throwAway.call(this);
3213926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.week = null;
3214926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3215926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3216926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)WeekNumberCell.prototype.setHighlighted = function(highlighted) {
32177242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if (highlighted) {
3218926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.element.classList.add(WeekNumberCell.ClassNameHighlighted);
32197242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        this.element.setAttribute("aria-selected", "true");
32207242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    } else {
3221926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.element.classList.remove(WeekNumberCell.ClassNameHighlighted);
32227242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        this.element.setAttribute("aria-selected", "false");
32237242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    }
3224926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3225926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3226926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)WeekNumberCell.prototype.setDisabled = function(disabled) {
3227926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (disabled)
3228926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.element.classList.add(WeekNumberCell.ClassNameDisabled);
3229926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    else
3230926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.element.classList.remove(WeekNumberCell.ClassNameDisabled);
3231926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3232926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3233926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3234926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @constructor
3235926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @extends View
3236926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!boolean} hasWeekNumberColumn
3237926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3238926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)function CalendarTableHeaderView(hasWeekNumberColumn) {
3239926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    View.call(this, createElement("div", "calendar-table-header-view"));
3240926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (hasWeekNumberColumn) {
3241926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var weekNumberLabelElement = createElement("div", "week-number-label", global.params.weekLabel);
3242926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        weekNumberLabelElement.style.width = WeekNumberCell.Width + "px";
3243926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.element.appendChild(weekNumberLabelElement);
3244926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
3245926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    for (var i = 0; i < DaysPerWeek; ++i) {
3246926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var weekDayNumber = (global.params.weekStartDay + i) % DaysPerWeek;
3247926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var labelElement = createElement("div", "week-day-label", global.params.dayLabels[weekDayNumber]);
3248926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        labelElement.style.width = DayCell.Width + "px";
3249926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.element.appendChild(labelElement);
3250926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (getLanguage() === "ja") {
3251926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            if (weekDayNumber === 0)
3252926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                labelElement.style.color = "red";
3253926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            else if (weekDayNumber === 6)
3254926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                labelElement.style.color = "blue";
3255926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
3256926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
3257926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
3258926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3259926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarTableHeaderView.prototype = Object.create(View.prototype);
3260926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3261926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarTableHeaderView.Height = 25;
3262926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3263926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3264926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @constructor
3265926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @extends ListCell
3266926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3267926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)function CalendarRowCell() {
3268926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ListCell.call(this);
3269926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.classList.add(CalendarRowCell.ClassNameCalendarRowCell);
3270926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.style.height = CalendarRowCell.Height + "px";
32717242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    this.element.setAttribute("role", "row");
3272926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3273926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
3274926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!Array}
3275926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @protected
3276926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
3277926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._dayCells = [];
3278926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
3279926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!number}
3280926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
3281926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.row = 0;
3282926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
3283926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {?CalendarTableView}
3284926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
3285926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.calendarTableView = null;
3286926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
3287926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3288926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarRowCell.prototype = Object.create(ListCell.prototype);
3289926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3290926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarRowCell.Height = DayCell.Height;
3291926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarRowCell.ClassNameCalendarRowCell = "calendar-row-cell";
3292926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3293926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarRowCell._recycleBin = [];
3294926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3295926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3296926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!Array}
3297926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @override
3298926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3299926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarRowCell.prototype._recycleBin = function() {
3300926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return CalendarRowCell._recycleBin;
3301926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3302926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3303926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3304926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} row
3305926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!CalendarTableView} calendarTableView
3306926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3307926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarRowCell.prototype.reset = function(row, calendarTableView) {
3308926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.row = row;
3309926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.calendarTableView = calendarTableView;
3310926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this.calendarTableView.hasWeekNumberColumn) {
3311926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var middleDay = this.calendarTableView.dayAtColumnAndRow(3, row);
3312926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var week = Week.createFromDay(middleDay);
3313926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.weekNumberCell = this.calendarTableView.prepareNewWeekNumberCell(week);
3314926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.weekNumberCell.attachTo(this);
3315926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
3316926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var day = calendarTableView.dayAtColumnAndRow(0, row);
3317926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    for (var i = 0; i < DaysPerWeek; ++i) {
3318926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var dayCell = this.calendarTableView.prepareNewDayCell(day);
3319926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        dayCell.attachTo(this);
3320926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this._dayCells.push(dayCell);
3321926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        day = day.next();
3322926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
3323926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.show();
3324926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3325926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3326926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3327926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @override
3328926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3329926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarRowCell.prototype.throwAway = function() {
3330926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ListCell.prototype.throwAway.call(this);
3331926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this.weekNumberCell)
3332926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.calendarTableView.throwAwayWeekNumberCell(this.weekNumberCell);
3333926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._dayCells.forEach(this.calendarTableView.throwAwayDayCell, this.calendarTableView);
3334926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._dayCells.length = 0;
3335926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3336926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3337926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3338926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @constructor
3339926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @extends ListView
3340926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!CalendarPicker} calendarPicker
3341926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3342926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)function CalendarTableView(calendarPicker) {
3343926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ListView.call(this);
3344926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.classList.add(CalendarTableView.ClassNameCalendarTableView);
3345926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.tabIndex = 0;
3346926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3347926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
3348926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!boolean}
3349926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @const
3350926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
3351926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.hasWeekNumberColumn = calendarPicker.type === "week";
3352926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
3353926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!CalendarPicker}
3354926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @const
3355926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
3356926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.calendarPicker = calendarPicker;
3357926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
3358926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!Object}
3359926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @const
3360926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
3361926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._dayCells = {};
3362926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var headerView = new CalendarTableHeaderView(this.hasWeekNumberColumn);
3363926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    headerView.attachTo(this, this.scrollView);
3364926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3365926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this.hasWeekNumberColumn) {
3366926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.setWidth(DayCell.Width * DaysPerWeek + WeekNumberCell.Width);
3367926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        /**
3368926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)         * @type {?Array}
3369926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)         * @const
3370926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)         */
3371926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this._weekNumberCells = [];
3372926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    } else {
3373926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.setWidth(DayCell.Width * DaysPerWeek);
3374926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
3375926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3376926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
3377926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!boolean}
3378926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @protected
3379926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
3380926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._ignoreMouseOutUntillNextMouseOver = false;
3381926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3382926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.addEventListener("click", this.onClick, false);
3383926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.addEventListener("mouseover", this.onMouseOver, false);
3384926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.addEventListener("mouseout", this.onMouseOut, false);
3385926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3386926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // You shouldn't be able to use the mouse wheel to scroll.
3387926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.scrollView.element.removeEventListener("mousewheel", this.scrollView.onMouseWheel, false);
3388926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // You shouldn't be able to do gesture scroll.
3389926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.scrollView.element.removeEventListener("touchstart", this.scrollView.onTouchStart, false);
3390926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
3391926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3392926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarTableView.prototype = Object.create(ListView.prototype);
3393926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3394926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarTableView.BorderWidth = 1;
3395926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarTableView.ClassNameCalendarTableView = "calendar-table-view";
3396926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3397926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3398926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} scrollOffset
3399926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!number}
3400926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3401926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarTableView.prototype.rowAtScrollOffset = function(scrollOffset) {
3402926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return Math.floor(scrollOffset / CalendarRowCell.Height);
3403926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3404926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3405926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3406926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} row
3407926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!number}
3408926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3409926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarTableView.prototype.scrollOffsetForRow = function(row) {
3410926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return row * CalendarRowCell.Height;
3411926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3412926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3413926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3414926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {?Event} event
3415926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3416926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarTableView.prototype.onClick = function(event) {
3417926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this.hasWeekNumberColumn) {
3418926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var weekNumberCellElement = enclosingNodeOrSelfWithClass(event.target, WeekNumberCell.ClassNameWeekNumberCell);
3419926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (weekNumberCellElement) {
3420926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            var weekNumberCell = weekNumberCellElement.$view;
3421926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            this.calendarPicker.selectRangeContainingDay(weekNumberCell.week.firstDay());
34225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return;
3423926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
3424926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
3425926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var dayCellElement = enclosingNodeOrSelfWithClass(event.target, DayCell.ClassNameDayCell);
3426926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!dayCellElement)
3427926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
3428926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var dayCell = dayCellElement.$view;
3429926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.calendarPicker.selectRangeContainingDay(dayCell.day);
3430926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3431926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3432926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3433926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {?Event} event
3434926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3435926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarTableView.prototype.onMouseOver = function(event) {
3436926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this.hasWeekNumberColumn) {
3437926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var weekNumberCellElement = enclosingNodeOrSelfWithClass(event.target, WeekNumberCell.ClassNameWeekNumberCell);
3438926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (weekNumberCellElement) {
3439926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            var weekNumberCell = weekNumberCellElement.$view;
3440926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            this.calendarPicker.highlightRangeContainingDay(weekNumberCell.week.firstDay());
3441926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            this._ignoreMouseOutUntillNextMouseOver = false;
34425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return;
3443926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
3444926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
3445926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var dayCellElement = enclosingNodeOrSelfWithClass(event.target, DayCell.ClassNameDayCell);
3446926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!dayCellElement)
3447926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
3448926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var dayCell = dayCellElement.$view;
3449926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.calendarPicker.highlightRangeContainingDay(dayCell.day);
3450926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._ignoreMouseOutUntillNextMouseOver = false;
3451926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3452926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3453926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3454926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {?Event} event
3455926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3456926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarTableView.prototype.onMouseOut = function(event) {
3457926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this._ignoreMouseOutUntillNextMouseOver)
3458926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
3459926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var dayCellElement = enclosingNodeOrSelfWithClass(event.target, DayCell.ClassNameDayCell);
3460926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!dayCellElement) {
3461926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.calendarPicker.highlightRangeContainingDay(null);
3462926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
3463926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3464926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3465926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3466926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} row
3467926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!CalendarRowCell}
3468926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3469926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarTableView.prototype.prepareNewCell = function(row) {
3470926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var cell = CalendarRowCell._recycleBin.pop() || new CalendarRowCell();
3471926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    cell.reset(row, this);
3472926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return cell;
3473926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3474926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3475926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3476926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!number} Height in pixels.
3477926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3478926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarTableView.prototype.height = function() {
3479926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return this.scrollView.height() + CalendarTableHeaderView.Height + CalendarTableView.BorderWidth * 2;
3480926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3481926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3482926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3483926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} height Height in pixels.
3484926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3485926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarTableView.prototype.setHeight = function(height) {
3486926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.scrollView.setHeight(height - CalendarTableHeaderView.Height - CalendarTableView.BorderWidth * 2);
3487926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3488926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3489926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3490926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!Month} month
3491926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!boolean} animate
3492926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3493926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarTableView.prototype.scrollToMonth = function(month, animate) {
3494926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var rowForFirstDayInMonth = this.columnAndRowForDay(month.firstDay()).row;
3495926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.scrollView.scrollTo(this.scrollOffsetForRow(rowForFirstDayInMonth), animate);
3496926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3497926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3498926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3499926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} column
3500926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} row
3501926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!Day}
3502926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3503926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarTableView.prototype.dayAtColumnAndRow = function(column, row) {
3504926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var daysSinceMinimum = row * DaysPerWeek + column + global.params.weekStartDay - CalendarTableView._MinimumDayWeekDay;
3505926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return Day.createFromValue(daysSinceMinimum * MillisecondsPerDay + CalendarTableView._MinimumDayValue);
3506926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3507926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3508926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarTableView._MinimumDayValue = Day.Minimum.valueOf();
3509926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarTableView._MinimumDayWeekDay = Day.Minimum.weekDay();
3510926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3511926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3512926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!Day} day
3513926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!Object} Object with properties column and row.
3514926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3515926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarTableView.prototype.columnAndRowForDay = function(day) {
3516926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var daysSinceMinimum = (day.valueOf() - CalendarTableView._MinimumDayValue) / MillisecondsPerDay;
3517926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var offset = daysSinceMinimum + CalendarTableView._MinimumDayWeekDay - global.params.weekStartDay;
3518926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var row = Math.floor(offset / DaysPerWeek);
3519926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var column = offset - row * DaysPerWeek;
3520926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return {
3521926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        column: column,
3522926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        row: row
3523926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    };
3524926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3525926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3526926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarTableView.prototype.updateCells = function() {
3527926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ListView.prototype.updateCells.call(this);
3528926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3529926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var selection = this.calendarPicker.selection();
3530926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var firstDayInSelection;
3531926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var lastDayInSelection;
3532926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (selection) {
3533926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        firstDayInSelection = selection.firstDay().valueOf();
3534926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        lastDayInSelection = selection.lastDay().valueOf();
3535926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    } else {
3536926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        firstDayInSelection = Infinity;
3537926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        lastDayInSelection = Infinity;
3538926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
3539926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var highlight = this.calendarPicker.highlight();
3540926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var firstDayInHighlight;
3541926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var lastDayInHighlight;
3542926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (highlight) {
3543926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        firstDayInHighlight = highlight.firstDay().valueOf();
3544926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        lastDayInHighlight = highlight.lastDay().valueOf();
3545926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    } else {
3546926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        firstDayInHighlight = Infinity;
3547926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        lastDayInHighlight = Infinity;
3548926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
3549926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var currentMonth = this.calendarPicker.currentMonth();
3550926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var firstDayInCurrentMonth = currentMonth.firstDay().valueOf();
3551926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var lastDayInCurrentMonth = currentMonth.lastDay().valueOf();
35527242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    var activeCell = null;
3553926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    for (var dayString in this._dayCells) {
3554926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var dayCell = this._dayCells[dayString];
3555926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var day = dayCell.day;
3556926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        dayCell.setIsToday(Day.createFromToday().equals(day));
3557926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        dayCell.setSelected(day >= firstDayInSelection && day <= lastDayInSelection);
35587242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        var isHighlighted = day >= firstDayInHighlight && day <= lastDayInHighlight;
35597242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        dayCell.setHighlighted(isHighlighted);
35607242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        if (isHighlighted) {
35617242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            if (firstDayInHighlight == lastDayInHighlight)
35627242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci                activeCell = dayCell;
35637242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            else if (this.calendarPicker.type == "month" && day == firstDayInHighlight)
35647242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci                activeCell = dayCell;
35657242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        }
3566926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        dayCell.setIsInCurrentMonth(day >= firstDayInCurrentMonth && day <= lastDayInCurrentMonth);
3567926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        dayCell.setDisabled(!this.calendarPicker.isValidDay(day));
3568926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
3569926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this.hasWeekNumberColumn) {
3570926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        for (var weekString in this._weekNumberCells) {
3571926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            var weekNumberCell = this._weekNumberCells[weekString];
3572926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            var week = weekNumberCell.week;
35737242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            var isWeekHighlighted = highlight && highlight.equals(week);
3574926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            weekNumberCell.setSelected(selection && selection.equals(week));
35757242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            weekNumberCell.setHighlighted(isWeekHighlighted);
35767242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            if (isWeekHighlighted)
35777242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci                activeCell = weekNumberCell;
3578926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            weekNumberCell.setDisabled(!this.calendarPicker.isValid(week));
3579926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
3580926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
35817242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if (activeCell) {
35827242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        // Ensure a renderer because an element with no renderer doesn't post
35837242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        // activedescendant events. This shouldn't run in the above |for| loop
35847242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        // to avoid CSS transition.
35857242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        activeCell.element.offsetLeft;
35867242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        this.element.setAttribute("aria-activedescendant", activeCell.element.id);
35877242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    }
3588926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3589926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3590926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3591926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!Day} day
3592926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!DayCell}
3593926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3594926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarTableView.prototype.prepareNewDayCell = function(day) {
3595926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var dayCell = DayCell.recycleOrCreate();
3596926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    dayCell.reset(day);
35977242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if (this.calendarPicker.type == "month")
35987242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        dayCell.element.setAttribute("aria-label", Month.createFromDay(day).toLocaleString());
3599926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._dayCells[dayCell.day.toString()] = dayCell;
3600926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return dayCell;
3601926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3602926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3603926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3604926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!Week} week
3605926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!WeekNumberCell}
3606926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3607926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarTableView.prototype.prepareNewWeekNumberCell = function(week) {
3608926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var weekNumberCell = WeekNumberCell.recycleOrCreate();
3609926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    weekNumberCell.reset(week);
3610926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._weekNumberCells[weekNumberCell.week.toString()] = weekNumberCell;
3611926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return weekNumberCell;
3612926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3613926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3614926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3615926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!DayCell} dayCell
3616926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3617926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarTableView.prototype.throwAwayDayCell = function(dayCell) {
3618926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    delete this._dayCells[dayCell.day.toString()];
3619926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    dayCell.throwAway();
3620926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3621926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3622926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3623926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!WeekNumberCell} weekNumberCell
3624926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3625926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarTableView.prototype.throwAwayWeekNumberCell = function(weekNumberCell) {
3626926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    delete this._weekNumberCells[weekNumberCell.week.toString()];
3627926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    weekNumberCell.throwAway();
3628926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3629926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3630926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3631926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @constructor
3632926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @extends View
3633926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!Object} config
3634926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3635926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)function CalendarPicker(type, config) {
3636926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    View.call(this, createElement("div", CalendarPicker.ClassNameCalendarPicker));
3637926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.classList.add(CalendarPicker.ClassNamePreparing);
3638926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3639926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
3640926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!string}
3641926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @const
3642926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
3643926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.type = type;
3644926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this.type === "week")
3645926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this._dateTypeConstructor = Week;
3646926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    else if (this.type === "month")
3647926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this._dateTypeConstructor = Month;
3648926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    else
3649926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this._dateTypeConstructor = Day;
3650926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
3651926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!Object}
3652926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @const
3653926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
3654926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.config = {};
3655926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._setConfig(config);
3656926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
3657926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!Month}
3658926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @const
3659926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
3660926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.minimumMonth = Month.createFromDay(this.config.minimum.firstDay());
3661926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
3662926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!Month}
3663926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @const
3664926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
3665926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.maximumMonth = Month.createFromDay(this.config.maximum.lastDay());
3666926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (global.params.isLocaleRTL)
3667926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.element.classList.add("rtl");
3668926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
3669926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!CalendarTableView}
3670926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @const
3671926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
3672926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.calendarTableView = new CalendarTableView(this);
3673926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.calendarTableView.hasNumberColumn = this.type === "week";
3674926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
3675926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!CalendarHeaderView}
3676926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @const
3677926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
3678926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.calendarHeaderView = new CalendarHeaderView(this);
3679926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.calendarHeaderView.monthPopupButton.on(MonthPopupButton.EventTypeButtonClick, this.onMonthPopupButtonClick);
3680926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
3681926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!MonthPopupView}
3682926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @const
3683926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
3684926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.monthPopupView = new MonthPopupView(this.minimumMonth, this.maximumMonth);
3685926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.monthPopupView.yearListView.on(YearListView.EventTypeYearListViewDidSelectMonth, this.onYearListViewDidSelectMonth);
3686926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.monthPopupView.yearListView.on(YearListView.EventTypeYearListViewDidHide, this.onYearListViewDidHide);
3687926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.calendarHeaderView.attachTo(this);
3688926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.calendarTableView.attachTo(this);
3689926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
3690926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!Month}
3691926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @protected
3692926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
3693926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._currentMonth = new Month(NaN, NaN);
3694926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
3695926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {?DateType}
3696926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @protected
3697926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
3698926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._selection = null;
3699926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
3700926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {?DateType}
3701926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @protected
3702926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
3703926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._highlight = null;
3704926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.calendarTableView.element.addEventListener("keydown", this.onCalendarTableKeyDown, false);
3705926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    document.body.addEventListener("keydown", this.onBodyKeyDown, false);
3706926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3707926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    window.addEventListener("resize", this.onWindowResize, false);
3708926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3709926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
3710926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!number}
3711926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @protected
3712926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
3713926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._height = -1;
3714926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3715926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var initialSelection = parseDateString(config.currentValue);
3716926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (initialSelection) {
3717926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.setCurrentMonth(Month.createFromDay(initialSelection.middleDay()), CalendarPicker.NavigationBehavior.None);
3718926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.setSelection(initialSelection);
3719926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    } else
3720926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.setCurrentMonth(Month.createFromToday(), CalendarPicker.NavigationBehavior.None);
3721926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
3722926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3723926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarPicker.prototype = Object.create(View.prototype);
3724926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3725926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarPicker.Padding = 10;
3726926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarPicker.BorderWidth = 1;
3727926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarPicker.ClassNameCalendarPicker = "calendar-picker";
3728926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarPicker.ClassNamePreparing = "preparing";
3729926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarPicker.EventTypeCurrentMonthChanged = "currentMonthChanged";
373009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)CalendarPicker.commitDelayMs = 100;
3731926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3732926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3733926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!Event} event
3734926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3735926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarPicker.prototype.onWindowResize = function(event) {
3736926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.element.classList.remove(CalendarPicker.ClassNamePreparing);
3737926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    window.removeEventListener("resize", this.onWindowResize, false);
3738926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3739926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3740926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3741926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!YearListView} sender
3742926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3743926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarPicker.prototype.onYearListViewDidHide = function(sender) {
3744926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.monthPopupView.hide();
3745926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.calendarHeaderView.setDisabled(false);
3746926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.adjustHeight();
3747926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3748926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3749926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3750926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!YearListView} sender
3751926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!Month} month
3752926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3753926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarPicker.prototype.onYearListViewDidSelectMonth = function(sender, month) {
3754926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.setCurrentMonth(month, CalendarPicker.NavigationBehavior.None);
3755926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3756926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3757926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3758926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!View|Node} parent
3759926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {?View|Node=} before
3760926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @override
3761926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3762926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarPicker.prototype.attachTo = function(parent, before) {
3763926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    View.prototype.attachTo.call(this, parent, before);
3764926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.calendarTableView.element.focus();
3765926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3766926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3767926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarPicker.prototype.cleanup = function() {
3768926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    window.removeEventListener("resize", this.onWindowResize, false);
3769926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.calendarTableView.element.removeEventListener("keydown", this.onBodyKeyDown, false);
3770926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // Month popup view might be attached to document.body.
3771926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.monthPopupView.hide();
3772926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3773926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3774926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3775926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {?MonthPopupButton} sender
3776926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3777926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarPicker.prototype.onMonthPopupButtonClick = function(sender) {
3778926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var clientRect = this.calendarTableView.element.getBoundingClientRect();
3779926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var calendarTableRect = new Rectangle(clientRect.left + document.body.scrollLeft, clientRect.top + document.body.scrollTop, clientRect.width, clientRect.height);
3780926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.monthPopupView.show(this.currentMonth(), calendarTableRect);
3781926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.calendarHeaderView.setDisabled(true);
3782926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.adjustHeight();
3783926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3784926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3785926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarPicker.prototype._setConfig = function(config) {
3786926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.config.minimum = (typeof config.min !== "undefined" && config.min) ? parseDateString(config.min) : this._dateTypeConstructor.Minimum;
3787926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.config.maximum = (typeof config.max !== "undefined" && config.max) ? parseDateString(config.max) : this._dateTypeConstructor.Maximum;
3788926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.config.minimumValue = this.config.minimum.valueOf();
3789926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.config.maximumValue = this.config.maximum.valueOf();
3790926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.config.step = (typeof config.step !== undefined) ? Number(config.step) : this._dateTypeConstructor.DefaultStep;
3791926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.config.stepBase = (typeof config.stepBase !== "undefined") ? Number(config.stepBase) : this._dateTypeConstructor.DefaultStepBase;
3792926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3793926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3794926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3795926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!Month}
3796926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3797926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarPicker.prototype.currentMonth = function() {
3798926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return this._currentMonth;
3799926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3800926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3801926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3802926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @enum {number}
3803926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3804926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarPicker.NavigationBehavior = {
3805926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    None: 0,
3806926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    WithAnimation: 1
3807926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3808926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3809926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3810926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!Month} month
3811926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!CalendarPicker.NavigationBehavior} animate
3812926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3813926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarPicker.prototype.setCurrentMonth = function(month, behavior) {
3814926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (month > this.maximumMonth)
3815926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        month = this.maximumMonth;
3816926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    else if (month < this.minimumMonth)
3817926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        month = this.minimumMonth;
3818926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this._currentMonth.equals(month))
3819926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
3820926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._currentMonth = month;
3821926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.calendarTableView.scrollToMonth(this._currentMonth, behavior === CalendarPicker.NavigationBehavior.WithAnimation);
3822926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.adjustHeight();
3823926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.calendarTableView.setNeedsUpdateCells(true);
3824926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.dispatchEvent(CalendarPicker.EventTypeCurrentMonthChanged, {
3825926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        target: this
3826926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    });
3827926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3828926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3829926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarPicker.prototype.adjustHeight = function() {
3830926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var rowForFirstDayInMonth = this.calendarTableView.columnAndRowForDay(this._currentMonth.firstDay()).row;
3831926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var rowForLastDayInMonth = this.calendarTableView.columnAndRowForDay(this._currentMonth.lastDay()).row;
3832926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var numberOfRows = rowForLastDayInMonth - rowForFirstDayInMonth + 1;
3833926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var calendarTableViewHeight = CalendarTableHeaderView.Height + numberOfRows * DayCell.Height + CalendarTableView.BorderWidth * 2;
3834926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var height = (this.monthPopupView.isVisible ? YearListView.Height : calendarTableViewHeight) + CalendarHeaderView.Height + CalendarHeaderView.BottomMargin + CalendarPicker.Padding * 2 + CalendarPicker.BorderWidth * 2;
3835926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.setHeight(height);
3836926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3837926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3838926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarPicker.prototype.selection = function() {
3839926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return this._selection;
3840926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3841926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3842926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarPicker.prototype.highlight = function() {
3843926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return this._highlight;
3844926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3845926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3846926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3847926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!Day}
3848926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3849926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarPicker.prototype.firstVisibleDay = function() {
3850926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var firstVisibleRow = this.calendarTableView.columnAndRowForDay(this.currentMonth().firstDay()).row;
3851926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var firstVisibleDay = this.calendarTableView.dayAtColumnAndRow(0, firstVisibleRow);
3852926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!firstVisibleDay)
3853926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        firstVisibleDay = Day.Minimum;
3854926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return firstVisibleDay;
3855926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3856926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3857926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3858926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!Day}
3859926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3860926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarPicker.prototype.lastVisibleDay = function() {
3861926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var lastVisibleRow = this.calendarTableView.columnAndRowForDay(this.currentMonth().lastDay()).row;
3862926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var lastVisibleDay = this.calendarTableView.dayAtColumnAndRow(DaysPerWeek - 1, lastVisibleRow);
3863926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!lastVisibleDay)
3864926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        lastVisibleDay = Day.Maximum;
3865926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return lastVisibleDay;
3866926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3867926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3868926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3869926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {?Day} day
3870926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3871926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarPicker.prototype.selectRangeContainingDay = function(day) {
3872926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var selection = day ? this._dateTypeConstructor.createFromDay(day) : null;
387309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    this.setSelectionAndCommit(selection);
3874926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3875926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3876926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3877926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {?Day} day
3878926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3879926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarPicker.prototype.highlightRangeContainingDay = function(day) {
3880926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var highlight = day ? this._dateTypeConstructor.createFromDay(day) : null;
3881926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._setHighlight(highlight);
3882926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3883926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3884926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
388509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) * Select the specified date.
3886926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {?DateType} dayOrWeekOrMonth
3887926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3888926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarPicker.prototype.setSelection = function(dayOrWeekOrMonth) {
3889926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!this._selection && !dayOrWeekOrMonth)
3890926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
3891926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this._selection && this._selection.equals(dayOrWeekOrMonth))
3892926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
3893926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var firstDayInSelection = dayOrWeekOrMonth.firstDay();
3894926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var lastDayInSelection = dayOrWeekOrMonth.lastDay();
389506f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    var candidateCurrentMonth = Month.createFromDay(firstDayInSelection);
389606f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    if (this.firstVisibleDay() > lastDayInSelection || this.lastVisibleDay() < firstDayInSelection) {
389706f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        // Change current month if the selection is not visible at all.
389806f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        this.setCurrentMonth(candidateCurrentMonth, CalendarPicker.NavigationBehavior.WithAnimation);
389906f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    } else if (this.firstVisibleDay() < firstDayInSelection || this.lastVisibleDay() > lastDayInSelection) {
390006f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        // If the selection is partly visible, only change the current month if
390106f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        // doing so will make the whole selection visible.
390206f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        var firstVisibleRow = this.calendarTableView.columnAndRowForDay(candidateCurrentMonth.firstDay()).row;
390306f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        var firstVisibleDay = this.calendarTableView.dayAtColumnAndRow(0, firstVisibleRow);
390406f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        var lastVisibleRow = this.calendarTableView.columnAndRowForDay(candidateCurrentMonth.lastDay()).row;
390506f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        var lastVisibleDay = this.calendarTableView.dayAtColumnAndRow(DaysPerWeek - 1, lastVisibleRow);
390606f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        if (firstDayInSelection >= firstVisibleDay && lastDayInSelection <= lastVisibleDay)
390706f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)            this.setCurrentMonth(candidateCurrentMonth, CalendarPicker.NavigationBehavior.WithAnimation);
3908926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
3909926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._setHighlight(dayOrWeekOrMonth);
3910926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!this.isValid(dayOrWeekOrMonth))
3911926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
3912926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._selection = dayOrWeekOrMonth;
3913926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.calendarTableView.setNeedsUpdateCells(true);
391409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)};
391509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
391609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)/**
391709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) * Select the specified date, commit it, and close the popup.
391809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) * @param {?DateType} dayOrWeekOrMonth
391909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) */
392009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)CalendarPicker.prototype.setSelectionAndCommit = function(dayOrWeekOrMonth) {
392109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    this.setSelection(dayOrWeekOrMonth);
392209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // Redraw the widget immidiately, and wait for some time to give feedback to
392309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // a user.
392409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    this.element.offsetLeft;
392509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    var value = this._selection.toString();
392609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (CalendarPicker.commitDelayMs == 0) {
392709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        // For testing.
392809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        window.pagePopupController.setValueAndClosePopup(0, value);
392909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    } else if (CalendarPicker.commitDelayMs < 0) {
393009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        // For testing.
393109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        window.pagePopupController.setValue(value);
393209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    } else {
393309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        setTimeout(function() {
393409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            window.pagePopupController.setValueAndClosePopup(0, value);
393509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        }, CalendarPicker.commitDelayMs);
393609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
3937926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3938926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3939926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3940926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {?DateType} dayOrWeekOrMonth
3941926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3942926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarPicker.prototype._setHighlight = function(dayOrWeekOrMonth) {
3943926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!this._highlight && !dayOrWeekOrMonth)
3944926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
3945926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!dayOrWeekOrMonth && !this._highlight)
3946926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
3947926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this._highlight && this._highlight.equals(dayOrWeekOrMonth))
3948926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
3949926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._highlight = dayOrWeekOrMonth;
3950926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.calendarTableView.setNeedsUpdateCells(true);
3951926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3952926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3953926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3954926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} value
3955926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!boolean}
3956926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3957926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarPicker.prototype._stepMismatch = function(value) {
395881a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)    var nextAllowedValue = Math.ceil((value - this.config.stepBase) / this.config.step) * this.config.step + this.config.stepBase;
395981a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)    return nextAllowedValue >= value + this._dateTypeConstructor.DefaultStep;
3960926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3961926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3962926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3963926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} value
3964926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!boolean}
3965926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3966926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarPicker.prototype._outOfRange = function(value) {
3967926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return value < this.config.minimumValue || value > this.config.maximumValue;
3968926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3969926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3970926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3971926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!DateType} dayOrWeekOrMonth
3972926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!boolean}
3973926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3974926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarPicker.prototype.isValid = function(dayOrWeekOrMonth) {
3975926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var value = dayOrWeekOrMonth.valueOf();
3976926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return dayOrWeekOrMonth instanceof this._dateTypeConstructor && !this._outOfRange(value) && !this._stepMismatch(value);
3977926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3978926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3979926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3980926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!Day} day
3981926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!boolean}
3982926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3983926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarPicker.prototype.isValidDay = function(day) {
3984926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return this.isValid(this._dateTypeConstructor.createFromDay(day));
3985926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
3986926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3987926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3988926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!DateType} dateRange
3989926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!boolean} Returns true if the highlight was changed.
3990926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3991926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarPicker.prototype._moveHighlight = function(dateRange) {
3992926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!dateRange)
3993926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return false;
3994926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this._outOfRange(dateRange.valueOf()))
3995926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return false;
3996926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this.firstVisibleDay() > dateRange.middleDay() || this.lastVisibleDay() < dateRange.middleDay())
3997926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.setCurrentMonth(Month.createFromDay(dateRange.middleDay()), CalendarPicker.NavigationBehavior.WithAnimation);
3998926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._setHighlight(dateRange);
3999926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return true;
4000926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
4001926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4002926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
4003926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {?Event} event
4004926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
4005926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarPicker.prototype.onCalendarTableKeyDown = function(event) {
4006926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var key = event.keyIdentifier;
4007926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var eventHandled = false;
4008926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (key == "U+0054") { // 't' key.
4009926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.selectRangeContainingDay(Day.createFromToday());
40105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        eventHandled = true;
4011926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    } else if (key == "PageUp") {
4012926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var previousMonth = this.currentMonth().previous();
4013926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (previousMonth && previousMonth >= this.config.minimumValue) {
4014926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            this.setCurrentMonth(previousMonth, CalendarPicker.NavigationBehavior.WithAnimation);
4015926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            eventHandled = true;
4016926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
4017926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    } else if (key == "PageDown") {
4018926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var nextMonth = this.currentMonth().next();
4019926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (nextMonth && nextMonth >= this.config.minimumValue) {
4020926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            this.setCurrentMonth(nextMonth, CalendarPicker.NavigationBehavior.WithAnimation);
40215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            eventHandled = true;
40225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
4023926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    } else if (this._highlight) {
4024926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (global.params.isLocaleRTL ? key == "Right" : key == "Left") {
4025926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            eventHandled = this._moveHighlight(this._highlight.previous());
4026926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        } else if (key == "Up") {
4027926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            eventHandled = this._moveHighlight(this._highlight.previous(this.type === "date" ? DaysPerWeek : 1));
4028926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        } else if (global.params.isLocaleRTL ? key == "Left" : key == "Right") {
4029926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            eventHandled = this._moveHighlight(this._highlight.next());
4030926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        } else if (key == "Down") {
4031926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            eventHandled = this._moveHighlight(this._highlight.next(this.type === "date" ? DaysPerWeek : 1));
4032926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        } else if (key == "Enter") {
403309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            this.setSelectionAndCommit(this._highlight);
4034926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
4035926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    } else if (key == "Left" || key == "Up" || key == "Right" || key == "Down") {
4036926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        // Highlight range near the middle.
4037926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.highlightRangeContainingDay(this.currentMonth().middleDay());
40385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        eventHandled = true;
40395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4040926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
40415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (eventHandled) {
40425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        event.stopPropagation();
40435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        event.preventDefault();
40445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
40455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
40465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
40475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
4048926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!number} Width in pixels.
40495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
4050926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarPicker.prototype.width = function() {
4051926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return this.calendarTableView.width() + (CalendarTableView.BorderWidth + CalendarPicker.BorderWidth + CalendarPicker.Padding) * 2;
4052926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
4053926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4054926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
4055926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @return {!number} Height in pixels.
4056926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
4057926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarPicker.prototype.height = function() {
4058926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return this._height;
4059926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
40605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4061926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
4062926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!number} height Height in pixels.
4063926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
4064926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarPicker.prototype.setHeight = function(height) {
4065926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (this._height === height)
40665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
4067926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._height = height;
4068926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    resizeWindow(this.width(), this._height);
4069926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this.calendarTableView.setHeight(this._height - CalendarHeaderView.Height - CalendarHeaderView.BottomMargin - CalendarPicker.Padding * 2 - CalendarTableView.BorderWidth * 2);
4070926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
4071926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4072926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
4073926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {?Event} event
4074926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
4075926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CalendarPicker.prototype.onBodyKeyDown = function(event) {
4076926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var key = event.keyIdentifier;
4077926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var eventHandled = false;
4078926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var offset = 0;
4079926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    switch (key) {
4080926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    case "U+001B": // Esc key.
4081926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        window.pagePopupController.closePopup();
4082926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        eventHandled = true;
4083926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        break;
4084926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    case "U+004D": // 'm' key.
4085926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        offset = offset || 1; // Fall-through.
4086926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    case "U+0059": // 'y' key.
4087926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        offset = offset || MonthsPerYear; // Fall-through.
4088926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    case "U+0044": // 'd' key.
4089926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        offset = offset || MonthsPerYear * 10;
4090926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var oldFirstVisibleRow = this.calendarTableView.columnAndRowForDay(this.currentMonth().firstDay()).row;
4091926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.setCurrentMonth(event.shiftKey ? this.currentMonth().previous(offset) : this.currentMonth().next(offset), CalendarPicker.NavigationBehavior.WithAnimation);
4092926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var newFirstVisibleRow = this.calendarTableView.columnAndRowForDay(this.currentMonth().firstDay()).row;
4093926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (this._highlight) {
4094926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            var highlightMiddleDay = this._highlight.middleDay();
4095926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            this.highlightRangeContainingDay(highlightMiddleDay.next((newFirstVisibleRow - oldFirstVisibleRow) * DaysPerWeek));
4096926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
4097926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        eventHandled  =true;
4098926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        break;
4099926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
4100926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (eventHandled) {
4101926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        event.stopPropagation();
4102926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        event.preventDefault();
4103926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
4104a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch};
41055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
41065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)if (window.dialogArguments) {
41075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    initialize(dialogArguments);
41085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} else {
41095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    window.addEventListener("message", handleMessage, false);
41105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4111