jquery.nicescroll.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415
  1. /* jquery.nicescroll
  2. -- versione 1.5.0
  3. -- copyright 2011 InuYaksa*2011
  4. -- licensed under the MIT
  5. --
  6. -- https://github.com/inuyaksa/jquery.nicescroll
  7. --
  8. */
  9. (function($){
  10. var domfocus = false;
  11. var mousefocus = false;
  12. var NiceScrollClass = function(myopt) {
  13. var self = this;
  14. this.opt = {
  15. doc:$("body"),
  16. win:false,
  17. zindex:9999,
  18. cursoropacitymin:0,
  19. cursoropacitymax:1,
  20. cursorcolor:"#424242",
  21. scrollspeed:60,
  22. mousescrollstep:8*6,
  23. };
  24. if (myopt) {
  25. for(var a in self.opt) {
  26. if (myopt[a]!==undefined) self.opt[a] = myopt[a];
  27. }
  28. }
  29. this.id = self.opt.doc[0].id||'';
  30. this.doc = self.opt.doc;
  31. this.ispage = (self.doc[0].nodeName=='BODY'||self.doc[0].nodeName=='HTML');
  32. this.docscroll = self.ispage?$(window):this.doc;
  33. this.win = self.opt.win||this.docscroll;
  34. this.isiframe = (this.doc[0].nodeName == 'IFRAME');
  35. if (self.isiframe) {
  36. this.docscroll = (this.doc[0].document)?$(this.doc[0].document.body):this.doc;
  37. this.doc.load(function() {
  38. var doc = 'contentDocument' in this? this.contentDocument : this.contentWindow.document;
  39. self.docscroll = $(doc.body);
  40. self.onResize();
  41. $(doc.body).css({'overflow-y':'hidden'});
  42. $(doc).scroll(self.onscroll);
  43. self.bind(doc,"mousewheel",self.onmousewheel);
  44. $(doc).keydown(self.onkeypress);
  45. });
  46. }
  47. this.view = false;
  48. this.page = false;
  49. this.scroll = {x:0,y:0};
  50. this.scrollratio = {x:0,y:0};
  51. this.cursorheight = 20;
  52. this.scrollvaluemax = 0;
  53. do {
  54. this.id = "ascrail"+Math.round(Math.random() * 99999);
  55. } while (document.getElementById(this.id));
  56. this.rail = false;
  57. this.cursor = false;
  58. this.cursorfreezed = false;
  59. this.hasfocus = false;
  60. this.hasmousefocus = false;
  61. this.isie = (document.all && !document.opera);
  62. this.scrollTop = function(val) {
  63. return (val === undefined) ? self.getScrollTop() : self.setScrollTop(val);
  64. };
  65. this.getScrollTop = function() {
  66. return self.docscroll.scrollTop();
  67. };
  68. this.setScrollTop = function(val) {
  69. return self.docscroll.scrollTop(val);
  70. };
  71. this.hasParent = function(e,id) {
  72. var el = e.target||e||false;
  73. while (el && el.id != id) {
  74. el = el.parentNode||false;
  75. }
  76. return (el!==false);
  77. };
  78. this.updateScrollBar = function() {
  79. var pos = self.win.offset();
  80. pos.top+=2;
  81. pos.left+=self.win.outerWidth()-16;
  82. self.rail.css({position:"absolute",top:pos.top,left:pos.left,height:self.win.outerHeight()});
  83. };
  84. this.init = function() {
  85. self.doc.css({'overflow-y':'hidden'});
  86. var rail = $(document.createElement('div'));
  87. rail.attr('id',self.id);
  88. rail.css({"padding-left":"4px",width:"12px",'z-index':self.opt.zindex,opacity:self.cursoropacitymin});
  89. self.rail = rail;
  90. if (self.ispage) {
  91. rail.css({position:"fixed",top:"0px",right:"0px",height:"100%"});
  92. self.doc.append(rail);
  93. } else {
  94. self.updateScrollBar();
  95. $("body").append(rail);
  96. }
  97. var cursor = $(document.createElement('div'));
  98. cursor.css({
  99. position:"relative",top:0,left:0,width:"8px",height:"0px",
  100. 'background-color':self.opt.cursorcolor,
  101. border:"1px solid #fff",
  102. '-webkit-border-radius':'4px',
  103. '-moz-border-radius':'4px',
  104. 'border-radius':'4px'
  105. });
  106. self.cursor = cursor;
  107. self.rail.append(cursor);
  108. self.win.resize(function(){self.onResize()});
  109. self.doc.resize(function(){self.onResize()});
  110. self.onResize();
  111. self.rail.mousedown(function(e) {
  112. self.rail.drag = {x:e.screenX,y:e.screenY,sx:self.scroll.x,sy:self.scroll.y};
  113. return self.cancelEvent(e);
  114. });
  115. self.rail.mouseup(function() {
  116. self.rail.drag = false;
  117. return false;
  118. });
  119. $(document).mouseup(function(e) {
  120. self.rail.drag = false;
  121. self.hideCursor();
  122. });
  123. $(document).mousemove(function(e) {
  124. if (self.rail.drag) {
  125. self.scroll.y = self.rail.drag.sy + (e.screenY-self.rail.drag.y);
  126. if (self.scroll.y<0) self.scroll.y=0;
  127. var my = self.scrollvaluemax;
  128. if (self.scroll.y>my) self.scroll.y=my;
  129. self.showCursor();
  130. self.cursorfreezed = true;
  131. self.doScroll(Math.round(self.scroll.y*self.scrollratio.y));
  132. return self.cancelEvent(e);
  133. }
  134. });
  135. self.rail.mouseenter(function() {
  136. $(self.rail).animate({opacity:self.opt.cursoropacitymax});
  137. self.rail.active = true;
  138. });
  139. self.rail.mouseleave(function() {
  140. self.rail.active = false;
  141. if (!self.rail.drag) self.hideCursor();
  142. });
  143. if (!self.isiframe) self.bind(self.docscroll,"mousewheel",self.onmousewheel);
  144. self.bind(self.rail,"mousewheel",self.onmousewheel);
  145. if (!self.ispage) {
  146. if (!self.win.attr("tabindex")) self.win.attr({"tabindex":(new Date()).getTime()});
  147. self.win.focus(function(e) {
  148. domfocus = e.target.id||true;
  149. self.hasfocus = true;
  150. self.showCursor();
  151. self.hideCursor();
  152. });
  153. self.win.blur(function(e) {
  154. domfocus = false;
  155. self.hasfocus = false;
  156. });
  157. self.win.mouseenter(function(e) {
  158. mousefocus = e.target.id||true;
  159. self.hasmousefocus = true;
  160. });
  161. self.win.mouseleave(function() {
  162. mousefocus = false;
  163. self.hasmousefocus = false;
  164. });
  165. };
  166. //Thanks to http://www.quirksmode.org !!
  167. self.onkeypress = function(e) {
  168. e = (e) ? e : window.e;
  169. if (e.target&&/(INPUT|TEXTAREA|SELECT)/.test(e.target.nodeName)) return;
  170. if (self.hasfocus||(self.hasmousefocus&&!domfocus)||(self.ispage&&!domfocus&&!mousefocus)) {
  171. var key = e.keyCode;
  172. var ret = true;
  173. switch (key) {
  174. case 38:
  175. case 63233: //safari
  176. self.doScrollBy(12);
  177. ret = false;
  178. break;
  179. case 40:
  180. case 63235: //safari
  181. self.doScrollBy(-12);
  182. ret = false;
  183. break;
  184. case 33:
  185. case 63276: // safari
  186. self.doScrollBy(self.view.h,true);
  187. ret = false;
  188. break;
  189. case 34:
  190. case 63277: // safari
  191. self.doScrollBy(-self.view.h,true);
  192. ret = false;
  193. break;
  194. case 36:
  195. case 63273: // safari
  196. self.doScrollTo(0,true);
  197. ret = false;
  198. break;
  199. case 35:
  200. case 63275: // safari
  201. self.doScrollTo(self.page.h,true);
  202. ret = false;
  203. break;
  204. }
  205. if (!ret) return self.cancelEvent(e);
  206. }
  207. };
  208. self.bind(document,"keydown",self.onkeypress);
  209. };
  210. this.showCursor = function() {
  211. if (self.cursortimeout) {
  212. clearTimeout(self.cursortimeout);
  213. self.cursortimeout = 0;
  214. }
  215. self.rail.clearQueue().css({opacity:self.opt.cursoropacitymax});
  216. self.cursor.css({height:self.cursorheight,top:self.scroll.y});
  217. };
  218. this.hideCursor = function(tm) {
  219. if (self.cursortimeout) return;
  220. self.cursortimeout = setTimeout(function() {
  221. if (self.rail.active) return;
  222. $(self.rail).animate({opacity:self.opt.cursoropacitymin});
  223. self.cursortimeout = 0;
  224. },tm||800);
  225. };
  226. this.getContentSize = function() {
  227. var pg = (self.ispage) ?
  228. {
  229. w:Math.max(document.body.scrollWidth,document.documentElement.scrollWidth),
  230. h:Math.max(document.body.scrollHeight,document.documentElement.scrollHeight)
  231. } :
  232. {
  233. w:self.docscroll[0].scrollWidth,
  234. h:self.docscroll[0].scrollHeight
  235. };
  236. pg.w-=1;
  237. pg.h-=1;
  238. return pg;
  239. };
  240. this.onResize = function() {
  241. if (!self.ispage) self.updateScrollBar();
  242. self.view = {
  243. w:(self.ispage) ? self.win.width() : self.win.innerWidth(),
  244. h:(self.ispage) ? self.win.height() : self.win.innerHeight()
  245. };
  246. self.page = self.getContentSize();
  247. self.cursorheight = Math.min(self.view.h,Math.round(self.view.h * (self.view.h / self.page.h)));
  248. self.scrollvaluemax = self.view.h-self.cursorheight-2;
  249. self.scrollratio = {
  250. x:0,
  251. y:((self.page.h - self.view.h)/self.scrollvaluemax)
  252. };
  253. self.scroll.y = Math.round(self.getScrollTop() * (1/self.scrollratio.y));
  254. self.showCursor();
  255. self.hideCursor();
  256. };
  257. this.bind = function(dom,name,fn,bubble) { // fixing jquery bind
  258. var el = (dom.length) ? dom[0] : dom;
  259. if (el.addEventListener) {
  260. el.addEventListener(name,fn,bubble||false);
  261. if (name=='mousewheel') el.addEventListener("DOMMouseScroll",fn,bubble||false);
  262. }
  263. else if (el.attachEvent) {
  264. el.attachEvent(name,fn);
  265. }
  266. else {
  267. el["on"+name] = fn;
  268. }
  269. };
  270. // Thanks to http://www.switchonthecode.com !!
  271. this.cancelEvent = function(e) {
  272. e = e ? e : window.event;
  273. if(e.stopPropagation) e.stopPropagation();
  274. if(e.preventDefault) e.preventDefault();
  275. e.cancelBubble = true;
  276. e.cancel = true;
  277. e.returnValue = false;
  278. return false;
  279. };
  280. this.onmousewheel = function(e) {
  281. var delta = 0;
  282. e = e ? e : window.event;
  283. var delta = e.detail ? e.detail * -1 : e.wheelDelta / 40;
  284. if (delta) {
  285. self.doScrollBy(delta*self.opt.mousescrollstep,true);
  286. }
  287. return self.cancelEvent(e);
  288. };
  289. this.mousewheel = function(fn) {
  290. if (!self.isie) self.bind(self.docscroll,'DOMMouseScroll',self.onmousewheel,false);
  291. self.bind(self.docscroll,'mousewheel',self.onmousewheel,false);
  292. if (!self.ispage) {
  293. if (!self.isie) self.bind(self.rail,'DOMMouseScroll',self.onmousewheel,false);
  294. self.bind(self.rail,'mousewheel',self.onmousewheel,false);
  295. }
  296. };
  297. this.doScroll = function(y) {
  298. self.newscrolly = y;
  299. if (self.timer) return;
  300. self.timer = setInterval(function() {
  301. var gp = self.newscrolly - self.getScrollTop();
  302. var df = (gp>0) ? Math.ceil(gp/4) : Math.floor(gp/4);
  303. var sc = self.getScrollTop()+df;
  304. self.setScrollTop(sc);
  305. if (sc == self.newscrolly) {
  306. clearInterval(self.timer);
  307. self.timer = 0;
  308. self.cursorfreezed = false;
  309. }
  310. },self.opt.scrollspeed);
  311. self.showCursor();
  312. self.hideCursor();
  313. };
  314. this.doScrollBy = function(stp,absolute) {
  315. if (absolute) stp = Math.round(stp * 1/self.scrollratio.y);
  316. var ny = self.scroll.y-stp;
  317. if (ny<0) ny=0;
  318. var my = self.scrollvaluemax;
  319. if (ny>my) ny=my;
  320. self.cursorfreezed = false;
  321. self.doScroll(Math.floor(ny*self.scrollratio.y));
  322. };
  323. this.doScrollTo = function(pos,absolute) {
  324. if (absolute) pos = Math.round(pos * 1/self.scrollratio.y);
  325. ny=pos;
  326. if (ny<0) ny=0;
  327. var my = self.scrollvaluemax;
  328. if (ny>my) ny=my;
  329. self.cursorfreezed = false;
  330. self.doScroll(Math.floor(ny*self.scrollratio.y));
  331. };
  332. self.onscroll = function(e) {
  333. var tm = (new Date()).getTime();
  334. if (!self.lastcontentcheck || self.lastcontentcheck<tm) {
  335. self.lastcontentcheck=tm+500;
  336. var pg = self.getContentSize();
  337. if (pg.h!=self.page.h) self.onResize();
  338. }
  339. if (self.rail.drag) return;
  340. if (!self.cursorfreezed) self.scroll.y = Math.round(self.getScrollTop() * (1/self.scrollratio.y));
  341. self.showCursor();
  342. self.hideCursor();
  343. };
  344. self.docscroll.scroll(function(e) {
  345. self.onscroll(e);
  346. });
  347. this.init();
  348. };
  349. $.fn.niceScroll = function(opt) {
  350. var ret = [];
  351. if (opt===undefined) opt = {};
  352. var docundef = (opt.doc===undefined);
  353. this.each(function() {
  354. opt.doc = (docundef) ? $(this) : opt.doc;
  355. ret.push(new NiceScrollClass(opt));
  356. });
  357. return (ret.length==1) ? ret[0] : ret;
  358. };
  359. })( jQuery );