//////////////////////////////////////////////////////////////////////////////// // // Kap IT - Copyright 2011 Kap IT - All Rights Reserved. // // This component is distributed under the GNU LGPL v2.1 // (available at : http://www.hnu.org/licences/old-licenses/lgpl-2.1.html) // //////////////////////////////////////////////////////////////////////////////// module com.deCampredon.spark.components { import DateChooserDataGrid = com.deCampredon.spark.components.supportClass.DateChooserDataGrid; import YearNavigatorSpinner = com.deCampredon.spark.components.supportClass.YearNavigatorSpinner; import DateChooserScrollEvent = com.deCampredon.spark.events.DateChooserScrollEvent; import DateChooserScrollEventDetail = com.deCampredon.spark.events.DateChooserScrollEventDetail; import DateChooserSelectionEvent = com.deCampredon.spark.events.DateChooserSelectionEvent; import Event = flash.events.Event; import MouseEvent = flash.events.MouseEvent; import ArrayList = mx.collections.ArrayList; import IList = mx.collections.IList; import DateChooser = mx.controls.DateChooser; import IVisualElement = mx.core.IVisualElement; import DateChooserEventDetail = mx.events.DateChooserEventDetail; import FlexEvent = mx.events.FlexEvent; import IFocusManagerComponent = mx.managers.IFocusManagerComponent; import CellPosition = spark.components.gridClasses.CellPosition; import GridColumn = spark.components.gridClasses.GridColumn; import GridSelectionMode = spark.components.gridClasses.GridSelectionMode; import ButtonBase = spark.components.supportClasses.ButtonBase; import SkinnableComponent = spark.components.supportClasses.SkinnableComponent; import IDisplayText = spark.core.IDisplayText; import GridEvent = spark.events.GridEvent; import GridSelectionEvent = spark.events.GridSelectionEvent; //-------------------------------------- // Events //-------------------------------------- /** * Dispatched when a date is selected or changed. * * @eventType com.deCampredon.sparkDateChooser.events.DateChooserSelectionEvent.SELECTION_CHANGE * */ /*[Event(name="selectionChange", type="com.deCampredon.spark.events.DateChooserSelectionEvent")]*/ /** * Dispatched when a date is going to be selected. * Calling the preventDefault() method * on the event prevents the selection from changing. * * @eventType com.deCampredon.sparkDateChooser.events.DateChooserSelectionEvent.SELECTION_CHANGING * */ /*[Event(name="selectionChanging", type="com.deCampredon.spark.events.DateChooserSelectionEvent")]*/ /** * Dispatched when the displayed month or year changes due to user interaction. * * @eventType com.deCampredon.sparkDateChooser.events.DateChooserScrollEvent.SCROLL * */ /*[Event(name="scroll", type="com.deCampredon.spark.events.DateChooserSelectionEvent")]*/ //-------------------------------------- // Styles //-------------------------------------- /** * Color of the text. * *

For the Spark theme, see * flashx.textLayout.formats.ITextLayoutFormat.color.

* *

For the Mobile theme, if using StyleableTextField, * see spark.components.supportClasses.StyleableTextField Style color, * and if using StyleableStageText, * see spark.components.supportClasses.StyleableStageText Style color.

* * @see flashx.textLayout.formats.ITextLayoutFormat#color * @see spark.components.supportClasses.StyleableTextField#style:color * @see spark.components.supportClasses.StyleableStageText#style:color * * @default 0x000000 * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ /*[Style(name="color", type="uint", format="Color", inherit="yes")]*/ /** * The name of the font to use, or a comma-separated list of font names. * *

For the Spark theme, see * flashx.textLayout.formats.ITextLayoutFormat.fontFamily.

* *

For the Mobile theme, if using StyleableTextField, * see spark.components.supportClasses.StyleableTextField Style fontFamily, * and if using StyleableStageText, * see spark.components.supportClasses.StyleableStageText Style fontFamily.

* *

The default value for the Spark theme is Arial. * The default value for the Mobile theme is _sans.

* * @see flashx.textLayout.formats.ITextLayoutFormat#fontFamily * @see spark.components.supportClasses.StyleableStageText#style:fontFamily * @see spark.components.supportClasses.StyleableTextField#style:fontFamily * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ /*[Style(name="fontFamily", type="String", inherit="yes")]*/ /** * Font lookup to use. * *

For the Spark theme, see * flashx.textLayout.formats.ITextLayoutFormat.fontLookup

* *

For the Mobile theme, this is not supported.

* * @see flashx.textLayout.formats.ITextLayoutFormat#fontLookup * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ /*[Style(name="fontLookup", type="String", enumeration="auto,device,embeddedCFF", inherit="yes")]*/ /** * Height of the text, in pixels. * *

For the Spark theme, see * flashx.textLayout.formats.ITextLayoutFormat.fontSize

* *

For the Mobile theme, if using StyleableTextField, * see spark.components.supportClasses.StyleableTextField Style fontSize, * and if using StyleableStageText, * see spark.components.supportClasses.StyleableStageText Style fontSize.

* *

The default value for the Spark theme is 12. * The default value for the Mobile theme is 24.

* * @see flashx.textLayout.formats.ITextLayoutFormat#fontSize * @see spark.components.supportClasses.StyleableStageText#style:fontSize * @see spark.components.supportClasses.StyleableTextField#style:fontSize * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ /*[Style(name="fontSize", type="Number", format="Length", inherit="yes", minValue="1.0", maxValue="720.0")]*/ /** * @copy spark.components.supportClasses.GroupBase#style:accentColor * * @default #0099FF * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ /*[Style(name="accentColor", type="uint", format="Color", inherit="yes", theme="spark, mobile")]*/ /** * Determines whether the text is italic font. * *

For the Spark theme, see * flashx.textLayout.formats.ITextLayoutFormat.fontStyle

* *

For the Mobile theme, if using StyleableTextField, * see spark.components.supportClasses.StyleableTextField Style fontStyle, * and if using StyleableStageText, * see spark.components.supportClasses.StyleableStageText Style fontStyle.

* * @see flashx.textLayout.formats.ITextLayoutFormat#fontStyle * @see spark.components.supportClasses.StyleableStageText#style:fontStyle * @see spark.components.supportClasses.StyleableTextField#style:fontStyle * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ /*[Style(name="fontStyle", type="String", enumeration="normal,italic", inherit="yes")]*/ /** * Determines whether the text is boldface. * *

For the Spark theme, see * flashx.textLayout.formats.ITextLayoutFormat.fontWeight

* *

For the Mobile theme, if using StyleableTextField, * see spark.components.supportClasses.StyleableTextField Style fontWeight, * and if using StyleableStageText, * see spark.components.supportClasses.StyleableStageText Style fontWeight.

* * @see flashx.textLayout.formats.ITextLayoutFormat#fontWeight * @see spark.components.supportClasses.StyleableStageText#style:fontWeight * @see spark.components.supportClasses.StyleableTextField#style:fontWeight * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ /*[Style(name="fontWeight", type="String", enumeration="normal,bold", inherit="yes")]*/ /** * The locale of the text. * Controls case transformations and shaping. * Uses standard locale identifiers as described in Unicode Technical Standard #35. * For example "en", "en_US" and "en-US" are all English, "ja" is Japanese. * *

The default value is undefined. This property inherits its value from an ancestor; if * still undefined, it inherits from the global locale style. * During the application initialization, if the global locale style is undefined, * then the default value is set to "en".

* *

When using the Spark formatters and globalization classes, you can set this style on the * root application to the value of the LocaleID.DEFAULT constant. * Those classes will then use the client operating system's international preferences.

* * @default undefined * @see http://www.unicode.org/reports/tr35/ * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ /*[Style(name="locale", type="String", inherit="yes")]*/ /** * @copy spark.components.supportClasses.GroupBase#style:alternatingItemColors * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ /*[Style(name="alternatingItemColors", type="Array", arrayType="uint", format="Color", inherit="yes", theme="spark, mobile")]*/ /** * Alpha level of the background for this component. * Valid values range from 0.0 to 1.0. * * @default 1.0 * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ /*[Style(name="backgroundAlpha", type="Number", inherit="no", theme="spark, mobile")]*/ /** * Background color of a component. * * @default 0xFFFFFF * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ /*[Style(name="backgroundColor", type="uint", format="Color", inherit="no", theme="spark, mobile")]*/ /** * The alpha of the content background for this component. * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ /*[Style(name="contentBackgroundAlpha", type="Number", inherit="yes", theme="spark, mobile")]*/ /** * @copy spark.components.supportClasses.GroupBase#style:contentBackgroundColor * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ /*[Style(name="contentBackgroundColor", type="uint", format="Color", inherit="yes", theme="spark, mobile")]*/ /** * @copy spark.components.supportClasses.GroupBase#style:downColor * * @langversion 3.0 * @playerversion Flash 10.1 * @playerversion AIR 2.5 * @productversion Flex 4.5 */ /*[Style(name="downColor", type="uint", format="Color", inherit="yes", theme="mobile")]*/ /** * @copy spark.components.supportClasses.GroupBase#style:focusColor * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ /*[Style(name="focusColor", type="uint", format="Color", inherit="yes", theme="spark, mobile")]*/ /** * @copy spark.components.supportClasses.GroupBase#style:rollOverColor * * @default 0xCEDBEF * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ /*[Style(name="rollOverColor", type="uint", format="Color", inherit="yes", theme="spark")]*/ /** * @copy spark.components.supportClasses.GroupBase#style:symbolColor * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ /*[Style(name="symbolColor", type="uint", format="Color", inherit="yes", theme="spark, mobile")]*/ /** * @copy spark.components.supportClasses.GroupBase#style:touchDelay * * @langversion 3.0 * @playerversion Flash 10.1 * @playerversion AIR 2.5 * @productversion Flex 4.5 */ /*[Style(name="touchDelay", type="Number", format="Time", inherit="yes", minValue="0.0")]*/ /** * Color of text shadows. * * @default #FFFFFF * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ /*[Style(name="textShadowColor", type="uint", format="Color", inherit="yes", theme="mobile")]*/ /** * Alpha of text shadows. * * @default 0.55 * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ /*[Style(name="textShadowAlpha", type="Number",inherit="yes", minValue="0.0", maxValue="1.0", theme="mobile")]*/ /** * The alpha of the border for this component. * * @default 0.5 * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ /*[Style(name="borderAlpha", type="Number", inherit="no", theme="spark")]*/ /** * The color of the border for this component. * * @default 0 * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ /*[Style(name="borderColor", type="uint", format="Color", inherit="no", theme="spark")]*/ /** * Controls the visibility of the border for this component. * * @default true * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ /*[Style(name="borderVisible", type="Boolean", inherit="no", theme="spark")]*/ /** * The radius of the corners for this component. * * @default 0 * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ /*[Style(name="cornerRadius", type="Number", format="Length", inherit="no", theme="spark")]*/ /** * Controls the visibility of the drop shadow for this component. * * @default true * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ /*[Style(name="dropShadowVisible", type="Boolean", inherit="no", theme="spark")]*/ /*[ResourceBundle("controls")]*/ /*[ResourceBundle("SharedResources")]*/ /*[SkinState("normal")]*/ /*[SkinState("disabled")]*/ /*[SkinState("normalWithYearNavigation")]*/ /*[SkinState("disabledWithYearNavigation")]*/ /** * The DateChooser control displays the name of a month, the year, * and a grid of the days of the month, with columns labeled * for the day of the week. * The user can select a date. * @author François de Campredon */ export class DateChooser extends SkinnableComponent implements IFocusManagerComponent { //-------------------------------------------------------------------------- // // Class Constant // //-------------------------------------------------------------------------- /** * @private */ private static dayProps:any[] = ["sun","mon","tue","wen","thu","fri","sat"]; //-------------------------------------------------------------------------- // // Constructor // //-------------------------------------------------------------------------- /** * Constructor */ constructor(value:Date = null) { super(); var currentDate:Date = value ? value : new Date(), hello: string; this.displayedMonth = currentDate.month; this.displayedYear = currentDate.fullYear; this.monthNames = null; this.dayNames = null; this.firstDayOfWeek = NaN; } //-------------------------------------------------------------------------- // // Skin Part // //-------------------------------------------------------------------------- /*[SkinPart(required="false")]*/ /** * SkinPart representing a navigation button */ public nextMonthButton:ButtonBase; /*[SkinPart(required="false")]*/ /** * SkinPart representing a navigation button */ public prevMonthButton:ButtonBase; /*[SkinPart(required="false")]*/ /** * SkinPart displaying the displayedMonth name */ public monthLabelDisplay:IDisplayText; /*[SkinPart(required="false")]*/ /** * Body of the chooser */ public bodyGrid:DateChooserDataGrid; /*[SkinPart(required="false")]*/ /** * Spinner allowing year navigation. */ public yearNavigator:YearNavigatorSpinner; /*[SkinPart(required="false")]*/ /** * Skin part that will renderer the "today" indicator, * that part should not be added as a child of the skin. */ public todayIndicator:IVisualElement; //-------------------------------------------------------------------------- // // Properties // //-------------------------------------------------------------------------- //---------------------------------- // baselinePosition //---------------------------------- /** * @private */ /*override*/ public get baselinePosition():number { return this.getBaselinePositionForPart(this.monthLabelDisplay ); } //---------------------------------- // selectedDate //---------------------------------- private _selectedDate:Date; private selectedDateChanged:boolean /*[Bindable(event="selectionChange")]*/ /** * Date selected in the DateChooser control. * If the incoming Date object has any time values, * they are zeroed out. */ public get selectedDate():Date { return this._selectedDate; } public set selectedDate(value:Date) { if( this._selectedDate == value || ( value && !this.isEnableddDate(value) ) ) return; var event:DateChooserSelectionEvent = new DateChooserSelectionEvent(DateChooserSelectionEvent.SELECTION_CHANGE); event.previousDate = this.selectedDate; event.newDate = value; this._selectedDate = value; this.selectedDateChanged = true; this.invalidateProperties(); this.dispatchEvent(event); } //---------------------------------- // displayedMonth //---------------------------------- /** * @private * Storage for the displayedMonth property. */ private _displayedMonth:number; /** * @private */ private displayedMonthChanged:boolean = false; /*[Bindable("displayedMonthChanged")]*/ /*[Inspectable(category="General")]*/ /** * Used together with the displayedYear property, * the displayedMonth property specifies the month * displayed in the DateChooser control. * Month numbers are zero-based, so January is 0 and December is 11. * Setting this property changes the appearance of the DateChooser control. * *

The default value is the current month.

* */ public get displayedMonth():number { return this._displayedMonth; } /** * @private */ public set displayedMonth(value:number) { if (value < 0 || value > 11 || this.displayedMonth == value) return; this._displayedMonth = value; this.displayedMonthChanged = true; this.invalidateProperties(); this.dispatchChangeEvent("displayedMonthChanged"); } //---------------------------------- // displayedYear //---------------------------------- /** * @private * Storage for the displayedYear property. */ private _displayedYear:number; /** * @private */ private displayedYearChanged:boolean = false; /*[Bindable("displayedYearChanged")]*/ /*[Inspectable(category="General")]*/ /** * Used together with the displayedMonth property, * the displayedYear property specifies the year * displayed in the DateChooser control. * Setting this property changes the appearance of the DateChooser control. * *

The default value is the current year.

* */ public get displayedYear():number { return this._displayedYear; } /** * @private */ public set displayedYear(value:number) { if (this.displayedYear == value || value < this.minYear || value > this.maxYear) return; this._displayedYear = value; this.displayedYearChanged = true; this.invalidateProperties(); this.dispatchChangeEvent("displayedYearChanged"); } //---------------------------------- // firstDayOfWeek //---------------------------------- /** * @private * Storage for the firstDayOfWeek property. */ private _firstDayOfWeek:number; /** * @private */ private firstDayOfWeekOverride:number; /** * @private */ private firstDayOfWeekChanged:boolean = false; /*[Bindable("firstDayOfWeekChanged")]*/ /*[Inspectable(category="General")]*/ /** * Number representing the day of the week to display in the * first column of the DateChooser control. * The value must be in the range 0 to 6, where 0 corresponds to Sunday, * the first element of the dayNames Array. * *

Setting this property changes the order of the day columns. * For example, setting it to 1 makes Monday the first column * in the control.

* * @default 0 (Sunday) * */ public get firstDayOfWeek():number { return this._firstDayOfWeek; } /** * @private */ public set firstDayOfWeek(value:number) { if (this.firstDayOfWeek == value) return; this.firstDayOfWeekOverride = value; this._firstDayOfWeek = !isNaN(value) ? int(value) : this.resourceManager.getInt( "controls", "firstDayOfWeek"); this.firstDayOfWeekChanged = true; this.invalidateProperties(); this.dispatchChangeEvent("firstDayOfWeekChanged"); } //---------------------------------- // dayNames //---------------------------------- /** * @private * Storage for the dayNames property. */ private _dayNames:string[]; /** * @private */ private dayNamesChanged:boolean = false; /** * @private */ private dayNamesOverride:string[]; /*[Bindable("dayNamesChanged")]*/ /** * The weekday names for DateChooser control. * Changing this property changes the day labels * of the DateChooser control. * Sunday is the first day (at index 0). * The rest of the week names follow in the normal order. * * @default [ "S", "M", "T", "W", "T", "F", "S" ]. * */ public get dayNames():string[] { return this._dayNames?this._dayNames.concat():null; } /** * @private */ public set dayNames(value:string[]) { if(value && value.length!=7) return; this.dayNamesOverride = value; this._dayNames = value != null ? value : (this.resourceManager.getStringArray("controls", "dayNamesShortest")) // _dayNames will be null if there are no resources. this._dayNames = this._dayNames ? this._dayNames.concat() : null; this.dayNamesChanged = true; this.invalidateProperties(); this.dispatchChangeEvent("dayNamesChanged"); } //---------------------------------- // monthNames //---------------------------------- /** * @private * Storage for the monthNames property. */ private _monthNames:string[]; private monthNamesOverride:string[]; /** * @private */ private monthNamesChanged:boolean = false; /*[Bindable("monthNamesChanged")]*/ /** * Names of the months displayed at the top of the DateChooser control. * The monthSymbol property is appended to the end of * the value specified by the monthNames property, * which is useful in languages such as Japanese. * * @default [ "January", "February", "March", "April", "May", "June", * "July", "August", "September", "October", "November", "December" ] * * */ public get monthNames():string[] { return this._monthNames?this._monthNames.concat():null; } /** * @private */ public set monthNames(value:string[]) { if(value && value.length!=12) return; this.monthNamesOverride = value; this._monthNames = value != null ? value : (this.resourceManager.getStringArray("SharedResources", "monthNames")); // _monthNames will be null if there are no resources. this._monthNames = this._monthNames ? this._monthNames.concat() : null; this.monthNamesChanged = true; this.invalidateProperties(); this.dispatchChangeEvent("monthNamesChanged"); } //---------------------------------- // monthSymbol //---------------------------------- /** * @private * Storage for the monthSymbol property. */ private _monthSymbol:string; private monthSymbolOverride:string; /** * @private */ private monthSymbolChanged:boolean = false; /*[Bindable("monthSymbolChanged")]*/ /*[Inspectable(defaultValue="")]*/ /** * This property is appended to the end of the value specified * by the monthNames property to define the names * of the months displayed at the top of the DateChooser control. * Some languages, such as Japanese, use an extra * symbol after the month name. * * @default "" * */ public get monthSymbol():string { return this._monthSymbol; } /** * @private */ public set monthSymbol(value:string) { this.monthSymbolOverride = value; this._monthSymbol = value != null ? value : this.resourceManager.getString( "SharedResources", "monthSymbol"); this.monthSymbolChanged = true; this.invalidateProperties(); this.dispatchChangeEvent("monthSymbolChanged"); } //---------------------------------- // yearSymbol //---------------------------------- /** * @private * Storage for the yearSymbol property. */ private _yearSymbol:string; /** * @private */ private yearSymbolOverride:string; /*[Bindable("yearSymbolChanged")]*/ /*[Inspectable(defaultValue="")]*/ /** * This property is appended to the end of the year * displayed at the top of the DateChooser control. * Some languages, such as Japanese, * add a symbol after the year. * * @default "" * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public get yearSymbol():string { return this._yearSymbol; } /** * @private */ public set yearSymbol(value:string) { this.yearSymbolOverride = value; this._yearSymbol = value != null ? value : this.resourceManager.getString( "controls", "yearSymbol"); if(this.yearNavigator) this.yearNavigator.yearSymbol = this.yearSymbol; this.dispatchChangeEvent("yearSymbolChanged"); } //---------------------------------- // yearNavigationEnabled //---------------------------------- /** * @private * Storage for the yearNavigationEnabled property. */ private _yearNavigationEnabled:boolean = false; /*[Bindable("yearNavigationEnabledChanged")]*/ /*[Inspectable(defaultValue="false")]*/ /** * Enables year navigation. When true * an up and down button appear to the right * of the displayed year. You can use these buttons * to change the current year. * These button appear to the left of the year in locales where year comes * before the month in the date format. * * @default false * */ public get yearNavigationEnabled():boolean { return this._yearNavigationEnabled; } /** * @private */ public set yearNavigationEnabled(value:boolean) { if(this._yearNavigationEnabled != value) { this._yearNavigationEnabled = value; this.invalidateSkinState(); this.dispatchChangeEvent("yearNavigationEnabledChanged"); } } //---------------------------------- // maxYear //---------------------------------- /** * @private * Storage for the maxYear property. */ private _maxYear:number = 2100; /** * @private */ private maxYearChanged:boolean; /*[Bindable("maxYearChanged")]*/ /*[Inspectable(defaultValue="2100")]*/ /** * The last year selectable in the control. * * @default 2100 * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public get maxYear():number { return this._maxYear; } /** * @private */ public set maxYear(value:number) { if (this._maxYear == value || value < this._minYear) return; this.maxYearChanged = true; this._maxYear = value; this.invalidateProperties(); this.dispatchChangeEvent("maxYearChanged"); } //---------------------------------- // minYear //---------------------------------- /** * @private * Storage for the minYear property. */ private _minYear:number = 1900; /** * @private */ private minYearChanged:boolean; /*[Bindable("minYearChanged")]*/ /*[Inspectable(defaultValue="1900")]*/ /** * The first year selectable in the control. * * @default 1900 * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public get minYear():number { return this._minYear; } /** * @private */ public set minYear(value:number) { if (this._minYear == value || this._maxYeartrue, specifies that today is highlighted * in the DateChooser control. * Setting this property changes the appearance of the DateChooser control. * * @default true * */ public get showToday():boolean { return this._showToday; } /** * @private */ public set showToday(value:boolean) { if(this.showToday == value) return; this._showToday = value; this.showTodayChanged = true; this.invalidateProperties(); this.dispatchChangeEvent("showTodayChanged"); } //---------------------------------- // disabledDays //---------------------------------- /** * @private * Storage for the disabledDays property. */ private _disabledDays:number[]; /** * @private */ private disabledDaysChanged:boolean = false; /*[Bindable("disabledDaysChanged")]*/ /** * The days to disable in a week. * All the dates in a month, for the specified day, are disabled. * This property changes the appearance of the DateChooser control. * The elements of this array can have values from 0 (Sunday) to * 6 (Saturday). * For example, a value of [ 0, 6 ] * disables Sunday and Saturday. * * @default [] * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public get disabledDays():number[] { return this._disabledDays?this._disabledDays.concat():null; } /** * @private */ public set disabledDays(value:number[]) { this._disabledDays = value?value.concat():null; this.disabledDaysChanged = true; this.invalidateProperties(); this.dispatchChangeEvent("disabledDaysChanged"); } //---------------------------------- // disabledRanges //---------------------------------- /** * @private * Storage for the disabledRanges property. */ private _disabledRanges:any[] = []; /** * @private */ private disabledRangesChanged:boolean = false; /*[Bindable("disabledRangesChanged")]*/ /*[Inspectable(arrayType="Object")]*/ /** * Disables single and multiple days. * *

This property accepts an Array of objects as a parameter. * Each object in this array is a Date object, specifying a * single day to disable; or an object containing either or both * of the rangeStart and rangeEnd properties, * each of whose values is a Date object. * The value of these properties describes the boundaries * of the date range. * If either is omitted, the range is considered * unbounded in that direction. * If you specify only rangeStart, * all the dates after the specified date are disabled, * including the rangeStart date. * If you specify only rangeEnd, * all the dates before the specified date are disabled, * including the rangeEnd date. * To disable a single day, use a single Date object specifying a date * in the Array. Time values are zeroed out from the Date * object if they are present.

* *

The following example, disables the following dates: January 11 * 2006, the range January 23 - February 10 2006, and March 1 2006 * and all following dates.

* *

disabledRanges="{[ new Date(2006,0,11), {rangeStart: * new Date(2006,0,23), rangeEnd: new Date(2006,1,10)}, * {rangeStart: new Date(2006,2,1)} ]}"

* * @default [] * */ public get disabledRanges():any[] { return this._disabledRanges; } /** * @private */ public set disabledRanges(value:any[]) { this._disabledRanges = this.scrubTimeValues(value); this.disabledRangesChanged = true; this.invalidateProperties(); this.dispatchChangeEvent("disabledRangesChanged"); } //---------------------------------- // selectableRange //---------------------------------- /** * @private * Storage for the selectableRange property. */ private _selectableRange:Object; /** * @private */ private selectableRangeChanged:boolean = false; /*[Bindable("selectableRangeChanged")]*/ /** * Range of dates between which dates are selectable. * For example, a date between 04-12-2006 and 04-12-2007 * is selectable, but dates out of this range are disabled. * *

This property accepts an Object as a parameter. * The Object contains two properties, rangeStart * and rangeEnd, of type Date. * If you specify only rangeStart, * all the dates after the specified date are enabled. * If you only specify rangeEnd, * all the dates before the specified date are enabled. * To enable only a single day in a DateChooser control, * you can pass a Date object directly. Time values are * zeroed out from the Date object if they are present.

* *

The following example enables only the range * January 1, 2006 through June 30, 2006. Months before January * and after June do not appear in the DateChooser.

* *

selectableRange="{{rangeStart : new Date(2006,0,1), * rangeEnd : new Date(2006,5,30)}}"

* * @default null * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public get selectableRange():Object { return this._selectableRange; } /** * @private */ public set selectableRange(value:Object) { this._selectableRange = this.scrubTimeValue(value); this.selectableRangeChanged = true; this.dispatchChangeEvent("selectableRangeChanged"); this.invalidateProperties(); } //-------------------------------------------------------------------------- // // Variables // //-------------------------------------------------------------------------- //---------------------------------- // gridColumns //---------------------------------- /** * @private */ private _gridColumns:IList; /** * @private * list of columns passed to the bodyGrid */ private get gridColumns():IList { return this._gridColumns; } /** * @private */ private set gridColumns(value:IList) { this._gridColumns = value; if(this.bodyGrid) this.bodyGrid.columns = value; } //---------------------------------- // gridDataProvider //---------------------------------- /** * @private */ private _gridDataProvider:IList; /** * @private * dataProvider passed to the bodyGrid */ private get gridDataProvider():IList { return this._gridDataProvider; } /** * @private */ private set gridDataProvider(value:IList) { this._gridDataProvider = value; if(this.bodyGrid) this.bodyGrid.dataProvider = value } //---------------------------------- // currentMonthText //---------------------------------- /** * @private */ private _currentMonthText:string; /** * @private * text displayed by the monthLabelDisplay */ private get currentMonthText():string { return this._currentMonthText; } /** * @private */ private set currentMonthText(value:string) { this._currentMonthText = value; if(this.monthLabelDisplay) this.monthLabelDisplay.text = value; } //---------------------------------- // selectedCellPosition //---------------------------------- /** * @private */ private _selectedCellPosition:CellPosition; /** * cell selected on the grid */ private get selectedCellPosition():CellPosition { return this._selectedCellPosition; } /** * @private */ private set selectedCellPosition(value:CellPosition) { this._selectedCellPosition = value; if(this.bodyGrid) this.bodyGrid.selectedCell = value } //-------------------------------------------------------------------------- // // Overriden methods // //-------------------------------------------------------------------------- /** * @private * retrieve the CellPosition of the cell displaying the current date */ public getTodayCellPosition():CellPosition { var today:Date = new Date(); if(this.displayedMonth == today.month && this.displayedYear == today.fullYear) { var cellPosition:CellPosition = new CellPosition(); var date:Date = new Date(this.displayedYear,this.displayedMonth,1); var currentWeek:number = -1. while(date.month == this.displayedMonth) { if(date.day == this.firstDayOfWeek || currentWeek==-1) { currentWeek++; } if(date.date == today.date) { cellPosition.rowIndex = currentWeek; cellPosition.columnIndex = (today.day+this.firstDayOfWeek)%7; return cellPosition; } date.date++; } } return null; } /** * @private */ public isEnabledCell(rowIndex:number, columnIndex:number):boolean { var date:Date = this.getDateForCell(rowIndex,columnIndex); return this.isEnableddDate(date); } /** * @private */ /*override*/ /*protected*/ commitProperties():void { super.commitProperties(); var i:number,weekObject:Object; if(this.maxYearChanged || this.minYearChanged) { if(this.displayedYear < this.minYear) this.displayedYear = this.minYear; if(this.displayedYear > this.maxYear) this.displayedYear = this.maxYear; if(this.yearNavigator) { this.yearNavigator.maximum = this.maxYear; this.yearNavigator.minimum = this.minYear; } } if(this.showTodayChanged || this.disabledDaysChanged || this.selectableRangeChanged) { if(this.bodyGrid && this.bodyGrid.grid) this.bodyGrid.grid.invalidateDisplayList(); } if(this.selectedDateChanged) { this.commitVisualSelection(true); } if(this.firstDayOfWeekChanged || this.displayedMonthChanged || this.displayedYearChanged || this.disabledRangesChanged) { this.updateGridDataProvider(); if(!this.selectedDateChanged) { this.commitVisualSelection(false); } else { if(this.bodyGrid) { this.bodyGrid.selectedCell = this.selectedCellPosition } } } if(this.firstDayOfWeekChanged || this.dayNamesChanged) { this.updateGridColumn(); } if(this.displayedMonthChanged || this.monthNamesChanged || this.monthSymbolChanged) { this.updateMonthText(); } if(this.displayedYearChanged && this.yearNavigator) { this.yearNavigator.value = this.displayedYear } this.monthNamesChanged = false; this.monthSymbolChanged = false; this.selectedDateChanged = false; this.displayedMonthChanged = false; this.displayedYearChanged = false; this.firstDayOfWeekChanged = false; this.dayNamesChanged = false; this.maxYearChanged = false; this.minYearChanged = false; this.disabledDaysChanged = false; this.showTodayChanged = false; this.disabledRangesChanged = false; this.selectableRangeChanged = false; } /** * @private */ /*override*/ /*protected*/ resourcesChanged():void { super.resourcesChanged(); this.dayNames = this.dayNamesOverride; this.firstDayOfWeek = this.firstDayOfWeekOverride; this.monthNames = this.monthNamesOverride; this.monthSymbol = this.monthSymbolOverride; this.yearSymbol = this.yearSymbolOverride; } /** * @private */ /*override*/ /*protected*/ getCurrentSkinState():string { if(this.yearNavigationEnabled) { return this.enabled?"normalWithYearNavigation":"disabledWithYearNavigation"; } return this.enabled?"normal":"disabled"; } /** * @private */ /*override*/ /*protected*/ partAdded(partName:string, instance:Object):void { super.partAdded(partName,instance); if(instance == this.bodyGrid) { this.bodyGrid.dateChooser = this; this.bodyGrid.columns = this.gridColumns; this.bodyGrid.dataProvider = this.gridDataProvider; this.bodyGrid.selectedCell = this.selectedCellPosition; this.bodyGrid.selectionMode = GridSelectionMode.SINGLE_CELL this.bodyGrid.addEventListener(GridSelectionEvent.SELECTION_CHANGING,this.bodyGrid_selectionChangingHandler); this.bodyGrid.addEventListener(GridSelectionEvent.SELECTION_CHANGE,this.bodyGrid_selectionChangeHandler); this.bodyGrid.addEventListener(GridEvent.GRID_ROLL_OVER,this.bodyGrid_gridRollOverHandler); } else if(instance == this.monthLabelDisplay) { this.monthLabelDisplay.text = this.currentMonthText; } else if(instance == this.nextMonthButton) { this.nextMonthButton.addEventListener(MouseEvent.CLICK,this.nextMonthButton_clickHandler); } else if(instance == this.prevMonthButton) { this.prevMonthButton.addEventListener(MouseEvent.CLICK,this.prevMonthButton_clickHandler); } else if(instance == this.yearNavigator) { this.yearNavigator.maximum = this.maxYear; this.yearNavigator.minimum = this.minYear; this.yearNavigator.value = this.displayedYear; this.yearNavigator.yearSymbol = this.yearSymbol; this.yearNavigator.addEventListener(Event.CHANGE,this.yearNavigator_changeHandler); } } /** * @private */ /*override*/ /*protected*/ partRemoved(partName:string, instance:Object):void { super.partRemoved(partName,instance); if(instance == this.bodyGrid) { this.bodyGrid.removeEventListener(GridSelectionEvent.SELECTION_CHANGING,this.bodyGrid_selectionChangingHandler); this.bodyGrid.removeEventListener(GridSelectionEvent.SELECTION_CHANGE,this.bodyGrid_selectionChangeHandler); this.bodyGrid.removeEventListener(GridEvent.GRID_ROLL_OVER,this.bodyGrid_gridRollOverHandler); } else if(instance == this.nextMonthButton) { this.nextMonthButton.removeEventListener(MouseEvent.CLICK,this.nextMonthButton_clickHandler); } else if(instance == this.prevMonthButton) { this.prevMonthButton.removeEventListener(MouseEvent.CLICK,this.prevMonthButton_clickHandler); } else if(instance == this.yearNavigator) { this.yearNavigator.removeEventListener(Event.CHANGE,this.yearNavigator_changeHandler); } } //-------------------------------------------------------------------------- // // Events Handler // //-------------------------------------------------------------------------- /** * @private * handle selectionChanging events displayed by the grid, prevent the selection * if the cell corresponding date should not be selected. */ /*protected*/ bodyGrid_selectionChangingHandler(event:GridSelectionEvent):void { if(!this.isEnabledCell(event.selectionChange.rowIndex,event.selectionChange.columnIndex)){ event.preventDefault(); } } /** * @private * handle selectionChange events dispatched by the grid, and commit the selection */ /*protected*/ bodyGrid_selectionChangeHandler(event:GridSelectionEvent):void { var date:Date = this.getDateForCell(event.selectionChange.rowIndex,event.selectionChange.columnIndex); date = new Date(date.time); this.setSelectedDate(date) } /** * @private * handle rollOver events on grid cell, prevent the rollOverIndicator to be displayed * if the cell is not selectable. */ /*protected*/ bodyGrid_gridRollOverHandler(event:GridEvent):void { if(!this.isEnabledCell(event.rowIndex,event.columnIndex) && this.bodyGrid && this.bodyGrid.grid) { this.bodyGrid.grid.hoverRowIndex = -1; this.bodyGrid.grid.hoverColumnIndex = -1; } } /** * @private * handle prevMonthButton click events */ /*protected*/ prevMonthButton_clickHandler(event:MouseEvent):void { this.decreaseDisplayedMonth(); } /** * @private * handle nextMonthButton click events */ /*protected*/ nextMonthButton_clickHandler(event:MouseEvent):void { this.increaseDisplayedMonth(); } /** * @private * handle yearNavigation change events */ /*protected*/ yearNavigator_changeHandler(event:Event):void { var increased:boolean = this.displayedYear < this.yearNavigator.value; this.displayedYear = this.yearNavigator.value; this.dispatchScrollingEvent(increased?DateChooserEventDetail.NEXT_YEAR:DateChooserEventDetail.PREVIOUS_YEAR); } //-------------------------------------------------------------------------- // // Private methods // //-------------------------------------------------------------------------- /** * @private * update the selectedDate */ private setSelectedDate(date:Date):void { //dispatch a selectionChanging event to allow the user to prevent/modify the selection var selectionEvent:DateChooserSelectionEvent = new DateChooserSelectionEvent(DateChooserSelectionEvent.SELECTION_CHANGING,false,true,this.selectedDate,date); this.dispatchEvent(selectionEvent); //if the event have not been default prevented commit the selection if(!selectionEvent.isDefaultPrevented()) { this.selectedDate = selectionEvent.newDate; this.dispatchEvent(new FlexEvent(FlexEvent.VALUE_COMMIT)); } //if event have been selected, or date have been modified commit the visual selection if(selectionEvent.isDefaultPrevented() || selectionEvent.newDate != date) this.commitVisualSelection(true); } /** * @private * increase the displayed month */ private increaseDisplayedMonth():void { if(this.displayedMonth == 11) { if(this.displayedYear >= this.maxYear) return; this.displayedYear++; this.displayedMonth = 0; } else { this.displayedMonth++; } this.dispatchScrollingEvent(DateChooserScrollEventDetail.NEXT_MONTH); } /** * @private * decrease the displayed month */ private decreaseDisplayedMonth():void { if(this.displayedMonth ==0) { if(this.displayedYear <= this.minYear) return; this.displayedYear--; this.displayedMonth = 11; } else { this.displayedMonth--; } this.dispatchScrollingEvent(DateChooserScrollEventDetail.PREVIOUS_MONTH); } private dispatchScrollingEvent(detail:string):void { this.dispatchEvent(new DateChooserScrollEvent(DateChooserScrollEvent.SCROLL,false,false,detail)); } /** * @private * create column passed to the bodyGrid skinPart */ private updateGridColumn():void { var days:number[] = new Array(); var gridColumnsArray:any[] = [] for(var i:number =0;i<7;i++) { var day:number = (i+this.firstDayOfWeek)%7; var collumn:GridColumn = new GridColumn(); collumn.dataField = DateChooser.dayProps[day]; collumn.headerText = this.dayNames[day]; collumn.labelFunction = this.gridLabelFunction; gridColumnsArray.push(collumn); } this.gridColumns = new ArrayList(gridColumnsArray); } /** * @private * create the dataProvider passed to the bodyGrid skinPart */ private updateGridDataProvider():void { var date:Date = new Date(this.displayedYear,this.displayedMonth,1); var weekObjects:any[] = new Array(6); var currentObject:Object; for (var i:number = 0; i < weekObjects.length; i++) { weekObjects[i] = currentObject = new Object(); } var currentWeek:number = -1; while(date.month == this.displayedMonth) { if(date.day == this.firstDayOfWeek || currentWeek==-1) { currentWeek++; currentObject = weekObjects[currentWeek]; } currentObject[DateChooser.dayProps[date.day]] = new Date(date.time); date.date++; } this.gridDataProvider = new ArrayList(weekObjects); } /** * @private * update the text displayed by the monthLabelDisplay */ private updateMonthText():void { this.currentMonthText = this.monthNames[this.displayedMonth]+this.monthSymbol; } /** * @private * commit the visual selection * @params overrideMonthAndYear * if true, will set the displayedMonth/displayedYear properties * to be sure that the selectedDate is currently displayed */ private commitVisualSelection(overrideMonthAndYear:boolean):void { if(this.selectedDate ) { if(this.displayedMonth != this.selectedDate.month || this.displayedYear != this.selectedDate.fullYear) { if(overrideMonthAndYear) { this.displayedMonth = this.selectedDate.month; this.displayedYear = this.selectedDate.fullYear; } else { this.selectedCellPosition = null; return; } } var date:Date = new Date(this.displayedYear,this.displayedMonth,1); var currentWeek:number = -1. while(date.month == this.displayedMonth) { if(date.day == this.firstDayOfWeek || currentWeek==-1) { currentWeek++; } if(date.date == this.selectedDate.date) { var cellPosition:CellPosition = new CellPosition(); cellPosition.rowIndex = currentWeek; cellPosition.columnIndex = (date.day+this.firstDayOfWeek)%7; this.selectedCellPosition = cellPosition; return; } date.date++; } } else { this.selectedCellPosition = null; } } /** * @private * label function used by gridColumns of the bodyGrud */ private gridLabelFunction(weekObject:Object,column:GridColumn):string { if(weekObject) { var date:Date = weekObject[column.dataField] ; if(date) return String(date.date); } return " "; } /** * @private * return true if the the given date is contained by the current range */ private dateInRange(date:Date, range:Object):boolean { var hasRangeStart:boolean = ( range.hasOwnProperty("rangeStart") && range.rangeStart instanceof Date ) var hasRangeEnd:boolean = ( range.hasOwnProperty("rangeEnd") && range.rangeEnd instanceof Date ) var afterRangeStart:boolean = hasRangeStart && range.rangeStart.time <= date.time; var beforeRangeEnd:boolean = hasRangeEnd && range.rangeEnd.time >= date.time ; if(hasRangeStart && hasRangeEnd) { if(afterRangeStart && beforeRangeEnd) return true; } else if(hasRangeStart) { if(afterRangeStart) return true; } else if(hasRangeEnd) { if(beforeRangeEnd) return true; } return false; } /** * @private * get the date corresponding to a grid cell rowIndex and columnIndex */ private getDateForCell(rowIndex:number,columnIndex:number):Date { if(this.gridDataProvider && this.gridColumns && rowIndex >=0 && rowIndex <7 && columnIndex >=0 && columnIndex < 7) { var week:Object = this.gridDataProvider.getItemAt(rowIndex); var column:GridColumn = this.gridColumns.getItemAt(columnIndex) ; return week[column.dataField]; } return null; } /** * @private * return true if the date is currently selectable in compiliance with * the disabledDays, disabledRanges and selectableRange properties */ private isEnableddDate(date:Date):boolean { if(!date) return false; if(this.disabledDays && this.disabledDays.indexOf(date.day)!=-1) return false; if(this.disabledRanges) { for (var i in this.disabledRanges) { var range:any = this.disabledRanges[i]; if(range instanceof Date && date.time == range.time) { return false; } else if(range instanceof Object && this.dateInRange(date,range)) { return false; } } for(i in this.disabledRanges) { var range:any = this.disabledRanges[i]; if(range instanceof Date && date.time == range.time) { return false; } else if(range instanceof Object && this.dateInRange(date,range)) { return false; } } } if(this.selectableRange && !this.dateInRange(date,this.selectableRange)) { return false; } return true; } /** * @private */ private dispatchChangeEvent(event:string):void { if(this.hasEventListener(event)) this.dispatchEvent(new Event(event)); } /** * @private * This method scrubs out time values from incoming date objects */ private scrubTimeValue(value:Object):Object { if (value instanceof Date) { return new Date(value.getFullYear(), value.getMonth(), value.getDate()); } else if (value instanceof Object) { var range:Object = {}; if (value.rangeStart) { range.rangeStart = new Date(value.rangeStart.getFullYear(), value.rangeStart.getMonth(), value.rangeStart.getDate()); } if (value.rangeEnd) { range.rangeEnd = new Date(value.rangeEnd.getFullYear(), value.rangeEnd.getMonth(), value.rangeEnd.getDate()); } return range; } return null; } /** * @private * This method scrubs out time values from incoming date objects */ private scrubTimeValues(values:any[]):any[] { var dates:any[] = []; for (var i:number = 0; i < values.length; i++) { dates[i] = this.scrubTimeValue(values[i]); } return dates; } } }