ASP.NET 2.0 AJAX, Safari and Scroll Offset Tricks | Targetprocess - Visual management software
11 years ago

ASP.NET 2.0 AJAX, Safari and Scroll Offset Tricks

Couple days ago, I faced odd bug with DragDropManager at Microsoft.Web.Preview.dll. It doesn’t work correctly if the page is scrolled down in Chrome and Safari browsers. Google did not help. Debugging did not help as well (DragDropManager file is really huge). The last way was to use reflector tool to dig into sources.

The first odd thing was classes hierarchy. Two classes were the most interesting to me: Sys.Preview.UI.IEDragDropManager and Sys.Preview.UI.GenericDragDropManager.

And the following declarations:

Sys.Preview.UI.IEDragDropManager.registerClass('Sys.Preview.UI.IEDragDropManager', Sys.Component);

Sys.Preview.UI.GenericDragDropManager.registerClass('Sys.Preview.UI.GenericDragDropManager', Sys.Preview.UI.IEDragDropManager);

The fuzzy thing is that GenericDragDropManager derives IEDragDropManager . It sounds like abstract class derives from concrete class. I truly believe such naming obscures readability. Gutting the code, I figured out that getScrollOffset method is overridden in for Safari browser (and it means for Chrome as well).

if (Sys.Browser.agent === Sys.Browser.Safari) {
    Sys.Preview.UI.GenericDragDropManager.__loadSafariCompatLayer =
        function Sys$Preview$UI$GenericDragDropManager$__loadSafariCompatLayer(ddm) {
            ddm._getScrollOffset = ddm.getScrollOffset;

            ddm.getScrollOffset = function ddm$getScrollOffset(element, recursive) {
                return { x: 0, y: 0 };

Sounds like code owners just didn’t care about scroll offset. What to do? All what I needed to do is just to prohibit override for Safari to allow base class IEDragDropManager to handle the scroll offset for Safari.

Sys.Preview.UI.IEDragDropManager.prototype.getScrollOffset = function () {

        var left = element.scrollLeft;
        var top = element.scrollTop;
        if (recursive) {
            var parent = element.parentNode;
            while (parent != null && parent.scrollLeft != null) {
                left += parent.scrollLeft;
                top += parent.scrollTop;
                                if (parent == document.body && (left != 0 && top != 0))
                parent = parent.parentNode;
        return { x: left, y: top };

The hack:

Sys.Preview.UI.DragDropManager._getInstance().getScrollOffset = Sys.Preview.UI.IEDragDropManager.prototype.getScrollOffset

Another annoying issue is auto scroll to the top during drag operation. The hack is as trivial as just an empty handler:

Sys.Preview.UI.DragDropManager._getInstance()._autoScroll = function() { }

The full hack for both issues looks quite strange:

if (Sys.Browser.agent === Sys.Browser.Safari) {
 Sys.Preview.UI.DragDropManager._getInstance().getScrollOffset =
 Sys.Preview.UI.DragDropManager._getInstance()._autoScroll = function() { }

The only excuse to ASP.NET Ajax development team is that it was RC build...

You can subscribe to our monthly newsletter here:

Thank you!

Сheck out latest blog posts:

Or start your
free trial

Get a live
product demo

Let one of our product specialists create your account
and shape Targetprocess for your company needs.