jquery.nicescroll.js 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940
  1. /* jquery.nicescroll
  2. -- versione 2.2.0
  3. -- copyright 2011 InuYaksa*2011
  4. -- licensed under the MIT
  5. --
  6. -- http://areaaperta.com/nicescroll
  7. -- https://github.com/inuyaksa/jquery.nicescroll
  8. --
  9. */
  10. (function($){
  11. // globals
  12. var domfocus = false;
  13. var mousefocus = false;
  14. var zoomactive = false;
  15. // http://stackoverflow.com/questions/2161159/get-script-path
  16. function getScriptPath() {
  17. var scripts= document.getElementsByTagName('script');
  18. var path= scripts[scripts.length-1].src.split('?')[0];
  19. return (path.split('/').length>0) ? path.split('/').slice(0,-1).join('/')+'/' : '';
  20. }
  21. var scriptpath = getScriptPath();
  22. var NiceScrollClass = function(myopt) {
  23. var self = this;
  24. this.opt = {
  25. doc:$("body"),
  26. win:false,
  27. zindex:9000,
  28. cursoropacitymin:0,
  29. cursoropacitymax:1,
  30. cursorcolor:"#424242",
  31. cursorwidth:"5px",
  32. cursorborder:"1px solid #fff",
  33. cursorborderradius:"5px",
  34. scrollspeed:60,
  35. mousescrollstep:8*6,
  36. touchbehavior:false,
  37. hwacceleration:true,
  38. usetransition:true,
  39. boxzoom:false,
  40. dblclickzoom:true,
  41. gesturezoom:true,
  42. grabcursorenabled:true,
  43. autohidemode:true,
  44. background:""
  45. };
  46. if (myopt||false) {
  47. for(var a in self.opt) {
  48. if (myopt[a]!==undefined) self.opt[a] = myopt[a];
  49. }
  50. }
  51. this.id = self.opt.doc[0].id||'';
  52. this.doc = self.opt.doc;
  53. this.ispage = (self.doc[0].nodeName=='BODY'||self.doc[0].nodeName=='HTML');
  54. this.haswrapper = (self.opt.win!==false);
  55. this.win = self.opt.win||(this.ispage?$(window):this.doc);
  56. this.docscroll = this.ispage?$(window):this.win;
  57. this.isiframe = ((this.doc[0].nodeName == 'IFRAME') && (this.win[0].nodeName == 'IFRAME'));
  58. this.istextarea = (this.win[0].nodeName == 'TEXTAREA');
  59. if (this.doc[0].nodeName == 'IFRAME') {
  60. function oniframeload(e) {
  61. var doc = 'contentDocument' in this? this.contentDocument : this.contentWindow.document;
  62. if (self.isiframe) self.docscroll = $(doc.body);
  63. self.onResize();
  64. $(doc.body).css({'overflow-y':'hidden'});
  65. $(doc).scroll(self.onscroll);
  66. $(doc).mouseup(function(){self.rail.drag = false;});
  67. self.bind(doc,"mousewheel",self.onmousewheel);
  68. $(doc).keydown(self.onkeypress);
  69. if (self.cantouch||self.opt.touchbehavior) {
  70. if (self.cursorgrabvalue) $(doc).css({'cursor':self.cursorgrabvalue});
  71. self.bind(doc,"mousedown",function(e) {
  72. self.rail.drag = {x:e.pageX,y:e.pageY,sx:self.scroll.x,sy:self.scroll.y,st:self.getScrollTop()};
  73. return self.cancelEvent(e);
  74. });
  75. self.bind(doc,"mouseup",function(e) {
  76. self.rail.drag = false;
  77. return self.cancelEvent(e);
  78. });
  79. self.bind(doc,"mousemove",function(e) {
  80. if (self.rail.drag) {
  81. self.doScrollTo(self.rail.drag.st - (e.pageY-self.rail.drag.y),true);
  82. return self.cancelEvent(e);
  83. }
  84. });
  85. }
  86. if (self.zoom) {
  87. self.bind(doc,'dblclick',self.doZoom);
  88. if (self.cantouch&&self.opt.gesturezoom) {
  89. self.bind(doc,"gesturechange",function(e) {
  90. if (e.scale>1.5) self.doZoomIn(e);
  91. if (e.scale<0.8) self.doZoomOut(e);
  92. return self.cancelEvent(e);
  93. });
  94. }
  95. }
  96. };
  97. if (this.doc[0].readyState&&this.doc[0].readyState=="complete"){
  98. setTimeout(function(){oniframeload.call(self.doc[0],false)},1000);
  99. } else {
  100. this.doc.load(oniframeload);
  101. }
  102. }
  103. this.view = false;
  104. this.page = false;
  105. this.scroll = {x:0,y:0};
  106. this.scrollratio = {x:0,y:0};
  107. this.cursorheight = 20;
  108. this.scrollvaluemax = 0;
  109. do {
  110. this.id = "ascrail"+Math.round(Math.random() * 99999);
  111. } while (document.getElementById(this.id));
  112. this.rail = false;
  113. this.cursor = false;
  114. this.cursorfreezed = false;
  115. this.zoom = false;
  116. this.zoomactive = false;
  117. this.hasfocus = false;
  118. this.hasmousefocus = false;
  119. this.locked = false;
  120. var domtest = document.createElement('DIV');
  121. this.isopera = ("opera" in window);
  122. this.isie = (("all" in document) && ("attachEvent" in domtest) && !this.isopera);
  123. this.isieold = (this.isie && !("msInterpolationMode" in domtest.style)); // IE6 and older
  124. this.isie7 = this.isie&&(!("documentMode" in document)||(document.documentMode==7));
  125. this.isie8 = this.isie&&("documentMode" in document)&&(document.documentMode==8);
  126. this.isie9 = this.isie&&("performance" in window)&&(document.documentMode>=9);
  127. this.ismozilla = ("MozAppearance" in domtest.style);
  128. this.cantouch = ("ontouchstart" in document.documentElement);
  129. if (this.cantouch && /iphone|ipad|ipod/i.test(navigator.platform)) {
  130. this.isios = true;
  131. this.isios4 = !("seal" in Object);
  132. } else {
  133. this.isios = false;
  134. this.isios4 = false;
  135. }
  136. if (self.opt.hwacceleration) { // if you dont need dont bother to look for
  137. this.trstyle = (window.opera) ? 'OTransform' : (document.all) ? 'msTransform' : (domtest.style.webkitTransform!==undefined) ? 'webkitTransform' : (domtest.style.MozTransform!==undefined) ? 'MozTransform' : false;
  138. if (this.trstyle && domtest.style[this.trstyle] === undefined) this.trstyle = false;
  139. this.hastransform = (this.trstyle != false);
  140. if (this.hastransform) {
  141. domtest.style[this.trstyle] = "translate3d(1px,2px,3px)";
  142. this.hastranslate3d = /translate3d/.test(domtest.style[this.trstyle]);
  143. }
  144. this.transitionstyle = false;
  145. this.prefixstyle = '';
  146. this.transitionend = false;
  147. var check = ['transition','webkitTransition','MozTransition','OTransition','msTransition','KhtmlTransition'];
  148. var prefix = ['','-webkit-','-moz-','-o-','-ms-','-khtml-'];
  149. var evs = ['transitionEnd','webkitTransitionEnd','transitionend','oTransitionEnd','msTransitionEnd','KhtmlTransitionEnd'];
  150. for(var a=0;a<check.length;a++) {
  151. if (check[a] in domtest.style) {
  152. this.transitionstyle = check[a];
  153. this.prefixstyle = prefix[a];
  154. this.transitionend = evs[a];
  155. break;
  156. }
  157. }
  158. this.hastransition = (this.transitionstyle);
  159. } else {
  160. this.trstyle = false;
  161. this.hastransform = false;
  162. this.transitionstyle = false;
  163. this.hastransition = false;
  164. }
  165. this.cursorgrabvalue = '';
  166. if (self.opt.grabcursorenabled&&self.opt.touchbehavior) { // check grab cursor support
  167. function detectCursorGrab() {
  168. if (!self.isie||self.isie9) { // some old IE return false positive
  169. var lst = ['grab','-moz-grab','-webkit-grab'];
  170. for(var a=0;a<lst.length;a++) {
  171. var p = lst[a];
  172. domtest.style['cursor']=p;
  173. if (domtest.style['cursor']==p) return p;
  174. }
  175. }
  176. return 'url(http://www.google.com/intl/en_ALL/mapfiles/openhand.cur),n-resize';
  177. }
  178. this.cursorgrabvalue = detectCursorGrab();
  179. }
  180. domtest = null;
  181. this.ishwscroll = (self.hastransform)&&(self.opt.hwacceleration)&&(self.haswrapper);
  182. this.scrollTop = function(val) {
  183. return (val === undefined) ? self.getScrollTop() : self.setScrollTop(val);
  184. };
  185. if (this.ishwscroll) {
  186. // hw accelerated scroll
  187. self.doc.translate = {x:0,y:0};
  188. this.getScrollTop = function() {
  189. return self.doc.translate.y;
  190. };
  191. if (this.hastranslate3d) {
  192. this.setScrollTop = function(val,silent) {
  193. self.doc.css(self.trstyle,"translate3d(0px,"+(val*-1)+"px,0px)");
  194. self.doc.translate.y = val;
  195. if (!silent) {
  196. if (document.createEvent) {
  197. var e = document.createEvent("UIEvents");
  198. e.initUIEvent("scroll", false, true, window, 1);
  199. self.docscroll[0].dispatchEvent(e);
  200. } else {
  201. var e = document.createEventObject();
  202. self.docscroll[0].fireEvent("onscroll");
  203. e.cancelBubble = true;
  204. }
  205. }
  206. };
  207. } else {
  208. this.setScrollTop = function(val,silent) {
  209. self.doc.css(self.trstyle,"translate(0px,"+(val*-1)+"px)");
  210. self.doc.translate.y = val;
  211. if (!silent) {
  212. if (document.createEvent) {
  213. var e = document.createEvent("UIEvents");
  214. e.initUIEvent("scroll", false, true, window, 1);
  215. self.docscroll[0].dispatchEvent(e);
  216. } else {
  217. var e = document.createEventObject();
  218. self.docscroll[0].fireEvent("onscroll");
  219. e.cancelBubble = true;
  220. }
  221. }
  222. };
  223. }
  224. } else {
  225. // native scroll
  226. this.getScrollTop = function() {
  227. return self.docscroll.scrollTop();
  228. };
  229. this.setScrollTop = function(val) {
  230. return self.docscroll.scrollTop(val);
  231. };
  232. }
  233. this.getTarget = function(e) {
  234. if (!e) return false;
  235. if (e.target) return e.target;
  236. if (e.srcElement) return e.srcElement;
  237. return false;
  238. };
  239. this.hasParent = function(e,id) {
  240. if (!e) return false;
  241. var el = e.target||e.srcElement||e||false;
  242. while (el && el.id != id) {
  243. el = el.parentNode||false;
  244. }
  245. return (el!==false);
  246. };
  247. this.updateScrollBar = function(len) {
  248. if (self.ishwscroll) {
  249. self.rail.css({height:self.win.innerHeight()});
  250. } else {
  251. var pos = self.win.offset();
  252. pos.top+=2;
  253. pos.left+=self.win.outerWidth()-self.rail.width-4;
  254. self.rail.css({position:"absolute",top:pos.top,left:pos.left,height:(len)?len.h:self.win.outerHeight()});
  255. if (self.zoom) self.zoom.css({position:"absolute",top:pos.top+1,left:pos.left-18});
  256. }
  257. };
  258. this.init = function() {
  259. if (!self.ispage || (!self.cantouch && !self.isieold)) {
  260. (self.ispage)?self.doc.css({'overflow-y':'hidden'}):self.docscroll.css({'overflow-y':'hidden'});
  261. if (self.ispage&&self.isie7) $("html").css({'overflow-y':'hidden'}); //IE7 double scrollbar issue
  262. var rail = $(document.createElement('div'));
  263. rail.attr('id',self.id);
  264. rail.width = 4+parseFloat(self.opt.cursorwidth);
  265. rail.css({"padding-left":"2px","padding-right":"1px",width:self.rail.width+"px",'zIndex':(self.ispage)?self.opt.zindex:self.opt.zindex+2,"background":self.opt.background});
  266. self.rail = rail;
  267. var zoom = false;
  268. if (self.opt.boxzoom&&!self.ispage&&!self.isieold) {
  269. zoom = document.createElement('div');
  270. self.bind(zoom,"click",self.doZoom);
  271. self.zoom = $(zoom);
  272. self.zoom.css({"cursor":"pointer",'z-index':self.opt.zindex,'backgroundImage':'url('+scriptpath+'zoomico.png)','height':18,'width':18,'backgroundPosition':'0px 0px'});
  273. if (self.opt.dblclickzoom) self.bind(self.win,"dblclick",self.doZoom);
  274. if (self.cantouch&&self.opt.gesturezoom) {
  275. self.bind(self.win,"gesturechange",function(e) {
  276. if (e.scale>1.5) self.doZoomIn(e);
  277. if (e.scale<0.8) self.doZoomOut(e);
  278. return self.cancelEvent(e);
  279. });
  280. }
  281. }
  282. if (self.ispage) {
  283. rail.css({position:"fixed",top:"0px",right:"0px",height:"100%"});
  284. self.doc.append(rail);
  285. } else {
  286. if (self.ishwscroll) {
  287. if (self.win.css('position')=='static') self.win.css('position','relative');
  288. if (self.zoom) {
  289. self.zoom.css({position:"absolute",top:1,right:0,"margin-right":rail.width+2});
  290. self.win.append(self.zoom);
  291. }
  292. rail.css({position:"absolute",top:0,right:0});
  293. self.win.append(rail);
  294. } else {
  295. self.updateScrollBar();
  296. $("body").append(rail);
  297. if (self.zoom) $("body").append(self.zoom);
  298. }
  299. }
  300. var cursor = $(document.createElement('div'));
  301. cursor.css({
  302. position:"relative",top:0,left:0,width:self.opt.cursorwidth,height:"0px",
  303. 'background-color':self.opt.cursorcolor,
  304. border:self.opt.cursorborder,
  305. 'background-clip':'padding-box',
  306. '-webkit-border-radius':self.opt.cursorborderradius,
  307. '-moz-border-radius':self.opt.cursorborderradius,
  308. 'border-radius':self.opt.cursorborderradius
  309. });
  310. self.cursor = cursor;
  311. self.rail.append(cursor);
  312. if (self.opt.autohidemode===false) {
  313. self.autohidedom = false;
  314. }
  315. else if (self.opt.autohidemode===true) {
  316. self.autohidedom = self.rail;
  317. }
  318. else if (self.opt.autohidemode=="cursor") {
  319. self.autohidedom = self.cursor;
  320. }
  321. $(window).resize(self.onResize)
  322. if (!self.ispage&&!self.haswrapper) {
  323. self.bind(self.win,(self.isie&&!self.isie9)?"propertychange":"DOMAttrModified",self.onAttributeChange);
  324. }
  325. if (!self.ispage&&self.opt.boxzoom) $(window).resize(self.resizeZoom);
  326. if (self.istextarea) self.win.mouseup(self.onResize);
  327. self.onResize();
  328. if (self.cantouch||self.opt.touchbehavior) {
  329. self.bind(self.win,"mousedown",function(e) {
  330. self.rail.drag = {x:e.pageX,y:e.pageY,sx:self.scroll.x,sy:self.scroll.y,st:self.getScrollTop(),lx:e.pageX,ly:e.pageY,nx:e.pageX,ny:e.pageY,tt:(new Date()).getTime(),lt:(new Date()).getTime()};
  331. return self.cancelEvent(e);
  332. });
  333. self.bind(self.win,"mouseup",function(e) {
  334. self.doScrollMomentum(self.rail.drag);
  335. self.rail.drag = false;
  336. return self.cancelEvent(e);
  337. });
  338. self.bind(self.rail,"mousedown",function(e) {
  339. self.rail.drag = {x:e.pageX,y:e.pageY,sx:self.scroll.x,sy:self.scroll.y,st:self.getScrollTop(),lx:e.pageX,ly:e.pageY,nx:e.pageX,ny:e.pageY,tt:(new Date()).getTime(),lt:(new Date()).getTime()};
  340. return self.cancelEvent(e);
  341. });
  342. self.bind(self.rail,"mouseup",function(e) {
  343. self.rail.drag = false;
  344. return self.cancelEvent(e);
  345. });
  346. self.bind(document,"mousemove",function(e) {
  347. if (self.rail.drag) {
  348. var my = (e.pageY-self.rail.drag.y);
  349. self.rail.drag.ly = self.rail.drag.ny;
  350. self.rail.drag.ny = e.pageY;
  351. self.rail.drag.lt = (new Date()).getTime();
  352. self.scroll.y = Math.round((self.rail.drag.st-my) * (1/self.scrollratio.y));
  353. if (self.scroll.y<0) self.scroll.y=0;
  354. if (self.scroll.y>self.scrollvaluemax) self.scroll.y=self.scrollvaluemax;
  355. self.showCursor();
  356. self.doScrollTo(self.rail.drag.st-my,true);
  357. return self.cancelEvent(e);
  358. }
  359. });
  360. if (self.cursorgrabvalue) self.win.css({'cursor':self.cursorgrabvalue});
  361. } else {
  362. self.bind(self.rail,"mousedown",function(e) {
  363. self.rail.drag = {x:e.screenX,y:e.screenY,sx:self.scroll.x,sy:self.scroll.y};
  364. return self.cancelEvent(e);
  365. });
  366. self.bind(self.rail,"mouseup",function(e) {
  367. self.rail.drag = false;
  368. self.hideCursor();
  369. return self.cancelEvent(e);
  370. });
  371. self.bind(document,"mousemove",function(e) {
  372. if (self.rail.drag) {
  373. self.scroll.y = self.rail.drag.sy + (e.screenY-self.rail.drag.y);
  374. if (self.scroll.y<0) self.scroll.y=0;
  375. var my = self.scrollvaluemax;
  376. if (self.scroll.y>my) self.scroll.y=my;
  377. self.showCursor();
  378. self.cursorfreezed = true;
  379. self.doScroll(Math.round(self.scroll.y*self.scrollratio.y));
  380. return self.cancelEvent(e);
  381. }
  382. });
  383. }
  384. self.bind(document,"mouseup",function(e) {
  385. self.rail.drag = false;
  386. self.hideCursor();
  387. });
  388. if (!self.cantouch) {
  389. self.rail.mouseenter(function() {
  390. self.showCursor();
  391. self.rail.active = true;
  392. });
  393. self.rail.mouseleave(function() {
  394. self.rail.active = false;
  395. if (!self.rail.drag) self.hideCursor();
  396. });
  397. if (!self.isiframe) self.bind((self.isie&&self.ispage) ? document : self.docscroll,"mousewheel",self.onmousewheel);
  398. self.bind(self.rail,"mousewheel",self.onmousewheel);
  399. }
  400. if (!self.ispage&&!self.cantouch) {
  401. if (!self.win.attr("tabindex")) self.win.attr({"tabindex":(new Date()).getTime()});
  402. self.win.focus(function(e) {
  403. domfocus = (self.getTarget(e)).id||true;
  404. self.hasfocus = true;
  405. self.noticeCursor();
  406. });
  407. self.win.blur(function(e) {
  408. domfocus = false;
  409. self.hasfocus = false;
  410. });
  411. self.win.mouseenter(function(e) {
  412. mousefocus = (self.getTarget(e)).id||true;
  413. self.hasmousefocus = true;
  414. self.noticeCursor();
  415. });
  416. self.win.mouseleave(function() {
  417. mousefocus = false;
  418. self.hasmousefocus = false;
  419. });
  420. };
  421. //Thanks to http://www.quirksmode.org !!
  422. self.onkeypress = function(e) {
  423. e = (e) ? e : window.e;
  424. var tg = self.getTarget(e);
  425. if (tg&&/(INPUT|TEXTAREA|SELECT)/.test(tg.nodeName)) return;
  426. if (self.hasfocus||(self.hasmousefocus&&!domfocus)||(self.ispage&&!domfocus&&!mousefocus)) {
  427. var key = e.keyCode;
  428. var ret = true;
  429. switch (key) {
  430. case 38:
  431. case 63233: //safari
  432. self.doScrollBy(12);
  433. ret = false;
  434. break;
  435. case 40:
  436. case 63235: //safari
  437. self.doScrollBy(-12);
  438. ret = false;
  439. break;
  440. case 33:
  441. case 63276: // safari
  442. self.doScrollBy(self.view.h,true);
  443. ret = false;
  444. break;
  445. case 34:
  446. case 63277: // safari
  447. self.doScrollBy(-self.view.h,true);
  448. ret = false;
  449. break;
  450. case 36:
  451. case 63273: // safari
  452. self.doScrollTo(0,true);
  453. ret = false;
  454. break;
  455. case 35:
  456. case 63275: // safari
  457. self.doScrollTo(self.page.h,true);
  458. ret = false;
  459. break;
  460. case 27: // ESC
  461. if (self.zoomactive) {
  462. self.doZoom();
  463. ret = false;
  464. }
  465. break;
  466. }
  467. if (!ret) return self.cancelEvent(e);
  468. }
  469. };
  470. self.bind(document,(self.isopera)?"keypress":"keydown",self.onkeypress);
  471. }
  472. };
  473. this.showCursor = function() {
  474. if (self.cursortimeout) {
  475. clearTimeout(self.cursortimeout);
  476. self.cursortimeout = 0;
  477. }
  478. if (!self.rail) return;
  479. if (!self.autohidedom) return;
  480. self.autohidedom.stop().css({opacity:self.opt.cursoropacitymax});
  481. self.cursor.css({height:self.cursorheight,top:self.scroll.y});
  482. if (self.zoom) self.zoom.stop().css({opacity:self.opt.cursoropacitymax});
  483. };
  484. this.hideCursor = function(tm) {
  485. if (self.cursortimeout) return;
  486. if (!self.rail) return;
  487. if (!self.autohidedom) return;
  488. self.cursortimeout = setTimeout(function() {
  489. if (!self.rail.active) {
  490. self.autohidedom.stop().animate({opacity:self.opt.cursoropacitymin});
  491. if (self.zoom) self.zoom.stop().animate({opacity:self.opt.cursoropacitymin});
  492. }
  493. self.cursortimeout = 0;
  494. },tm||800);
  495. };
  496. this.noticeCursor = function(tm) {
  497. self.showCursor();
  498. self.hideCursor(tm);
  499. };
  500. this.getContentSize = function() {
  501. var pg =
  502. (self.ispage) ?
  503. {
  504. w:Math.max(document.body.scrollWidth,document.documentElement.scrollWidth),
  505. h:Math.max(document.body.scrollHeight,document.documentElement.scrollHeight)
  506. }
  507. : (self.haswrapper) ?
  508. {
  509. w:self.doc.outerWidth()+parseInt(self.win.css('paddingLeft'))+parseInt(self.win.css('paddingRight')),
  510. h:self.doc.outerHeight()+parseInt(self.win.css('paddingTop'))+parseInt(self.win.css('paddingBottom'))
  511. }
  512. :
  513. {
  514. w:self.docscroll[0].scrollWidth,
  515. h:self.docscroll[0].scrollHeight
  516. };
  517. pg.w-=1;
  518. pg.h-=1;
  519. return pg;
  520. };
  521. this.onAttributeChange = function(e) {
  522. if (e&&e.target) {
  523. if (e.target !== self.win[0]) return true;
  524. if (e.target !== self.doc[0]) return true;
  525. var attr = ("attrChange" in e)?e.attrName:("propertyName" in e)?e.propertyName:false;
  526. if (attr&&/width|height|style/i.test(attr)) {
  527. if (self.lastattributechange) self.lastattributechange=clearTimeout(self.lastattributechange);
  528. self.lastattributechange = setTimeout(function(){
  529. self.lastattributechange = 0;
  530. self.onResize();
  531. },60);
  532. }
  533. }
  534. };
  535. this.onResize = function() {
  536. self.view = {
  537. w:(self.ispage) ? self.win.width() : self.win.innerWidth(),
  538. h:(self.ispage) ? self.win.height() : self.win.innerHeight()
  539. };
  540. if (self.istextarea&&self.win.css('resize')&&self.win.css('resize')!='none') self.view.h-=20;
  541. if (!self.ispage) self.updateScrollBar(self.view);
  542. self.page = self.getContentSize();
  543. self.cursorheight = Math.min(self.view.h,Math.round(self.view.h * (self.view.h / self.page.h)));
  544. self.scrollvaluemax = self.view.h-self.cursorheight-2;
  545. self.scrollratio = {
  546. x:0,
  547. y:((self.page.h - self.view.h)/self.scrollvaluemax)
  548. };
  549. self.scroll.y = Math.round(self.getScrollTop() * (1/self.scrollratio.y));
  550. self.noticeCursor();
  551. };
  552. this.bind = function(dom,name,fn,bubble) { // touch-oriented & fixing jquery bind
  553. var el = (dom.length) ? dom[0] : dom;
  554. if (el.addEventListener) {
  555. if (self.cantouch && /mouseup|mousedown|mousemove/.test(name)) { // touch device support
  556. var tt = (name=='mousedown')?'touchstart':(name=='mouseup')?'touchend':'touchmove';
  557. el.addEventListener(tt,function(e){
  558. if(e.touches.length<2){var ev=(e.touches.length>0)?e.touches[0]:e;ev.original=e;fn.call(this,ev);}
  559. },bubble||false);
  560. }
  561. el.addEventListener(name,fn,bubble||false);
  562. if (name=='mousewheel') el.addEventListener("DOMMouseScroll",fn,bubble||false);
  563. }
  564. else if (el.attachEvent) {
  565. el.attachEvent("on"+name,function(e) {
  566. if (e&&!("pageY" in e)&&("screenY" in e)) {
  567. e.pageX = e.screenX;
  568. e.pageY = e.screenY;
  569. }
  570. if (!fn.call(el,e)||!bubble) return self.cancelEvent(e);
  571. });
  572. }
  573. else {
  574. el["on"+name] = function(e) {
  575. var rt=fn.call(el,e);
  576. if (!rt||!bubble) return self.cancelEvent(e);
  577. };
  578. }
  579. };
  580. // Thanks to http://www.switchonthecode.com !!
  581. this.cancelEvent = function(e) {
  582. if (self.cantouch) {
  583. e = e ? e.original : false;
  584. } else {
  585. e = e ? e : window.event||false;
  586. }
  587. if (!e) return false;
  588. if(e.stopPropagation) e.stopPropagation();
  589. if(e.preventDefault) e.preventDefault();
  590. e.cancelBubble = true;
  591. e.cancel = true;
  592. e.returnValue = false;
  593. return false;
  594. };
  595. this.onmousewheel = function(e) {
  596. e = e ? e : window.event;
  597. if (self.rail.drag) return self.cancelEvent(e);
  598. var delta = 0;
  599. var delta = e.detail ? e.detail * -1 : e.wheelDelta / 40;
  600. if (delta) {
  601. self.doScrollBy(delta*self.opt.mousescrollstep,true);
  602. }
  603. return self.cancelEvent(e);
  604. };
  605. this.stop = function() {
  606. if (self.timer) clearInterval(self.timer);
  607. self.timer = 0;
  608. self.cursorfreezed = false;
  609. self.scroll.y = Math.round(self.getScrollTop() * (1/self.scrollratio.y));
  610. self.noticeCursor();
  611. };
  612. if (self.ishwscroll&&self.hastransition&&self.opt.usetransition) {
  613. this.prepareTransition = function(dif,trend) {
  614. var sp = Math.round(self.opt.scrollspeed*10);
  615. var ex = Math.min(sp,Math.round((dif / 20) * self.opt.scrollspeed));
  616. var trans = (ex>20) ? self.prefixstyle+'transform '+ex+'ms ease-out 0s' : '';
  617. if (!self.lasttransitionstyle||self.lasttransitionstyle!=trans) {
  618. self.lasttransitionstyle = trans;
  619. self.doc.css(self.transitionstyle,trans);
  620. }
  621. };
  622. this.doScroll = function(y) {
  623. self.newscrolly = y;
  624. if (self.timer) return;
  625. self.timer = setTimeout(function() {
  626. var top = self.getScrollTop();
  627. var dif = (top>self.newscrolly) ? top-self.newscrolly : self.newscrolly-top;
  628. self.prepareTransition(dif)
  629. self.setScrollTop(self.newscrolly);
  630. self.timer = 0;
  631. },self.opt.scrollspeed);
  632. self.noticeCursor();
  633. };
  634. // self.bind(self.doc,'transitionend',function(e){console.log(e)},false); TEST!!
  635. } else {
  636. this.doScroll = function(y) {
  637. self.newscrolly = y;
  638. if (self.timer) return;
  639. self.timer = setInterval(function() {
  640. var gp = self.newscrolly - self.getScrollTop();
  641. var df = (gp>0) ? Math.ceil(gp/4) : Math.floor(gp/4);
  642. var sc = self.getScrollTop()+df;
  643. self.setScrollTop(sc);
  644. if (sc == self.newscrolly) {
  645. clearInterval(self.timer);
  646. self.timer = 0;
  647. self.cursorfreezed = false;
  648. }
  649. },self.opt.scrollspeed);
  650. self.noticeCursor();
  651. };
  652. }
  653. this.doScrollBy = function(stp,absolute) {
  654. if (absolute) stp = Math.round(stp * 1/self.scrollratio.y);
  655. var ny = self.scroll.y-stp;
  656. if (ny<0) ny=0;
  657. var my = self.scrollvaluemax;
  658. if (ny>my) ny=my;
  659. self.cursorfreezed = false;
  660. self.doScroll(Math.floor(ny*self.scrollratio.y));
  661. };
  662. /*
  663. this.doScrollBy = function(stp,absolute) {
  664. var ny = (absolute)?self.scroll.y-Math.round(stp * 1/self.scrollratio.y):self.scroll.y-stp;
  665. if (ny<0) stp=0;
  666. var my = self.scrollvaluemax;
  667. if (ny>my) stp=(absolute)?Math.round(my*self.scrollratio.y):my;
  668. self.cursorfreezed = false;
  669. console.log((absolute)?stp:Math.round(stp*self.scrollratio.y));
  670. self.doScroll((absolute)?stp:Math.round(stp*self.scrollratio.y));
  671. };
  672. */
  673. this.doScrollTo = function(pos,absolute) {
  674. ny=(absolute)?Math.round(pos * 1/self.scrollratio.y):pos;
  675. if (ny<0) pos=0;
  676. var my = self.scrollvaluemax;
  677. if (ny>my) pos=(absolute)?Math.round(my*self.scrollratio.y):my;
  678. self.cursorfreezed = false;
  679. self.doScroll((absolute)?pos:Math.round(pos*self.scrollratio.y));
  680. };
  681. this.doScrollMomentum = function(mom) {
  682. var dy = mom.ly-mom.ny;
  683. var tt = ((new Date()).getTime()-mom.lt);
  684. if ((Math.abs(dy)>1)&&(tt<601)) {
  685. var my = dy;
  686. // if (dy<0) my=-my;
  687. // console.log(my+' '+tt);
  688. self.doScrollBy(my,true);
  689. }
  690. };
  691. self.onscroll = function(e) {
  692. var tm = (new Date()).getTime();
  693. if (!self.lastcontentcheck || self.lastcontentcheck<tm) {
  694. self.lastcontentcheck=tm+500;
  695. var pg = self.getContentSize();
  696. if (pg.h!=self.page.h) self.onResize();
  697. }
  698. if (self.rail.drag) return;
  699. if (!self.cursorfreezed) self.scroll.y = Math.round(self.getScrollTop() * (1/self.scrollratio.y));
  700. self.noticeCursor();
  701. };
  702. self.docscroll.scroll(function(e) {
  703. self.onscroll(e);
  704. });
  705. this.doZoomIn = function(e) {
  706. if (self.zoomactive) return;
  707. self.zoomrestore = {
  708. style:{}
  709. };
  710. var lst = ['position','top','left','zIndex','backgroundColor','marginTop','marginBottom','marginLeft','marginRight'];
  711. var win = self.win[0].style;
  712. for(var a in lst) {
  713. var pp = lst[a];
  714. self.zoomrestore.style[pp] = (typeof win[pp]!='undefined') ? win[pp] : '';
  715. }
  716. self.zoomrestore.style.width = self.win.css('width');
  717. self.zoomrestore.style.height = self.win.css('height');
  718. self.zoomrestore.padding = {
  719. w:self.win.outerWidth()-self.win.width(),
  720. h:self.win.outerHeight()-self.win.height()
  721. };
  722. if (self.isios4) {
  723. self.zoomrestore.scrollTop = $(window).scrollTop();
  724. $(window).scrollTop(0);
  725. }
  726. self.win.css({
  727. "position":(self.isios4)?"absolute":"fixed",
  728. "top":0,
  729. "left":0,
  730. "z-index":self.opt.zindex+100,
  731. "margin":"0px"
  732. });
  733. var bkg = self.win.css("backgroundColor");
  734. if (bkg==""||/transparent|rgba\(0, 0, 0, 0\)|rgba\(0,0,0,0\)/.test(bkg)) self.win.css("backgroundColor","#fff");
  735. self.rail.css({"z-index":self.opt.zindex+110});
  736. self.zoom.css({"z-index":self.opt.zindex+112});
  737. self.zoomactive = true;
  738. self.zoom.css('backgroundPosition','0px -18px');
  739. self.resizeZoom();
  740. return self.cancelEvent(e);
  741. };
  742. this.doZoomOut = function(e) {
  743. if (!self.zoomactive) return;
  744. self.win.css("margin","");
  745. self.win.css(self.zoomrestore.style);
  746. if (self.isios4) {
  747. $(window).scrollTop(self.zoomrestore.scrollTop);
  748. }
  749. self.rail.css({"z-index":(self.ispage)?self.opt.zindex:self.opt.zindex+2});
  750. self.zoom.css({"z-index":self.opt.zindex});
  751. self.zoomactive = false;
  752. self.zoomrestore = false;
  753. self.zoom.css('backgroundPosition','0px 0px');
  754. self.win.resize();
  755. return self.cancelEvent(e);
  756. };
  757. this.doZoom = function(e) {
  758. return (self.zoomactive) ? self.doZoomOut(e) : self.doZoomIn(e);
  759. };
  760. this.resizeZoom = function() {
  761. if (!self.zoomactive) return;
  762. var py = self.getScrollTop(); //preserve scrolling position
  763. self.win.css({
  764. width:$(window).width()-self.zoomrestore.padding.w+"px",
  765. height:$(window).height()-self.zoomrestore.padding.h+"px"
  766. });
  767. self.setScrollTop(py);
  768. self.win.resize();
  769. };
  770. this.init();
  771. };
  772. $.fn.niceScroll = function(wrapper,opt) {
  773. if ((typeof wrapper=="object") && (typeof opt=="undefined")) {
  774. opt = wrapper;
  775. wrapper = false;
  776. }
  777. var ret = [];
  778. if (typeof opt=="undefined") opt = {};
  779. if (wrapper||false) {
  780. opt.doc = $(wrapper);
  781. opt.win = $(this);
  782. }
  783. var docundef = !("doc" in opt);
  784. this.each(function() {
  785. var nice = $(this).data('__nicescroll')||false;
  786. if (!nice) {
  787. opt.doc = (docundef) ? $(this) : opt.doc;
  788. nice = new NiceScrollClass(opt);
  789. $(this).data('__nicescroll',nice);
  790. }
  791. ret.push(nice);
  792. });
  793. return (ret.length==1) ? ret[0] : ret;
  794. };
  795. // override jQuery scrollTop
  796. var _scrollTop = jQuery.fn.scrollTop; // preserve original function
  797. $.cssHooks.scrollTop = {
  798. get: function(elem,computed,extra) {
  799. var nice = $.data(elem,'__nicescroll')||false;
  800. return (nice&&nice.ishwscroll) ? nice.getScrollTop() : _scrollTop.call(elem);
  801. },
  802. set: function(elem,value) {
  803. var nice = $.data(elem,'__nicescroll')||false;
  804. (nice&&nice.ishwscroll) ? nice.setScrollTop(parseInt(value)) : _scrollTop.call(elem,value);
  805. return this;
  806. }
  807. };
  808. jQuery.fn.scrollTop = function(value) {
  809. if (typeof value == "undefined") {
  810. var nice = $.data(this,'__nicescroll')||false;
  811. return (nice&&nice.ishwscroll) ? nice.getScrollTop() : _scrollTop.call(this);
  812. } else {
  813. return this.each(function() {
  814. var nice = $.data(this,'__nicescroll')||false;
  815. (nice&&nice.ishwscroll) ? nice.setScrollTop(parseInt(value)) : _scrollTop.call($(this),value);
  816. });
  817. }
  818. }
  819. jQuery.fn.getNiceScroll = function(index) {
  820. if (typeof index == "undefined") {
  821. for(a=0;a<this.length;a++) {
  822. var nice = $.data(this[a],'__nicescroll')||false;
  823. if (nice) return nice;
  824. };
  825. return false;
  826. } else {
  827. var nice = $.data(this[index],'__nicescroll')||false;
  828. return nice;
  829. }
  830. }
  831. })( jQuery );