diff --git a/calendar/js/app.js b/calendar/js/app.js index 6ab75ce0de..43a465ffb0 100644 --- a/calendar/js/app.js +++ b/calendar/js/app.js @@ -464,17 +464,22 @@ app.classes.calendar = AppJS.extend( .on('wheel.calendar','.et2_container .calendar_calTimeGrid, .et2_container .calendar_plannerWidget', function(e) { - var at_bottom = true; - var at_top = true; - $j(this).children().each(function() { + // Ignore if they're going the other way + var direction = e.originalEvent.deltaY > 0 ? 1 : -1; + var at_bottom = direction !== -1; + var at_top = direction !== 1; + + $j(this).children(":not(.calendar_calGridHeader)").each(function() { at_bottom = at_bottom && this.scrollTop === (this.scrollHeight - this.offsetHeight) }).each(function() { at_top = at_top && this.scrollTop === 0; }); if(!at_bottom && !at_top) return; - + + // Scrolling too fast? + if(app.calendar._scroll_disabled) return; + e.preventDefault(); - var direction = e.originalEvent.deltaY > 0 ? 1 : -1; var delta = 1; var start = new Date(app.calendar.state.date); var end = null; @@ -485,6 +490,80 @@ app.classes.calendar = AppJS.extend( var template = etemplate2.getById(id); if(!template) return; + // Prevent scrolling too fast + app.calendar._scroll_disabled = true; + + // Animate the transition, if possible + var widget = null + template.widgetContainer.iterateOver(function(w) { + if (w.getDOMNode() == this) widget = w; + },this,et2_widget); + if(widget == null) return; + + // We apply the reverse quickly, then let it animate as the changes are + // removed, leaving things where they should be. + var original = $j(this); + var cloned = original.clone(true).attr("id","CLONE"); + var wrapper = $j(document.createElement("div")); + original.parent().append(wrapper); + // This is to hide the scrollbar + wrapper.wrap("
"); + wrapper.height(original.outerHeight() + cloned.outerHeight()); + wrapper.append(original); + if(direction == -1) + { + // Scrolling up + original.parent().append(cloned); + wrapper.css({"transform": "translateY(" + (direction * 50) + "%)"}); + // Makes it jump to destination + wrapper.css({ + "transition-duration": "0s", + "transition-delay": "0s" + }); + wrapper.css({ + "transition-duration": "", + "transition-delay": "" + }); + } + else + { + // Scrolling down + $j(this).parent().prepend(cloned); + $j('.calendar_calTimeGridScroll',cloned).scrollTop(10000); + } + + // Remove + var remove = function() { + // Starting animation + wrapper.addClass("calendar_slide"); + wrapper.css({"transform": direction == 1 ? "translateY(-50%)" : ""}); + window.setTimeout(function() { + // Clean up from animation + cloned.remove(); + // Moving this stuff around breaks scroll to day start in Chrome + var scrollTop = $j('.calendar_calTimeGridScroll',original).scrollTop(); + var parent = wrapper.parent().parent(); + wrapper.parent().remove(); + original.appendTo(parent); + // Also detaches events + if(widget) + { + widget.attachToDOM(); + } + // Re-scroll to start of day + $j('.calendar_calTimeGridScroll',original).scrollTop(scrollTop); + + + window.setTimeout(function() { + if(app.calendar) + { + app.calendar._scroll_disabled = false; + } + }, 500); + },1000); + } + // If detecting the transition end worked, we wouldn't need to use a timeout. + window.setTimeout(remove,100); // Get the view to calculate var view = app.classes.calendar.views[app.calendar.state.view] || false; @@ -498,6 +577,7 @@ app.classes.calendar = AppJS.extend( // Home - always 1 week // TODO return false; + /* var widget = []; var value = []; template.widgetContainer.iterateOver(function(w) { @@ -523,6 +603,7 @@ app.classes.calendar = AppJS.extend( app.calendar._need_data([value[i]], state); widget[i].set_value(value[i]); } + */ } return false; @@ -1419,13 +1500,15 @@ app.classes.calendar = AppJS.extend( } // Hide other views + var view = app.classes.calendar.views[state.state.view]; for(var _view in app.classes.calendar.views) { if(state.state.view != _view && app.classes.calendar.views[_view]) { for(var i = 0; i < app.classes.calendar.views[_view].etemplates.length; i++) { - if(typeof app.classes.calendar.views[_view].etemplates[i] !== 'string') + if(typeof app.classes.calendar.views[_view].etemplates[i] !== 'string' && + view.etemplates.indexOf(app.classes.calendar.views[_view].etemplates[i]) == -1) { $j(app.classes.calendar.views[_view].etemplates[i].DOMContainer).hide(); } @@ -1469,8 +1552,6 @@ app.classes.calendar = AppJS.extend( // cause infinite loops. this.state_update_in_progress = true; - var view = app.classes.calendar.views[state.state.view]; - // Sanitize owner so it's always an array if(state.state.owner === null) { @@ -1632,11 +1713,12 @@ app.classes.calendar = AppJS.extend( $j(view.etemplates[i].DOMContainer).show(); } // Toggle todos - if(state.state.view == 'day') + if(state.state.view == 'day' || this.state.view == 'day') { - if(state.state.owner.length === 1 && !isNaN(state.state.owner) && state.state.owner[0] > 0) + if(state.state.view == 'day' && state.state.owner.length === 1 && !isNaN(state.state.owner) && state.state.owner[0] > 0) { - view.etemplates[0].widgetContainer.set_width("70%"); + view.etemplates[0].DOMContainer.style.width = "70%"; + $j(view.etemplates[1].DOMContainer).css("left","69%"); // TODO: Maybe some caching here this.egw.jsonq('calendar_uiviews::ajax_get_todos', [state.state.date, state.state.owner[0]], function(data) { this.getWidgetById('label').set_value(data.label||''); @@ -1645,13 +1727,17 @@ app.classes.calendar = AppJS.extend( } else { - $j(view.etemplates[1].DOMContainer).hide(); - view.etemplates[0].widgetContainer.set_width(""); + $j(app.classes.calendar.views.day.etemplates[1].DOMContainer).show(); + $j(app.classes.calendar.views.day.etemplates[1].DOMContainer).css("left","100%"); + window.setTimeout(jQuery.proxy(function() { + $j(this).hide(); + },app.classes.calendar.views.day.etemplates[1].DOMContainer),1000); + $j(app.classes.calendar.views.day.etemplates[0].DOMContainer).css("width","100%"); } } else { - view.etemplates[0].widgetContainer.set_width(""); + $j(view.etemplates[0].DOMContainer).css("width","100%"); } this.state = jQuery.extend({},state.state); diff --git a/calendar/js/et2_widget_daycol.js b/calendar/js/et2_widget_daycol.js index b75ce175b4..5ea8c8b5a4 100644 --- a/calendar/js/et2_widget_daycol.js +++ b/calendar/js/et2_widget_daycol.js @@ -64,12 +64,15 @@ var et2_calendar_daycol = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResizea // Main container this.div = $j(document.createElement("div")) .addClass("calendar_calDayCol") - .css('width',this.options.width); + .css('width',this.options.width) + .css('left', this.options.left); this.header = $j(document.createElement('div')) - .addClass("calendar_calDayColHeader"); + .addClass("calendar_calDayColHeader") + .css('width',this.options.width) + .css('left', this.options.left); this.title = $j(document.createElement('div')) .appendTo(this.header); - + this.setDOMNode(this.div[0]); // Used for its date calculations - note this is a datetime, parent @@ -132,7 +135,24 @@ var et2_calendar_daycol = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResizea this.display_settings.wd_start = 60*this._parent.options.day_start; this.display_settings.wd_end = 60*this._parent.options.day_end; this.display_settings.granularity = this._parent.options.granularity; - this._parent.dayHeader.append(this.header); + var header = this._parent.dayHeader.children(); + + // Figure out insert index + var idx = 0; + var siblings = this._parent.getDOMNode(this).childNodes + while(idx < siblings.length && siblings[idx] != this.getDOMNode()) + { + idx++; + } + // Stick header in the right place + if(idx == 0) + { + this._parent.dayHeader.prepend(this.header); + } + else if(header.length) + { + header.eq(Math.min(header.length,idx)-1).after(this.header); + } } this.display_settings.rowsToDisplay = ((this.display_settings.wd_end - this.display_settings.wd_start)/this.display_settings.granularity); @@ -295,16 +315,25 @@ var et2_calendar_daycol = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResizea }, set_left: function(left) { - this.div.css('left',left); // Maybe? window.setTimeout(jQuery.proxy(function() { - this.header.css('left',left); + if(this.div) + { + this.div.css('left',left); + this.header.css('left',left); + } },this),1); }, set_width: function(width) { - this._super.apply(this, arguments); - this.header.width(width); + this.options.width = width; + window.setTimeout(jQuery.proxy(function() { + if(this.div) + { + this.div.width(this.options.width); + this.header.width(this.options.width); + } + },this),1); }, /** @@ -528,8 +557,7 @@ var et2_calendar_daycol = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResizea if(columns[c][i].options.value.whole_day_on_top) { columns[c][i].div - .appendTo(this.header) - .css('position', 'relative'); + .appendTo(this.header); continue; } else diff --git a/calendar/js/et2_widget_timegrid.js b/calendar/js/et2_widget_timegrid.js index e018e0e33d..c9f80db790 100644 --- a/calendar/js/et2_widget_timegrid.js +++ b/calendar/js/et2_widget_timegrid.js @@ -578,35 +578,61 @@ var et2_calendar_timegrid = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResiz this.day_list = this._calculate_day_list(this.options.start_date, this.options.end_date, this.options.show_weekend); } + var day_width = (100/this.day_list.length).toFixed(2); + // Create any needed widgets - otherwise, we'll just recycle // Add any needed day widgets (now showing more days) + var add_index = 0; + var before = true; while(this.day_list.length > this.day_widgets.length) { + var existing_index = this.day_widgets[add_index] ? this.day_list.indexOf(this.day_widgets[add_index].options.date) : -1; + before = existing_index > add_index; + var day = et2_createWidget('calendar-daycol',{ - owner: this.options.owner + owner: this.options.owner, + width: (before ? 0 : day_width) + "%" },this); if(this.isInTree()) { day.doLoadingFinished(); } - this.day_widgets.push(day); + if(existing_index != -1 && parseInt(this.day_list[add_index]) < parseInt(this.day_list[existing_index])) + { + this.day_widgets.unshift(day); + $j(this.getDOMNode(day)).prepend(day.getDOMNode(day)); + } + else + { + this.day_widgets.push(day); + } + add_index++; } // Remove any extra day widgets (now showing less) var delete_index = this.day_widgets.length - 1; + before = false; while(this.day_widgets.length > this.day_list.length) { // If we're going down to an existing one, just keep it for cool CSS animation while(this.day_list.indexOf(this.day_widgets[delete_index].options.date) > -1) { delete_index--; + before = true; + } + // Wait until any animations or other timeouts are done + window.setTimeout(jQuery.proxy(function() { + this.free(); + },this.day_widgets[delete_index]),1000); + + // Widgets that are before our date shrink, after just get pushed out + if(before) + { + this.day_widgets[delete_index].set_width('0px'); } - this.day_widgets[delete_index].set_width('0px'); - this.day_widgets[delete_index].free(); this.day_widgets.splice(delete_index--,1); } // Create / update day widgets with dates and data - var day_width = (100/this.day_list.length).toFixed(2); for(var i = 0; i < this.day_list.length; i++) { day = this.day_widgets[i]; @@ -619,7 +645,7 @@ var et2_calendar_timegrid = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResiz day.set_id(this.day_list[i]); day.set_width(day_width + '%'); } - + // Don't hold on to value any longer, use the data cache for best info this.value = {}; diff --git a/calendar/templates/default/app.css b/calendar/templates/default/app.css index bac9698db0..88589b7114 100644 --- a/calendar/templates/default/app.css +++ b/calendar/templates/default/app.css @@ -36,8 +36,16 @@ } #calendar-todo { - float: right; + position: absolute; width: 30%; + + /* Nice transition when changing days in a week */ + transition: 1s ease-in-out; +} + +#calendar-view { + width: 100%; + transition: width 1s ease-in-out; } /* Header classes */ tr.dialogHeader td, tr.dialogHeader2 td, tr.dialogHeader3 td, tr.dialogHeader4 td, @@ -189,6 +197,7 @@ e.g. the div with class calendar_calTimeGrid is generated by the timeGridWidget height: 100%; left: 45px; right: 0px; + white-space: nowrap; } /* 12h timeformat with am/pm */ @@ -235,12 +244,21 @@ e.g. the div with class calendar_calTimeGrid is generated by the timeGridWidget line-height: 16px; } .calendar_calDayColHeader { + vertical-align: top; + height: 100%; + /* Nice transition when changing days in a week */ + transition: width 1s ease-in-out; z-index:30; } +.calendar_calDayColHeader > div[data-date] { + height: 16px; +} .calendar_calGridHeader > div { + position: absolute; left: 45px; right: 15px; width: initial; + white-space: nowrap; } .calendar_calDayColHeader img { vertical-align: middle; @@ -250,15 +268,6 @@ e.g. the div with class calendar_calTimeGrid is generated by the timeGridWidget left: 0px; width: 100%; right: 0px; - /* does not work in IE, but looks better in other browsers then width:100% */ - text-align: center; - font-size: 100%; - white-space: nowrap; - border-bottom: 1px solid silver; - border-right: 1px solid silver; - height: 16px; - line-height: 12px; - z-index: 30; } .calendar_calWeekNavHeader,.calendar_calMonthNavHeader img { vertical-align: middle; @@ -397,6 +406,13 @@ e.g. the div with class calendar_calTimeGrid is generated by the timeGridWidget border-width: 1px; } +/** + * Events in the header (all day) + */ +.calendar_calDayColHeader .calendar_calEvent { + position: static; + display: inline-block; +} .calendar_calEventTooltip{ border-radius: 6px; -moz-border-radius: 6px; @@ -792,6 +808,14 @@ img.calendar_print_button, img.calendar_print_appicon { display: inline-block; } +/** + * View animation stuff + */ +.calendar_slide { + transition-duration: 1s; + transition-delay: 100ms; +} + /** * Home page portlets */ @@ -814,4 +838,4 @@ img.calendar_print_button, img.calendar_print_appicon { border-top: 0; margin: 0; padding-right: 3px; -} \ No newline at end of file +} diff --git a/calendar/templates/pixelegg/app.css b/calendar/templates/pixelegg/app.css index 038825fd80..a4aa7205c9 100755 --- a/calendar/templates/pixelegg/app.css +++ b/calendar/templates/pixelegg/app.css @@ -581,9 +581,6 @@ div.calendar { #calendar-edit #calendar-edit_calendar-edit-links span.et2_label { padding: 1em; } -#calendar-edit #calendar-edit_calendar-edit-links div.delete { - background-image: url("https:://192.168.1.100/egroupware2/pixelegg/images/delete.png"); -} #calendar-edit #calendar-edit_calendar-edit-alarms tbody { display: table; width: 100%; @@ -721,19 +718,8 @@ e.g. the div with class calendar_calTimeGrid is generated by the timeGridWidget */ .calendar_calDayColHeader, .calendar_calGridHeader { - position: absolute; - top: 0px; - left: 0px; - width: 100%; - right: 0px; - /* does not work in IE, but looks better in other browsers then width:100% */ - text-align: center; - font-size: 100%; - white-space: nowrap; border-bottom: 1px solid silver; border-right: 1px solid silver; - height: 16px; - line-height: 12px; } .calendar_calDayColHeader a img, .calendar_calGridHeader a img { @@ -802,27 +788,10 @@ e.g. the div with class calendar_calTimeGrid is generated by the timeGridWidget text-align: left; padding-left: 3px; } -/* contains (multiple) events's - */ -.calendar_calEventCol { - position: absolute; - top: 0px; - /* bottom: 0px; does NOT work in IE, IE needs height: 100%! */ - height: 100%; - /* set via inline style on runtime: - * left: - * width: - */ -} /* contains one event: header-row & -body */ .calendar_calEvent, .calendar_calEventPrivate { - position: absolute; - left: 0px; - right: 0px; - overflow: hidden; - z-index: 20; border-width: 1px; border-radius: 6px; -moz-border-radius: 6px; diff --git a/calendar/templates/pixelegg/app.less b/calendar/templates/pixelegg/app.less index bbb15abf60..5c47bd6463 100755 --- a/calendar/templates/pixelegg/app.less +++ b/calendar/templates/pixelegg/app.less @@ -661,8 +661,6 @@ div.calendar { position: relative; } } span.et2_label {padding: 1em;} - - div.delete {background-image: url("https:://192.168.1.100/egroupware2/pixelegg/images/delete.png");} } /*###########################################*/ @@ -767,7 +765,7 @@ e.g. the div with class calendar_calTimeGrid is generated by the timeGridWidget } .calendar_calWeek{ // background: #ffffcc; - background-color : @gray_0; + background-color : @gray_0; width:auto; margin:0 auto; text-align:center; @@ -834,18 +832,8 @@ e.g. the div with class calendar_calTimeGrid is generated by the timeGridWidget /* header for the dayCol */ .calendar_calDayColHeader,.calendar_calGridHeader{ - position: absolute; - top: 0px; - left: 0px; - width: 100%; - right: 0px; /* does not work in IE, but looks better in other browsers then width:100% */ - text-align: center; - font-size: 100%; - white-space: nowrap; border-bottom: 1px solid silver; border-right: 1px solid silver; - .dimension_height_s; - line-height: 12px; a { img { @@ -927,27 +915,9 @@ e.g. the div with class calendar_calTimeGrid is generated by the timeGridWidget padding-left: 3px; } -/* contains (multiple) events's - */ -.calendar_calEventCol{ - position: absolute; - top: 0px; - /* bottom: 0px; does NOT work in IE, IE needs height: 100%! */ - height: 100%; - /* set via inline style on runtime: - * left: - * width: - */ -} - /* contains one event: header-row & -body */ .calendar_calEvent,.calendar_calEventPrivate{ - position: absolute; - left: 0px; - right: 0px; - overflow: hidden; - z-index: 20; border-width: 1px; border-radius: 6px; -moz-border-radius: 6px;