/*! Copyright (c) 2011 Piotr Rochala (http://rocha.la)

 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)

 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.

 *

 * Improved by keenthemes for Metronic Theme

 * Version: 1.3.2

 *

 */

(function($) {



    jQuery.fn.extend({

        slimScroll: function(options) {



            var defaults = {



                // width in pixels of the visible scroll area

                width: 'auto',



                // height in pixels of the visible scroll area

                height: '250px',



                // width in pixels of the scrollbar and rail

                size: '7px',



                // scrollbar color, accepts any hex/color value

                color: '#000',



                // scrollbar position - left/right

                position: 'right',



                // distance in pixels between the side edge and the scrollbar

                distance: '1px',



                // default scroll position on load - top / bottom / $('selector')

                start: 'top',



                // sets scrollbar opacity

                opacity: .4,



                // enables always-on mode for the scrollbar

                alwaysVisible: false,



                // check if we should hide the scrollbar when user is hovering over

                disableFadeOut: false,



                // sets visibility of the rail

                railVisible: false,



                // sets rail color

                railColor: '#333',



                // sets rail opacity

                railOpacity: .2,



                // whether  we should use jQuery UI Draggable to enable bar dragging

                railDraggable: true,



                // defautlt CSS class of the slimscroll rail

                railClass: 'slimScrollRail',



                // defautlt CSS class of the slimscroll bar

                barClass: 'slimScrollBar',



                // defautlt CSS class of the slimscroll wrapper

                wrapperClass: 'slimScrollDiv',



                // check if mousewheel should scroll the window if we reach top/bottom

                allowPageScroll: false,



                // scroll amount applied to each mouse wheel step

                wheelStep: 20,



                // scroll amount applied when user is using gestures

                touchScrollStep: 200,



                // sets border radius

                borderRadius: '7px',



                // sets border radius of the rail

                railBorderRadius: '7px',



                // sets animation status on a given scroll(added my keenthemes)

                animate: true

            };



            var o = $.extend(defaults, options);



            // do it for every element that matches selector

            this.each(function() {



                var isOverPanel, isOverBar, isDragg, queueHide, touchDif,

                    barHeight, percentScroll, lastScroll,

                    divS = '<div></div>',

                    minBarHeight = 30,

                    releaseScroll = false;



                // used in event handlers and for better minification

                var me = $(this);



                //begin: windows phone fix added by keenthemes

                if ('ontouchstart' in window && window.navigator.msPointerEnabled) {

                  me.css("-ms-touch-action", "none");

              }

                //end: windows phone fix added by keenthemes



                // ensure we are not binding it again

                if (me.parent().hasClass(o.wrapperClass)) {

                    // start from last bar position

                    var offset = me.scrollTop();



                    // find bar and rail

                    bar = me.parent().find('.' + o.barClass);

                    rail = me.parent().find('.' + o.railClass);



                    getBarHeight();



                    // check if we should scroll existing instance

                    if ($.isPlainObject(options)) {

                        // Pass height: auto to an existing slimscroll object to force a resize after contents have changed

                        if ('height' in options && options.height == 'auto') {

                            me.parent().css('height', 'auto');

                            me.css('height', 'auto');

                            var height = me.parent().parent().height();

                            me.parent().css('height', height);

                            me.css('height', height);

                        }



                        if ('scrollTo' in options) {

                            // jump to a static point

                            offset = parseInt(o.scrollTo);

                        } else if ('scrollBy' in options) {

                            // jump by value pixels

                            offset += parseInt(o.scrollBy);

                        } else if ('destroy' in options) {

                            // remove slimscroll elements

                            bar.remove();

                            rail.remove();

                            me.unwrap();

                            return;

                        }



                        // scroll content by the given offset

                        scrollContent(offset, false, true);

                    }



                    return;

                }



                // optionally set height to the parent's height

                o.height = (options.height == 'auto') ? me.parent().height() : options.height;



                // wrap content

                var wrapper = $(divS)

                    .addClass(o.wrapperClass)

                    .css({

                        position: 'relative',

                        overflow: 'hidden',

                        width: o.width,

                        height: o.height

                    });



                // update style for the div

                me.css({

                    overflow: 'hidden',

                    width: o.width,

                    height: o.height

                });



                // create scrollbar rail

                var rail = $(divS)

                    .addClass(o.railClass)

                    .css({

                        width: o.size,

                        height: '100%',

                        position: 'absolute',

                        top: 0,

                        display: (o.alwaysVisible && o.railVisible) ? 'block' : 'none',

                        'border-radius': o.railBorderRadius,

                        background: o.railColor,

                        opacity: o.railOpacity,

                        zIndex: 90

                    });



                // create scrollbar

                var bar = $(divS)

                    .addClass(o.barClass)

                    .css({

                        background: o.color,

                        width: o.size,

                        position: 'absolute',

                        top: 0,

                        opacity: o.opacity,

                        display: o.alwaysVisible ? 'block' : 'none',

                        'border-radius': o.borderRadius,

                        BorderRadius: o.borderRadius,

                        MozBorderRadius: o.borderRadius,

                        WebkitBorderRadius: o.borderRadius,

                        zIndex: 99

                    });



                // set position

                var posCss = (o.position == 'right') ? {

                    right: o.distance

                } : {

                    left: o.distance

                };

                rail.css(posCss);

                bar.css(posCss);



                // wrap it

                me.wrap(wrapper);



                // append to parent div

                me.parent().append(bar);

                me.parent().append(rail);



                // make it draggable and no longer dependent on the jqueryUI

                if (o.railDraggable) {

                    bar.bind("mousedown", function(e) {

                        var $doc = $(document);

                        isDragg = true;

                        t = parseFloat(bar.css('top'));

                        pageY = e.pageY;



                        $doc.bind("mousemove.slimscroll", function(e) {

                            currTop = t + e.pageY - pageY;

                            bar.css('top', currTop);

                            scrollContent(0, bar.position().top, false); // scroll content

                        });



                        $doc.bind("mouseup.slimscroll", function(e) {

                            isDragg = false;

                            hideBar();

                            $doc.unbind('.slimscroll');

                        });

                        return false;

                    }).bind("selectstart.slimscroll", function(e) {

                        e.stopPropagation();

                        e.preventDefault();

                        return false;

                    });

                }



                //begin: windows phone fix added by keenthemes

                if ('ontouchstart' in window && window.navigator.msPointerEnabled) {

                    me.bind('MSPointerDown', function(e, b) {

                        // record where touch started

                        touchDif = e.originalEvent.pageY;

                    });



                    me.bind('MSPointerMove', function(e) {

                        // prevent scrolling the page if necessary

                        e.originalEvent.preventDefault();

                        // see how far user swiped

                        var diff = (touchDif - e.originalEvent.pageY) / o.touchScrollStep;

                        // scroll content

                        scrollContent(diff, true);

                        touchDif = e.originalEvent.pageY;

                    });

                }

                //end: windows phone fix added by keenthemes



                // on rail over

                rail.hover(function() {

                    showBar();

                }, function() {

                    hideBar();

                });



                // on bar over

                bar.hover(function() {

                    isOverBar = true;

                }, function() {

                    isOverBar = false;

                });



                // show on parent mouseover

                me.hover(function() {

                    isOverPanel = true;

                    showBar();

                    hideBar();

                }, function() {

                    isOverPanel = false;

                    hideBar();

                });



                // support for mobile

                me.bind('touchstart', function(e, b) {

                    if (e.originalEvent.touches.length) {

                        // record where touch started

                        touchDif = e.originalEvent.touches[0].pageY;

                    }

                });



                me.bind('touchmove', function(e) {

                    // prevent scrolling the page if necessary

                    if (!releaseScroll) {

                        e.originalEvent.preventDefault();

                    }

                    if (e.originalEvent.touches.length) {

                        // see how far user swiped

                        var diff = (touchDif - e.originalEvent.touches[0].pageY) / o.touchScrollStep;

                        // scroll content

                        scrollContent(diff, true);

                        touchDif = e.originalEvent.touches[0].pageY;

                    }

                });



                // set up initial height

                getBarHeight();



                // check start position

                if (o.start === 'bottom') {

                    // scroll content to bottom

                    bar.css({

                        top: me.outerHeight() - bar.outerHeight()

                    });

                    scrollContent(0, true);

                } else if (o.start !== 'top') {

                    // assume jQuery selector

                    scrollContent($(o.start).position().top, null, true);



                    // make sure bar stays hidden

                    if (!o.alwaysVisible) {

                        bar.hide();

                    }

                }



                // attach scroll events

                attachWheel();



                function _onWheel(e) {

                    // use mouse wheel only when mouse is over

                    if (!isOverPanel) {

                        return;

                    }



                    var e = e || window.event;



                    var delta = 0;

                    if (e.wheelDelta) {

                        delta = -e.wheelDelta / 120;

                    }

                    if (e.detail) {

                        delta = e.detail / 3;

                    }



                    var target = e.target || e.srcTarget || e.srcElement;

                    if ($(target).closest('.' + o.wrapperClass).is(me.parent())) {

                        // scroll content

                        scrollContent(delta, true);

                    }



                    // stop window scroll

                    if (e.preventDefault && !releaseScroll) {

                        e.preventDefault();

                    }

                    if (!releaseScroll) {

                        e.returnValue = false;

                    }

                }



                function scrollContent(y, isWheel, isJump) {

                    releaseScroll = false;

                    var delta = y;

                    var maxTop = me.outerHeight() - bar.outerHeight();



                    if (isWheel) {

                        // move bar with mouse wheel

                        delta = parseInt(bar.css('top')) + y * parseInt(o.wheelStep) / 100 * bar.outerHeight();



                        // move bar, make sure it doesn't go out

                        delta = Math.min(Math.max(delta, 0), maxTop);



                        // if scrolling down, make sure a fractional change to the

                        // scroll position isn't rounded away when the scrollbar's CSS is set

                        // this flooring of delta would happened automatically when

                        // bar.css is set below, but we floor here for clarity

                        delta = (y > 0) ? Math.ceil(delta) : Math.floor(delta);



                        // scroll the scrollbar

                        bar.css({

                            top: delta + 'px'

                        });

                    }



                    // calculate actual scroll amount

                    percentScroll = parseInt(bar.css('top')) / (me.outerHeight() - bar.outerHeight());

                    delta = percentScroll * (me[0].scrollHeight - me.outerHeight());



                    if (isJump) {

                        delta = y;

                        var offsetTop = delta / me[0].scrollHeight * me.outerHeight();

                        offsetTop = Math.min(Math.max(offsetTop, 0), maxTop);

                        bar.css({

                            top: offsetTop + 'px'

                        });

                    }



                    // scroll content

                    if ('scrollTo' in o && o.animate) {

                        me.animate({

                            scrollTop: delta

                        });

                    } else {

                        me.scrollTop(delta);

                    }



                    // fire scrolling event

                    me.trigger('slimscrolling', ~~delta);



                    // ensure bar is visible

                    showBar();



                    // trigger hide when scroll is stopped

                    hideBar();



                }



                function attachWheel() {

                    if (window.addEventListener) {

                        this.addEventListener('DOMMouseScroll', _onWheel, false);

                        this.addEventListener('mousewheel', _onWheel, false);

                    } else {

                        document.attachEvent("onmousewheel", _onWheel)

                    }

                }



                function getBarHeight() {

                    // calculate scrollbar height and make sure it is not too small

                    barHeight = Math.max((me.outerHeight() / me[0].scrollHeight) * me.outerHeight(), minBarHeight);

                    bar.css({

                        height: barHeight + 'px'

                    });



                    // hide scrollbar if content is not long enough

                    var display = barHeight == me.outerHeight() ? 'none' : 'block';

                    bar.css({

                        display: display

                    });

                }



                function showBar() {

                    // recalculate bar height

                    getBarHeight();

                    clearTimeout(queueHide);



                    // when bar reached top or bottom

                    if (percentScroll == ~~percentScroll) {

                        //release wheel

                        releaseScroll = o.allowPageScroll;



                        // publish approporiate event

                        if (lastScroll != percentScroll) {

                            var msg = (~~percentScroll == 0) ? 'top' : 'bottom';

                            me.trigger('slimscroll', msg);

                        }

                    } else {

                        releaseScroll = false;

                    }

                    lastScroll = percentScroll;



                    // show only when required

                    if (barHeight >= me.outerHeight()) {

                        //allow window scroll

                        releaseScroll = true;

                        return;

                    }

                    bar.stop(true, true).fadeIn('fast');

                    if (o.railVisible) {

                        rail.stop(true, true).fadeIn('fast');

                    }

                }



                function hideBar() {

                    // only hide when options allow it

                    if (!o.alwaysVisible) {

                        queueHide = setTimeout(function() {

                            if (!(o.disableFadeOut && isOverPanel) && !isOverBar && !isDragg) {

                                bar.fadeOut('slow');

                                rail.fadeOut('slow');

                            }

                        }, 1000);

                    }

                }



            });



            // maintain chainability

            return this;

        }

    });



    jQuery.fn.extend({

        slimscroll: jQuery.fn.slimScroll

    });



})(jQuery);