Better way to get the viewport of a scrollable DIV in RTL mode?

Problem: (Ex. Scroll Width = 100)

Chrome - Most Right: 100 Most Left: 0.

IE- Most Right: 0 Most Left: 100.

Firefox - Most Right: 0 Most Left: -100.

Solution #1

As mentioned by @Lucas Trzesniewski.

You could use this Jquery plugin:

https://github.com/othree/jquery.rtl-scroll-type

The plugin is used to detect which type is the browser are using. Assign the result to jQuery's support object named 'rtlScrollType'. You will need the scrollWidth of the element to transform between these three types of value

Solution #2

Credits: jQuery.scrollLeft() when direction is rtl - different values in different browsers

I know you didn't want to include browser detection individually for each browser. With this example, only 2 extra lines of code are added for Safari and Chrome and it works like a charm!

Modified it to demonstrate it better for you.

$('div.Container').scroll(function () {
    st = $("div.Container").scrollLeft() + ' ' + GetScrollLeft($("div.Container"));
    $('#scrollLeft').html(st);
});

function GetScrollLeft(elem) {
    var scrollLeft = elem.scrollLeft();
    if ($("body").css("direction").toLowerCase() == "rtl") {
        // Absolute value - gets IE and FF to return the same values
        var scrollLeft = Math.abs(scrollLeft);

        // Get Chrome and Safari to return the same value as well
        if ($.browser.webkit) {
            scrollLeft = elem[0].scrollWidth - elem[0].clientWidth - scrollLeft;
        }
    }
    return scrollLeft;
}

JSFiddle:

http://jsfiddle.net/SSZRd/1/

The value on the left should be the same for all browser while the value on the right is the older value which is different on all browser. (Tested on Firefox, Safari, Chrome, IE9).


You can try this:-

         var initialScrollLeft = $('#box').scrollLeft(), negativeToZero, startFromZero;
            if(initialScrollLeft === 0){
                startFromZero = true; 
            } else if(initialScrollLeft < 0){
                negativeToZero = true;
            } 
            var box = $('#box').scroll(function(){
                if(startFromZero){
                    if(box.scrollLeft()>0){
                        $('#scrollLeft').text(- (box.scrollLeft()));
                    }else {
                        $('#scrollLeft').text(box.scrollLeft()); 
                    }
                } else if(negativeToZero){
                    $('#scrollLeft').text(box.scrollLeft()+(box[0].scrollWidth - box[0].clientWidth));  
                } else{
                    $('#scrollLeft').text(box.scrollLeft()-(box[0].scrollWidth - box[0].clientWidth));  
                }

            });

Here's a jQuery plugin which does not use browser detection: https://github.com/othree/jquery.rtl-scroll-type

Using this plugin you could replace jQuery's scrollLeft function with your own predictable version, like this:

var origScrollLeft = jQuery.fn.scrollLeft;
jQuery.fn.scrollLeft = function(i) {
    var value = origScrollLeft.apply(this, arguments);

    if (i === undefined) {
        switch(jQuery.support.rtlScrollType) {
            case "negative":
                return value + this[0].scrollWidth - this[0].clientWidth;
            case "reverse":
                return this[0].scrollWidth - value - this[0].clientWidth;
        }
    }

    return value;
};

I didn't include the code for setting the scroll offset, but you get the idea.

Here's the fiddle: http://jsfiddle.net/scA63/

Also, this lib may be of interest too.