1. #1
    Sencha User
    Join Date
    Oct 2007
    Location
    Iran
    Posts
    165
    Vote Rating
    0
    vahid4134 is on a distinguished road

      0  

    Default Persian Datepicker -- full work

    Persian Datepicker -- full work


    Hi
    For this you need
    http://www.extjs.com/forum/showthrea...593#post396593
    Update 4 Dec 2009, some fix for IE
    Code:
    Ext.override(Ext.DatePicker, {
        PmonthNames: Date.PmonthNames,
        PersianType: true,
    
        // private
        getShortMonthName: function(m) {
            return Date[(this.PersianType == true) ? "getPShortMonthName": "getShortMonthName"](m);
        },
    
        addDate: function(k, v) {
            return this.activeDate[(this.PersianType == true) ? "Padd": "add"](k, v);
        },
    
        // private
        onRender: function(container, position) {
            var m = [
                '<table cellspacing="0">',
                    '<tr>',
                        '<td class="x-date-left"><a href="#" title="', this.prevText, '">&#160;</a></td>',
                        '<td class="x-date-middle" align="center"></td>',
                        '<td class="x-date-right"><a href="#" title="', this.nextText, '">&#160;</a></td>',
                    '</tr>', 
                    '<tr>',
                        '<td colspan="3">',
                            '<table class="x-date-inner" cellspacing="0">',
                                '<thead>',
                                    '<tr>'
                ],
                dn = this.dayNames,
                i;
    
            for (i = 0; i < 7; i++) {
                var d = this.startDay + i;
                if (d > 6) {
                    d = d - 7;
                }
                m.push('<th><span>', dn[d].substr(0, 1), '</span></th>');
            }
    
            m[m.length] = '</tr></thead><tbody><tr>';
            
            for (i = 0; i < 42; i++) {
                if (i % 7 === 0 && i !== 0) {
                    m[m.length] = '</tr><tr>';
                }
                m[m.length] = '<td><a href="#" hidefocus="on" class="x-date-date" tabIndex="1"><em><span></span></em></a></td>';
            }
            
            m.push(
                '</tr></tbody></table></td></tr>',
                this.showToday ? '<tr><td colspan="3" class="x-date-bottom" align="center"></td></tr>' : '',
                '</table><div class="x-date-mp"></div>'
            );
    
            var el = document.createElement('div');
            el.className = 'x-date-picker';
            el.innerHTML = m.join('');
    
            container.dom.insertBefore(el, position);
    
            this.el = Ext.get(el);
            this.eventEl = Ext.get(el.firstChild);
    
            this.prevRepeater = new Ext.util.ClickRepeater(this.el.child('td.x-date-left a'), {
                handler: this.showPrevMonth,
                scope: this,
                preventDefault: true,
                stopDefault: true
            });
    
            this.nextRepeater = new Ext.util.ClickRepeater(this.el.child('td.x-date-right a'), {
                handler: this.showNextMonth,
                scope: this,
                preventDefault: true,
                stopDefault: true
            });
    
            this.monthPicker = this.el.down('div.x-date-mp');
            this.monthPicker.enableDisplayMode('block');
    
            this.keyNav = new Ext.KeyNav(this.eventEl, {
                'left': function(e) {
                    if (e.ctrlKey) {
                        this.showPrevMonth();
                    } else {
                        this.update(this.addDate('d', -1));
                    }
                },
    
                'right': function(e) {
                    if (e.ctrlKey) {
                        this.showNextMonth();
                    } else {
                        this.update(this.addDate('d', 1));
                    }
                },
    
                'up': function(e) {
                    if (e.ctrlKey) {
                        this.showNextYear();
                    } else {
                        this.update(this.addDate('d', -7));
                    }
                },
    
                'down': function(e) {
                    if (e.ctrlKey) {
                        this.showPrevYear();
                    } else {
                        this.update(this.addDate('d', 7));
                    }
                },
    
                'pageUp': function(e) {
                    this.showNextMonth();
                },
    
                'pageDown': function(e) {
                    this.showPrevMonth();
                },
    
                'enter': function(e) {
                    e.stopPropagation();
                    return true;
                },
    
                scope: this
            });
    
            this.el.unselectable();
    
            this.cells = this.el.select('table.x-date-inner tbody td');
            this.textNodes = this.el.query('table.x-date-inner tbody span');
    
            this.mbtn = new Ext.Button({
                text: '&#160;',
                tooltip: this.monthYearText,
                renderTo: this.el.child('td.x-date-middle', true)
            });
            this.mbtn.el.child('em').addClass('x-btn-arrow');
    
            if (this.showToday) {
                this.todayKeyListener = this.eventEl.addKeyListener(Ext.EventObject.SPACE, this.selectToday, this);
                var today = (new Date()).dateFormat(this.format);
                this.todayBtn = new Ext.Button({
                    renderTo: this.el.child('td.x-date-bottom', true),
                    text: String.format(this.todayText, today),
                    tooltip: String.format(this.todayTip, today),
                    handler: this.selectToday,
                    scope: this
                });
            }
            this.mon(this.eventEl, 'mousewheel', this.handleMouseWheel, this);
            this.mon(this.eventEl, 'click', this.handleDateClick, this, {
                delegate: 'a.x-date-date'
            });
            this.mon(this.mbtn, 'click', this.showMonthPicker, this);
            this.onEnable(true);
        },
    
        // private
        createMonthPicker: function() {
            if (!this.monthPicker.dom.firstChild) {
                var buf = ['<table border="0" cellspacing="0">'];
                for (var i = 0; i < 6; i++) {
                    buf.push(
                        '<tr>',
                            '<td class="x-date-mp-month"><a href="#">', this.getShortMonthName(i), '</a></td>', 
                            '<td class="x-date-mp-month x-date-mp-sep"><a href="#">', this.getShortMonthName(i + 6), '</a></td>', 
                            i === 0 ? '<td class="x-date-mp-ybtn" align="center"><a class="x-date-mp-prev"></a></td><td class="x-date-mp-ybtn" align="center"><a class="x-date-mp-next"></a></td></tr>' : '<td class="x-date-mp-year"><a href="#"></a></td><td class="x-date-mp-year"><a href="#"></a></td></tr>'
                    );
                }
                buf.push(
                    '<tr class="x-date-mp-btns"><td colspan="4"><button type="button" class="x-date-mp-ok">', this.okText, '</button>',
                    '<button type="button" class="x-date-mp-cancel">', this.cancelText, '</button></td></tr>', 
                    '</table>'
                );
                this.monthPicker.update(buf.join(''));
    
                this.mon(this.monthPicker, 'click', this.onMonthClick, this);
                this.mon(this.monthPicker, 'dblclick', this.onMonthDblClick, this);
    
                this.mpMonths = this.monthPicker.select('td.x-date-mp-month');
                this.mpYears = this.monthPicker.select('td.x-date-mp-year');
    
                this.mpMonths.each(function(m, a, i) {
                    i += 1;
                    if ((i % 2) === 0) {
                        m.dom.xmonth = 5 + Math.round(i * 0.5);
                    } else {
                        m.dom.xmonth = Math.round((i - 1) * 0.5);
                    }
                });
            }
        },
        
        // private
        showMonthPicker: function() {
            if (!this.disabled) {
                this.createMonthPicker();
                var size = this.el.getSize();
                this.monthPicker.setSize(size);
                this.monthPicker.child('table').setSize(size);
                if (this.PersianType == true) {
                    this.mpSelMonth = (this.activeDate || this.value).getPMonth();
                    this.mpSelYear = (this.activeDate || this.value).getPFullYear();
                } else {
                    this.mpSelMonth = (this.activeDate || this.value).getMonth();
                    this.mpSelYear = (this.activeDate || this.value).getFullYear();
                }
                this.updateMPMonth(this.mpSelMonth);
                this.updateMPYear(this.mpSelYear);
    
                this.monthPicker.slideIn('t', {
                    duration: 0.2
                });
            }
        },
    
        // private
        onMonthClick: function(e, t) {
            e.stopEvent();
    
            var el = new Ext.Element(t),
            pn;
            if (el.is('button.x-date-mp-cancel')) {
                this.hideMonthPicker();
            } else if (el.is('button.x-date-mp-ok')) {
                var d = new Date().clearTime();
                if (this.PersianType == true) {
                    d.setPFullYear(this.mpSelYear, this.mpSelMonth, (this.activeDate || this.value).getPDate());
                } else {
                    d.setFullYear(this.mpSelYear, this.mpSelMonth, (this.activeDate || this.value).getDate());
                }
    
                if (d[(this.PersianType == true) ? "getPMonth": "getMonth"]() != this.mpSelMonth) {
                    // 'fix' the JS rolling date conversion if needed
                    if (this.PersianType == true) {
                        d.setPDate(1);
                        d = d.getPLastDateOfMonth();
                    } else {
                        d.setDate(1);
                        d = getLastDateOfMonth();
                    }
                }
                this.update(d);
                this.hideMonthPicker();
            } else if ((pn = el.up('td.x-date-mp-month', 2))) {
                this.mpMonths.removeClass('x-date-mp-sel');
                pn.addClass('x-date-mp-sel');
                this.mpSelMonth = pn.dom.xmonth;
            } else if ((pn = el.up('td.x-date-mp-year', 2))) {
                this.mpYears.removeClass('x-date-mp-sel');
                pn.addClass('x-date-mp-sel');
                this.mpSelYear = pn.dom.xyear;
            } else if (el.is('a.x-date-mp-prev')) {
                this.updateMPYear(this.mpyear - 10);
            } else if (el.is('a.x-date-mp-next')) {
                this.updateMPYear(this.mpyear + 10);
            }
        },
    
        // private
        onMonthDblClick: function(e, t) {
            e.stopEvent();
            var el = new Ext.Element(t),
            pn;
            var d = new Date().clearTime();
            if ((pn = el.up('td.x-date-mp-month', 2))) {
                if (this.PersianType == true) {
                    d.setPFullYear(this.mpSelYear, pn.dom.xmonth, (this.activeDate || this.value).getPDate());
                } else {
                    d.setFullYear(this.mpSelYear, pn.dom.xmonth, (this.activeDate || this.value).getDate());
                }
            } else if ((pn = el.up('td.x-date-mp-year', 2))) {
                if (this.PersianType == true) {
                    d.setPFullYear(pn.dom.xyear, this.mpSelMonth, (this.activeDate || this.value).getPDate());
                } else {
                    d.setFullYear(pn.dom.xyear, this.mpSelMonth, (this.activeDate || this.value).getDate());
                }
            }
            this.update(d);
            this.hideMonthPicker();
        },
    
        // private
        showPrevMonth: function(e) {
            this.update(this.addDate('mo', -1));
        },
    
        // private
        showNextMonth: function(e) {
            this.update(this.addDate('mo', 1));
        },
    
        // private
        showPrevYear: function() {
            this.update(this.addDate('y', -1));
        },
    
        // private
        showNextYear: function() {
            this.update(this.addDate('y', 1));
        },
    
        // private
        update: function(date, forceRefresh) {
            if (this.rendered) {
                var vd = this.activeDate,
                vis = this.isVisible();
                this.activeDate = date;
                if (!forceRefresh && vd && this.el) {
                    var t = date.getTime();
                    if (vd.getMonth() == date.getMonth() && vd.getFullYear() == date.getFullYear()) {
                        this.cells.removeClass('x-date-selected');
                        this.cells.each(function(c) {
                            if (c.dom.firstChild.dateValue == t) {
                                c.addClass('x-date-selected');
                                if (vis) {
                                    Ext.fly(c.dom.firstChild).focus(50);
                                }
                                return false;
                            }
                        });
                        return;
                    }
                }
    
                var isP = this.PersianType;
                var days = date[(isP) ? "getPDaysInMonth": "getDaysInMonth"](),
                firstOfMonth = date[(isP) ? "getPFirstDateOfMonth": "getFirstDateOfMonth"](),
                startingPos = firstOfMonth.getDay() - this.startDay;
    
                if (startingPos < 0) {
                    startingPos += 7;
                }
    
                days += startingPos;
    
                var pm = date[(isP) ? "Padd": "add"]('mo', -1),
                prevStart = pm[(isP) ? "getPDaysInMonth": "getDaysInMonth"]() - startingPos,
                cells = this.cells.elements,
                textEls = this.textNodes,
                // convert everything to numbers so it's fast
                d = (new Date()).clearTime();
                if (isP) d.setPFullYear(pm.getPFullYear(), pm.getPMonth(), prevStart);
                else d.setFullYear(pm.getFullYear(), pm.getMonth(), prevStart);
                day = 86400000,
                today = new Date().clearTime().getTime(),
                sel = date.clearTime(true).getTime(),
                min = this.minDate ? this.minDate.clearTime(true) : Number.NEGATIVE_INFINITY,
                max = this.maxDate ? this.maxDate.clearTime(true) : Number.POSITIVE_INFINITY,
                ddMatch = this.disabledDatesRE,
                ddText = this.disabledDatesText,
                ddays = this.disabledDays ? this.disabledDays.join('') : false,
                ddaysText = this.disabledDaysText,
                format = this.format;
    
                if (this.showToday) {
                    var td = new Date().clearTime(),
                    disable = (td < min || td > max || (ddMatch && format && ddMatch.test(td.dateFormat(format))) || (ddays && ddays.indexOf(td.getDay()) != -1));
    
                    if (!this.disabled) {
                        this.todayBtn.setDisabled(disable);
                        this.todayKeyListener[disable ? 'disable': 'enable']();
                    }
                }
    
                var setCellClass = function(cal, cell) {
                    cell.title = '';
                    var t = d.getTime();
                    cell.firstChild.dateValue = t;
                    if (t == today) {
                        cell.className += ' x-date-today';
                        cell.title = cal.todayText;
                    }
                    if (t == sel) {
                        cell.className += ' x-date-selected';
                        if (vis) {
                            Ext.fly(cell.firstChild).focus(50);
                        }
                    }
                    // disabling
                    if (t < min) {
                        cell.className = ' x-date-disabled';
                        cell.title = cal.minText;
                        return;
                    }
                    if (t > max) {
                        cell.className = ' x-date-disabled';
                        cell.title = cal.maxText;
                        return;
                    }
                    if (ddays) {
                        if (ddays.indexOf(d.getDay()) != -1) {
                            cell.title = ddaysText;
                            cell.className = ' x-date-disabled';
                        }
                    }
                    if (ddMatch && format) {
                        var fvalue = d.dateFormat(format);
                        if (ddMatch.test(fvalue)) {
                            cell.title = ddText.replace('%0', fvalue);
                            cell.className = ' x-date-disabled';
                        }
                    }
                };
    
                var i = 0;
                for (; i < startingPos; i++) {
                    textEls[i].innerHTML = (++prevStart);
                    d.setDate(d.getDate() + 1);
                    cells[i].className = 'x-date-prevday';
                    setCellClass(this, cells[i]);
                }
                for (; i < days; i++) {
                    var intDay = i - startingPos + 1;
                    textEls[i].innerHTML = (intDay);
                    d.setDate(d.getDate() + 1);
                    cells[i].className = 'x-date-active';
                    setCellClass(this, cells[i]);
                }
                var extraDays = 0;
                for (; i < 42; i++) {
                    textEls[i].innerHTML = (++extraDays);
                    d.setDate(d.getDate() + 1);
                    cells[i].className = 'x-date-nextday';
                    setCellClass(this, cells[i]);
                }
                if (isP) {
                    this.mbtn.setText(this.PmonthNames[date.getPMonth()] + ' ' + date.getPFullYear());
                } else {
                    this.mbtn.setText(this.monthNames[date.getMonth()] + ' ' + date.getFullYear());
                }
    
                if (!this.internalRender) {
                    var main = this.el.dom.firstChild,
                    w = main.offsetWidth;
                    this.el.setWidth(w + this.el.getBorderWidth('lr'));
                    Ext.fly(main).setWidth(w);
                    this.internalRender = true;
    
                    // opera does not respect the auto grow header center column
                    // then, after it gets a width opera refuses to recalculate
                    // without a second pass
                    if (Ext.isOpera && !this.secondPass) {
                        main.rows[0].cells[1].style.width = (w - (main.rows[0].cells[0].offsetWidth + main.rows[0].cells[2].offsetWidth)) + 'px';
                        this.secondPass = true;
                        this.update.defer(10, this, [date]);
                    }
                }
            }
        }
    
    });
    
    Ext.override(Ext.form.DateField, {
        PersianType: true,
        
        initComponent: function() {
            Ext.form.DateField.superclass.initComponent.call(this);
    
            this.addEvents(
            /**
                 * @event select
                 * Fires when a date is selected via the date picker.
                 * @param {Ext.form.DateField} this
                 * @param {Date} date The date that was selected
                 */
            '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();
        },
    
        onTriggerClick: function() {
            if (this.disabled) {
                return;
            }
            if (this.menu == null) {
                this.menu = new Ext.menu.DateMenu({
                    hideOnClick: false
                });
            }
            this.onFocus();
            Ext.apply(this.menu.picker, {
                minDate: this.minValue,
                maxDate: this.maxValue,
                disabledDatesRE: this.disabledDatesRE,
                disabledDatesText: this.disabledDatesText,
                disabledDays: this.disabledDays,
                disabledDaysText: this.disabledDaysText,
                format: this.format,
                showToday: this.showToday,
                PersianType: this.PersianType,
                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');
        },
    
        parseDate: function(value) {
            if (!value || Ext.isDate(value)) {
                return value;
            }
            var isP = this.PersianType;
            var v = Date[(isP) ? "PparseDate": "parseDate"](value, this.format);
            if (!v && this.altFormats) {
                if (!this.altFormatsArray) {
                    this.altFormatsArray = this.altFormats.split("|");
                }
                for (var i = 0, len = this.altFormatsArray.length; i < len && !v; i++) {
                    v = Date[(isP) ? "PparseDate": "parseDate"](value, this.altFormatsArray[i]);
                }
            }
            return v;
        },
    
        formatDate: function(date) {
            return Ext.isDate(date) ? date[(this.PersianType) ? "PdateFormat": "dateFormat"](this.format) : date;
        }
    });
    Example
    PHP Code:
    Ext.onReady(function(){

        
    Ext.QuickTips.init();

        
    // turn on validation errors beside the field globally
        
    Ext.form.Field.prototype.msgTarget 'side';

        var 
    bd Ext.getBody();

        
    /*
         * ================  Simple form  =======================
         */
        
    bd.createChild({tag'h2'html'Form 1 - Very Simple'});


        var 
    simple = new Ext.FormPanel({
            
    labelWidth75// label settings here cascade unless overridden
            
    url:'save-form.php',
            
    frame:true,
            
    title'Simple Form',
            
    bodyStyle:'padding:5px 5px 0',
            
    width350,
            
    defaults: {width230},
            
    defaultType'textfield',

            
    items: [{
                    
    fieldLabel'Persian Date picker',
                    
    name'pdatepicker',
                    
    allowBlank:false,
            
    PersianType:true,
            
    format:"d-m-Y F",
            
    xtype:"datefield"
                
    }
            ],

            
    buttons: [{
                
    text'Save'
            
    },{
                
    text'Cancel'
            
    }]
        });

        
    simple.render(document.body);

     
    }); 
    Last edited by mystix; 5 Dec 2009 at 7:53 AM. Reason: edited extension code for missing non-breaking space  
    No honor is like knowledge

  2. #2
    Sencha User
    Join Date
    Oct 2009
    Location
    Tehran
    Posts
    18
    Vote Rating
    0
    mrlayeghi is on a distinguished road

      0  

    Default


    Thanks.

Thread Participants: 1