diff --git a/bower.json b/bower.json index 9c5c4de..1af471f 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "ng-scrollbar", - "version": "0.0.7", + "version": "0.0.8", "dependencies": { }, "main": [ diff --git a/dist/ng-scrollbar.js b/dist/ng-scrollbar.js index 7b613c1..6e9ddc8 100644 --- a/dist/ng-scrollbar.js +++ b/dist/ng-scrollbar.js @@ -12,6 +12,8 @@ angular.module('ngScrollbar', []).directive('ngScrollbar', [ var mainElm, transculdedContainer, tools, thumb, thumbLine, track; var flags = { bottom: attrs.hasOwnProperty('bottom') }; var win = angular.element($window); + var hasAddEventListener = !!win[0].addEventListener; + var hasRemoveEventListener = !!win[0].removeEventListener; // Elements var dragger = { top: 0 }, page = { top: 0 }; // Styles @@ -55,10 +57,18 @@ angular.module('ngScrollbar', []).directive('ngScrollbar', [ event.stopPropagation(); }; var wheelHandler = function (event) { - var wheelDivider = 20; - // so it can be changed easily - var deltaY = event.wheelDeltaY !== undefined ? event.wheelDeltaY / wheelDivider : event.wheelDelta !== undefined ? event.wheelDelta / wheelDivider : -event.detail * (wheelDivider / 10); - dragger.top = Math.max(0, Math.min(parseInt(page.height, 10) - parseInt(dragger.height, 10), parseInt(dragger.top, 10) - deltaY)); + var wheelSpeed = 40; + // Mousewheel speed normalization approach adopted from + // http://stackoverflow.com/a/13650579/1427418 + var o = event, d = o.detail, w = o.wheelDelta, n = 225, n1 = n - 1; + // Normalize delta + d = d ? w && (f = w / d) ? d / f : -d / 1.35 : w / 120; + // Quadratic scale if |d| > 1 + d = d < 1 ? d < -1 ? (-Math.pow(d, 2) - n1) / n : d : (Math.pow(d, 2) + n1) / n; + // Delta *should* not be greater than 2... + event.delta = Math.min(Math.max(d / 2, -1), 1); + event.delta = event.delta * wheelSpeed; + dragger.top = Math.max(0, Math.min(parseInt(page.height, 10) - parseInt(dragger.height, 10), parseInt(dragger.top, 10) - event.delta)); redraw(); if (!!event.preventDefault) { event.preventDefault(); @@ -93,10 +103,23 @@ angular.module('ngScrollbar', []).directive('ngScrollbar', [ win.off('touchend', _touchEnd); event.stopPropagation(); }; - var buildScrollbar = function (rollToBottom) { - // Getting top position of a parent element to place scroll correctly - var parentOffsetTop = element[0].parentElement.offsetTop; + var registerEvent = function (elm) { + var wheelEvent = win[0].onmousewheel !== undefined ? 'mousewheel' : 'DOMMouseScroll'; + if (hasAddEventListener) { + elm.addEventListener(wheelEvent, wheelHandler, false); + } else { + elm.attachEvent('onmousewheel', wheelHandler); + } + }; + var removeEvent = function (elm) { var wheelEvent = win[0].onmousewheel !== undefined ? 'mousewheel' : 'DOMMouseScroll'; + if (hasRemoveEventListener) { + elm.removeEventListener(wheelEvent, wheelHandler, false); + } else { + elm.detachEvent('onmousewheel', wheelHandler); + } + }; + var buildScrollbar = function (rollToBottom) { rollToBottom = flags.bottom || rollToBottom; mainElm = angular.element(element.children()[0]); transculdedContainer = angular.element(mainElm.children()[0]); @@ -104,11 +127,7 @@ angular.module('ngScrollbar', []).directive('ngScrollbar', [ thumb = angular.element(angular.element(tools.children()[0]).children()[0]); thumbLine = angular.element(thumb.children()[0]); track = angular.element(angular.element(tools.children()[0]).children()[1]); - // Check if scroll bar is needed - page.height = element[0].offsetHeight - parentOffsetTop; - if (page.height < 0) { - page.height = element[0].offsetHeight; - } + page.height = element[0].offsetHeight; page.scrollHeight = transculdedContainer[0].scrollHeight; if (page.height < page.scrollHeight) { scope.showYScrollbar = true; @@ -125,8 +144,8 @@ angular.module('ngScrollbar', []).directive('ngScrollbar', [ thumbLine.css(draggerLineStyle); // Bind scroll bar events track.bind('click', trackClick); - // Handl mousewheel - transculdedContainer[0].addEventListener(wheelEvent, wheelHandler, false); + // Handle mousewheel + registerEvent(transculdedContainer[0]); // Drag the scroller with the mouse thumb.on('mousedown', function (event) { lastOffsetY = event.pageY - thumb[0].offsetTop; @@ -152,7 +171,7 @@ angular.module('ngScrollbar', []).directive('ngScrollbar', [ scope.showYScrollbar = false; scope.$emit('scrollbar.hide'); thumb.off('mousedown'); - transculdedContainer[0].removeEventListener(wheelEvent, wheelHandler, false); + removeEvent(transculdedContainer[0]); transculdedContainer.attr('style', 'position:relative;top:0'); // little hack to remove other inline styles mainElm.css({ height: '100%' }); diff --git a/dist/ng-scrollbar.min.js b/dist/ng-scrollbar.min.js index 8ce2b29..51b7948 100644 --- a/dist/ng-scrollbar.min.js +++ b/dist/ng-scrollbar.min.js @@ -1,8 +1,8 @@ /** * ng-scrollbar - * @version v0.0.5 - 2014-09-29 + * @version v0.0.7 - 2015-06-19 * @link https://github.com/asafdav/ng-scrollbar * @author Asaf David * @license MIT License, http://www.opensource.org/licenses/MIT */ -"use strict";angular.module("ngScrollbar",[]).directive("ngScrollbar",["$parse","$window",function(a,b){return{restrict:"A",replace:!0,transclude:!0,scope:{showYScrollbar:"=?isBarShown"},link:function(a,c,d){var e,f,g,h,i,j,k,l,m,n,o,p={bottom:d.hasOwnProperty("bottom")},q=angular.element(b),r={top:0},s={top:0},t=function(){k={position:"relative",overflow:"hidden","max-width":"100%",height:"100%"},s.height&&(k.height=s.height+"px"),l={position:"absolute",height:r.height+"px",top:r.top+"px"},m={position:"relative","line-height":r.height+"px"},n={position:"relative",top:s.top+"px",overflow:"hidden"}},u=function(){h.css("top",r.top+"px");var a=r.top/s.height;s.top=-Math.round(s.scrollHeight*a),f.css("top",s.top+"px")},v=function(a){var b=a.hasOwnProperty("offsetY")?a.offsetY:a.layerY,c=Math.max(0,Math.min(parseInt(r.trackHeight,10)-parseInt(r.height,10),b));r.top=c,u(),a.stopPropagation()},w=function(a){var b=20,c=void 0!==a.wheelDeltaY?a.wheelDeltaY/b:void 0!==a.wheelDelta?a.wheelDelta/b:-a.detail*(b/10);return r.top=Math.max(0,Math.min(parseInt(s.height,10)-parseInt(r.height,10),parseInt(r.top,10)-c)),u(),a.preventDefault?void a.preventDefault():!1},x=0,y=function(a,b,c){r.top=Math.max(0,Math.min(parseInt(r.trackHeight,10)-parseInt(r.height,10),c)),a.stopPropagation()},z=function(a){var b=0,c=a.pageY-h[0].scrollTop-x;y(a,b,c),u()},A=function(a){q.off("mousemove",z),q.off("mouseup",A),a.stopPropagation()},B=function(a){var b=0,c=a.originalEvent.changedTouches[0].pageY-h[0].scrollTop-x;y(a,b,c),u()},C=function(a){q.off("touchmove",B),q.off("touchend",C),a.stopPropagation()},D=function(b){var d=c[0].parentElement.offsetTop,o=void 0!==q[0].onmousewheel?"mousewheel":"DOMMouseScroll";b=p.bottom||b,e=angular.element(c.children()[0]),f=angular.element(e.children()[0]),g=angular.element(e.children()[1]),h=angular.element(angular.element(g.children()[0]).children()[0]),i=angular.element(h.children()[0]),j=angular.element(angular.element(g.children()[0]).children()[1]),s.height=c[0].offsetHeight-d,s.height<0&&(s.height=c[0].offsetHeight),s.scrollHeight=f[0].scrollHeight,s.height
'}}]); \ No newline at end of file +"use strict";angular.module("ngScrollbar",[]).directive("ngScrollbar",["$parse","$window",function(a,b){return{restrict:"A",replace:!0,transclude:!0,scope:{showYScrollbar:"=?isBarShown"},link:function(a,c,d){var e,g,h,i,j,k,l,m,n,o,p,q={bottom:d.hasOwnProperty("bottom")},r=angular.element(b),s=!!r[0].addEventListener,t=!!r[0].removeEventListener,u={top:0},v={top:0},w=function(){l={position:"relative",overflow:"hidden","max-width":"100%",height:"100%"},v.height&&(l.height=v.height+"px"),m={position:"absolute",height:u.height+"px",top:u.top+"px"},n={position:"relative","line-height":u.height+"px"},o={position:"relative",top:v.top+"px",overflow:"hidden"}},x=function(){i.css("top",u.top+"px");var a=u.top/v.height;v.top=-Math.round(v.scrollHeight*a),g.css("top",v.top+"px")},y=function(a){var b=a.hasOwnProperty("offsetY")?a.offsetY:a.layerY,c=Math.max(0,Math.min(parseInt(u.trackHeight,10)-parseInt(u.height,10),b));u.top=c,x(),a.stopPropagation()},z=function(a){var b=40,c=a,d=c.detail,e=c.wheelDelta,g=225,h=g-1;return d=d?e&&(f=e/d)?d/f:-d/1.35:e/120,d=1>d?-1>d?(-Math.pow(d,2)-h)/g:d:(Math.pow(d,2)+h)/g,a.delta=Math.min(Math.max(d/2,-1),1),a.delta=a.delta*b,u.top=Math.max(0,Math.min(parseInt(v.height,10)-parseInt(u.height,10),parseInt(u.top,10)-a.delta)),x(),a.preventDefault?void a.preventDefault():!1},A=0,B=function(a,b,c){u.top=Math.max(0,Math.min(parseInt(u.trackHeight,10)-parseInt(u.height,10),c)),a.stopPropagation()},C=function(a){var b=0,c=a.pageY-i[0].scrollTop-A;B(a,b,c),x()},D=function(a){r.off("mousemove",C),r.off("mouseup",D),a.stopPropagation()},E=function(a){var b=0,c=a.originalEvent.changedTouches[0].pageY-i[0].scrollTop-A;B(a,b,c),x()},F=function(a){r.off("touchmove",E),r.off("touchend",F),a.stopPropagation()},G=function(a){var b=void 0!==r[0].onmousewheel?"mousewheel":"DOMMouseScroll";s?a.addEventListener(b,z,!1):a.attachEvent("onmousewheel",z)},H=function(a){var b=void 0!==r[0].onmousewheel?"mousewheel":"DOMMouseScroll";t?a.removeEventListener(b,z,!1):a.detachEvent("onmousewheel",z)},I=function(b){b=q.bottom||b,e=angular.element(c.children()[0]),g=angular.element(e.children()[0]),h=angular.element(e.children()[1]),i=angular.element(angular.element(h.children()[0]).children()[0]),j=angular.element(i.children()[0]),k=angular.element(angular.element(h.children()[0]).children()[1]),v.height=c[0].offsetHeight,v.scrollHeight=g[0].scrollHeight,v.height
'}}]); \ No newline at end of file diff --git a/package.json b/package.json index 1811c1f..2a37bbd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ng-scrollbar", - "version": "0.0.7", + "version": "0.0.8", "main": "dist/ng-scrollbar.min.js", "description": "A custom scrollbar written in pure AngularJS", "keywords": [