We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 27519
    • 275 Posts
    I want to replace the standard date picker used by date fields with my own implementation.

    I’m looking for a way of setting a date field with my new implemented date picker.

    Any help on how to do this is much appreciated.
      MODx Revolution / MAMP / OS X
      • 27519
      • 275 Posts
      You’ll have to do the following
      :
      1. Create a subclass of Ext.menu.DateMenu and override its initComponent method to create an instance of custom DatePicker
      2. Create a subclass of Ext.form.DateField and override its onTriggerClick method to create an instance of the class sub (1)

      Remember to call all overridden methods by calling YourNameSpace.YourClass.superclass.initComponent.call(this) otherwise you might miss out on vital functionality / initialisation.
        MODx Revolution / MAMP / OS X
      • Do you have an example of how to do this? I got a basic date-picker working following this article:
        http://www.devarticles.com/c/a/JavaScript/Using-the-EXT-JS-Date-Picker-Widget/3/

        but I’m lost at how to do more than that...
          • 3749
          • 24,544 Posts
          Quote from: Everett at Nov 08, 2010, 06:10 PM

          Do you have an example of how to do this? I got a basic date-picker working following this article:
          http://www.devarticles.com/c/a/JavaScript/Using-the-EXT-JS-Date-Picker-Widget/3/

          but I’m lost at how to do more than that...

          That worked for me too, but I’m still working on getting it to handle more than one date field on the same page.


          I also can’t find the calendar icon that the Manager uses. I know it’s there somewhere, but it’s pretty well hidden. wink

          BTW, you need to add

          return false;

          to the clickHandler function in that article in order to keep FF from submitting the form when you click on the datepicker.
            Did I help you? Buy me a beer
            Get my Book: MODX:The Official Guide
            MODX info for everyone: http://bobsguides.com/modx.html
            My MODX Extras
            Bob's Guides is now hosted at A2 MODX Hosting
          • That’s helpful Bob. Man, it’s maddening when you *know* that JS Ext does all this stuff, but I end up including a bunch of jQuery files because I can’t decipher JS Ext. I got that example working... kind of... but not formatted or anything. We should get a page up in the docs for how to emulate MODx’s use of this in our own Snippets / Custom Manager Pages.

            Good tip re the false bit. Could it be because any use of the <button> tag will default to type="submit"? Normally you have to specify type="button" to avoid the form submitting.
              • 3749
              • 24,544 Posts
              Quote from: Everett at Nov 08, 2010, 07:55 PM

              That’s helpful Bob. Man, it’s maddening when you *know* that JS Ext does all this stuff, but I end up including a bunch of jQuery files because I can’t decipher JS Ext. I got that example working... kind of... but not formatted or anything. We should get a page up in the docs for how to emulate MODx’s use of this in our own Snippets / Custom Manager Pages.

              Good tip re the false bit. Could it be because any use of the <button> tag will default to type="submit"? Normally you have to specify type="button" to avoid the form submitting.

              Great idea (can you put it up yesterday -- I’ve got about 6 hours of my life I need back). wink

              FF submitted the form for me even with type="button."

              BTW, here’s what I have included for the snippet -- the date picker is pretty well formatted:

              $modx->regClientCSS(MODX_MANAGER_URL . 'assets/ext3/resources/css/ext-all-notheme-min.css');
              $modx->regClientCSS(MODX_MANAGER_URL . 'templates/default/css/xtheme-modx.css');
              $modx->regClientCSS(MODX_MANAGER_URL . 'templates/default/css/index.css');
              
              
              $modx->regClientScript(MODX_MANAGER_URL . 'assets/ext3/adapter/ext/ext-base.js');
              $modx->regClientScript(MODX_MANAGER_URL . 'assets/ext3/ext-all.js');
              $modx->regClientScript(MODX_ASSETS_URL . 'components/newspublisher/newspublisher.js');
              

              newspublisher.js contains the JS from the tutorial (minus the script tags).
                Did I help you? Buy me a beer
                Get my Book: MODX:The Official Guide
                MODX info for everyone: http://bobsguides.com/modx.html
                My MODX Extras
                Bob's Guides is now hosted at A2 MODX Hosting
                • 27519
                • 275 Posts
                Quote from: Everett at Nov 08, 2010, 06:10 PM

                Do you have an example of how to do this? I got a basic date-picker working following this article:
                http://www.devarticles.com/c/a/JavaScript/Using-the-EXT-JS-Date-Picker-Widget/3/

                but I’m lost at how to do more than that...

                Sorry, I missed your post.

                Here’s my version of date field. In the end I did not touch the actual DatePicker class but had a wrestle with the date field. The crux is in the onTriggerClick where I added a new JSON store to wander off to the database and retrieve all booked dates. These dates are then marked as disabled, which is standard behaviour of the Date Picker.

                When overriding default Ext methods, make sure you inspect the method you override and call the superclass methods as well to prevent eliminating essential initialisation or default behaviour. Where you call the superclass method in your own method depends on what you want to achieve, so there’s no simple rule there.

                This is not the finished article; I still need to come back to this and apply some custom styles to the date picker. Right now booked dates are shown using the standard style of DatePicker but I want to apply my own styles. I found the method that actually does this but I’m not too sure where to put my custom styles.

                Anyway, hope this helps... feel free to ask if you need further information.

                Ext.namespace('Tariffs.form');
                Ext.namespace('Tariffs.menu');
                
                Tariffs.form.CalendarField = Ext.extend(Ext.form.DateField,  {
                
                	cottage: 0,
                
                	setCottage : function(value) {
                		this.cottage = value;
                	},
                
                	onTriggerClick : function(){
                		if(this.disabled){
                			return;
                		}
                		if(this.menu == null){
                			this.menu = new Tariffs.menu.CalendarMenu({
                				hideOnClick: false,
                				focusOnSelect: false
                			});
                		}
                		this.onFocus();
                		// JsonStore fetches booked dates from the backend calendar to register
                		// as  disabled dates with the date picker object.
                		var dstore = new Ext.data.JsonStore({
                			url: Tariffs.config.connector_url
                			,baseParams: {
                				action: 'mgr/calendar/getinvaliddates'
                				,cottage: this.cottage
                			}
                			,fields: ['invalids']
                			,root: 'invalids'
                			,listeners: {
                				// Wait for load to complete and then process disabled dates
                				// into date picket.
                				'load': {fn:function() {
                					var count = dstore.getCount();
                					var invalids = [];
                					for (i=0; i<count; i++) {
                						var rec = dstore.getAt(i);
                						invalids[i] = rec.json;
                					}
                					if (invalids.length > 0) {
                						this.setDisabledDates(invalids);
                					} else {
                						this.setDisabledDates(null);
                					}
                					Ext.apply(this.menu.picker,  {
                						startDay: this.startDay,
                						minDate : this.minValue,
                						maxDate : this.maxValue,
                						disabledDatesRE : this.disabledDatesRE,
                						disabledDatesText : this.disabledDatesText,
                						disabledDaysText : this.disabledDaysText,
                						format : this.format,
                						showToday : this.showToday,
                						minText : String.format(this.minText, this.formatDate(this.minValue)),
                						maxText : String.format(this.maxText, this.formatDate(this.maxValue))
                					});
                					this.menu.picker.setValue(this.getValue() || new Date());
                					this.menu.show(this.el, "tl-bl?");
                					this.menuEvents('on');
                				}, scope:this}
                			}
                		});
                		dstore.load();
                	},
                
                	initComponent : function(){
                		Ext.form.DateField.superclass.initComponent.call(this);
                		this.addEvents(
                			'select'
                		);
                		if(Ext.isString(this.minValue)){
                			this.minValue = this.parseDate(this.minValue);
                		}
                		if(Ext.isString(this.maxValue)){
                			this.maxValue = this.parseDate(this.maxValue);
                		}
                		/*this.disabledDatesRE = null;*/
                		this.initDisabledDays();
                	},
                
                	initDisabledDays : function(){
                		if(this.disabledDates){
                			var dd = this.disabledDates,
                				len = dd.length - 1,
                				re = "(?:";
                			Ext.each(dd, function(d, i){
                				re += Ext.isDate(d) ? '^' + Ext.escapeRe(d.dateFormat(this.format)) + '$' : dd[i];
                				if(i != len){
                					re += '|';
                				}
                			}, this);
                			this.disabledDatesRE = new RegExp(re + ')');
                		} else {
                			this.disabledDatesRE = null;
                		}
                    }
                
                
                });
                Ext.reg('calendarfield', Tariffs.form.CalendarField);
                
                Tariffs.menu.CalendarMenu = Ext.extend(Ext.menu.DateMenu, {
                
                    initComponent : function(){
                        this.on('beforeshow', this.onBeforeShow, this);
                        if(this.strict = (Ext.isIE7 && Ext.isStrict)){
                            this.on('show', this.onShow, this, {single: true, delay: 20});
                        }
                        Ext.apply(this, {
                            plain: true,
                            showSeparator: false,
                            items: this.picker = new Tariffs.CalendarPicker(Ext.applyIf({
                                internalRender: this.strict || !Ext.isIE,
                                ctCls: 'x-menu-date-item',
                                id: this.pickerId
                            }, this.initialConfig))
                        });
                        this.picker.purgeListeners();
                        Tariffs.menu.CalendarMenu.superclass.initComponent.call(this);
                        /**
                         * @event select
                         * Fires when a date is selected from the {@link #picker Ext.DatePicker}
                         * @param {DatePicker} picker The {@link #picker Ext.DatePicker}
                         * @param {Date} date The selected date
                         */
                        this.relayEvents(this.picker, ['select']);
                        this.on('show', this.picker.focus, this.picker);
                        this.on('select', this.menuHide, this);
                        if(this.handler){
                            this.on('select', this.handler, this.scope || this);
                        }
                    }
                
                });
                Ext.reg('calendarmenu', Tariffs.menu.CalendarMenu);
                
                Tariffs.CalendarPicker = Ext.extend(Ext.DatePicker, {
                
                    initComponent : function(){
                        Tariffs.CalendarPicker.superclass.initComponent.call(this);
                    }
                
                });
                Ext.reg('calendarpicker', Tariffs.CalendarPicker);

                  MODx Revolution / MAMP / OS X
                  • 3749
                  • 24,544 Posts
                  After spending a day trying to get the ext built-in datepicker to handle multiple fields on the same page, I tried this datepicker:
                  http://www.frequency-decoder.com/2009/02/03/unobtrusive-date-picker-widget-v4.

                  I had it working in about 20 minutes and it has a number of really nices features although the calendar is not as pretty as it might be and it generates an unnecessary last row for some months.

                    Did I help you? Buy me a beer
                    Get my Book: MODX:The Official Guide
                    MODX info for everyone: http://bobsguides.com/modx.html
                    My MODX Extras
                    Bob's Guides is now hosted at A2 MODX Hosting
                    • 4172
                    • 5,888 Posts
                    Bob, see how Shaun has it done with date-tvs.
                    Perhaps you can try to load complete tv-input-types to your form-panel with autolaod/load/extjs-updater for revo-newspublisher as I did it in xdbedit-custom-table-editor.
                    Then, if you need special input-types you need only create a new custum-tv-input-type and you can use them on backend and on frontend.
                      -------------------------------

                      you can buy me a beer, if you like MIGX

                      http://webcmsolutions.de/migx.html

                      Thanks!
                      • 3749
                      • 24,544 Posts
                      Quote from: Bruno17 at Nov 09, 2010, 03:37 PM

                      Bob, see how Shaun has it done with date-tvs.
                      Perhaps you can try to load complete tv-input-types to your form-panel with autolaod/load/extjs-updater for revo-newspublisher as I did it in xdbedit-custom-table-editor.
                      Then, if you need special input-types you need only create a new custum-tv-input-type and you can use them on backend and on frontend.

                      Thanks for the tip. I’m not sure how far I want to take it, since it might be better to base front-end editing solutions on FormIt and FormIt2Resource. That would give you superior validation options and probably a smaller footprint. I just wanted to provide a NewsPublisher equivalent for people who already use that in Evo and want to convert. It does that now, with the exception of the RTE (which I haven’t tried yet) and the NewsPublisher minimal validation. I also quite like the Unobtrusive datepicker. It has built-in multilanguage support and lets you disable certain days of the week. It’s also really easy to configure just by editing the <input> string in the form.

                      BTW, is there a Revo equivalent to webAlert()?

                        Did I help you? Buy me a beer
                        Get my Book: MODX:The Official Guide
                        MODX info for everyone: http://bobsguides.com/modx.html
                        My MODX Extras
                        Bob's Guides is now hosted at A2 MODX Hosting