1. #1
    Ext JS Premium Member
    Join Date
    Oct 2007
    Location
    Herndon, VA
    Posts
    265
    Vote Rating
    3
    durlabh is on a distinguished road

      0  

    Default Simple Calendar Panel

    Simple Calendar Panel


    I needed a simple calendar simple to DatePicker control. The example includes handling of mouse over and click events for showing additional information for each day. Live example at:

    http://www.durlabh.com/extJS/example.../calendar.html

    You can download the code from:

    http://www.durlabh.com/extJS/example...r/calendar.zip

    Some of the features are:
    * Ability to easily specify the mouse over, color/ content of individual cell based on date
    * Resizable
    * Fast switching between months

    To test, place the files in extJS\examples\Calendar folder. Here is the code if you are having trouble downloading:

    Calendar.css
    Code:
    .ux-cal
    {
        font-size:11px;
    }
    
    .ux-cal .ux-cal-weekday
    {
        background:#DFECFB url(../../resources/images/default/shared/glass-bg.gif) repeat-x scroll left top;
        font-weight:bold;
        height:25px;
    }
    
    .ux-cal .ux-cal-header
    {
        background:transparent url(../../resources/images/default/shared/hd-sprite.gif) repeat-x scroll 0 -83px;
        height:25px;
    }
    
    .ux-cal .ux-cal-header .ux-cal-monthTitle
    {
        text-align:center;
        color:#ffffff;
        font-weight:bold;
    }
    
    
    .ux-cal td
    {
        text-align: center;
        vertical-align: middle;
        border:solid 1px white;
        cursor:pointer;
    }
    
    .ux-cal .ux-cal-row td:hover
    {
        background: #ddecfe;
    }
    
    .ux-cal .otherMonth
    {
        color: #AAAAAA;
    }
    
    .ux-cal-weekday td
    {
        cursor:default;
    }
    Calendar.js
    Code:
    Ext.ux.Calendar = function(config) {
        Ext.ux.Calendar.superclass.constructor.call(this, config);
        this.addEvents({
            click: true,
            mouseover: true,
            mouseout: true
        });
    };
    
    Ext.ux.Calendar = Ext.extend(Ext.Panel, {
        onRender: function(container, position) {
            Ext.ux.Calendar.superclass.onRender.apply(this, arguments);
            this.createInitialLayout();
            this.update();
        },
        daysOfWeek: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
        value: new Date(),
        moveMonths: function(months) {
            this.value = this.value.add(Date.MONTH, months);
            this.update();
        },
        showPrevMonth: function() {
            this.moveMonths(-1);
        },
        showNextMonth: function() {
            this.moveMonths(1);
        },
        showNavigation: true,
    
        createInitialLayout: function() {
            var htmlData = [];
            htmlData.push("<table class=\"ux-cal\" width='100%' height='100%' cellspacing='0'>");
    
            htmlData.push("<thead>");
            htmlData.push("<tr class='ux-cal-header'>");
            htmlData.push("<th><div class='x-date-left'><a href='#'>&nbsp;</a></th>")
            htmlData.push("<th colspan='5' class='ux-cal-monthTitle'>&nbsp;</th>");
            htmlData.push("<th><div class='x-date-right' style='float:right'><a href='#'>&nbsp;</a></div></th>")
            htmlData.push('</th></tr>');
            htmlData.push('</thead>');
            htmlData.push('<tbody>');
    
            htmlData.push("<tr class='ux-cal-weekday'>");
            var daysOfWeek = this.daysOfWeek;
            for (var i = 0; i < 7; i++) {
                var width = i == 0 || i == 6 ? 15 : 14;
                htmlData.push('<td width="' + width + '%">' + daysOfWeek[i] + '</td>');
            }
            htmlData.push('</tr>');
    
            for (var i = 0; i < 42; i++) {
                if (i % 7 == 0) { // First day of week
                    htmlData.push("<tr class='ux-cal-row'>");
                }
                htmlData.push("<td>&nbsp;</td>");
                if (i % 7 == 6) { // Last day of week
                    htmlData.push("</tr>");
                }
            }
            htmlData.push('</tbody>');
            htmlData.push("</table>");
            this.body.update(htmlData.join(""));
    
            var leftNav = this.body.child("div.x-date-left a");
            var rightNav = this.body.child("div.x-date-right a");
            this.leftClickRpt = new Ext.util.ClickRepeater(leftNav, { handler: this.showPrevMonth, scope: this, preventDefault: true, stopDefault: true });
            this.rightClickRpt = new Ext.util.ClickRepeater(rightNav, { handler: this.showNextMonth, scope: this, preventDefault: true, stopDefault: true });
    
            var showNavigation = this.showNavigation;
            leftNav.setDisplayed(showNavigation);
            rightNav.setDisplayed(showNavigation);
            this.calendarHeaderEl = this.body.child('th.ux-cal-monthTitle');
    
            var table = this.body.select('table');
            table.on({
                mouseover: this.onMouseOver,
                mouseout: this.onMouseOut,
                click: this.onClick,
                scope: this
            });
    
            this.cells = this.body.select('tbody td');
        },
    
        beforeDestroy: function() {
            this.leftClickRpt.destroy();
            this.rightClickRpt.destroy();
            this.cells.destroy();
            Ext.ux.Calendar.superclass.beforeDestroy.apply(this, arguments);
        },
    
        onMouseOver: function(e) {
            this.processEvent('mouseover', e);
        },
    
        onMouseOut: function(e) {
            this.fireEvent('mouseout', e, this);
        },
    
        onClick: function(e) {
            this.processEvent('click', e);
        },
    
        processEvent: function(eventName, e) {
            var t = e.getTarget();
            var o = {};
            if (t.tagName == 'TD') {
                var cell = t;
                var row = t.parentNode;
                var rowIndex = row.rowIndex - 2; // Ignore header rows
                o = { cellIndex: cell.cellIndex, rowIndex: rowIndex, row: row, cell: cell };
                if (rowIndex >= 0) {
                    o.date = this.startOfCalendar.add(Date.DAY, ((o.rowIndex) * 7) + o.cellIndex);
                }
            }
            this.fireEvent(eventName, o, e);
        },
    
        update: function() {
            var value = this.value.clearTime();
            var startOfCalendar = value.getFirstDateOfMonth();
            var endOfCalendar = startOfCalendar.getLastDateOfMonth();
    
            var startWeekDay = Number(startOfCalendar.format("N"));
            if (startWeekDay > 0) {
                startOfCalendar = startOfCalendar.add(Date.DAY, -startWeekDay);
            }
    
            var endWeekDay = Number(endOfCalendar.format("N"));
            if (endWeekDay < 6) {
                endOfCalendar = endOfCalendar.add(Date.DAY, 6 - endWeekDay);
            }
    
            var duration = endOfCalendar - startOfCalendar;
            var oneDay = 1000 * 60 * 60 * 24;
            duration = duration / oneDay + 1;
    
            endOfCalendar = endOfCalendar.add(Date.DAY, 42 - duration);
    
            var htmlData = [];
    
            var calendarTitle = value.format("F, Y");
            this.calendarHeaderEl.update(calendarTitle);
    
            var currentMonth = value.format("m");
            var o = { today: new Date().clearTime(), date: startOfCalendar };
            var cells = this.cells.elements;
            this.startOfCalendar = startOfCalendar;
            for (var i = 0; i < 42; i++) {
    
                o.css = o.date.format("m") == currentMonth ? "sameMonth" : "otherMonth";
                o.css += " x-unselectable";
                o.caption = o.date.format("d");
                o.cell = cells[i + 7];
    
                this.formatDay(o);
    
                o.cell.className = o.css;
                o.cell.innerHTML = o.caption;
                o.date = o.date.add(Date.DAY, 1);
            }
        },
        beforeDestroy: function() {
            if (this.rendered) {
                Ext.destroy(
                    this.leftClickRpt,
                    this.rightClickRpt
                );
            }
            Ext.ux.Calendar.superclass.beforeDestroy.apply(this, arguments);
        }
    });
    Ext.reg('ux-cal', Ext.ux.Calendar);
    Sample implementation showing mouse over/ click event handling:
    Code:
    <html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
        <title>Calendar Example</title>
        <link rel="stylesheet" type="text/css" href="../../resources/css/ext-all.css" />
         <script type="text/javascript" src="../../adapter/ext/ext-base.js"></script>
        <script type="text/javascript" src="../../ext-all.js"></script>
    
        <script language="javascript" src="calendar.js"></script>
        <link rel="stylesheet" type="text/css" href="calendar.css" />
        <style>
            .ux-cal-highlight { background-color: gray; }
        </style>
    </head>
    <body>
        <a href="javascript:emulateAJAX()">Reset calendar data</a>
    </body>
    <script type="text/javascript">
        emulateAJAX = function() {
            // Sample data that could have been from AJAX request
            homeCalendar.dates = {
                '20090614': '14-Jun-2009 Data'
            }
            if (homeCalendar.rendered) {
                homeCalendar.update();
            }
        };
    
    
        homeCalendar = new Ext.ux.Calendar({
            // Sample data
            dates: {
                '20090615': 'Test'
            },
            getData: function(o) {
                return this.dates[o.date.format("Ymd")];
            },
            // Custom formatting based on date
            formatDay: function(o) {
                var data = this.getData(o);
                if (data) {
                    o.css += " ux-cal-highlight";
                    o.caption += "*";
                }
            },
            listeners: {
                // Sample for click handling
                click: function(o) {
                    if (o.date) {
                        var data = this.getData(o);
                        if (data) {
                            Ext.Msg.alert('Alert', 'Event on ' + o.date.toString() + ":" + data);
                        } else {
                            Ext.Msg.alert('Alert', 'No event scheduled on ' + o.date.toString());
                        }
                    }
                },
    
                // Sample for mouse over handling to show tool-tip
                mouseover: function(o) {
                    if (!o.date) {
                        this.tooltip.hide();
                    } else {
                        var text = o.date.toString();
                        if (this.tooltip.rendered) {
                            this.tooltip.body.dom.innerHTML = text;
                        } else {
                            this.tooltip.html = text;
                        }
                        this.tooltip.show();
                    }
                },
    
                // Adding tool-tip to the calendar
                render: function() {
                    this.tooltip = new Ext.ToolTip({
                        target: this.body,
                        showDelay: 20,
                        trackMouse: true
                    })
                },
    
                destroy: function() {
                    this.tooltip.destroy();
                }
            }
        });
        Ext.QuickTips.init();
    
        var win = new Ext.Window({
            height: 300,
            width: 300,
            layout: 'fit',
            items: homeCalendar,
            title: 'Calendar'
        });
        win.show();
    </script>
    </html>
    Last edited by durlabh; 17 Jun 2009 at 10:21 AM. Reason: Include source inline

  2. #2
    Ext User
    Join Date
    Apr 2009
    Posts
    49
    Vote Rating
    0
    canakaltun is on a distinguished road

      0  

    Default


    this is not working
    i downloaded the zip fıle and
    error message is homeCalendar is not defined
    help please

  3. #3
    Sencha User
    Join Date
    Mar 2009
    Posts
    356
    Vote Rating
    0
    koko2589 is on a distinguished road

      0  

    Default


    tankyou how i open windo from date?i want cklick on date 1 to open window 1
    click date 2 to open window 2?
    my ext js site
    http://www.itoto4.com/

  4. #4
    Sencha User
    Join Date
    Mar 2008
    Posts
    566
    Vote Rating
    0
    moegal is on a distinguished road

      0  

    Default


    Looks great. I am suprised there is not already something like this. Go figure.

    Marty

  5. #5
    Ext JS Premium Member
    Join Date
    Oct 2007
    Location
    Herndon, VA
    Posts
    265
    Vote Rating
    3
    durlabh is on a distinguished road

      0  

    Default


    canakaltun: Can you make sure that you extracted the files in the ExtJS samples folder? Ideally files should be in something like extJS\examples\calendar. If it is not, please make sure the references to extJS resources/ JS files are correct.

    koko2589: In calendar.html you have example where you can do selective handling of events based on date clicked. So, you can do something like:

    Code:
                    if (o.date) {
                        if(o.date.format("Ymd") == '20080615') {
                             Ext.Msg.alert('My action of 15-Jun-2008');
                        } else {
                             Ext.Msg.alert('Other date clicked: ' + o.date.toString());
                        }
                    }

  6. #6
    Ext User
    Join Date
    Apr 2009
    Posts
    49
    Vote Rating
    0
    canakaltun is on a distinguished road

      0  

    Default


    hi durlabh
    tahnk for reply
    if i start calander.html only it works
    but
    i wanna put it into a tab (i am working on docs like layout browser sample)
    can u help me

  7. #7
    Ext JS Premium Member
    Join Date
    Oct 2007
    Location
    Herndon, VA
    Posts
    265
    Vote Rating
    3
    durlabh is on a distinguished road

      0  

    Default


    Can you put some code so that we can figure out what's the issue? I tried changing calendar.html by giving a title to homeCalendar and then instead of declaring win:

    Code:
        var tab = new Ext.TabPanel({
            height: 300,
            width: 300,
            items: [homeCalendar, { title: 'Another Tab'}],
            activeTab: 0
        });
        tab.render(document.body);
    It is working absolutely fine for me!

  8. #8
    Sencha - Community Support Team mankz's Avatar
    Join Date
    Nov 2007
    Location
    Stockholm, Sweden
    Posts
    2,804
    Vote Rating
    133
    mankz is a splendid one to behold mankz is a splendid one to behold mankz is a splendid one to behold mankz is a splendid one to behold mankz is a splendid one to behold mankz is a splendid one to behold

      0  

    Default


    Nice work! 2 small requests:

    1. Remove time in tooltip
    2. Animate month transitions


  9. #9
    Ext JS Premium Member
    Join Date
    Oct 2007
    Location
    Herndon, VA
    Posts
    265
    Vote Rating
    3
    durlabh is on a distinguished road

      0  

    Default


    mankz, Tooltip is not part of the control itself. It is just to demonstrate the capabilities of the UX itself. So, you can customize whatever way you want.

    As for transition animation, since I replace the cell content right now instead of replacing the whole table (for speed), animation won't be easily possible.

  10. #10
    Sencha User Remy's Avatar
    Join Date
    Apr 2008
    Posts
    298
    Vote Rating
    0
    Remy is on a distinguished road

      0  

    Default


    +1 for tranisition animation

    Can I also suggest a trigger for year/month selection (possibly in header)?