--- /dev/null
+<!DOCTYPE html>
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <title>The source code</title>
+ <link href="../prettify/prettify.css" type="text/css" rel="stylesheet" />
+ <script type="text/javascript" src="../prettify/prettify.js"></script>
+ <style type="text/css">
+ .highlight { display: block; background-color: #ddd; }
+ </style>
+ <script type="text/javascript">
+ function highlight() {
+ document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
+ }
+ </script>
+</head>
+<body onload="prettyPrint(); highlight();">
+ <pre class="prettyprint lang-js"><span id='Ext-picker-Month-method-constructor'><span id='Ext-picker-Month'>/**
+</span></span> * @private
+ * @class Ext.picker.Month
+ * @extends Ext.Component
+ * <p>A month picker component. This class is used by the {@link Ext.picker.Date DatePicker} class
+ * to allow browsing and selection of year/months combinations.</p>
+ * @constructor
+ * Create a new MonthPicker
+ * @param {Object} config The config object
+ * @xtype monthpicker
+ * @private
+ */
+Ext.define('Ext.picker.Month', {
+ extend: 'Ext.Component',
+ requires: ['Ext.XTemplate', 'Ext.util.ClickRepeater', 'Ext.Date', 'Ext.button.Button'],
+ alias: 'widget.monthpicker',
+ alternateClassName: 'Ext.MonthPicker',
+
+ renderTpl: [
+ '<div class="{baseCls}-body">',
+ '<div class="{baseCls}-months">',
+ '<tpl for="months">',
+ '<div class="{parent.baseCls}-item {parent.baseCls}-month"><a href="#" hidefocus="on">{.}</a></div>',
+ '</tpl>',
+ '</div>',
+ '<div class="{baseCls}-years">',
+ '<div class="{baseCls}-yearnav">',
+ '<button class="{baseCls}-yearnav-prev"></button>',
+ '<button class="{baseCls}-yearnav-next"></button>',
+ '</div>',
+ '<tpl for="years">',
+ '<div class="{parent.baseCls}-item {parent.baseCls}-year"><a href="#" hidefocus="on">{.}</a></div>',
+ '</tpl>',
+ '</div>',
+ '</div>',
+ '<div class="' + Ext.baseCSSPrefix + 'clear"></div>',
+ '<tpl if="showButtons">',
+ '<div class="{baseCls}-buttons"></div>',
+ '</tpl>'
+ ],
+
+<span id='Ext-picker-Month-cfg-okText'> /**
+</span> * @cfg {String} okText The text to display on the ok button. Defaults to <tt>'OK'</tt>
+ */
+ okText: 'OK',
+
+<span id='Ext-picker-Month-cfg-cancelText'> /**
+</span> * @cfg {String} cancelText The text to display on the cancel button. Defaults to <tt>'Cancel'</tt>
+ */
+ cancelText: 'Cancel',
+
+<span id='Ext-picker-Month-cfg-baseCls'> /**
+</span> * @cfg {String} baseCls The base CSS class to apply to the picker element. Defaults to <tt>'x-monthpicker'</tt>
+ */
+ baseCls: Ext.baseCSSPrefix + 'monthpicker',
+
+<span id='Ext-picker-Month-cfg-showButtons'> /**
+</span> * @cfg {Boolean} showButtons True to show ok and cancel buttons below the picker. Defaults to <tt>true</tt>.
+ */
+ showButtons: true,
+
+<span id='Ext-picker-Month-cfg-selectedCls'> /**
+</span> * @cfg {String} selectedCls The class to be added to selected items in the picker. Defaults to
+ * <tt>'x-monthpicker-selected'</tt>
+ */
+
+<span id='Ext-picker-Month-cfg-value'> /**
+</span> * @cfg {Date/Array} value The default value to set. See {#setValue setValue}
+ */
+
+ width: 175,
+
+ height: 195,
+
+
+ // private
+ totalYears: 10,
+ yearOffset: 5, // 10 years in total, 2 per row
+ monthOffset: 6, // 12 months, 2 per row
+
+ // private, inherit docs
+ initComponent: function(){
+ var me = this;
+
+ me.selectedCls = me.baseCls + '-selected';
+ me.addEvents(
+<span id='Ext-picker-Month-event-cancelclick'> /**
+</span> * @event cancelclick
+ * Fires when the cancel button is pressed.
+ * @param {Ext.picker.Month} this
+ */
+ 'cancelclick',
+
+<span id='Ext-picker-Month-event-monthclick'> /**
+</span> * @event monthclick
+ * Fires when a month is clicked.
+ * @param {Ext.picker.Month} this
+ * @param {Array} value The current value
+ */
+ 'monthclick',
+
+<span id='Ext-picker-Month-event-monthdblclick'> /**
+</span> * @event monthdblclick
+ * Fires when a month is clicked.
+ * @param {Ext.picker.Month} this
+ * @param {Array} value The current value
+ */
+ 'monthdblclick',
+
+<span id='Ext-picker-Month-event-okclick'> /**
+</span> * @event okclick
+ * Fires when the ok button is pressed.
+ * @param {Ext.picker.Month} this
+ * @param {Array} value The current value
+ */
+ 'okclick',
+
+<span id='Ext-picker-Month-event-select'> /**
+</span> * @event select
+ * Fires when a month/year is selected.
+ * @param {Ext.picker.Month} this
+ * @param {Array} value The current value
+ */
+ 'select',
+
+<span id='Ext-picker-Month-event-yearclick'> /**
+</span> * @event yearclick
+ * Fires when a year is clicked.
+ * @param {Ext.picker.Month} this
+ * @param {Array} value The current value
+ */
+ 'yearclick',
+
+<span id='Ext-picker-Month-event-yeardblclick'> /**
+</span> * @event yeardblclick
+ * Fires when a year is clicked.
+ * @param {Ext.picker.Month} this
+ * @param {Array} value The current value
+ */
+ 'yeardblclick'
+ );
+
+ me.setValue(me.value);
+ me.activeYear = me.getYear(new Date().getFullYear() - 4, -4);
+ this.callParent();
+ },
+
+ // private, inherit docs
+ onRender: function(ct, position){
+ var me = this,
+ i = 0,
+ months = [],
+ shortName = Ext.Date.getShortMonthName,
+ monthLen = me.monthOffset;
+
+ for (; i < monthLen; ++i) {
+ months.push(shortName(i), shortName(i + monthLen));
+ }
+
+ Ext.apply(me.renderData, {
+ months: months,
+ years: me.getYears(),
+ showButtons: me.showButtons
+ });
+
+ Ext.apply(me.renderSelectors, {
+ bodyEl: '.' + me.baseCls + '-body',
+ prevEl: '.' + me.baseCls + '-yearnav-prev',
+ nextEl: '.' + me.baseCls + '-yearnav-next',
+ buttonsEl: '.' + me.baseCls + '-buttons'
+ });
+ this.callParent([ct, position]);
+ },
+
+ // private, inherit docs
+ afterRender: function(){
+ var me = this,
+ body = me.bodyEl,
+ buttonsEl = me.buttonsEl;
+
+ me.callParent();
+
+ me.mon(body, 'click', me.onBodyClick, me);
+ me.mon(body, 'dblclick', me.onBodyClick, me);
+
+ // keep a reference to the year/month elements since we'll be re-using them
+ me.years = body.select('.' + me.baseCls + '-year a');
+ me.months = body.select('.' + me.baseCls + '-month a');
+
+ if (me.showButtons) {
+ me.okBtn = Ext.create('Ext.button.Button', {
+ text: me.okText,
+ renderTo: buttonsEl,
+ handler: me.onOkClick,
+ scope: me
+ });
+ me.cancelBtn = Ext.create('Ext.button.Button', {
+ text: me.cancelText,
+ renderTo: buttonsEl,
+ handler: me.onCancelClick,
+ scope: me
+ });
+ }
+
+ me.backRepeater = Ext.create('Ext.util.ClickRepeater', me.prevEl, {
+ handler: Ext.Function.bind(me.adjustYear, me, [-me.totalYears])
+ });
+
+ me.prevEl.addClsOnOver(me.baseCls + '-yearnav-prev-over');
+ me.nextRepeater = Ext.create('Ext.util.ClickRepeater', me.nextEl, {
+ handler: Ext.Function.bind(me.adjustYear, me, [me.totalYears])
+ });
+ me.nextEl.addClsOnOver(me.baseCls + '-yearnav-next-over');
+ me.updateBody();
+ },
+
+<span id='Ext-picker-Month-method-setValue'> /**
+</span> * Set the value for the picker.
+ * @param {Date/Array} value The value to set. It can be a Date object, where the month/year will be extracted, or
+ * it can be an array, with the month as the first index and the year as the second.
+ * @return {Ext.picker.Month} this
+ */
+ setValue: function(value){
+ var me = this,
+ active = me.activeYear,
+ offset = me.monthOffset,
+ year,
+ index;
+
+ if (!value) {
+ me.value = [null, null];
+ } else if (Ext.isDate(value)) {
+ me.value = [value.getMonth(), value.getFullYear()];
+ } else {
+ me.value = [value[0], value[1]];
+ }
+
+ if (me.rendered) {
+ year = me.value[1];
+ if (year !== null) {
+ if ((year < active || year > active + me.yearOffset)) {
+ me.activeYear = year - me.yearOffset + 1;
+ }
+ }
+ me.updateBody();
+ }
+
+ return me;
+ },
+
+<span id='Ext-picker-Month-method-getValue'> /**
+</span> * Gets the selected value. It is returned as an array [month, year]. It may
+ * be a partial value, for example [null, 2010]. The month is returned as
+ * 0 based.
+ * @return {Array} The selected value
+ */
+ getValue: function(){
+ return this.value;
+ },
+
+<span id='Ext-picker-Month-method-hasSelection'> /**
+</span> * Checks whether the picker has a selection
+ * @return {Boolean} Returns true if both a month and year have been selected
+ */
+ hasSelection: function(){
+ var value = this.value;
+ return value[0] !== null && value[1] !== null;
+ },
+
+<span id='Ext-picker-Month-method-getYears'> /**
+</span> * Get an array of years to be pushed in the template. It is not in strict
+ * numerical order because we want to show them in columns.
+ * @private
+ * @return {Array} An array of years
+ */
+ getYears: function(){
+ var me = this,
+ offset = me.yearOffset,
+ start = me.activeYear, // put the "active" year on the left
+ end = start + offset,
+ i = start,
+ years = [];
+
+ for (; i < end; ++i) {
+ years.push(i, i + offset);
+ }
+
+ return years;
+ },
+
+<span id='Ext-picker-Month-method-updateBody'> /**
+</span> * Update the years in the body based on any change
+ * @private
+ */
+ updateBody: function(){
+ var me = this,
+ years = me.years,
+ months = me.months,
+ yearNumbers = me.getYears(),
+ cls = me.selectedCls,
+ value = me.getYear(null),
+ month = me.value[0],
+ monthOffset = me.monthOffset,
+ year;
+
+ if (me.rendered) {
+ years.removeCls(cls);
+ months.removeCls(cls);
+ years.each(function(el, all, index){
+ year = yearNumbers[index];
+ el.dom.innerHTML = year;
+ if (year == value) {
+ el.dom.className = cls;
+ }
+ });
+ if (month !== null) {
+ if (month < monthOffset) {
+ month = month * 2;
+ } else {
+ month = (month - monthOffset) * 2 + 1;
+ }
+ months.item(month).addCls(cls);
+ }
+ }
+ },
+
+<span id='Ext-picker-Month-method-getYear'> /**
+</span> * Gets the current year value, or the default.
+ * @private
+ * @param {Number} defaultValue The default value to use if the year is not defined.
+ * @param {Number} offset A number to offset the value by
+ * @return {Number} The year value
+ */
+ getYear: function(defaultValue, offset) {
+ var year = this.value[1];
+ offset = offset || 0;
+ return year === null ? defaultValue : year + offset;
+ },
+
+<span id='Ext-picker-Month-method-onBodyClick'> /**
+</span> * React to clicks on the body
+ * @private
+ */
+ onBodyClick: function(e, t) {
+ var me = this,
+ isDouble = e.type == 'dblclick';
+
+ if (e.getTarget('.' + me.baseCls + '-month')) {
+ e.stopEvent();
+ me.onMonthClick(t, isDouble);
+ } else if (e.getTarget('.' + me.baseCls + '-year')) {
+ e.stopEvent();
+ me.onYearClick(t, isDouble);
+ }
+ },
+
+<span id='Ext-picker-Month-method-adjustYear'> /**
+</span> * Modify the year display by passing an offset.
+ * @param {Number} offset The offset to move by. If not specified, it defaults to 10.
+ */
+ adjustYear: function(offset){
+ if (typeof offset != 'number') {
+ offset = this.totalYears;
+ }
+ this.activeYear += offset;
+ this.updateBody();
+ },
+
+<span id='Ext-picker-Month-method-onOkClick'> /**
+</span> * React to the ok button being pressed
+ * @private
+ */
+ onOkClick: function(){
+ this.fireEvent('okclick', this, this.value);
+ },
+
+<span id='Ext-picker-Month-method-onCancelClick'> /**
+</span> * React to the cancel button being pressed
+ * @private
+ */
+ onCancelClick: function(){
+ this.fireEvent('cancelclick', this);
+ },
+
+<span id='Ext-picker-Month-method-onMonthClick'> /**
+</span> * React to a month being clicked
+ * @private
+ * @param {HTMLElement} target The element that was clicked
+ * @param {Boolean} isDouble True if the event was a doubleclick
+ */
+ onMonthClick: function(target, isDouble){
+ var me = this;
+ me.value[0] = me.resolveOffset(me.months.indexOf(target), me.monthOffset);
+ me.updateBody();
+ me.fireEvent('month' + (isDouble ? 'dbl' : '') + 'click', me, me.value);
+ me.fireEvent('select', me, me.value);
+ },
+
+<span id='Ext-picker-Month-method-onYearClick'> /**
+</span> * React to a year being clicked
+ * @private
+ * @param {HTMLElement} target The element that was clicked
+ * @param {Boolean} isDouble True if the event was a doubleclick
+ */
+ onYearClick: function(target, isDouble){
+ var me = this;
+ me.value[1] = me.activeYear + me.resolveOffset(me.years.indexOf(target), me.yearOffset);
+ me.updateBody();
+ me.fireEvent('year' + (isDouble ? 'dbl' : '') + 'click', me, me.value);
+ me.fireEvent('select', me, me.value);
+
+ },
+
+<span id='Ext-picker-Month-method-resolveOffset'> /**
+</span> * Returns an offsetted number based on the position in the collection. Since our collections aren't
+ * numerically ordered, this function helps to normalize those differences.
+ * @private
+ * @param {Object} index
+ * @param {Object} offset
+ * @return {Number} The correctly offsetted number
+ */
+ resolveOffset: function(index, offset){
+ if (index % 2 === 0) {
+ return (index / 2);
+ } else {
+ return offset + Math.floor(index / 2);
+ }
+ },
+
+ // private, inherit docs
+ beforeDestroy: function(){
+ var me = this;
+ me.years = me.months = null;
+ Ext.destroyMembers('backRepeater', 'nextRepeater', 'okBtn', 'cancelBtn');
+ this.callParent();
+ }
+});
+</pre>
+</body>
+</html>