| RadControls version |
Telerik.Web.UI.2008.3 -
Telerik.Web.UI.2010.2
|
| .NET version |
any
|
| Visual Studio version |
any
|
| programming language |
any
|
| browser support |
all browsers supported by RadControls
|
PROJECT DESCRIPTION
The issue raised when a RadDatePicker/RadDateTimePicker/RadComboBox control is placed inside a scrollable container element, for example in RadSplitter pane or in simple
<div style="overflow:auto">.
STR:
- place RadDatePicker/RadDateTimePicker/RadComboBox control inside a scrollable container;
- ensure that the content of the scrollable container element is large enough to make the scrollbars visible;
- click the popup button to show calendar/time/combobox popup;
- scroll the parent element;
* content is scrolled along with the control, the control's popup is misplaced.
The problem is inherent to the control structure since the popup element is appended to the topmost body/form element and does not know anything about owner control location.
SOLUTION
Implement a workaround which tracks scroll event and calls hide popup methods when appropriate.
IMPLEMENTATION
Fixing of the control prototypes implemented in the scope of the fix utility. Methods of the utility are called on the page init.
The code below contains calls to utility methods with self-describing names.
// fixes the prototype of the control with popup functionality so that
// it closes the popup when a scrollable parent element, if any, scrolls.
this.fixPopupControlForScroll = function(controlPrototype, hideMethod){
var base_initialize = controlPrototype.initialize;
controlPrototype.initialize = function(){
base_initialize.apply(this);
// find parent scrollable element
var scrollableParent = $wf.dom.findUp(this.get_element(), function(node){
var style = $wf.dom.getCurrentStyle(node);
return style && (style.overflowX == "auto"
|| style.overflowX == "scroll"
|| style.overflowY == "auto"
|| style.overflowY == "scroll");
});
if (!scrollableParent)
return;
var me = this,
scrollableParent_scroll = function(e){
hideMethod.apply(me, [e]);
};
$addHandler(scrollableParent, "scroll", scrollableParent_scroll);
this.add_disposing(function(){
if (scrollableParent._events) // when parent is not disposed first
$removeHandler(scrollableParent, "scroll", scrollableParent_scroll);
me = scrollableParent = scrollableParent_scroll = null;
});
};
};
...
// fix date/time pickers
this.fixPopupControlForScroll(datePickerPrototype, function(e){
if (this.isPopupVisible()){
var calendarPopup = this.get__popup();
// change the hide animation duration to 0
// in order to make it hide at once
var hideDuration = calendarPopup.HideAnimationDuration;
calendarPopup.HideAnimationDuration = 0;
try {
this.hidePopup();
} finally {
calendarPopup.HideAnimationDuration = hideDuration;
}
}
var timePopup;
if (this.get_timeView && this.get_timeView()
&& (timePopup = this.get__TimePopup()).IsVisible()){
// change the hide animation duration to 0
// in order to make it hide at once
var hideDuration = timePopup.HideAnimationDuration;
timePopup.HideAnimationDuration = 0;
try {
this.hideTimePopup();
} finally {
timePopup.HideAnimationDuration = hideDuration;
}
}
});
// fix combobox
this.fixPopupControlForScroll(radComboBoxPrototype, function(e){
if (!this.get_dropDownVisible())
return;
// change the collapse animation type to None
// in order to make it close at once
var collapseAnimType = this._slide._collapseAnimation._type;
this._slide._collapseAnimation._type = Telerik.Web.UI.AnimationType.None;
try {
this._hideDropDown(e);
} finally {
this._slide._collapseAnimation._type = collapseAnimType;
}
});
Would be nice to implement such functionality in the core telerik controls, however it might introduce unwanted overhead.
Enjoy,
Vadim