| //////////////////////////////////////////////////////////////////////////////// |
| // |
| // Licensed to the Apache Software Foundation (ASF) under one or more |
| // contributor license agreements. See the NOTICE file distributed with |
| // this work for additional information regarding copyright ownership. |
| // The ASF licenses this file to You under the Apache License, Version 2.0 |
| // (the "License"); you may not use this file except in compliance with |
| // the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| // |
| //////////////////////////////////////////////////////////////////////////////// |
| |
| package mx.controls |
| { |
| |
| import flash.display.DisplayObject; |
| import flash.events.Event; |
| import flash.events.KeyboardEvent; |
| import flash.events.MouseEvent; |
| import flash.geom.Point; |
| import flash.text.TextLineMetrics; |
| import flash.ui.Keyboard; |
| import flash.utils.describeType; |
| import flash.utils.getQualifiedClassName; |
| |
| import mx.core.IFlexDisplayObject; |
| import mx.core.IFlexModuleFactory; |
| import mx.core.IFontContextComponent; |
| import mx.core.IUITextField; |
| import mx.core.UIComponent; |
| import mx.core.UITextField; |
| import mx.core.mx_internal; |
| import mx.events.CalendarLayoutChangeEvent; |
| import mx.events.DateChooserEvent; |
| import mx.events.DateChooserEventDetail; |
| import mx.managers.IFocusManagerComponent; |
| import mx.skins.halo.DateChooserIndicator; |
| import mx.styles.ISimpleStyleClient; |
| |
| use namespace mx_internal; |
| |
| //-------------------------------------- |
| // Styles |
| //-------------------------------------- |
| |
| include "../styles/metadata/GapStyles.as" |
| include "../styles/metadata/LeadingStyle.as" |
| include "../styles/metadata/PaddingStyles.as" |
| include "../styles/metadata/TextStyles.as" |
| |
| /** |
| * Number of pixels between the component's top border |
| * and the top edge of its content area. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| [Style(name="paddingTop", type="Number", format="Length", inherit="no")] |
| |
| /** |
| * Number of pixels between the component's bottom border |
| * and the bottom edge of its content area. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| [Style(name="paddingBottom", type="Number", format="Length", inherit="no")] |
| |
| /** |
| * Name of the skin for the <code>rollOverIndicator</code>. |
| * It can be customized to some other shape other than rectangular. |
| * If you want to change just the color, |
| * use the <code>rollOverColor</code> instead. |
| * The default value is the DateChooserRollOverIndicator class. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| [Style(name="rollOverIndicatorSkin", type="Class", inherit="no")] |
| |
| /** |
| * Name of the skin for <code>selectionIndicator</code>. |
| * It can customized to some other shape other than rectangular. |
| * If one just needs to change color, |
| * use the <code>selectionColor</code> instead. |
| * The default value is the DateChooserSelectionIndicator class. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| [Style(name="selectionIndicatorSkin", type="Class", inherit="no")] |
| |
| /** |
| * Color of the background of today's date. |
| * The default value is <code>0x818181</code>. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| [Style(name="todayColor", type="uint", format="Color", inherit="yes")] |
| |
| /** |
| * Name of the skin for <code>todayIndicator</code> style property. It can be customized |
| * to some other shape other than rectangular. If you |
| * want to change just the color, use the <code>todayColor</code> style property instead. |
| * The default value is the DateChooserTodayIndicator class. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| [Style(name="todayIndicatorSkin", type="Class", inherit="no")] |
| |
| /** |
| * Name of the style sheet definition to configure the appearence of the current day's |
| * numeric text, which is highlighted |
| * in the control when the <code>showToday</code> property is <code>true</code>. |
| * Specify a "color" style to change the font color. |
| * If omitted, the current day text inherits |
| * the text styles of the control. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| [Style(name="todayStyleName", type="String", inherit="no")] |
| |
| /** |
| * Name of the style sheet definition to configure the weekday names of |
| * the control. If omitted, the weekday names inherit the text |
| * styles of the control. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| [Style(name="weekDayStyleName", type="String", inherit="no")] |
| |
| //-------------------------------------- |
| // Other metadata |
| //-------------------------------------- |
| |
| [ExcludeClass] |
| |
| [ResourceBundle("controls")] |
| |
| /** |
| * @private |
| * The CalendarLayout class handles the layout of the date grid in a month. |
| * CalendarLayout can be extended to develop DateControls with |
| * single month display control or side-by-side month displays. |
| * |
| * @see mx.styles.StyleManager |
| */ |
| public class CalendarLayout extends UIComponent |
| implements IFocusManagerComponent, IFontContextComponent |
| { |
| include "../core/Version.as"; |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Constructor |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * Constructor. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function CalendarLayout() |
| { |
| super(); |
| |
| addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler); |
| addEventListener(MouseEvent.MOUSE_OVER, mouseOverHandler); |
| addEventListener(MouseEvent.MOUSE_OUT, mouseOutHandler); |
| } |
| |
| private static const START_END:int = 1; |
| private static const START_ONLY:int = 2; |
| private static const END_ONLY:int = 3; |
| private static const SINGLE_DATE:int = 4; |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Variables |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| */ |
| private var todayRow:int = -1; |
| |
| /** |
| * @private |
| */ |
| private var todayColumn:int = -1; |
| |
| /** |
| * @private |
| */ |
| private var enabledDaysInMonth:Array = []; |
| |
| /** |
| * @private |
| */ |
| private var disabledRangeMode:Array; |
| |
| /** |
| * @private |
| */ |
| private var cellHeight:Number = 14; |
| |
| /** |
| * @private |
| */ |
| private var cellWidth:Number = 14; |
| |
| /** |
| * @private |
| */ |
| private var yOffset:Number = -1; |
| |
| /** |
| * @private |
| */ |
| mx_internal var dayBlocksArray:Array = []; |
| |
| /** |
| * @private |
| */ |
| private var disabledArrays:Array = []; // An Array of Arrays |
| |
| /** |
| * @private |
| */ |
| private var todaysLabelReference:IUITextField = null; |
| |
| /** |
| * @private |
| */ |
| private var selectedMonthYearChanged:Boolean = false; |
| |
| /** |
| * @private |
| */ |
| private var todayIndicator:IFlexDisplayObject; |
| |
| /** |
| * @private |
| */ |
| private var selectionIndicator:Array = []; |
| |
| /** |
| * @private |
| */ |
| private var rollOverIndicator:IFlexDisplayObject; |
| |
| /** |
| * @private |
| */ |
| private var selectedRangeCount:int = 0; |
| |
| /** |
| * @private |
| */ |
| private var lastSelectedDate:Date; |
| |
| /** |
| * @private |
| */ |
| private var rangeStartDate:Date = null; |
| |
| /** |
| * @private |
| */ |
| mx_internal var selRangeMode:int = START_END; |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Overridden properties |
| // |
| //-------------------------------------------------------------------------- |
| |
| //---------------------------------- |
| // enabled |
| //---------------------------------- |
| |
| /** |
| * @private |
| * Storage for the displayedYear property. |
| */ |
| private var _enabled:Boolean = true; |
| |
| /** |
| * @private |
| */ |
| private var enabledChanged:Boolean = false; |
| |
| [Inspectable(category="General", defaultValue="true")] |
| |
| /** |
| * @private |
| */ |
| override public function get enabled():Boolean |
| { |
| return _enabled; |
| } |
| |
| /** |
| * @private |
| */ |
| override public function set enabled(value:Boolean):void |
| { |
| super.enabled = value; |
| |
| _enabled = value; |
| enabledChanged = true; |
| |
| invalidateProperties(); |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Properties |
| // |
| //-------------------------------------------------------------------------- |
| |
| //---------------------------------- |
| // allowDisjointSelection |
| //---------------------------------- |
| |
| /** |
| * @private |
| * Storage for the allowDisjointSelection property. |
| */ |
| private var _allowDisjointSelection:Boolean = true; |
| |
| [Inspectable(category="General", defaultValue="true")] |
| |
| /** |
| * @private |
| */ |
| public function get allowDisjointSelection():Boolean |
| { |
| return _allowDisjointSelection; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set allowDisjointSelection(value:Boolean):void |
| { |
| _allowDisjointSelection = value; |
| } |
| |
| //---------------------------------- |
| // allowMultipleSelection |
| //---------------------------------- |
| |
| /** |
| * @private |
| * Storage for the allowMultipleSelection property. |
| */ |
| private var _allowMultipleSelection:Boolean = false; |
| |
| [Inspectable(category="General", defaultValue="false")] |
| |
| /** |
| * @private |
| */ |
| public function get allowMultipleSelection():Boolean |
| { |
| return _allowMultipleSelection; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set allowMultipleSelection(value:Boolean):void |
| { |
| _allowMultipleSelection = value; |
| } |
| |
| //---------------------------------- |
| // dayNames |
| //---------------------------------- |
| |
| /** |
| * @private |
| * Storage for the dayNames property. |
| */ |
| private var _dayNames:Array; |
| |
| /** |
| * @private |
| */ |
| private var dayNamesChanged:Boolean = false; |
| |
| /** |
| * @private |
| */ |
| private var dayNamesOverride:Array; |
| |
| [Inspectable(category="Other", arrayType="String", defaultValue="null")] |
| |
| /** |
| * @private |
| */ |
| public function get dayNames():Array |
| { |
| return _dayNames; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set dayNames(value:Array):void |
| { |
| dayNamesOverride = value; |
| |
| _dayNames = value != null ? |
| value : |
| resourceManager.getStringArray( |
| "controls", "dayNamesShortest"); |
| |
| // _dayNames will be null if there are no resources. |
| _dayNames = _dayNames ? _dayNames.slice(0) : null; |
| |
| dayNamesChanged = true; |
| |
| invalidateProperties(); |
| invalidateSize(); |
| invalidateDisplayList(); |
| } |
| |
| //---------------------------------- |
| // disabledDays |
| //---------------------------------- |
| |
| /** |
| * @private |
| * Storage for the disabledDays property. |
| */ |
| private var _disabledDays:Array = []; |
| |
| [Inspectable(category="General", arrayType="int")] |
| |
| /** |
| * @private |
| */ |
| public function get disabledDays():Array |
| { |
| var result:Array = []; |
| |
| for (var i:int = 0, k:int = 0; i < _disabledDays.length; i++) |
| { |
| if (_disabledDays[i] >= 0 && _disabledDays[i] <= 6) |
| { |
| result[k] = _disabledDays[i]; |
| k++; |
| } |
| } |
| |
| return result; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set disabledDays(value:Array):void |
| { |
| _disabledDays = value.slice(0); |
| selectedMonthYearChanged = true; |
| |
| invalidateProperties(); |
| |
| // This removes the disabled ranges/days from the selected ranges. |
| var selRange:Array = selectedRanges; |
| } |
| |
| //---------------------------------- |
| // disabledRanges |
| //---------------------------------- |
| |
| /** |
| * @private |
| * Storage for the disabledRanges property. |
| */ |
| private var _disabledRanges:Array = []; |
| |
| [Inspectable(category="General", arrayType="Object")] |
| |
| /** |
| * @private |
| */ |
| public function get disabledRanges():Array |
| { |
| return _disabledRanges.slice(0); |
| } |
| |
| /** |
| * @private |
| */ |
| public function set disabledRanges(value:Array):void |
| { |
| _disabledRanges = value.slice(0); |
| disabledRangeMode = []; |
| |
| for (var i:int = 0; i < _disabledRanges.length; i++) |
| { |
| if (_disabledRanges[i] is Date) |
| { |
| disabledRangeMode[i] = SINGLE_DATE; |
| _disabledRanges[i] = new Date(value[i].getFullYear(), |
| value[i].getMonth(), |
| value[i].getDate()); |
| } |
| else if (_disabledRanges[i] is Object) |
| { |
| _disabledRanges[i] = {}; |
| _disabledRanges[i] = value[i]; |
| |
| if (!_disabledRanges[i].rangeStart && |
| _disabledRanges[i].rangeEnd) |
| { |
| disabledRangeMode[i] = END_ONLY; |
| } |
| else if (_disabledRanges[i].rangeStart && |
| !_disabledRanges[i].rangeEnd) |
| { |
| disabledRangeMode[i] = START_ONLY; |
| } |
| else if (_disabledRanges[i].rangeStart && |
| _disabledRanges[i].rangeEnd) |
| { |
| disabledRangeMode[i] = START_END; |
| } |
| } |
| } |
| |
| selectedMonthYearChanged = true; |
| |
| invalidateProperties(); |
| |
| // To remove the disabled ranges/days from the selected ranges. |
| var selRange:Array=selectedRanges; |
| } |
| |
| //---------------------------------- |
| // displayedMonth |
| //---------------------------------- |
| |
| /** |
| * @private |
| * Storage for the displayedMonth property. |
| */ |
| private var _displayedMonth:int = (new Date()).getMonth(); |
| |
| /** |
| * @private |
| * Holds the proposed value of displayedMonth until it can be verified in commitProperties |
| */ |
| private var _proposedDisplayedMonth:int = -1; |
| |
| [Inspectable(category="General", defaultValue="0")] |
| |
| /** |
| * @private |
| */ |
| public function get displayedMonth():int |
| { |
| return _proposedDisplayedMonth == -1 ? _displayedMonth : _proposedDisplayedMonth; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set displayedMonth(value:int):void |
| { |
| if (value < 0 || value > 11) |
| return; |
| |
| if (value == _proposedDisplayedMonth) |
| return; |
| |
| _proposedDisplayedMonth = value; |
| selectedMonthYearChanged = true; |
| invalidateProperties(); |
| } |
| |
| //---------------------------------- |
| // displayedYear |
| //---------------------------------- |
| |
| /** |
| * @private |
| * Storage for the displayedYear property. |
| */ |
| private var _displayedYear:int = (new Date()).getFullYear(); |
| |
| /** |
| * @private |
| * Holds the proposed value of displayedYear until it can be verified in commitProperties |
| */ |
| private var _proposedDisplayedYear:int = -1; |
| |
| [Inspectable(category="General", defaultValue="2014")] |
| |
| /** |
| * @private |
| */ |
| public function get displayedYear():int |
| { |
| return _proposedDisplayedYear == -1 ? _displayedYear : _proposedDisplayedYear; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set displayedYear(value:int):void |
| { |
| if (value <= 0) |
| return; |
| |
| if (value == _displayedYear) |
| return; |
| |
| _proposedDisplayedYear = value; |
| selectedMonthYearChanged = true; |
| invalidateProperties(); |
| } |
| |
| //---------------------------------- |
| // firstDayOfWeek |
| //---------------------------------- |
| |
| /** |
| * @private |
| * Storage for the firstDayOfWeek property. |
| */ |
| private var _firstDayOfWeek:int = 0; // Sunday |
| |
| [Inspectable(category="General", defaultValue="0")] |
| |
| /** |
| * @private |
| */ |
| public function get firstDayOfWeek():int |
| { |
| return _firstDayOfWeek; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set firstDayOfWeek(value:int):void |
| { |
| if (value < 0 || value > 6) |
| return; |
| |
| if (value == _firstDayOfWeek) |
| return; |
| |
| _firstDayOfWeek = value; |
| dayNamesChanged = true; |
| selectedMonthYearChanged = true; |
| |
| invalidateProperties(); |
| } |
| |
| //---------------------------------- |
| // fontContext |
| //---------------------------------- |
| |
| /** |
| * @private |
| */ |
| public function get fontContext():IFlexModuleFactory |
| { |
| return moduleFactory; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set fontContext(moduleFactory:IFlexModuleFactory):void |
| { |
| this.moduleFactory = moduleFactory; |
| } |
| |
| //---------------------------------- |
| // selectableRange |
| //---------------------------------- |
| |
| /** |
| * @private |
| * Storage for the selectableRange property. |
| */ |
| private var _selectableRange:Object = null; |
| |
| [Inspectable(category="General")] |
| |
| /** |
| * @private |
| */ |
| public function get selectableRange():Object |
| { |
| return _selectableRange; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set selectableRange(value:Object):void |
| { |
| if (!value) |
| { |
| _selectableRange = null; |
| selectedMonthYearChanged = true; |
| invalidateProperties(); |
| return; |
| } |
| |
| var todaysDate:Date = new Date(); |
| var todaysMonth:int = todaysDate.getMonth(); |
| var todaysYear:int = todaysDate.getFullYear(); |
| var callMonth:int; |
| var callYear:int; |
| |
| if (value is Date) |
| { |
| selRangeMode = SINGLE_DATE; |
| |
| _selectableRange = new Date(value.getFullYear(), |
| value.getMonth(), |
| value.getDate()); |
| |
| callMonth = value.getMonth(); |
| callYear = value.getFullYear(); |
| } |
| else if (value is Object) |
| { |
| _selectableRange = {}; |
| |
| if (!value.rangeStart && value.rangeEnd) |
| { |
| selRangeMode = END_ONLY; |
| _selectableRange.rangeEnd = value.rangeEnd; |
| |
| if (todaysYear <= _selectableRange.rangeEnd.getFullYear()) |
| { |
| if (todaysMonth >= _selectableRange.rangeEnd.getMonth()) |
| { |
| callMonth = _selectableRange.rangeEnd.getMonth(); |
| callYear = _selectableRange.rangeEnd.getFullYear(); |
| } |
| else if (todaysMonth <= |
| _selectableRange.rangeEnd.getMonth()) |
| { |
| callMonth = todaysMonth; |
| callYear = todaysYear; |
| } |
| } |
| else if (todaysYear > _selectableRange.rangeEnd.getFullYear()) |
| { |
| callMonth = _selectableRange.rangeEnd.getMonth(); |
| callYear = _selectableRange.rangeEnd.getFullYear(); |
| } |
| |
| } |
| else if (!value.rangeEnd && value.rangeStart) |
| { |
| selRangeMode = START_ONLY; |
| _selectableRange.rangeStart = value.rangeStart; |
| |
| if (todaysYear >= _selectableRange.rangeStart.getFullYear()) |
| { |
| if (todaysMonth <= _selectableRange.rangeStart.getMonth()) |
| { |
| callMonth = _selectableRange.rangeStart.getMonth(); |
| callYear = _selectableRange.rangeStart.getFullYear(); |
| } |
| else if (todaysMonth >= |
| _selectableRange.rangeStart.getMonth()) |
| { |
| callMonth = todaysMonth; |
| callYear = todaysYear; |
| } |
| } |
| else if (todaysYear < _selectableRange.rangeStart.getFullYear()) |
| { |
| callMonth = _selectableRange.rangeStart.getMonth(); |
| callYear = _selectableRange.rangeStart.getFullYear(); |
| } |
| } |
| else if (value.rangeStart && value.rangeEnd) |
| { |
| selRangeMode = START_END; |
| _selectableRange.rangeStart = value.rangeStart; |
| _selectableRange.rangeEnd = value.rangeEnd; |
| |
| if (todaysDate >= _selectableRange.rangeStart && |
| todaysDate <= _selectableRange.rangeEnd) |
| { |
| callMonth = todaysMonth; |
| callYear = todaysYear; |
| } |
| else if (todaysDate < _selectableRange.rangeStart) |
| { |
| callMonth = _selectableRange.rangeStart.getMonth(); |
| callYear = _selectableRange.rangeStart.getFullYear(); |
| } |
| else if (todaysDate > _selectableRange.rangeEnd) |
| { |
| callMonth = _selectableRange.rangeEnd.getMonth(); |
| callYear = _selectableRange.rangeEnd.getFullYear(); |
| } |
| } |
| } |
| |
| _displayedMonth = callMonth; |
| _displayedYear = callYear; |
| |
| selectedMonthYearChanged = true; |
| invalidateProperties(); |
| |
| // This removes the non-selectable ranges from the selected ranges. |
| var selRange:Array = selectedRanges; |
| } |
| |
| //---------------------------------- |
| // selectedRanges |
| //---------------------------------- |
| |
| /** |
| * @private |
| * Storage for the selectableRange property. |
| */ |
| private var _selectedRanges:Array = []; |
| |
| [Inspectable(category="General", arrayType="Object")] |
| |
| /** |
| * @private |
| */ |
| public function get selectedRanges():Array |
| { |
| if (_selectableRange) |
| { |
| switch (selRangeMode) |
| { |
| case START_END: |
| { |
| removeRangeFromSelection(null, addSubtractDays(_selectableRange.rangeStart, -1)); |
| removeRangeFromSelection(addSubtractDays(_selectableRange.rangeEnd, +1), null); |
| break; |
| } |
| |
| case START_ONLY: |
| case END_ONLY: |
| { |
| removeRangeFromSelection(addSubtractDays(_selectableRange.rangeStart, -1), |
| addSubtractDays(_selectableRange.rangeEnd, +1)); |
| break; |
| } |
| |
| case SINGLE_DATE: |
| { |
| removeDayFromSelection(_selectableRange as Date); |
| break; |
| } |
| } |
| } |
| |
| var i:int; |
| |
| for (i = 0; i < _disabledRanges.length; i++) |
| { |
| switch (disabledRangeMode[i]) |
| { |
| case START_END: |
| case START_ONLY: |
| case END_ONLY: |
| { |
| removeRangeFromSelection(_disabledRanges[i].rangeStart, _disabledRanges[i].rangeEnd); |
| break; |
| } |
| |
| case SINGLE_DATE: |
| { |
| removeDayFromSelection(_disabledRanges[i]); |
| break; |
| } |
| } |
| } |
| |
| if (_disabledDays.length > 0 && selectedRangeCount) |
| { |
| var minDate:Date = _selectedRanges[0].rangeStart; |
| var maxDate:Date = _selectedRanges[0].rangeEnd; |
| |
| for (i = 1; i < selectedRangeCount; i++) |
| { |
| if (minDate > _selectedRanges[i].rangeStart) |
| minDate = _selectedRanges[i].rangeStart; |
| |
| if (maxDate < _selectedRanges[i].rangeEnd) |
| maxDate = _selectedRanges[i].rangeEnd; |
| } |
| |
| for (i = 0; i < _disabledDays.length; i++) |
| { |
| var tempDate:Date = minDate; |
| |
| var dayOffset:int = _disabledDays[i] - tempDate.getDay(); |
| |
| if (dayOffset < 0) |
| dayOffset += 7; |
| |
| tempDate = addSubtractDays(tempDate, dayOffset); |
| |
| while (tempDate < maxDate) |
| { |
| removeDayFromSelection(tempDate); |
| tempDate = addSubtractDays(tempDate, 7); |
| } |
| } |
| } |
| |
| _selectedRanges.length = selectedRangeCount; |
| return _selectedRanges; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set selectedRanges(value:Array):void |
| { |
| _selectedRanges = value; |
| |
| selectedRangeCount = _selectedRanges.length; |
| |
| setSelectedIndicators(); |
| } |
| |
| //---------------------------------- |
| // showToday |
| //---------------------------------- |
| |
| /** |
| * @private |
| * Storage for the showToday property. |
| */ |
| private var _showToday:Boolean = true; |
| |
| [Inspectable(category="General", defaultValue="true")] |
| |
| /** |
| * @private |
| */ |
| public function get showToday():Boolean |
| { |
| return _showToday; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set showToday(value:Boolean):void |
| { |
| if (_showToday != value) |
| _showToday = value; |
| |
| selectedMonthYearChanged = true; |
| |
| invalidateProperties(); |
| } |
| |
| //---------------------------------- |
| // selectedDate |
| //---------------------------------- |
| |
| [Inspectable(category="General", defaultValue="null")] |
| |
| /** |
| * @private |
| */ |
| public function get selectedDate():Date |
| { |
| return selectedRangeCount ? _selectedRanges[0].rangeStart : null; |
| } |
| |
| /** |
| * @private |
| */ |
| public function set selectedDate(value:Date):void |
| { |
| selectedRangeCount = 0; |
| |
| if (value && !checkDateIsDisabled(value)) |
| { |
| addToSelected(value); |
| |
| _displayedMonth = value.getMonth(); |
| _displayedYear = value.getFullYear(); |
| selectedMonthYearChanged = true; |
| |
| invalidateProperties(); |
| } |
| else |
| { |
| setSelectedIndicators(); |
| } |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Overridden methods |
| // |
| //-------------------------------------------------------------------------- |
| |
| /* |
| |
| A note about DayBlocks: |
| |
| dayBlock0..dayBlock6 are skins for the 7 grid columns. |
| They are dynamically created instances of the "DayBlock" symbol. |
| Three additional properties are set when each dayBlock is created |
| in createChildren(): |
| |
| columnIndex:int (0-6) |
| keeps track of where this dayBlock is in the grid |
| |
| selectedArray:Array |
| 7 elements, one for each row |
| selectedArray[rowIndex] is true |
| if that row in the dayBlock is selected |
| |
| disabledArray:Array |
| 7 elements, one for each row |
| disabledArray[rowIndex] is true |
| if that row in the dayBlock is disabled |
| |
| Additional properties are created dynamically to hold the skins |
| for selected and disabled rows in the dayBlock: |
| |
| selectedSkin0..selectedSkin6 |
| |
| disabledSkin0..disabledSkin6 |
| |
| */ |
| |
| /** |
| * @private |
| * Everything that gets initially created now exists. |
| * Some things, such as the selection skins and disabled skins, |
| * are created later as they are needed. |
| * Set the "S", "M", etc. labels in the first row. |
| * |
| * Set the day-number labels ("1".."31") in the other rows. |
| * This method also displays the selection skins, |
| * the disabled skins, and the "today" indicator. |
| */ |
| override protected function createChildren():void |
| { |
| super.createChildren(); |
| |
| var labelPosition:Number = 0; |
| |
| createDayLabels(-1); |
| createTodayIndicator(0); |
| |
| if (!rollOverIndicator) |
| { |
| var rollOverIndicatorClass:Class = getStyle("rollOverIndicatorSkin"); |
| if (!rollOverIndicatorClass) |
| rollOverIndicatorClass = DateChooserIndicator; |
| rollOverIndicator = IFlexDisplayObject(new rollOverIndicatorClass()); |
| // too lazy to make an interface for this. |
| if (isDateChooserIndicator(rollOverIndicator)) |
| Object(rollOverIndicator).indicatorColor = "rollOverColor"; |
| if (rollOverIndicator is ISimpleStyleClient) |
| ISimpleStyleClient(rollOverIndicator).styleName = this; |
| addChildAt(DisplayObject(rollOverIndicator), 0); |
| rollOverIndicator.visible = false; |
| } |
| |
| // Wait for all of the properties to be set before calling setSelectedMonthAndYear |
| dayNamesChanged = true; |
| selectedMonthYearChanged = true; |
| } |
| |
| /** |
| * @private |
| */ |
| override protected function commitProperties():void |
| { |
| super.commitProperties(); |
| |
| if (hasFontContextChanged() && todayIndicator != null) |
| { |
| // Re-create the children so we can display |
| // the embedded font from the new font context. |
| removeSelectionIndicators(); |
| |
| var childIndex:int = getChildIndex(DisplayObject(todayIndicator)); |
| removeTodayIndicator(); |
| createTodayIndicator(childIndex); |
| |
| childIndex = getChildIndex(dayBlocksArray[0][0]); |
| removeDayLabels(); |
| createDayLabels(childIndex); |
| |
| enabledChanged = true; |
| dayNamesChanged = true; |
| selectedMonthYearChanged = true; |
| } |
| |
| if (enabledChanged) |
| { |
| enabledChanged = false; |
| |
| for (var o:int = 0; o < 7; o++) |
| { |
| for (var r:int = 0; r < 7; r++) |
| { |
| dayBlocksArray[o][r].enabled = _enabled; |
| disabledArrays[o][r] = _enabled; |
| } |
| } |
| |
| if (!_enabled) |
| { |
| |
| if (todayIndicator) |
| todayIndicator.alpha = 0.3; |
| |
| // Remove the mouse event listeners |
| removeEventListener(MouseEvent.MOUSE_UP, mouseUpHandler); |
| removeEventListener(MouseEvent.MOUSE_OVER, mouseOverHandler); |
| removeEventListener(MouseEvent.MOUSE_OUT, mouseOutHandler); |
| removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler); |
| } |
| else |
| { |
| if (todayIndicator) |
| todayIndicator.alpha = 1.0; |
| |
| selectedMonthYearChanged = true; |
| |
| // Restore the mouse event listeners |
| addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler); |
| addEventListener(MouseEvent.MOUSE_OVER, mouseOverHandler); |
| addEventListener(MouseEvent.MOUSE_OUT, mouseOutHandler); |
| addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler); |
| } |
| } |
| |
| if (dayNamesChanged) |
| { |
| dayNamesChanged = false; |
| |
| drawDayNames(); |
| } |
| |
| if (selectedMonthYearChanged) |
| { |
| selectedMonthYearChanged = false; |
| |
| var proposedDate:Date = |
| new Date(_proposedDisplayedYear == -1 ? _displayedYear : _proposedDisplayedYear, |
| _proposedDisplayedMonth == -1 ? _displayedMonth : _proposedDisplayedMonth); |
| |
| if (isDateInRange(proposedDate, _selectableRange, selRangeMode, true)) |
| { |
| setSelectedMonthAndYear(); |
| } |
| |
| _proposedDisplayedYear = -1; |
| _proposedDisplayedMonth = -1; |
| } |
| } |
| |
| /** |
| * @private |
| */ |
| override protected function measure():void |
| { |
| super.measure(); |
| |
| var verticalGap:Number = getStyle("verticalGap"); |
| var horizontalGap:Number = getStyle("horizontalGap"); |
| |
| var paddingLeft:Number = getStyle("paddingLeft"); |
| var paddingRight:Number = getStyle("paddingRight"); |
| var paddingBottom:Number = getStyle("paddingBottom"); |
| var paddingTop:Number = getStyle("paddingTop"); |
| |
| var lineMetrics:TextLineMetrics; |
| |
| cellWidth = 0; |
| cellHeight = 0; |
| |
| for (var dayOfWeek:int = 0; dayOfWeek < 7; dayOfWeek++) |
| { |
| // dayNames will be null if there are no resources. |
| var dayName:String = dayNames ? dayNames[dayOfWeek] : ""; |
| lineMetrics = measureText(dayName); |
| if (lineMetrics.width > cellWidth) |
| cellWidth = lineMetrics.width; |
| if (lineMetrics.height > cellHeight) |
| cellHeight = lineMetrics.height; |
| } |
| |
| lineMetrics = measureText("30"); |
| |
| if (lineMetrics.width > cellWidth) |
| cellWidth = lineMetrics.width; |
| |
| if (lineMetrics.height > cellHeight) |
| cellHeight = lineMetrics.height; |
| |
| measuredWidth = paddingLeft + horizontalGap * 6 + |
| cellWidth * 7 + paddingRight; |
| measuredHeight = verticalGap * 6 + cellHeight * 7 + |
| paddingBottom + paddingTop; |
| measuredMinWidth = cellWidth * 7; |
| measuredMinHeight = cellHeight * 7; |
| } |
| |
| /** |
| * @private |
| */ |
| override protected function updateDisplayList(unscaledWidth:Number, |
| unscaledHeight:Number):void |
| { |
| super.updateDisplayList(unscaledWidth, unscaledHeight); |
| |
| //var verticalGap:Number = getStyle("verticalGap"); |
| //var horizontalGap:Number = getStyle("horizontalGap"); |
| |
| var paddingLeft:Number = getStyle("paddingLeft"); |
| var paddingRight:Number = getStyle("paddingRight"); |
| var paddingBottom:Number = getStyle("paddingBottom"); |
| var paddingTop:Number = getStyle("paddingTop"); |
| |
| var blockX:Number = paddingLeft; |
| |
| // Bug 134794, clip height/width so that RTE's are not thrown |
| cellWidth = Math.max((unscaledWidth - (paddingLeft + paddingRight))/7, 4); |
| cellHeight = Math.max((unscaledHeight - paddingBottom)/7, 4); |
| |
| var labelPosition:Number = paddingTop; |
| |
| rollOverIndicator.setActualSize(cellWidth, cellHeight); |
| todayIndicator.setActualSize(cellWidth, cellHeight); |
| |
| for (var columnIndex:int = 0; columnIndex < 7; columnIndex++) |
| { |
| // Remember the height of the cells if not set by user. |
| // Create the 7 labels within each DayBlock. |
| // The first row in each column displays a day name string, such as "Sun". |
| // The other six rows displays day numbers in the range 1-31. |
| |
| for (var rowIndex:int = 0; rowIndex < 7; rowIndex++) |
| { |
| var label:IUITextField = dayBlocksArray[columnIndex][rowIndex]; |
| if (rowIndex == 0) |
| labelPosition = paddingTop; |
| else |
| labelPosition += cellHeight; |
| |
| label.setActualSize(cellWidth, cellHeight); |
| label.move(blockX, labelPosition); |
| |
| if (selectionIndicator[columnIndex][rowIndex]) |
| { |
| selectionIndicator[columnIndex][rowIndex].setActualSize(cellWidth, cellHeight); |
| selectionIndicator[columnIndex][rowIndex].move(blockX, labelPosition + yOffset); |
| } |
| //label.width = cellWidth; |
| //label.height = cellHeight; |
| //label.x = blockX; |
| //label.y = labelPosition; |
| } |
| |
| blockX += cellWidth; |
| } |
| |
| drawDayNames(); |
| setSelectedMonthAndYear(); |
| } |
| |
| /** |
| * @private |
| */ |
| override public function styleChanged(styleProp:String):void |
| { |
| var allStyles:Boolean = !styleProp || styleProp == "styleName"; |
| |
| if (allStyles || styleProp == "todayStyleName") |
| { |
| selectedMonthYearChanged = true; |
| invalidateProperties(); |
| } |
| |
| if (allStyles || styleProp == "weekDayStyleName") |
| { |
| var weekDayStyleName:Object = getStyle("weekDayStyleName"); |
| if (!weekDayStyleName) |
| weekDayStyleName = this; |
| |
| if (dayBlocksArray) |
| { |
| for (var i:int = 0; i < 7; i++) |
| { |
| // Set the styleName on the top row of day name labels |
| if (dayBlocksArray[i] && dayBlocksArray[i][0]) |
| dayBlocksArray[i][0].styleName = weekDayStyleName; |
| } |
| } |
| } |
| |
| super.styleChanged(styleProp); |
| } |
| |
| /** |
| * @private |
| */ |
| override protected function resourcesChanged():void |
| { |
| super.resourcesChanged(); |
| |
| dayNames = dayNamesOverride; |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Methods |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| * Creates the day labels and adds them as children of this component. |
| * |
| * @param childIndex The index of where to add the children. |
| * If -1, the text fields are appended to the end of the list. |
| */ |
| mx_internal function createDayLabels(childIndex:int):void |
| { |
| var weekDayStyleName:Object = getStyle("weekDayStyleName"); |
| |
| // Remember the height of the cells if not set by user. |
| // Create the 7 labels within each DayBlock. |
| // The first row in each column displays a day name string, |
| // such as "Sun". |
| // The other six rows displays day numbers in the range 1-31. |
| |
| // Calendar days |
| for (var columnIndex:int = 0; columnIndex < 7; columnIndex++) |
| { |
| dayBlocksArray[columnIndex] = []; |
| selectionIndicator[columnIndex] = []; |
| |
| for (var rowIndex:int = 0; rowIndex < 7; rowIndex++) |
| { |
| var label:IUITextField = |
| dayBlocksArray[columnIndex][rowIndex] = |
| IUITextField(createInFontContext(UITextField)); |
| |
| label.selectable = false; |
| label.ignorePadding = true; |
| |
| if (childIndex == -1) |
| addChild(DisplayObject(label)); |
| else |
| addChildAt(DisplayObject(label), childIndex++); |
| |
| if (rowIndex == 0) |
| { |
| label.styleName = weekDayStyleName ? |
| weekDayStyleName : |
| this; |
| } |
| else |
| { |
| label.styleName = this; |
| } |
| } |
| |
| disabledArrays[columnIndex] = new Array(7); |
| } |
| } |
| |
| /** |
| * @private |
| * Removes the day labels from this component. |
| */ |
| mx_internal function removeDayLabels():void |
| { |
| for (var columnIndex:int = 0; columnIndex < 7; columnIndex++) |
| { |
| for (var rowIndex:int = 0; rowIndex < 7; rowIndex++) |
| { |
| removeChild(dayBlocksArray[columnIndex][rowIndex]); |
| dayBlocksArray[columnIndex][rowIndex] = null; |
| } |
| } |
| } |
| |
| /** |
| * @private |
| * @param childIndex The index of where to add the child. |
| */ |
| mx_internal function createTodayIndicator(childIndex:int):void |
| { |
| if (!todayIndicator) |
| { |
| var todayIndicatorClass:Class = getStyle("todayIndicatorSkin"); |
| if (!todayIndicatorClass) |
| todayIndicatorClass = DateChooserIndicator; |
| todayIndicator = IFlexDisplayObject(new todayIndicatorClass()); |
| |
| if (isDateChooserIndicator(todayIndicator)) |
| { |
| Object(todayIndicator).indicatorColor = |
| "todayColor"; |
| } |
| if (todayIndicator is ISimpleStyleClient) |
| ISimpleStyleClient(todayIndicator).styleName = this; |
| |
| addChildAt(DisplayObject(todayIndicator), childIndex); |
| |
| todayIndicator.visible = false; |
| } |
| } |
| |
| /** |
| * @private |
| */ |
| mx_internal function removeTodayIndicator():void |
| { |
| if (todayIndicator) |
| { |
| removeChild(DisplayObject(todayIndicator)); |
| todayIndicator = null; |
| } |
| } |
| |
| /** |
| * @private |
| */ |
| mx_internal function drawDayNames():void |
| { |
| for (var columnIndex:int = 0; columnIndex < 7; columnIndex++) |
| { |
| var dayOfWeek:int = (columnIndex + firstDayOfWeek) % 7; |
| // dayNames will be null if there are no resources. |
| var dayName:String = dayNames ? dayNames[dayOfWeek] : ""; |
| dayBlocksArray[columnIndex][0].text = dayName; |
| } |
| } |
| |
| /** |
| * @private |
| */ |
| mx_internal function setSelectedMonthAndYear(monthVal:int = -1, yearVal:int = -1):void |
| { |
| // This lengthy method updates the UI to display a specified month |
| // and year. In particular, it updates the day numbers (1-31) in the grid. |
| |
| // It does NOT update the day names ("Sun", "Mon", etc.), |
| // since these do not change when the month and year change. |
| // |
| // It also takes care of displaying days that are disabled or selected. |
| // Instances of the skins cal_monthDayDisabled (for disabled days) and |
| // cal_monthDaySelected (for selected days) get created as they |
| // are required, to minimize initialization time. |
| |
| var dayNumber:int; // 1 - 31 |
| var columnIndex:int; // 0 - 6 |
| var rowIndex:int; // 1 - 6 |
| var i:int; |
| var displayTodayInCurrentMonth:Boolean = false; |
| var displayDate:Date = null; |
| |
| |
| // When another method needs to redraw the UI without changing the |
| // currently selected month and year (because the firstDayOfWeek |
| // property changed, for example) it calls setSelectedMonthAndYear() |
| // with no arguments. Therefore we need to handle undefined arguments. |
| var newMonth:int = monthVal == -1 ? displayedMonth : monthVal; |
| var newYear:int = yearVal == -1 ? displayedYear : yearVal; |
| |
| // Determine where in the grid the 1st of the month should appear, |
| // how many days are in the month, and today's date. |
| |
| enabledDaysInMonth = []; |
| var offset:int = getOffsetOfMonth(newYear, newMonth); |
| var daysInMonth:int = getNumberOfDaysInMonth(newYear, newMonth); |
| |
| // Determine whether this month contains today. |
| var today:Date = new Date(); |
| var currentMonthContainsToday:Boolean = (today.getFullYear() == newYear && today.getMonth() == newMonth); |
| |
| // Set up the days (if any) in row 1 that come from the previous month. |
| var previousMonth:int = Math.max(newMonth - 1,0); |
| var previousMonthDate:Date = new Date(newYear, previousMonth, 1); |
| dayNumber = getNumberOfDaysInMonth(previousMonthDate.getFullYear(), previousMonthDate.getMonth()); |
| rowIndex = 1; |
| |
| for (columnIndex = 0; columnIndex < offset; columnIndex++) |
| { |
| dayBlocksArray[columnIndex][rowIndex].text = ""; |
| |
| // Disable the day. |
| disabledArrays[columnIndex][rowIndex] = true; |
| |
| removeSelectionIndicator(columnIndex,rowIndex); |
| } |
| |
| // Set up the days of the new month. |
| for (dayNumber = 1; dayNumber <= daysInMonth; dayNumber++) |
| { |
| var cellDate:Date = new Date(newYear, newMonth, dayNumber); |
| i = offset + dayNumber - 1; |
| columnIndex = i % 7; |
| rowIndex = 1 + Math.floor(i / 7); |
| |
| var todayLabel:IUITextField = dayBlocksArray[columnIndex][rowIndex];//this["dayBlock" + columnIndex+"label" + rowIndex]; |
| todayLabel.text = dayNumber.toString(); |
| // Enable the day. |
| |
| if (_enabled) |
| { |
| disabledArrays[columnIndex][rowIndex] = false; |
| todayLabel.enabled = true; |
| } |
| |
| if (!todayLabel.styleName) |
| todayLabel.styleName = this; |
| |
| // Some of these days may be selected. |
| // One of these days may be today's date. |
| if (currentMonthContainsToday && (cellDate.getDate() == today.getDate()) && _showToday) |
| { |
| todayRow = rowIndex; |
| todayColumn = columnIndex; |
| displayTodayInCurrentMonth = true; |
| |
| todayIndicator.visible = _showToday; |
| todayLabel.styleName = getStyle("todayStyleName"); |
| |
| todayIndicator.move(todayLabel.x, todayLabel.y + yOffset); // Don't trigger layout |
| todaysLabelReference = todayLabel; |
| |
| } |
| else |
| { |
| if (!displayTodayInCurrentMonth) |
| { |
| if (todaysLabelReference) |
| { |
| todaysLabelReference.styleName = this; |
| //todaysLabelReference.styleName = this; |
| } |
| todayIndicator.visible = false; |
| } |
| } |
| |
| var cellString:String; |
| |
| // Selectable Range |
| // set up the selectable Range: type: Object/ Date Object |
| // Object Attrib: rangeStart[Date Object], rangeEnd[Date Object] |
| // 1 :: if both attribs are defined |
| // 2 :: If only rangeStart is defined: All dates after the specified date are enabled |
| // 3 :: if only rangeEnd is defined: All dates before ths specified date are enabled |
| // 4 :: If selectable Range param is a Date Object, then only that day has to be defined |
| |
| if (_selectableRange) |
| { |
| if (!isDateInRange(cellDate, _selectableRange, selRangeMode)) |
| { |
| todayLabel.enabled = false; |
| disabledArrays[columnIndex][rowIndex] = true; |
| } |
| } |
| |
| // Disabled Ranges |
| // set up the disabledRanges: type: Array |
| // Array can contain an Object || Date Object. |
| // Attrib for Object: rangeStart[Date Object], rangeEnd[Date Object] |
| // "start"::All dates after the specified date are disabled, including the startDate |
| // "end"::All dates before ths specified date are disabled, including the end Date |
| // "date"::Only that day has to be disabled |
| // "normal"::range is disabled including the start and end date |
| if (_disabledRanges.length > 0) |
| { |
| for (var dRanges:int = 0; dRanges < _disabledRanges.length; dRanges++) |
| { |
| if (isDateInRange(cellDate, _disabledRanges[dRanges], disabledRangeMode[dRanges])) |
| { |
| todayLabel.enabled = false; |
| disabledArrays[columnIndex][rowIndex] = true; |
| } |
| } |
| } |
| |
| var valToPush:Object = {}; |
| if (todayLabel.enabled) |
| { |
| valToPush.name = todayLabel.name; |
| valToPush.text = todayLabel.text; |
| valToPush.x = todayLabel.x; |
| valToPush.y = todayLabel.y; |
| } |
| enabledDaysInMonth.push(valToPush); |
| } |
| |
| // Set up the days (if any) at the end of the grid |
| // that come from the following month. |
| dayNumber = 1; |
| for (i = offset + daysInMonth; i < 42; i++) |
| { |
| columnIndex = i % 7; |
| rowIndex = 1 + Math.floor(i / 7); |
| |
| dayBlocksArray[columnIndex][rowIndex].text = ""; |
| |
| |
| // Disable the day. |
| disabledArrays[columnIndex][rowIndex] = true; |
| removeSelectionIndicator(columnIndex,rowIndex); |
| } |
| |
| if (_disabledDays.length>0) |
| { |
| for (i = 0; i < _disabledDays.length; i++) |
| { |
| if (_disabledDays[i] >= 0 && _disabledDays[i] <= 6 && _disabledDays[i] != -1) |
| { |
| columnIndex = ((7 + _disabledDays[i] - _firstDayOfWeek) % 7); |
| |
| for (rowIndex = 1; rowIndex < 7; rowIndex++) |
| { |
| // Disable the day. |
| disabledArrays[columnIndex][rowIndex] = true; |
| var tempCalcDate:Number = Number(dayBlocksArray[columnIndex][rowIndex].text); |
| var tempOffset:Number; |
| if (!isNaN(tempCalcDate)) |
| { |
| tempOffset = offset + tempCalcDate % 7; |
| enabledDaysInMonth[tempCalcDate-1] = null; |
| } |
| dayBlocksArray[columnIndex][rowIndex].enabled = false; |
| } |
| } |
| } |
| } |
| |
| _displayedMonth = newMonth; |
| _displayedYear = newYear; |
| displayDate = new Date(newYear, newMonth, 1); |
| todayIndicator.alpha = (todaysLabelReference) ? ((todaysLabelReference.enabled == false) ? 0.3 : 1.0) : 1.0; |
| setSelectedIndicators(); |
| invalidateDisplayList(); |
| } |
| |
| /** |
| * @private |
| * Called from setSelectedMonthAndYear() to get an Offset of the starting day of the month |
| */ |
| mx_internal function getOffsetOfMonth(year:int, month:int):int |
| { |
| // Determine whether the 1st of the month is a Sunday, Monday, etc. |
| // and then determine which column of the grid where it appears. |
| var first:Date = new Date(year, month, 1); |
| var offset:int = first.getDay() - _firstDayOfWeek; |
| return offset < 0 ? offset + 7 : offset; |
| } |
| |
| /** |
| * @private |
| */ |
| mx_internal function getNumberOfDaysInMonth(year:int, month:int):int |
| { |
| // "Thirty days hath September..." |
| |
| var n:int; |
| |
| if (month == 1) // Feb |
| { |
| if (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0)) // leap year |
| n = 29; |
| else |
| n = 28; |
| } |
| |
| else if (month == 3 || month == 5 || month == 8 || month == 10) |
| n = 30; |
| |
| else |
| n = 31; |
| |
| return n; |
| } |
| |
| /** |
| * @private |
| */ |
| mx_internal function stepDate(deltaY:int, deltaM:int, triggerEvent:Event = null):void |
| { |
| var oldYear:int = displayedYear; |
| var oldMonth:int = displayedMonth; |
| |
| var newDate:Object = getNewIncrementDate(oldYear, oldMonth, deltaY, deltaM); |
| |
| var newYear:int = newDate.year; |
| var newMonth:int = newDate.month; |
| |
| _displayedMonth = newMonth; |
| _displayedYear = newYear; |
| selectedMonthYearChanged = true; |
| invalidateProperties(); |
| |
| var event:DateChooserEvent = new DateChooserEvent(DateChooserEvent.SCROLL); |
| event.triggerEvent = triggerEvent; |
| if (newYear > oldYear) |
| event.detail = DateChooserEventDetail.NEXT_YEAR; |
| else if (newYear < oldYear) |
| event.detail = DateChooserEventDetail.PREVIOUS_YEAR; |
| else if (newMonth > oldMonth) |
| event.detail = DateChooserEventDetail.NEXT_MONTH; |
| else if (newMonth < oldMonth) |
| event.detail = DateChooserEventDetail.PREVIOUS_MONTH; |
| dispatchEvent(event); |
| } |
| |
| /** |
| * @private Takes a year and a month as well as an increment year and month value |
| * and returns a new valid year/month. |
| */ |
| static mx_internal function getNewIncrementDate(oldYear:int, oldMonth:int, deltaY:int, deltaM:int):Object |
| { |
| var newYear:int = oldYear + deltaY; |
| var newMonth:int = oldMonth + deltaM; |
| |
| while (newMonth < 0) |
| { |
| newYear--; |
| newMonth += 12; |
| } |
| |
| while (newMonth > 11) |
| { |
| newYear++; |
| newMonth -= 12; |
| } |
| |
| return {month: newMonth, year: newYear}; |
| } |
| |
| /** |
| * @private |
| */ |
| mx_internal function dispatchChangeEvent(triggerEvent:Event = null):void |
| { |
| var change:CalendarLayoutChangeEvent = |
| new CalendarLayoutChangeEvent(CalendarLayoutChangeEvent.CHANGE); |
| change.newDate = lastSelectedDate; |
| change.triggerEvent = triggerEvent; |
| dispatchEvent(change); |
| } |
| |
| /** |
| * @private |
| * |
| * Returns true if the date is within the dates specified by the dateRange object. |
| */ |
| mx_internal function isDateInRange(value:Date, dateRange:Object, rangeMode:int, ignoreDay:Boolean = false):Boolean |
| { |
| var result:Boolean = true; |
| |
| if (dateRange) |
| { |
| if (ignoreDay) |
| { |
| var dateRangeCopy:Object = {}; |
| if (dateRange.rangeStart) |
| { |
| var startDate:Date = dateRange.rangeStart; |
| dateRangeCopy.rangeStart = new Date(startDate.fullYear, startDate.month, 1); |
| } |
| if (dateRange.rangeEnd) |
| { |
| var endDate:Date = dateRange.rangeEnd; |
| dateRangeCopy.rangeEnd = new Date(endDate.fullYear, endDate.month, getNumberOfDaysInMonth(endDate.fullYear, endDate.month)); |
| } |
| dateRange = dateRangeCopy; |
| } |
| |
| switch (rangeMode) |
| { |
| case START_END: |
| { |
| if (value < dateRange.rangeStart || |
| value > dateRange.rangeEnd) |
| { |
| result = false; |
| } |
| break; |
| } |
| |
| case START_ONLY: |
| { |
| if (value < dateRange.rangeStart) |
| result = false; |
| break; |
| } |
| |
| case END_ONLY: |
| { |
| if (value > dateRange.rangeEnd) |
| result = false; |
| break; |
| } |
| |
| case SINGLE_DATE: |
| { |
| if (value > dateRange || value < dateRange) |
| result = false; |
| break; |
| } |
| |
| default: |
| { |
| break; |
| } |
| } |
| } |
| |
| return result; |
| } |
| |
| |
| /** |
| * @private |
| * |
| * Checking for valid dates, months and Years before setting them through API |
| * Returns true is date is disabled. null date is considered enabled, |
| * as one can set date to null. |
| */ |
| mx_internal function checkDateIsDisabled(value:Date):Boolean |
| { |
| if (!value) |
| return false; |
| |
| var selectedDateIsDisabled:Boolean = false; |
| |
| if (_selectableRange) |
| { |
| if (!isDateInRange(value, _selectableRange, selRangeMode)) |
| { |
| selectedDateIsDisabled = true; |
| } |
| } |
| |
| if (_disabledRanges.length > 0) |
| { |
| for (var dRanges:int = 0; dRanges < _disabledRanges.length; dRanges++) |
| { |
| if (isDateInRange(value, _disabledRanges[dRanges], disabledRangeMode[dRanges])) |
| { |
| selectedDateIsDisabled = true; |
| } |
| } |
| } |
| |
| if (_disabledDays.length > 0) |
| { |
| for (var i:int = 0; i < _disabledDays.length; i++) |
| { |
| if (value.getDay() == _disabledDays[i]) |
| selectedDateIsDisabled = true; |
| } |
| } |
| |
| return selectedDateIsDisabled; |
| } |
| |
| /** |
| * @private |
| * Adds the newDate to the list of selected dates. |
| * If range is true, a range of dates starting from the previous selection is selected. |
| */ |
| mx_internal function addToSelected(newDate:Date, range:Boolean = false):void |
| { |
| |
| if (selectedRangeCount == 0) |
| rangeStartDate = null; |
| |
| lastSelectedDate = newDate; |
| |
| if (range == false) |
| { |
| _selectedRanges[selectedRangeCount] = {}; |
| _selectedRanges[selectedRangeCount].rangeStart = |
| new Date(newDate); |
| _selectedRanges[selectedRangeCount].rangeEnd = |
| _selectedRanges[selectedRangeCount].rangeStart; |
| selectedRangeCount++; |
| } |
| else |
| { |
| if (selectedRangeCount == 0) |
| { |
| _selectedRanges[0] = {}; |
| _selectedRanges[0].rangeStart = new Date(newDate); |
| } |
| else |
| { |
| selectedRangeCount = 1; |
| |
| if (!rangeStartDate) |
| rangeStartDate = _selectedRanges[0].rangeStart; |
| |
| _selectedRanges[0].rangeStart = new Date(rangeStartDate); |
| |
| if (newDate < _selectedRanges[0].rangeStart) |
| { |
| _selectedRanges[0].rangeEnd = _selectedRanges[0].rangeStart; |
| _selectedRanges[0].rangeStart = new Date(newDate); |
| return; |
| } |
| } |
| |
| _selectedRanges[0].rangeEnd = new Date(newDate); |
| } |
| } |
| |
| /** |
| * @private |
| * Increments/decrements a date by 'No. of days' |
| * specified by amount and returns the new date. |
| */ |
| mx_internal function addSubtractDays(value:Date, amount:int):Date |
| { |
| var newDate:Date = new Date(value); |
| |
| if (value) |
| return new Date(newDate.fullYear, newDate.month, newDate.date + amount); |
| else |
| return null; |
| } |
| |
| /** |
| * @private |
| * Returns true if newDate is selected. |
| */ |
| mx_internal function isSelected(newDate:Date):Boolean |
| { |
| for (var i:int = 0; i < selectedRangeCount; i++) |
| { |
| if (newDate >= _selectedRanges[i].rangeStart && |
| newDate <=_selectedRanges[i].rangeEnd) |
| { |
| return true; |
| } |
| } |
| |
| return false; |
| } |
| |
| /** |
| * @private |
| * Removes the range of dates specified by startDate and endDate |
| * from the selected dates. |
| */ |
| mx_internal function removeRangeFromSelection(startDate:Date, endDate:Date):void |
| { |
| var rangeEnd:Date; |
| var rangeStart:Date; |
| |
| if (endDate < startDate) |
| return; |
| |
| for (var n:int = 0; n < selectedRangeCount; n++) |
| { |
| rangeStart = _selectedRanges[n].rangeStart; |
| rangeEnd = _selectedRanges[n].rangeEnd; |
| |
| // ignore selection range outsie of date range |
| if (endDate < rangeStart || startDate > rangeEnd) |
| continue; |
| |
| // remove selection range inside of date range |
| if (startDate <= rangeStart && endDate >= rangeEnd) |
| { |
| _selectedRanges[n] = null; |
| } |
| // split selection range if date range inside selection range |
| else if (startDate > rangeStart && endDate < rangeEnd) |
| { |
| var temp:Date = _selectedRanges[n].rangeEnd; |
| |
| _selectedRanges[n].rangeEnd = addSubtractDays(startDate, -1); |
| |
| _selectedRanges[selectedRangeCount] = {}; |
| _selectedRanges[selectedRangeCount].rangeStart = addSubtractDays(endDate, +1); |
| _selectedRanges[selectedRangeCount].rangeEnd = temp; |
| |
| selectedRangeCount++; |
| } |
| // remove day at start of range |
| else if (endDate.time == rangeStart.time) { |
| _selectedRanges[n].rangeStart = addSubtractDays(startDate, +1); |
| } |
| // remove day at end of range |
| else if (startDate.time == rangeEnd.time) { |
| _selectedRanges[n].rangeEnd = addSubtractDays(endDate, -1); |
| } |
| // move selection start date if end overlaps |
| else if (endDate >= rangeStart) |
| { |
| _selectedRanges[n].rangeStart = addSubtractDays(endDate, +1); |
| } |
| // move selection end date if start overlaps |
| else if (startDate <= rangeEnd) |
| { |
| _selectedRanges[n].rangeEnd = addSubtractDays(startDate, -1); |
| } |
| } |
| |
| // clean up any removed selections |
| for (n = selectedRangeCount -1; n >= 0; n--) |
| { |
| if (_selectedRanges[n] == null) |
| { |
| _selectedRanges.splice(n,1); |
| selectedRangeCount--; |
| } |
| } |
| } |
| |
| /** |
| * @private |
| * Removes a single date specified by singleDate from the selected dates. |
| */ |
| mx_internal function removeDayFromSelection(singleDate:Date):void |
| { |
| removeRangeFromSelection(singleDate, singleDate); |
| } |
| |
| /** |
| * @private |
| * Updates the visible property of all the selected indicators. |
| * Called when a date range has been selected or deselected. |
| */ |
| mx_internal function setSelectedIndicators():void |
| { |
| var offset:int = getOffsetOfMonth(displayedYear, displayedMonth); |
| var daysInMonth:int = getNumberOfDaysInMonth(displayedYear, displayedMonth); |
| |
| var columnIndex:int; // 0 - 6 |
| var rowIndex:int; // 1 - 6 |
| var i:int; |
| for (var dayNumber:int = 1; dayNumber <= daysInMonth; dayNumber++) |
| { |
| var cellDate:Date = new Date(displayedYear, displayedMonth, dayNumber); |
| i = offset + dayNumber - 1; |
| columnIndex = i % 7; |
| rowIndex = 1 + Math.floor(i / 7); |
| |
| if (isSelected(cellDate) && disabledArrays[columnIndex][rowIndex] == false) |
| addSelectionIndicator(columnIndex,rowIndex); |
| else |
| removeSelectionIndicator(columnIndex,rowIndex); |
| } |
| |
| var today:Date = new Date(); |
| if (isSelected(today)) |
| todayIndicator.alpha = 1.0; |
| } |
| |
| /** |
| * @private |
| */ |
| mx_internal function addSelectionIndicator(columnIndex:int, rowIndex:int):void |
| { |
| if (!selectionIndicator[columnIndex][rowIndex]) |
| { |
| |
| var selectionIndicatorClass:Class = |
| getStyle("selectionIndicatorSkin"); |
| if (!selectionIndicatorClass) |
| selectionIndicatorClass = DateChooserIndicator; |
| selectionIndicator[columnIndex][rowIndex] = |
| IFlexDisplayObject(new selectionIndicatorClass()); |
| |
| if (isDateChooserIndicator(selectionIndicator[columnIndex][rowIndex])) |
| Object(selectionIndicator[columnIndex][rowIndex]).indicatorColor = |
| "selectionColor"; |
| if (selectionIndicator[columnIndex][rowIndex] is ISimpleStyleClient) |
| ISimpleStyleClient(selectionIndicator[columnIndex][rowIndex]).styleName = this; |
| |
| addChildAt(DisplayObject(selectionIndicator[columnIndex][rowIndex]), 0); |
| |
| var selCell:IUITextField = dayBlocksArray[columnIndex][rowIndex]; |
| selectionIndicator[columnIndex][rowIndex].move(selCell.x, selCell.y + yOffset); |
| selectionIndicator[columnIndex][rowIndex].setActualSize(cellWidth, cellHeight); |
| } |
| selectionIndicator[columnIndex][rowIndex].visible = true; |
| } |
| |
| /** |
| * @private |
| */ |
| mx_internal function removeSelectionIndicator(columnIndex:int, |
| rowIndex:int):void |
| { |
| if (selectionIndicator[columnIndex][rowIndex]) |
| { |
| removeChild(selectionIndicator[columnIndex][rowIndex]); |
| selectionIndicator[columnIndex][rowIndex] = null; |
| } |
| } |
| |
| /** |
| * @private |
| * |
| * Removes the selection indicators from this component. |
| */ |
| mx_internal function removeSelectionIndicators():void |
| { |
| for (var columnIndex:int = 0; columnIndex < 7; columnIndex++) |
| { |
| for (var rowIndex:int = 0; rowIndex < 7; rowIndex++) |
| { |
| removeSelectionIndicator(columnIndex, rowIndex); |
| } |
| } |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Overridden event handlers |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| */ |
| override protected function keyDownHandler(event:KeyboardEvent):void |
| { |
| /* |
| PageUp: Previous Month |
| PageDown: Next Month |
| */ |
| |
| var selChanged:Boolean = false; |
| |
| var date:int = lastSelectedDate ? lastSelectedDate.getDate() : 1; |
| |
| /* |
| calculate Days to move will take the following values: |
| |
| 1: Left |
| 2: Right |
| 3: Up |
| 4: Down |
| 5. Home |
| 6. End |
| |
| */ |
| |
| var daysInMonth:int = getNumberOfDaysInMonth(displayedYear, displayedMonth); |
| |
| // If rtl layout, need to swap LEFT and RIGHT so correct action |
| // is done. |
| var keyCode:uint = mapKeycodeForLayoutDirection(event); |
| |
| for (var i:uint = 0; i < 31; i++) |
| { |
| if (keyCode == Keyboard.LEFT) |
| { |
| if (date > 1) |
| { |
| date--; |
| selChanged = true; |
| } |
| else |
| return; |
| } |
| |
| else if (keyCode == Keyboard.RIGHT) |
| { |
| if (date < daysInMonth) |
| { |
| date++; |
| selChanged = true; |
| } |
| else |
| return; |
| } |
| |
| else if (keyCode == Keyboard.UP) |
| { |
| if (date > 7) |
| { |
| date -= 7; |
| selChanged = true; |
| } |
| else |
| return; |
| } |
| |
| else if (keyCode == Keyboard.DOWN) |
| { |
| if (date + 7 <= daysInMonth) |
| { |
| date += 7; |
| selChanged = true; |
| } |
| else |
| return; |
| } |
| |
| else if (keyCode == Keyboard.HOME) |
| { |
| if (i == 0) |
| date = 1; |
| else |
| date++; |
| selChanged = true; |
| } |
| |
| else if (keyCode == Keyboard.END) |
| { |
| if (i == 0) |
| date = daysInMonth; |
| else |
| date--; |
| selChanged = true; |
| } |
| |
| else if (lastSelectedDate && event.shiftKey && |
| (keyCode == Keyboard.PAGE_UP || |
| keyCode == Keyboard.PAGE_DOWN)) |
| { |
| selChanged = true; |
| } |
| |
| else if (lastSelectedDate && |
| (keyCode == 189 || |
| keyCode == 187)) // for year - and + |
| { |
| selChanged = true; |
| } |
| |
| if (keyCode >= Keyboard.PAGE_UP && |
| keyCode <= Keyboard.DOWN) |
| { |
| event.stopPropagation(); |
| } |
| |
| if (selChanged) |
| { |
| var newDate:Date = new Date(displayedYear, displayedMonth, date); |
| |
| if (checkDateIsDisabled(newDate) && !event.shiftKey) |
| continue; |
| |
| if (!(event.shiftKey && _allowMultipleSelection)) |
| selectedRangeCount = 0; |
| |
| addToSelected(newDate, event.shiftKey && _allowMultipleSelection); |
| |
| setSelectedIndicators(); |
| |
| dispatchChangeEvent(event); |
| return; |
| } |
| } |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Event handlers |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| */ |
| private function mouseOverHandler(event:MouseEvent):void |
| { |
| if (event.relatedObject && event.relatedObject.parent != this) |
| addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler); |
| else |
| event.stopImmediatePropagation(); |
| } |
| |
| /** |
| * @private |
| */ |
| private function mouseOutHandler(event:MouseEvent):void |
| { |
| if (event.relatedObject && event.relatedObject.parent != this) |
| { |
| |
| removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler); |
| rollOverIndicator.visible = false; |
| |
| |
| // If todayColumn and todayRow exist and today is not disabled |
| if (todayColumn != -1 && todayRow != -1 && !disabledArrays[todayColumn][todayRow]) |
| { |
| var today:Date = new Date(); |
| if (!isSelected(today)) |
| todayIndicator.alpha = 1.0; |
| } |
| } |
| else |
| { |
| event.stopImmediatePropagation(); |
| } |
| } |
| |
| /** |
| * @private |
| */ |
| private function mouseMoveHandler(event:MouseEvent):void |
| { |
| var paddingLeft:Number = getStyle("paddingLeft"); |
| var paddingTop:Number = getStyle("paddingTop"); |
| |
| var firstColX:Number = dayBlocksArray[0][0].x; |
| var lastColX:Number = dayBlocksArray[6][0].x; |
| var firstRowY:Number = dayBlocksArray[6][0].y + cellHeight; |
| |
| var mousePoint:Point = new Point(event.stageX, event.stageY); |
| mousePoint = globalToLocal(mousePoint); |
| var mouseY:Number = mousePoint.y; |
| var mouseX:Number = mousePoint.x; |
| |
| if (mouseX < firstColX || |
| mouseX > lastColX + cellWidth || |
| mouseY < firstRowY) |
| return; |
| |
| var rowIndex:int = Math.floor((mouseY-paddingTop) / cellHeight); |
| var colIndex:int = Math.floor((mouseX-paddingLeft) / cellWidth); |
| |
| colIndex = Math.min(colIndex, 6); |
| rowIndex = Math.min(rowIndex, 6); |
| |
| var selCell:IUITextField = dayBlocksArray[colIndex][rowIndex]; |
| |
| // If it is disabled, we're done. |
| if (disabledArrays[colIndex][rowIndex] || rowIndex == 0) |
| return; |
| |
| if (mouseY >= selCell.y && |
| mouseY <= selCell.y + cellHeight && |
| mouseX >= selCell.x && |
| mouseX <= selCell.x + cellWidth) |
| { |
| rollOverIndicator.move(selCell.x, selCell.y + yOffset); // Don't trigger layout |
| rollOverIndicator.visible = true; |
| |
| // Don't show rollover if we're over the selected date |
| if (selectionIndicator[colIndex][rowIndex]) |
| { |
| rollOverIndicator.visible = false; |
| } |
| |
| // Set alpha only if today is not disabled |
| if (todayColumn != -1 && todayRow != -1 && !disabledArrays[todayColumn][todayRow]) |
| { |
| var today:Date = new Date(); |
| if (rollOverIndicator.x == todayIndicator.x && |
| rollOverIndicator.y == todayIndicator.y) |
| { |
| todayIndicator.alpha = 0.6; |
| } |
| else if (!isSelected(today)) |
| { |
| todayIndicator.alpha = 1.0; |
| } |
| } |
| } |
| } |
| |
| /** |
| * @private |
| */ |
| private function mouseUpHandler(event:MouseEvent):void |
| { |
| var paddingLeft:Number = getStyle("paddingLeft"); |
| var paddingTop:Number = getStyle("paddingTop"); |
| |
| var firstColX:Number = dayBlocksArray[0][0].x; |
| var lastColX:Number = dayBlocksArray[6][0].x; |
| var firstRowY:Number = dayBlocksArray[6][0].y + cellHeight; |
| |
| var mousePoint:Point = new Point(event.stageX, event.stageY); |
| mousePoint = globalToLocal(mousePoint); |
| var mouseY:Number = mousePoint.y; |
| var mouseX:Number = mousePoint.x; |
| |
| if (mouseX < firstColX && |
| mouseX >= lastColX + cellWidth || |
| mouseY < firstRowY) |
| return; |
| |
| var rowIndex:int = Math.floor((mouseY-paddingTop) / cellHeight); |
| |
| if (rowIndex <= 0) |
| return; |
| rowIndex = Math.min(rowIndex, 6); |
| |
| var colIndex:int = Math.floor((mouseX-paddingLeft) / cellWidth); |
| colIndex = Math.min(colIndex, 6); |
| |
| var selCell:IUITextField = dayBlocksArray[colIndex][rowIndex];//this["dayBlock"+colIndex+"label"+rowIndex]; |
| // If it is disabled, we're done. |
| if (disabledArrays[colIndex][rowIndex]) |
| return; |
| |
| if (mouseY >= selCell.y && |
| mouseY <= selCell.y + cellHeight && |
| mouseX >= selCell.x && |
| mouseX <= selCell.x + cellWidth) |
| { |
| var newDate:Date = new Date(displayedYear, displayedMonth, int(selCell.text)); |
| |
| if (event.shiftKey && _allowMultipleSelection) |
| { |
| addToSelected(newDate,true); |
| setSelectedIndicators(); |
| } |
| else |
| { |
| var alreadySelected:Boolean = selectionIndicator[colIndex][rowIndex] ? true : false; |
| |
| if (event.ctrlKey && _allowMultipleSelection && _allowDisjointSelection) |
| { |
| if (alreadySelected) |
| { |
| removeSelectionIndicator(colIndex, rowIndex); |
| removeDayFromSelection(newDate); |
| } |
| else |
| { |
| addSelectionIndicator(colIndex, rowIndex); |
| addToSelected(newDate); |
| } |
| } |
| else |
| { |
| rangeStartDate = null; |
| |
| if (alreadySelected) |
| { |
| if (selectedRangeCount > 1 || (selectedRangeCount == 1 && _selectedRanges[0].rangeStart != _selectedRanges[0].rangeEnd)) |
| { |
| selectedRangeCount = 0; |
| addSelectionIndicator(colIndex,rowIndex); |
| addToSelected(newDate); |
| setSelectedIndicators(); |
| } |
| else if (event.ctrlKey) |
| { |
| removeSelectionIndicator(colIndex, rowIndex); |
| removeDayFromSelection(newDate); |
| } |
| } |
| else |
| { |
| selectedRangeCount = 0; |
| addSelectionIndicator(colIndex, rowIndex); |
| addToSelected(newDate); |
| setSelectedIndicators(); |
| } |
| } |
| } |
| |
| dispatchChangeEvent(event); |
| |
| if (todayColumn != -1 && todayRow != -1 && !disabledArrays[todayColumn][todayRow]) // Set alpha only if today is not disabled |
| { |
| var todaysDate:Date = new Date(); |
| todayIndicator.alpha = isSelected(todaysDate) ? 0.6 : 1.0; |
| } |
| |
| // Hide the rollover indicator if it is the selected cell |
| if (selectionIndicator[colIndex][rowIndex]) |
| rollOverIndicator.visible = false; |
| } |
| } |
| |
| /** |
| * We don't use 'is' to prevent dependency issues |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| private static var dcis:Object = {}; |
| |
| private static function isDateChooserIndicator(parent:Object):Boolean |
| { |
| var s:String = getQualifiedClassName(parent); |
| if (dcis[s] == 1) |
| return true; |
| |
| if (dcis[s] == 0) |
| return false; |
| |
| if (s == "mx.skins.halo::DateChooserIndicator") |
| { |
| dcis[s] == 1; |
| return true; |
| } |
| |
| var x:XML = describeType(parent); |
| var xmllist:XMLList = x.extendsClass.(@type == "mx.skins.halo::DateChooserIndicator"); |
| if (xmllist.length() == 0) |
| { |
| dcis[s] = 0; |
| return false; |
| } |
| |
| dcis[s] = 1; |
| return true; |
| } |
| } |
| |
| } |