[COMPLETE] Ability to use times other than :00 and :30

Plugins and extensions for Extensible components, usage examples, links to applications using Extensible, etc.

[COMPLETE] Ability to use times other than :00 and :30

Postby nebbian » Sun Oct 31, 2010 5:02 am


I'm not entirely sure where to post this, so please feel free to move it if I've put this in the wrong section...

I'm evaluating Extensible at the moment for a project I'm working on, and it looks quite nice. However my situation requires ten minute increments on the times when dragging events around.

So I've updated CalendarView.js to use a new config variable called "incrementsPerHour", which in my application I override to 6. By default it's set to 2, which means that existing functionality is preserved.

Code: Select all
     * @cfg {Integer} incrementsPerHour
     * the number of time increments to show per hour.  2 = thirty minute increments, 6 = ten minute increments
    incrementsPerHour: 2,

Now in DayBodyView.js, I've modified getDayAt to use this new config variable:

Code: Select all
    // private
    getDayAt : function(x, y){
        var sel = '.ext-cal-body-ct',
            xoffset = this.el.child('.ext-cal-day-times').getWidth(),
            viewBox = this.el.getBox(),
            daySize = this.getDaySize(false),
            relX = x - viewBox.x - xoffset,
            dayIndex = Math.floor(relX / daySize.width), // clicked col index
            scroll = this.el.getScroll(),
            row = this.el.child('.ext-cal-bg-row'), // first avail row, just to calc size
            rowH = row.getHeight() / this.incrementsPerHour, // use the incrementsPerHour config variable
            relY = y - viewBox.y - rowH + scroll.top,
            rowIndex = Math.max(0, Math.ceil(relY / rowH)),
            mins = rowIndex * (60 / this.incrementsPerHour),
            dt = this.viewStart.add(Date.DAY, dayIndex).add(Date.MINUTE, mins),
            el = this.getDayEl(dt),
            timeX = x;
            timeX = el.getLeft();
        return {
            date: dt,
            el: el,
            // this is the box for the specific time block in the day that was clicked on:
            timeBox: {
                x: timeX,
                y: (rowIndex * 42 / this.incrementsPerHour) + viewBox.y - scroll.top,
                width: daySize.width,
                height: rowH

It's also necessary to replace all instances of '30' with (60 / this.view.incrementsPerHour) inside calendar/dd/DayViewDD.js:

Code: Select all
Ext.ensible.cal.DayViewDropZone = Ext.extend(Ext.ensible.cal.DropZone, {
    ddGroup : 'DayViewDD',
    dateRangeFormat : '{0}-{1}',
    dateFormat : 'n/j',
    onNodeOver : function(n, dd, e, data){
        var dt, text = this.createText,
            timeFormat = Ext.ensible.Date.use24HourTime ? 'G:i' : 'g:ia';
        if(data.type == 'caldrag'){
                // Since the container can scroll, this gets a little tricky.
                // There is no el in the DOM that we can measure by default since
                // the box is simply calculated from the original drag start (as opposed
                // to dragging or resizing the event where the orig event box is present).
                // To work around this we add a placeholder el into the DOM and give it
                // the original starting time's box so that we can grab its updated
                // box measurements as the underlying container scrolls up or down.
                // This placeholder is removed in onNodeDrop.
                this.dragStartMarker = n.el.parent().createChild({
                    style: 'position:absolute;'
                this.dragCreateDt = n.date;
            var endDt, box = this.dragStartMarker.getBox();
            box.height = Math.ceil(Math.abs(e.xy[1] - box.y) / n.timeBox.height) * n.timeBox.height;
            if(e.xy[1] < box.y){
                box.height += n.timeBox.height;
                box.y = box.y - box.height + n.timeBox.height;
                endDt = this.dragCreateDt.add(Date.MINUTE, (60 / this.view.incrementsPerHour));
                n.date = n.date.add(Date.MINUTE, (60 / this.view.incrementsPerHour));
            this.shim(this.dragCreateDt, box);
            var curr = Ext.ensible.Date.copyTime(n.date, this.dragCreateDt);
            this.dragStartDate = Ext.ensible.Date.min(this.dragCreateDt, curr);
            this.dragEndDate = endDt || Ext.ensible.Date.max(this.dragCreateDt, curr);
            dt = String.format(this.dateRangeFormat, this.dragStartDate.format(timeFormat), this.dragEndDate.format(timeFormat));
            var evtEl = Ext.get(data.ddel),
                dayCol = evtEl.parent().parent(),
                box = evtEl.getBox();
            box.width = dayCol.getWidth();
            if(data.type == 'eventdrag'){
                if(this.dragOffset === undefined){
                    this.dragOffset = n.timeBox.y-box.y;
                    box.y = n.timeBox.y-this.dragOffset;
                    box.y = n.timeBox.y;
                dt = n.date.format(this.dateFormat + ' ' + timeFormat);
                box.x = n.el.getLeft();
                this.shim(n.date, box);
                text = this.moveText;
            if(data.type == 'eventresize'){
                    this.resizeDt = n.date;
                box.x = dayCol.getLeft();
                box.height = Math.ceil(Math.abs(e.xy[1] - box.y) / n.timeBox.height) * n.timeBox.height;
                if(e.xy[1] < box.y){
                    box.y -= box.height;
                    n.date = n.date.add(Date.MINUTE, (60 / this.view.incrementsPerHour));
                this.shim(this.resizeDt, box);
                var curr = Ext.ensible.Date.copyTime(n.date, this.resizeDt),
                    start = Ext.ensible.Date.min(data.eventStart, curr),
                    end = Ext.ensible.Date.max(data.eventStart, curr);
                data.resizeDates = {
                    StartDate: start,
                    EndDate: end
                dt = String.format(this.dateRangeFormat, start.format(timeFormat), end.format(timeFormat));
                text = this.resizeText;
        data.proxy.updateMsg(String.format(text, dt));
        return this.dropAllowed;


Now by changing your viewConfig you can get ten minute increments:
Code: Select all
 // Any generic view options that should be applied to all sub views:
                        viewConfig: {
                            //enableFx: false
                            incrementsPerHour: 6

Screen shot 2010-10-31 at 7.59.39 PM.png
Screen shot 2010-10-31 at 7.59.39 PM.png (15.56 KiB) Viewed 6140 times

I hope this helps someone :)
Posts: 17
Joined: Sat Oct 30, 2010 9:22 pm

Re: Ability to use times other than :00 and :30

Postby devil1591 » Sun Oct 31, 2010 3:03 pm

Thanks for this addon!
This should be added as a new feature in the next release!
ExtJS: 3.3.1 - Ext.ensible: 1.0.1 - Windows XP SP3 - Firefox 6.0.1
User avatar
Posts: 36
Joined: Thu Oct 07, 2010 2:34 am
Location: Paris, France

Re: Ability to use times other than :00 and :30

Postby brian.moeskau » Mon Jan 10, 2011 11:09 pm

I have (finally) integrated this feature into Git. I started with the patch kindly provided by nebbian via Github, but I also refactored it for various reasons. You can see the changes I made in the commit page, but here are the main points:

  • Removed the "incrementsPerHour" config from CalendarView -- it only applies to DayView and subclasses (although you can still pass it generically in viewCfg and it will get applied correctly).
  • Added config to DayView but renamed it to "ddIncrement". From the user's perspective this setting really only applies to drag operations, so I thought that name was more descriptive of the function (and sorts with the other dd configs). More importantly, the meaning has been switched to an explicit minute increment, rather than an hour division increment. The difference is that I think it's easier to specify that you want to drag in "10 minute increments" as opposed to having to mentally calculate "60 mins / 10 mins = 6 increments per hour" the previous way.
  • I also added a "minEventDisplayMinutes" option on DayView while I was messing with the overlap code. This controls the minimum display height for events. Rather than basing the overlap logic on the ddIncrement (as before) I simply made the minimum height configurable for added flexibility. See the docs inline for details.
Other changes were internal, based on the changes above. Let me know what you think.
Personal Blog: Extraneous / Twitter: @bmoeskau / Meetup: Austin Bleeding Edge Web
User avatar
Site Admin
Site Admin
Posts: 1344
Joined: Sat Sep 18, 2010 5:00 pm
Location: Austin, Texas

Re: [COMPLETE] Ability to use times other than :00 and :30

Postby nebbian » Thu Apr 07, 2011 7:45 am

Hi Brian,

That's brilliant, and works very well.

Thanks for putting it in :D
Posts: 17
Joined: Sat Oct 30, 2010 9:22 pm

Return to Plugins, Examples & Extras

Who is online

Users browsing this forum: No registered users and 1 guest