Month.html 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  5. <title>The source code</title>
  6. <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
  7. <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
  8. <style type="text/css">
  9. .highlight { display: block; background-color: #ddd; }
  10. </style>
  11. <script type="text/javascript">
  12. function highlight() {
  13. document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
  14. }
  15. </script>
  16. </head>
  17. <body onload="prettyPrint(); highlight();">
  18. <pre class="prettyprint lang-js"><span id='Ext-picker-Month'>/**
  19. </span> * @private
  20. * A month picker component. This class is used by the {@link Ext.picker.Date Date picker} class
  21. * to allow browsing and selection of year/months combinations.
  22. */
  23. Ext.define('Ext.picker.Month', {
  24. extend: 'Ext.Component',
  25. requires: [
  26. 'Ext.XTemplate',
  27. 'Ext.util.ClickRepeater',
  28. 'Ext.Date',
  29. 'Ext.button.Button'
  30. ],
  31. alias: 'widget.monthpicker',
  32. alternateClassName: 'Ext.MonthPicker',
  33. childEls: [
  34. 'bodyEl', 'prevEl', 'nextEl', 'buttonsEl', 'monthEl', 'yearEl'
  35. ],
  36. renderTpl: [
  37. '&lt;div id=&quot;{id}-bodyEl&quot; class=&quot;{baseCls}-body&quot;&gt;',
  38. '&lt;div id=&quot;{id}-monthEl&quot; class=&quot;{baseCls}-months&quot;&gt;',
  39. '&lt;tpl for=&quot;months&quot;&gt;',
  40. '&lt;div class=&quot;{parent.baseCls}-item {parent.baseCls}-month&quot;&gt;&lt;a style=&quot;{parent.monthStyle}&quot; href=&quot;#&quot; hidefocus=&quot;on&quot;&gt;{.}&lt;/a&gt;&lt;/div&gt;',
  41. '&lt;/tpl&gt;',
  42. '&lt;/div&gt;',
  43. '&lt;div id=&quot;{id}-yearEl&quot; class=&quot;{baseCls}-years&quot;&gt;',
  44. '&lt;div class=&quot;{baseCls}-yearnav&quot;&gt;',
  45. '&lt;button id=&quot;{id}-prevEl&quot; class=&quot;{baseCls}-yearnav-prev&quot;&gt;&lt;/button&gt;',
  46. '&lt;button id=&quot;{id}-nextEl&quot; class=&quot;{baseCls}-yearnav-next&quot;&gt;&lt;/button&gt;',
  47. '&lt;/div&gt;',
  48. '&lt;tpl for=&quot;years&quot;&gt;',
  49. '&lt;div class=&quot;{parent.baseCls}-item {parent.baseCls}-year&quot;&gt;&lt;a href=&quot;#&quot; hidefocus=&quot;on&quot;&gt;{.}&lt;/a&gt;&lt;/div&gt;',
  50. '&lt;/tpl&gt;',
  51. '&lt;/div&gt;',
  52. '&lt;div class=&quot;' + Ext.baseCSSPrefix + 'clear&quot;&gt;&lt;/div&gt;',
  53. '&lt;/div&gt;',
  54. '&lt;tpl if=&quot;showButtons&quot;&gt;',
  55. '&lt;div id=&quot;{id}-buttonsEl&quot; class=&quot;{baseCls}-buttons&quot;&gt;{%',
  56. 'var me=values.$comp, okBtn=me.okBtn, cancelBtn=me.cancelBtn;',
  57. 'okBtn.ownerLayout = cancelBtn.ownerLayout = me.componentLayout;',
  58. 'okBtn.ownerCt = cancelBtn.ownerCt = me;',
  59. 'Ext.DomHelper.generateMarkup(okBtn.getRenderTree(), out);',
  60. 'Ext.DomHelper.generateMarkup(cancelBtn.getRenderTree(), out);',
  61. '%}&lt;/div&gt;',
  62. '&lt;/tpl&gt;'
  63. ],
  64. //&lt;locale&gt;
  65. <span id='Ext-picker-Month-cfg-okText'> /**
  66. </span> * @cfg {String} okText The text to display on the ok button.
  67. */
  68. okText: 'OK',
  69. //&lt;/locale&gt;
  70. //&lt;locale&gt;
  71. <span id='Ext-picker-Month-cfg-cancelText'> /**
  72. </span> * @cfg {String} cancelText The text to display on the cancel button.
  73. */
  74. cancelText: 'Cancel',
  75. //&lt;/locale&gt;
  76. <span id='Ext-picker-Month-cfg-baseCls'> /**
  77. </span> * @cfg {String} [baseCls='x-monthpicker']
  78. * The base CSS class to apply to the picker element.
  79. */
  80. baseCls: Ext.baseCSSPrefix + 'monthpicker',
  81. <span id='Ext-picker-Month-cfg-showButtons'> /**
  82. </span> * @cfg {Boolean} showButtons True to show ok and cancel buttons below the picker.
  83. */
  84. showButtons: true,
  85. <span id='Ext-picker-Month-cfg-selectedCls'> /**
  86. </span> * @cfg {String} [selectedCls='x-monthpicker-selected'] The class to be added to selected items in the picker.
  87. */
  88. <span id='Ext-picker-Month-cfg-value'> /**
  89. </span> * @cfg {Date/Number[]} value The default value to set. See {@link #setValue}
  90. */
  91. width: 178,
  92. measureWidth: 35,
  93. measureMaxHeight: 20,
  94. // used when attached to date picker which isnt showing buttons
  95. smallCls: Ext.baseCSSPrefix + 'monthpicker-small',
  96. // private
  97. totalYears: 10,
  98. yearOffset: 5, // 10 years in total, 2 per row
  99. monthOffset: 6, // 12 months, 2 per row
  100. // private, inherit docs
  101. initComponent: function(){
  102. var me = this;
  103. me.selectedCls = me.baseCls + '-selected';
  104. me.addEvents(
  105. <span id='Ext-picker-Month-event-cancelclick'> /**
  106. </span> * @event cancelclick
  107. * Fires when the cancel button is pressed.
  108. * @param {Ext.picker.Month} this
  109. */
  110. 'cancelclick',
  111. <span id='Ext-picker-Month-event-monthclick'> /**
  112. </span> * @event monthclick
  113. * Fires when a month is clicked.
  114. * @param {Ext.picker.Month} this
  115. * @param {Array} value The current value
  116. */
  117. 'monthclick',
  118. <span id='Ext-picker-Month-event-monthdblclick'> /**
  119. </span> * @event monthdblclick
  120. * Fires when a month is clicked.
  121. * @param {Ext.picker.Month} this
  122. * @param {Array} value The current value
  123. */
  124. 'monthdblclick',
  125. <span id='Ext-picker-Month-event-okclick'> /**
  126. </span> * @event okclick
  127. * Fires when the ok button is pressed.
  128. * @param {Ext.picker.Month} this
  129. * @param {Array} value The current value
  130. */
  131. 'okclick',
  132. <span id='Ext-picker-Month-event-select'> /**
  133. </span> * @event select
  134. * Fires when a month/year is selected.
  135. * @param {Ext.picker.Month} this
  136. * @param {Array} value The current value
  137. */
  138. 'select',
  139. <span id='Ext-picker-Month-event-yearclick'> /**
  140. </span> * @event yearclick
  141. * Fires when a year is clicked.
  142. * @param {Ext.picker.Month} this
  143. * @param {Array} value The current value
  144. */
  145. 'yearclick',
  146. <span id='Ext-picker-Month-event-yeardblclick'> /**
  147. </span> * @event yeardblclick
  148. * Fires when a year is clicked.
  149. * @param {Ext.picker.Month} this
  150. * @param {Array} value The current value
  151. */
  152. 'yeardblclick'
  153. );
  154. if (me.small) {
  155. me.addCls(me.smallCls);
  156. }
  157. me.setValue(me.value);
  158. me.activeYear = me.getYear(new Date().getFullYear() - 4, -4);
  159. if (me.showButtons) {
  160. me.okBtn = new Ext.button.Button({
  161. text: me.okText,
  162. handler: me.onOkClick,
  163. scope: me
  164. });
  165. me.cancelBtn = new Ext.button.Button({
  166. text: me.cancelText,
  167. handler: me.onCancelClick,
  168. scope: me
  169. });
  170. }
  171. this.callParent();
  172. },
  173. // private, inherit docs
  174. beforeRender: function(){
  175. var me = this,
  176. i = 0,
  177. months = [],
  178. shortName = Ext.Date.getShortMonthName,
  179. monthLen = me.monthOffset,
  180. margin = me.monthMargin,
  181. style = '';
  182. me.callParent();
  183. for (; i &lt; monthLen; ++i) {
  184. months.push(shortName(i), shortName(i + monthLen));
  185. }
  186. if (Ext.isDefined(margin)) {
  187. style = 'margin: 0 ' + margin + 'px;';
  188. }
  189. Ext.apply(me.renderData, {
  190. months: months,
  191. years: me.getYears(),
  192. showButtons: me.showButtons,
  193. monthStyle: style
  194. });
  195. },
  196. // private, inherit docs
  197. afterRender: function(){
  198. var me = this,
  199. body = me.bodyEl,
  200. buttonsEl = me.buttonsEl;
  201. me.callParent();
  202. me.mon(body, 'click', me.onBodyClick, me);
  203. me.mon(body, 'dblclick', me.onBodyClick, me);
  204. // keep a reference to the year/month elements since we'll be re-using them
  205. me.years = body.select('.' + me.baseCls + '-year a');
  206. me.months = body.select('.' + me.baseCls + '-month a');
  207. me.backRepeater = new Ext.util.ClickRepeater(me.prevEl, {
  208. handler: Ext.Function.bind(me.adjustYear, me, [-me.totalYears])
  209. });
  210. me.prevEl.addClsOnOver(me.baseCls + '-yearnav-prev-over');
  211. me.nextRepeater = new Ext.util.ClickRepeater(me.nextEl, {
  212. handler: Ext.Function.bind(me.adjustYear, me, [me.totalYears])
  213. });
  214. me.nextEl.addClsOnOver(me.baseCls + '-yearnav-next-over');
  215. me.updateBody();
  216. if (!Ext.isDefined(me.monthMargin)) {
  217. Ext.picker.Month.prototype.monthMargin = me.calculateMonthMargin();
  218. }
  219. },
  220. calculateMonthMargin: function(){
  221. // We use this method for locales where the short month name
  222. // may be longer than we see in English. For example in the
  223. // zh_TW locale the month ends up spanning lines, so we loosen
  224. // the margins to get some extra space
  225. var me = this,
  226. monthEl = me.monthEl,
  227. months = me.months,
  228. first = months.first(),
  229. itemMargin = first.getMargin('l');
  230. while (itemMargin &amp;&amp; me.getLargest() &gt; me.measureMaxHeight) {
  231. --itemMargin;
  232. months.setStyle('margin', '0 ' + itemMargin + 'px');
  233. }
  234. return itemMargin;
  235. },
  236. getLargest: function(months){
  237. var largest = 0;
  238. this.months.each(function(item){
  239. var h = item.getHeight();
  240. if (h &gt; largest) {
  241. largest = h;
  242. }
  243. });
  244. return largest;
  245. },
  246. <span id='Ext-picker-Month-method-setValue'> /**
  247. </span> * Set the value for the picker.
  248. * @param {Date/Number[]} value The value to set. It can be a Date object, where the month/year will be extracted, or
  249. * it can be an array, with the month as the first index and the year as the second.
  250. * @return {Ext.picker.Month} this
  251. */
  252. setValue: function(value){
  253. var me = this,
  254. active = me.activeYear,
  255. offset = me.monthOffset,
  256. year,
  257. index;
  258. if (!value) {
  259. me.value = [null, null];
  260. } else if (Ext.isDate(value)) {
  261. me.value = [value.getMonth(), value.getFullYear()];
  262. } else {
  263. me.value = [value[0], value[1]];
  264. }
  265. if (me.rendered) {
  266. year = me.value[1];
  267. if (year !== null) {
  268. if ((year &lt; active || year &gt; active + me.yearOffset)) {
  269. me.activeYear = year - me.yearOffset + 1;
  270. }
  271. }
  272. me.updateBody();
  273. }
  274. return me;
  275. },
  276. <span id='Ext-picker-Month-method-getValue'> /**
  277. </span> * Gets the selected value. It is returned as an array [month, year]. It may
  278. * be a partial value, for example [null, 2010]. The month is returned as
  279. * 0 based.
  280. * @return {Number[]} The selected value
  281. */
  282. getValue: function(){
  283. return this.value;
  284. },
  285. <span id='Ext-picker-Month-method-hasSelection'> /**
  286. </span> * Checks whether the picker has a selection
  287. * @return {Boolean} Returns true if both a month and year have been selected
  288. */
  289. hasSelection: function(){
  290. var value = this.value;
  291. return value[0] !== null &amp;&amp; value[1] !== null;
  292. },
  293. <span id='Ext-picker-Month-method-getYears'> /**
  294. </span> * Get an array of years to be pushed in the template. It is not in strict
  295. * numerical order because we want to show them in columns.
  296. * @private
  297. * @return {Number[]} An array of years
  298. */
  299. getYears: function(){
  300. var me = this,
  301. offset = me.yearOffset,
  302. start = me.activeYear, // put the &quot;active&quot; year on the left
  303. end = start + offset,
  304. i = start,
  305. years = [];
  306. for (; i &lt; end; ++i) {
  307. years.push(i, i + offset);
  308. }
  309. return years;
  310. },
  311. <span id='Ext-picker-Month-method-updateBody'> /**
  312. </span> * Update the years in the body based on any change
  313. * @private
  314. */
  315. updateBody: function(){
  316. var me = this,
  317. years = me.years,
  318. months = me.months,
  319. yearNumbers = me.getYears(),
  320. cls = me.selectedCls,
  321. value = me.getYear(null),
  322. month = me.value[0],
  323. monthOffset = me.monthOffset,
  324. year,
  325. yearItems, y, yLen, el;
  326. if (me.rendered) {
  327. years.removeCls(cls);
  328. months.removeCls(cls);
  329. yearItems = years.elements;
  330. yLen = yearItems.length;
  331. for (y = 0; y &lt; yLen; y++) {
  332. el = Ext.fly(yearItems[y]);
  333. year = yearNumbers[y];
  334. el.dom.innerHTML = year;
  335. if (year == value) {
  336. el.dom.className = cls;
  337. }
  338. }
  339. if (month !== null) {
  340. if (month &lt; monthOffset) {
  341. month = month * 2;
  342. } else {
  343. month = (month - monthOffset) * 2 + 1;
  344. }
  345. months.item(month).addCls(cls);
  346. }
  347. }
  348. },
  349. <span id='Ext-picker-Month-method-getYear'> /**
  350. </span> * Gets the current year value, or the default.
  351. * @private
  352. * @param {Number} defaultValue The default value to use if the year is not defined.
  353. * @param {Number} offset A number to offset the value by
  354. * @return {Number} The year value
  355. */
  356. getYear: function(defaultValue, offset) {
  357. var year = this.value[1];
  358. offset = offset || 0;
  359. return year === null ? defaultValue : year + offset;
  360. },
  361. <span id='Ext-picker-Month-method-onBodyClick'> /**
  362. </span> * React to clicks on the body
  363. * @private
  364. */
  365. onBodyClick: function(e, t) {
  366. var me = this,
  367. isDouble = e.type == 'dblclick';
  368. if (e.getTarget('.' + me.baseCls + '-month')) {
  369. e.stopEvent();
  370. me.onMonthClick(t, isDouble);
  371. } else if (e.getTarget('.' + me.baseCls + '-year')) {
  372. e.stopEvent();
  373. me.onYearClick(t, isDouble);
  374. }
  375. },
  376. <span id='Ext-picker-Month-method-adjustYear'> /**
  377. </span> * Modify the year display by passing an offset.
  378. * @param {Number} [offset=10] The offset to move by.
  379. */
  380. adjustYear: function(offset){
  381. if (typeof offset != 'number') {
  382. offset = this.totalYears;
  383. }
  384. this.activeYear += offset;
  385. this.updateBody();
  386. },
  387. <span id='Ext-picker-Month-method-onOkClick'> /**
  388. </span> * React to the ok button being pressed
  389. * @private
  390. */
  391. onOkClick: function(){
  392. this.fireEvent('okclick', this, this.value);
  393. },
  394. <span id='Ext-picker-Month-method-onCancelClick'> /**
  395. </span> * React to the cancel button being pressed
  396. * @private
  397. */
  398. onCancelClick: function(){
  399. this.fireEvent('cancelclick', this);
  400. },
  401. <span id='Ext-picker-Month-method-onMonthClick'> /**
  402. </span> * React to a month being clicked
  403. * @private
  404. * @param {HTMLElement} target The element that was clicked
  405. * @param {Boolean} isDouble True if the event was a doubleclick
  406. */
  407. onMonthClick: function(target, isDouble){
  408. var me = this;
  409. me.value[0] = me.resolveOffset(me.months.indexOf(target), me.monthOffset);
  410. me.updateBody();
  411. me.fireEvent('month' + (isDouble ? 'dbl' : '') + 'click', me, me.value);
  412. me.fireEvent('select', me, me.value);
  413. },
  414. <span id='Ext-picker-Month-method-onYearClick'> /**
  415. </span> * React to a year being clicked
  416. * @private
  417. * @param {HTMLElement} target The element that was clicked
  418. * @param {Boolean} isDouble True if the event was a doubleclick
  419. */
  420. onYearClick: function(target, isDouble){
  421. var me = this;
  422. me.value[1] = me.activeYear + me.resolveOffset(me.years.indexOf(target), me.yearOffset);
  423. me.updateBody();
  424. me.fireEvent('year' + (isDouble ? 'dbl' : '') + 'click', me, me.value);
  425. me.fireEvent('select', me, me.value);
  426. },
  427. <span id='Ext-picker-Month-method-resolveOffset'> /**
  428. </span> * Returns an offsetted number based on the position in the collection. Since our collections aren't
  429. * numerically ordered, this function helps to normalize those differences.
  430. * @private
  431. * @param {Object} index
  432. * @param {Object} offset
  433. * @return {Number} The correctly offsetted number
  434. */
  435. resolveOffset: function(index, offset){
  436. if (index % 2 === 0) {
  437. return (index / 2);
  438. } else {
  439. return offset + Math.floor(index / 2);
  440. }
  441. },
  442. // private, inherit docs
  443. beforeDestroy: function(){
  444. var me = this;
  445. me.years = me.months = null;
  446. Ext.destroyMembers(me, 'backRepeater', 'nextRepeater', 'okBtn', 'cancelBtn');
  447. me.callParent();
  448. },
  449. // Do the job of a container layout at this point even though we are not a Container.
  450. // TODO: Refactor as a Container.
  451. finishRenderChildren: function () {
  452. var me = this;
  453. this.callParent(arguments);
  454. if (this.showButtons) {
  455. me.okBtn.finishRender();
  456. me.cancelBtn.finishRender();
  457. }
  458. },
  459. onDestroy: function() {
  460. Ext.destroyMembers(this, 'okBtn', 'cancelBtn');
  461. this.callParent();
  462. }
  463. });
  464. </pre>
  465. </body>
  466. </html>