A Twitch.tv viewer reward and games system.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

873 lines
39 KiB

11 years ago
  1. /*
  2. == malihu jquery custom scrollbars plugin ==
  3. version: 2.3.2
  4. author: malihu (http://manos.malihu.gr)
  5. plugin home: http://manos.malihu.gr/jquery-custom-content-scroller
  6. */
  7. (function($){
  8. var methods={
  9. init:function(options){
  10. var defaults={
  11. set_width:false, /*optional element width: boolean, pixels, percentage*/
  12. set_height:false, /*optional element height: boolean, pixels, percentage*/
  13. horizontalScroll:false, /*scroll horizontally: boolean*/
  14. scrollInertia:550, /*scrolling inertia: integer (milliseconds)*/
  15. scrollEasing:"easeOutCirc", /*scrolling easing: string*/
  16. mouseWheel:"pixels", /*mousewheel support and velocity: boolean, "auto", integer, "pixels"*/
  17. mouseWheelPixels:60, /*mousewheel pixels amount: integer*/
  18. autoDraggerLength:true, /*auto-adjust scrollbar dragger length: boolean*/
  19. scrollButtons:{ /*scroll buttons*/
  20. enable:false, /*scroll buttons support: boolean*/
  21. scrollType:"continuous", /*scroll buttons scrolling type: "continuous", "pixels"*/
  22. scrollSpeed:20, /*scroll buttons continuous scrolling speed: integer*/
  23. scrollAmount:40 /*scroll buttons pixels scroll amount: integer (pixels)*/
  24. },
  25. advanced:{
  26. updateOnBrowserResize:true, /*update scrollbars on browser resize (for layouts based on percentages): boolean*/
  27. updateOnContentResize:false, /*auto-update scrollbars on content resize (for dynamic content): boolean*/
  28. autoExpandHorizontalScroll:false, /*auto-expand width for horizontal scrolling: boolean*/
  29. autoScrollOnFocus:true /*auto-scroll on focused elements: boolean*/
  30. },
  31. callbacks:{
  32. onScrollStart:function(){}, /*user custom callback function on scroll start event*/
  33. onScroll:function(){}, /*user custom callback function on scroll event*/
  34. onTotalScroll:function(){}, /*user custom callback function on scroll end reached event*/
  35. onTotalScrollBack:function(){}, /*user custom callback function on scroll begin reached event*/
  36. onTotalScrollOffset:0, /*scroll end reached offset: integer (pixels)*/
  37. whileScrolling:false, /*user custom callback function on scrolling event*/
  38. whileScrollingInterval:30 /*interval for calling whileScrolling callback: integer (milliseconds)*/
  39. }
  40. },
  41. options=$.extend(true,defaults,options);
  42. /*check for touch device*/
  43. $(document).data("mCS-is-touch-device",false);
  44. if(is_touch_device()){
  45. $(document).data("mCS-is-touch-device",true);
  46. }
  47. function is_touch_device(){
  48. return !!("ontouchstart" in window) ? 1 : 0;
  49. }
  50. return this.each(function(){
  51. var $this=$(this);
  52. /*set element width/height, create markup for custom scrollbars, add classes*/
  53. if(options.set_width){
  54. $this.css("width",options.set_width);
  55. }
  56. if(options.set_height){
  57. $this.css("height",options.set_height);
  58. }
  59. if(!$(document).data("mCustomScrollbar-index")){
  60. $(document).data("mCustomScrollbar-index","1");
  61. }else{
  62. var mCustomScrollbarIndex=parseInt($(document).data("mCustomScrollbar-index"));
  63. $(document).data("mCustomScrollbar-index",mCustomScrollbarIndex+1);
  64. }
  65. $this.wrapInner("<div class='mCustomScrollBox' id='mCSB_"+$(document).data("mCustomScrollbar-index")+"' style='position:relative; height:100%; overflow:hidden; max-width:100%;' />").addClass("mCustomScrollbar _mCS_"+$(document).data("mCustomScrollbar-index"));
  66. var mCustomScrollBox=$this.children(".mCustomScrollBox");
  67. if(options.horizontalScroll){
  68. mCustomScrollBox.addClass("mCSB_horizontal").wrapInner("<div class='mCSB_h_wrapper' style='position:relative; left:0; width:999999px;' />");
  69. var mCSB_h_wrapper=mCustomScrollBox.children(".mCSB_h_wrapper");
  70. mCSB_h_wrapper.wrapInner("<div class='mCSB_container' style='position:absolute; left:0;' />").children(".mCSB_container").css({"width":mCSB_h_wrapper.children().outerWidth(),"position":"relative"}).unwrap();
  71. }else{
  72. mCustomScrollBox.wrapInner("<div class='mCSB_container' style='position:relative; top:0;' />");
  73. }
  74. var mCSB_container=mCustomScrollBox.children(".mCSB_container");
  75. if($(document).data("mCS-is-touch-device")){
  76. mCSB_container.addClass("mCS_touch");
  77. }
  78. mCSB_container.after("<div class='mCSB_scrollTools' style='position:absolute;'><div class='mCSB_draggerContainer' style='position:relative;'><div class='mCSB_dragger' style='position:absolute;'><div class='mCSB_dragger_bar' style='position:relative;'></div></div><div class='mCSB_draggerRail'></div></div></div>");
  79. var mCSB_scrollTools=mCustomScrollBox.children(".mCSB_scrollTools"),
  80. mCSB_draggerContainer=mCSB_scrollTools.children(".mCSB_draggerContainer"),
  81. mCSB_dragger=mCSB_draggerContainer.children(".mCSB_dragger");
  82. if(options.horizontalScroll){
  83. mCSB_dragger.data("minDraggerWidth",mCSB_dragger.width());
  84. }else{
  85. mCSB_dragger.data("minDraggerHeight",mCSB_dragger.height());
  86. }
  87. if(options.scrollButtons.enable){
  88. if(options.horizontalScroll){
  89. mCSB_scrollTools.prepend("<a class='mCSB_buttonLeft' style='display:block; position:relative;'></a>").append("<a class='mCSB_buttonRight' style='display:block; position:relative;'></a>");
  90. }else{
  91. mCSB_scrollTools.prepend("<a class='mCSB_buttonUp' style='display:block; position:relative;'></a>").append("<a class='mCSB_buttonDown' style='display:block; position:relative;'></a>");
  92. }
  93. }
  94. /*mCustomScrollBox scrollTop and scrollLeft is always 0 to prevent browser focus scrolling*/
  95. mCustomScrollBox.bind("scroll",function(){
  96. if(!$this.is(".mCS_disabled")){ /*native focus scrolling for disabled scrollbars*/
  97. mCustomScrollBox.scrollTop(0).scrollLeft(0);
  98. }
  99. });
  100. /*store options, global vars/states, intervals and update element*/
  101. $this.data({
  102. /*init state*/
  103. "mCS_Init":true,
  104. /*option parameters*/
  105. "horizontalScroll":options.horizontalScroll,
  106. "scrollInertia":options.scrollInertia,
  107. "scrollEasing":options.scrollEasing,
  108. "mouseWheel":options.mouseWheel,
  109. "mouseWheelPixels":options.mouseWheelPixels,
  110. "autoDraggerLength":options.autoDraggerLength,
  111. "scrollButtons_enable":options.scrollButtons.enable,
  112. "scrollButtons_scrollType":options.scrollButtons.scrollType,
  113. "scrollButtons_scrollSpeed":options.scrollButtons.scrollSpeed,
  114. "scrollButtons_scrollAmount":options.scrollButtons.scrollAmount,
  115. "autoExpandHorizontalScroll":options.advanced.autoExpandHorizontalScroll,
  116. "autoScrollOnFocus":options.advanced.autoScrollOnFocus,
  117. "onScrollStart_Callback":options.callbacks.onScrollStart,
  118. "onScroll_Callback":options.callbacks.onScroll,
  119. "onTotalScroll_Callback":options.callbacks.onTotalScroll,
  120. "onTotalScrollBack_Callback":options.callbacks.onTotalScrollBack,
  121. "onTotalScroll_Offset":options.callbacks.onTotalScrollOffset,
  122. "whileScrolling_Callback":options.callbacks.whileScrolling,
  123. "whileScrolling_Interval":options.callbacks.whileScrollingInterval,
  124. /*events binding state*/
  125. "bindEvent_scrollbar_click":false,
  126. "bindEvent_mousewheel":false,
  127. "bindEvent_focusin":false,
  128. "bindEvent_buttonsContinuous_y":false,
  129. "bindEvent_buttonsContinuous_x":false,
  130. "bindEvent_buttonsPixels_y":false,
  131. "bindEvent_buttonsPixels_x":false,
  132. "bindEvent_scrollbar_touch":false,
  133. "bindEvent_content_touch":false,
  134. /*buttons intervals*/
  135. "mCSB_buttonScrollRight":false,
  136. "mCSB_buttonScrollLeft":false,
  137. "mCSB_buttonScrollDown":false,
  138. "mCSB_buttonScrollUp":false,
  139. /*callback intervals*/
  140. "whileScrolling":false
  141. }).mCustomScrollbar("update");
  142. /*detect max-width*/
  143. if(options.horizontalScroll){
  144. if($this.css("max-width")!=="none"){
  145. if(!options.advanced.updateOnContentResize){ /*needs updateOnContentResize*/
  146. options.advanced.updateOnContentResize=true;
  147. }
  148. $this.data({"mCS_maxWidth":parseInt($this.css("max-width")),"mCS_maxWidth_Interval":setInterval(function(){
  149. if(mCSB_container.outerWidth()>$this.data("mCS_maxWidth")){
  150. clearInterval($this.data("mCS_maxWidth_Interval"));
  151. $this.mCustomScrollbar("update");
  152. }
  153. },150)});
  154. }
  155. }else{
  156. /*detect max-height*/
  157. if($this.css("max-height")!=="none"){
  158. $this.data({"mCS_maxHeight":parseInt($this.css("max-height")),"mCS_maxHeight_Interval":setInterval(function(){
  159. mCustomScrollBox.css("max-height",$this.data("mCS_maxHeight"));
  160. if(mCSB_container.outerHeight()>$this.data("mCS_maxHeight")){
  161. clearInterval($this.data("mCS_maxHeight_Interval"));
  162. $this.mCustomScrollbar("update");
  163. }
  164. },150)});
  165. }
  166. }
  167. /*window resize fn (for layouts based on percentages)*/
  168. if(options.advanced.updateOnBrowserResize){
  169. var mCSB_resizeTimeout;
  170. $(window).resize(function(){
  171. if(mCSB_resizeTimeout){
  172. clearTimeout(mCSB_resizeTimeout);
  173. }
  174. mCSB_resizeTimeout=setTimeout(function(){
  175. if(!$this.is(".mCS_disabled") && !$this.is(".mCS_destroyed")){
  176. $this.mCustomScrollbar("update");
  177. }
  178. },150);
  179. });
  180. }
  181. /*content resize fn (for dynamically generated content)*/
  182. if(options.advanced.updateOnContentResize){
  183. var mCSB_onContentResize;
  184. if(options.horizontalScroll){
  185. var mCSB_containerOldSize=mCSB_container.outerWidth();
  186. }else{
  187. var mCSB_containerOldSize=mCSB_container.outerHeight();
  188. }
  189. mCSB_onContentResize=setInterval(function(){
  190. if(options.horizontalScroll){
  191. if(options.advanced.autoExpandHorizontalScroll){
  192. mCSB_container.css({"position":"absolute","width":"auto"}).wrap("<div class='mCSB_h_wrapper' style='position:relative; left:0; width:999999px;' />").css({"width":mCSB_container.outerWidth(),"position":"relative"}).unwrap();
  193. }
  194. var mCSB_containerNewSize=mCSB_container.outerWidth();
  195. }else{
  196. var mCSB_containerNewSize=mCSB_container.outerHeight();
  197. }
  198. if(mCSB_containerNewSize!=mCSB_containerOldSize){
  199. $this.mCustomScrollbar("update");
  200. mCSB_containerOldSize=mCSB_containerNewSize;
  201. }
  202. },300);
  203. }
  204. });
  205. },
  206. update:function(){
  207. var $this=$(this),
  208. mCustomScrollBox=$this.children(".mCustomScrollBox"),
  209. mCSB_container=mCustomScrollBox.children(".mCSB_container");
  210. mCSB_container.removeClass("mCS_no_scrollbar");
  211. $this.removeClass("mCS_disabled mCS_destroyed");
  212. mCustomScrollBox.scrollTop(0).scrollLeft(0); /*reset scrollTop/scrollLeft to prevent browser focus scrolling*/
  213. var mCSB_scrollTools=mCustomScrollBox.children(".mCSB_scrollTools"),
  214. mCSB_draggerContainer=mCSB_scrollTools.children(".mCSB_draggerContainer"),
  215. mCSB_dragger=mCSB_draggerContainer.children(".mCSB_dragger");
  216. if($this.data("horizontalScroll")){
  217. var mCSB_buttonLeft=mCSB_scrollTools.children(".mCSB_buttonLeft"),
  218. mCSB_buttonRight=mCSB_scrollTools.children(".mCSB_buttonRight"),
  219. mCustomScrollBoxW=mCustomScrollBox.width();
  220. if($this.data("autoExpandHorizontalScroll")){
  221. mCSB_container.css({"position":"absolute","width":"auto"}).wrap("<div class='mCSB_h_wrapper' style='position:relative; left:0; width:999999px;' />").css({"width":mCSB_container.outerWidth(),"position":"relative"}).unwrap();
  222. }
  223. var mCSB_containerW=mCSB_container.outerWidth();
  224. }else{
  225. var mCSB_buttonUp=mCSB_scrollTools.children(".mCSB_buttonUp"),
  226. mCSB_buttonDown=mCSB_scrollTools.children(".mCSB_buttonDown"),
  227. mCustomScrollBoxH=mCustomScrollBox.height(),
  228. mCSB_containerH=mCSB_container.outerHeight();
  229. }
  230. if(mCSB_containerH>mCustomScrollBoxH && !$this.data("horizontalScroll")){ /*content needs vertical scrolling*/
  231. mCSB_scrollTools.css("display","block");
  232. var mCSB_draggerContainerH=mCSB_draggerContainer.height();
  233. /*auto adjust scrollbar dragger length analogous to content*/
  234. if($this.data("autoDraggerLength")){
  235. var draggerH=Math.round(mCustomScrollBoxH/mCSB_containerH*mCSB_draggerContainerH),
  236. minDraggerH=mCSB_dragger.data("minDraggerHeight");
  237. if(draggerH<=minDraggerH){ /*min dragger height*/
  238. mCSB_dragger.css({"height":minDraggerH});
  239. }else if(draggerH>=mCSB_draggerContainerH-10){ /*max dragger height*/
  240. var mCSB_draggerContainerMaxH=mCSB_draggerContainerH-10;
  241. mCSB_dragger.css({"height":mCSB_draggerContainerMaxH});
  242. }else{
  243. mCSB_dragger.css({"height":draggerH});
  244. }
  245. mCSB_dragger.children(".mCSB_dragger_bar").css({"line-height":mCSB_dragger.height()+"px"});
  246. }
  247. var mCSB_draggerH=mCSB_dragger.height(),
  248. /*calculate and store scroll amount, add scrolling*/
  249. scrollAmount=(mCSB_containerH-mCustomScrollBoxH)/(mCSB_draggerContainerH-mCSB_draggerH);
  250. $this.data("scrollAmount",scrollAmount).mCustomScrollbar("scrolling",mCustomScrollBox,mCSB_container,mCSB_draggerContainer,mCSB_dragger,mCSB_buttonUp,mCSB_buttonDown,mCSB_buttonLeft,mCSB_buttonRight);
  251. /*scroll*/
  252. var mCSB_containerP=Math.abs(Math.round(mCSB_container.position().top));
  253. $this.mCustomScrollbar("scrollTo",mCSB_containerP,{callback:false});
  254. }else if(mCSB_containerW>mCustomScrollBoxW && $this.data("horizontalScroll")){ /*content needs horizontal scrolling*/
  255. mCSB_scrollTools.css("display","block");
  256. var mCSB_draggerContainerW=mCSB_draggerContainer.width();
  257. /*auto adjust scrollbar dragger length analogous to content*/
  258. if($this.data("autoDraggerLength")){
  259. var draggerW=Math.round(mCustomScrollBoxW/mCSB_containerW*mCSB_draggerContainerW),
  260. minDraggerW=mCSB_dragger.data("minDraggerWidth");
  261. if(draggerW<=minDraggerW){ /*min dragger height*/
  262. mCSB_dragger.css({"width":minDraggerW});
  263. }else if(draggerW>=mCSB_draggerContainerW-10){ /*max dragger height*/
  264. var mCSB_draggerContainerMaxW=mCSB_draggerContainerW-10;
  265. mCSB_dragger.css({"width":mCSB_draggerContainerMaxW});
  266. }else{
  267. mCSB_dragger.css({"width":draggerW});
  268. }
  269. }
  270. var mCSB_draggerW=mCSB_dragger.width(),
  271. /*calculate and store scroll amount, add scrolling*/
  272. scrollAmount=(mCSB_containerW-mCustomScrollBoxW)/(mCSB_draggerContainerW-mCSB_draggerW);
  273. $this.data("scrollAmount",scrollAmount).mCustomScrollbar("scrolling",mCustomScrollBox,mCSB_container,mCSB_draggerContainer,mCSB_dragger,mCSB_buttonUp,mCSB_buttonDown,mCSB_buttonLeft,mCSB_buttonRight);
  274. /*scroll*/
  275. var mCSB_containerP=Math.abs(Math.round(mCSB_container.position().left));
  276. $this.mCustomScrollbar("scrollTo",mCSB_containerP,{callback:false});
  277. }else{ /*content does not need scrolling*/
  278. /*unbind events, reset content position, hide scrollbars, remove classes*/
  279. mCustomScrollBox.unbind("mousewheel focusin");
  280. if($this.data("horizontalScroll")){
  281. mCSB_dragger.add(mCSB_container).css("left",0);
  282. }else{
  283. mCSB_dragger.add(mCSB_container).css("top",0);
  284. }
  285. mCSB_scrollTools.css("display","none");
  286. mCSB_container.addClass("mCS_no_scrollbar");
  287. $this.data({"bindEvent_mousewheel":false,"bindEvent_focusin":false});
  288. }
  289. },
  290. scrolling:function(mCustomScrollBox,mCSB_container,mCSB_draggerContainer,mCSB_dragger,mCSB_buttonUp,mCSB_buttonDown,mCSB_buttonLeft,mCSB_buttonRight){
  291. var $this=$(this);
  292. /*while scrolling callback*/
  293. $this.mCustomScrollbar("callbacks","whileScrolling");
  294. /*drag scrolling*/
  295. if(!mCSB_dragger.hasClass("ui-draggable")){ /*apply drag function once*/
  296. if($this.data("horizontalScroll")){
  297. var draggableAxis="x";
  298. }else{
  299. var draggableAxis="y";
  300. }
  301. mCSB_dragger.draggable({
  302. axis:draggableAxis,
  303. containment:"parent",
  304. drag:function(event,ui){
  305. $this.mCustomScrollbar("scroll");
  306. mCSB_dragger.addClass("mCSB_dragger_onDrag");
  307. },
  308. stop:function(event,ui){
  309. mCSB_dragger.removeClass("mCSB_dragger_onDrag");
  310. }
  311. });
  312. }
  313. if(!$this.data("bindEvent_scrollbar_click")){ /*bind once*/
  314. mCSB_draggerContainer.bind("click",function(e){
  315. if($this.data("horizontalScroll")){
  316. var mouseCoord=(e.pageX-mCSB_draggerContainer.offset().left);
  317. if(mouseCoord<mCSB_dragger.position().left || mouseCoord>(mCSB_dragger.position().left+mCSB_dragger.width())){
  318. var scrollToPos=mouseCoord;
  319. if(scrollToPos>=mCSB_draggerContainer.width()-mCSB_dragger.width()){ /*max dragger position is bottom*/
  320. scrollToPos=mCSB_draggerContainer.width()-mCSB_dragger.width();
  321. }
  322. mCSB_dragger.css("left",scrollToPos);
  323. $this.mCustomScrollbar("scroll");
  324. }
  325. }else{
  326. var mouseCoord=(e.pageY-mCSB_draggerContainer.offset().top);
  327. if(mouseCoord<mCSB_dragger.position().top || mouseCoord>(mCSB_dragger.position().top+mCSB_dragger.height())){
  328. var scrollToPos=mouseCoord;
  329. if(scrollToPos>=mCSB_draggerContainer.height()-mCSB_dragger.height()){ /*max dragger position is bottom*/
  330. scrollToPos=mCSB_draggerContainer.height()-mCSB_dragger.height();
  331. }
  332. mCSB_dragger.css("top",scrollToPos);
  333. $this.mCustomScrollbar("scroll");
  334. }
  335. }
  336. });
  337. $this.data({"bindEvent_scrollbar_click":true});
  338. }
  339. /*mousewheel scrolling*/
  340. if($this.data("mouseWheel")){
  341. var mousewheelVel=$this.data("mouseWheel");
  342. if($this.data("mouseWheel")==="auto"){
  343. mousewheelVel=8; /*default mousewheel velocity*/
  344. /*check for safari browser on mac osx to lower mousewheel velocity*/
  345. var os=navigator.userAgent;
  346. if(os.indexOf("Mac")!=-1 && os.indexOf("Safari")!=-1 && os.indexOf("AppleWebKit")!=-1 && os.indexOf("Chrome")==-1){
  347. mousewheelVel=1;
  348. }
  349. }
  350. if(!$this.data("bindEvent_mousewheel")){ /*bind once*/
  351. mCustomScrollBox.bind("mousewheel",function(event,delta){
  352. event.preventDefault();
  353. var vel=Math.abs(delta*mousewheelVel);
  354. if($this.data("horizontalScroll")){
  355. if($this.data("mouseWheel")==="pixels"){
  356. if(delta<0){
  357. delta=-1;
  358. }else{
  359. delta=1;
  360. }
  361. var scrollTo=Math.abs(Math.round(mCSB_container.position().left))-(delta*$this.data("mouseWheelPixels"));
  362. $this.mCustomScrollbar("scrollTo",scrollTo);
  363. }else{
  364. var posX=mCSB_dragger.position().left-(delta*vel);
  365. mCSB_dragger.css("left",posX);
  366. if(mCSB_dragger.position().left<0){
  367. mCSB_dragger.css("left",0);
  368. }
  369. var mCSB_draggerContainerW=mCSB_draggerContainer.width(),
  370. mCSB_draggerW=mCSB_dragger.width();
  371. if(mCSB_dragger.position().left>mCSB_draggerContainerW-mCSB_draggerW){
  372. mCSB_dragger.css("left",mCSB_draggerContainerW-mCSB_draggerW);
  373. }
  374. $this.mCustomScrollbar("scroll");
  375. }
  376. }else{
  377. if($this.data("mouseWheel")==="pixels"){
  378. if(delta<0){
  379. delta=-1;
  380. }else{
  381. delta=1;
  382. }
  383. var scrollTo=Math.abs(Math.round(mCSB_container.position().top))-(delta*$this.data("mouseWheelPixels"));
  384. $this.mCustomScrollbar("scrollTo",scrollTo);
  385. }else{
  386. var posY=mCSB_dragger.position().top-(delta*vel);
  387. mCSB_dragger.css("top",posY);
  388. if(mCSB_dragger.position().top<0){
  389. mCSB_dragger.css("top",0);
  390. }
  391. var mCSB_draggerContainerH=mCSB_draggerContainer.height(),
  392. mCSB_draggerH=mCSB_dragger.height();
  393. if(mCSB_dragger.position().top>mCSB_draggerContainerH-mCSB_draggerH){
  394. mCSB_dragger.css("top",mCSB_draggerContainerH-mCSB_draggerH);
  395. }
  396. $this.mCustomScrollbar("scroll");
  397. }
  398. }
  399. });
  400. $this.data({"bindEvent_mousewheel":true});
  401. }
  402. }
  403. /*buttons scrolling*/
  404. if($this.data("scrollButtons_enable")){
  405. if($this.data("scrollButtons_scrollType")==="pixels"){ /*scroll by pixels*/
  406. var pixelsScrollTo;
  407. if($.browser.msie && parseInt($.browser.version)<9){ /*stupid ie8*/
  408. $this.data("scrollInertia",0);
  409. }
  410. if($this.data("horizontalScroll")){
  411. mCSB_buttonRight.add(mCSB_buttonLeft).unbind("mousedown touchstart onmsgesturestart mouseup mouseout touchend onmsgestureend",mCSB_buttonRight_stop,mCSB_buttonLeft_stop);
  412. $this.data({"bindEvent_buttonsContinuous_x":false});
  413. if(!$this.data("bindEvent_buttonsPixels_x")){ /*bind once*/
  414. /*scroll right*/
  415. mCSB_buttonRight.bind("click",function(e){
  416. e.preventDefault();
  417. if(!mCSB_container.is(":animated")){
  418. pixelsScrollTo=Math.abs(mCSB_container.position().left)+$this.data("scrollButtons_scrollAmount");
  419. $this.mCustomScrollbar("scrollTo",pixelsScrollTo);
  420. }
  421. });
  422. /*scroll left*/
  423. mCSB_buttonLeft.bind("click",function(e){
  424. e.preventDefault();
  425. if(!mCSB_container.is(":animated")){
  426. pixelsScrollTo=Math.abs(mCSB_container.position().left)-$this.data("scrollButtons_scrollAmount");
  427. if(mCSB_container.position().left>=-$this.data("scrollButtons_scrollAmount")){
  428. pixelsScrollTo="left";
  429. }
  430. $this.mCustomScrollbar("scrollTo",pixelsScrollTo);
  431. }
  432. });
  433. $this.data({"bindEvent_buttonsPixels_x":true});
  434. }
  435. }else{
  436. mCSB_buttonDown.add(mCSB_buttonUp).unbind("mousedown touchstart onmsgesturestart mouseup mouseout touchend onmsgestureend",mCSB_buttonRight_stop,mCSB_buttonLeft_stop);
  437. $this.data({"bindEvent_buttonsContinuous_y":false});
  438. if(!$this.data("bindEvent_buttonsPixels_y")){ /*bind once*/
  439. /*scroll down*/
  440. mCSB_buttonDown.bind("click",function(e){
  441. e.preventDefault();
  442. if(!mCSB_container.is(":animated")){
  443. pixelsScrollTo=Math.abs(mCSB_container.position().top)+$this.data("scrollButtons_scrollAmount");
  444. $this.mCustomScrollbar("scrollTo",pixelsScrollTo);
  445. }
  446. });
  447. /*scroll up*/
  448. mCSB_buttonUp.bind("click",function(e){
  449. e.preventDefault();
  450. if(!mCSB_container.is(":animated")){
  451. pixelsScrollTo=Math.abs(mCSB_container.position().top)-$this.data("scrollButtons_scrollAmount");
  452. if(mCSB_container.position().top>=-$this.data("scrollButtons_scrollAmount")){
  453. pixelsScrollTo="top";
  454. }
  455. $this.mCustomScrollbar("scrollTo",pixelsScrollTo);
  456. }
  457. });
  458. $this.data({"bindEvent_buttonsPixels_y":true});
  459. }
  460. }
  461. }else{ /*continuous scrolling*/
  462. if($this.data("horizontalScroll")){
  463. mCSB_buttonRight.add(mCSB_buttonLeft).unbind("click");
  464. $this.data({"bindEvent_buttonsPixels_x":false});
  465. if(!$this.data("bindEvent_buttonsContinuous_x")){ /*bind once*/
  466. /*scroll right*/
  467. mCSB_buttonRight.bind("mousedown touchstart onmsgesturestart",function(e){
  468. e.preventDefault();
  469. e.stopPropagation();
  470. $this.data({"mCSB_buttonScrollRight":setInterval(function(){
  471. var scrollTo=Math.round((Math.abs(Math.round(mCSB_container.position().left))+$this.data("scrollButtons_scrollSpeed"))/$this.data("scrollAmount"));
  472. $this.mCustomScrollbar("scrollTo",scrollTo,{moveDragger:true});
  473. },30)});
  474. });
  475. var mCSB_buttonRight_stop=function(e){
  476. e.preventDefault();
  477. e.stopPropagation();
  478. clearInterval($this.data("mCSB_buttonScrollRight"));
  479. }
  480. mCSB_buttonRight.bind("mouseup touchend onmsgestureend mouseout",mCSB_buttonRight_stop);
  481. /*scroll left*/
  482. mCSB_buttonLeft.bind("mousedown touchstart onmsgesturestart",function(e){
  483. e.preventDefault();
  484. e.stopPropagation();
  485. $this.data({"mCSB_buttonScrollLeft":setInterval(function(){
  486. var scrollTo=Math.round((Math.abs(Math.round(mCSB_container.position().left))-$this.data("scrollButtons_scrollSpeed"))/$this.data("scrollAmount"));
  487. $this.mCustomScrollbar("scrollTo",scrollTo,{moveDragger:true});
  488. },30)});
  489. });
  490. var mCSB_buttonLeft_stop=function(e){
  491. e.preventDefault();
  492. e.stopPropagation();
  493. clearInterval($this.data("mCSB_buttonScrollLeft"));
  494. }
  495. mCSB_buttonLeft.bind("mouseup touchend onmsgestureend mouseout",mCSB_buttonLeft_stop);
  496. $this.data({"bindEvent_buttonsContinuous_x":true});
  497. }
  498. }else{
  499. mCSB_buttonDown.add(mCSB_buttonUp).unbind("click");
  500. $this.data({"bindEvent_buttonsPixels_y":false});
  501. if(!$this.data("bindEvent_buttonsContinuous_y")){ /*bind once*/
  502. /*scroll down*/
  503. mCSB_buttonDown.bind("mousedown touchstart onmsgesturestart",function(e){
  504. e.preventDefault();
  505. e.stopPropagation();
  506. $this.data({"mCSB_buttonScrollDown":setInterval(function(){
  507. var scrollTo=Math.round((Math.abs(Math.round(mCSB_container.position().top))+$this.data("scrollButtons_scrollSpeed"))/$this.data("scrollAmount"));
  508. $this.mCustomScrollbar("scrollTo",scrollTo,{moveDragger:true});
  509. },30)});
  510. });
  511. var mCSB_buttonDown_stop=function(e){
  512. e.preventDefault();
  513. e.stopPropagation();
  514. clearInterval($this.data("mCSB_buttonScrollDown"));
  515. }
  516. mCSB_buttonDown.bind("mouseup touchend onmsgestureend mouseout",mCSB_buttonDown_stop);
  517. /*scroll up*/
  518. mCSB_buttonUp.bind("mousedown touchstart onmsgesturestart",function(e){
  519. e.preventDefault();
  520. e.stopPropagation();
  521. $this.data({"mCSB_buttonScrollUp":setInterval(function(){
  522. var scrollTo=Math.round((Math.abs(Math.round(mCSB_container.position().top))-$this.data("scrollButtons_scrollSpeed"))/$this.data("scrollAmount"));
  523. $this.mCustomScrollbar("scrollTo",scrollTo,{moveDragger:true});
  524. },30)});
  525. });
  526. var mCSB_buttonUp_stop=function(e){
  527. e.preventDefault();
  528. e.stopPropagation();
  529. clearInterval($this.data("mCSB_buttonScrollUp"));
  530. }
  531. mCSB_buttonUp.bind("mouseup touchend onmsgestureend mouseout",mCSB_buttonUp_stop);
  532. $this.data({"bindEvent_buttonsContinuous_y":true});
  533. }
  534. }
  535. }
  536. }
  537. /*scrolling on element focus (e.g. via TAB key)*/
  538. if($this.data("autoScrollOnFocus")){
  539. if(!$this.data("bindEvent_focusin")){ /*bind once*/
  540. mCustomScrollBox.bind("focusin",function(){
  541. mCustomScrollBox.scrollTop(0).scrollLeft(0);
  542. var focusedElem=$(document.activeElement);
  543. if(focusedElem.is("input,textarea,select,button,a[tabindex],area,object")){
  544. if($this.data("horizontalScroll")){
  545. var mCSB_containerX=mCSB_container.position().left,
  546. focusedElemX=focusedElem.position().left,
  547. mCustomScrollBoxW=mCustomScrollBox.width(),
  548. focusedElemW=focusedElem.outerWidth();
  549. if(mCSB_containerX+focusedElemX>=0 && mCSB_containerX+focusedElemX<=mCustomScrollBoxW-focusedElemW){
  550. /*just focus...*/
  551. }else{ /*scroll, then focus*/
  552. var moveDragger=focusedElemX/$this.data("scrollAmount");
  553. if(moveDragger>=mCSB_draggerContainer.width()-mCSB_dragger.width()){ /*max dragger position is bottom*/
  554. moveDragger=mCSB_draggerContainer.width()-mCSB_dragger.width();
  555. }
  556. mCSB_dragger.css("left",moveDragger);
  557. $this.mCustomScrollbar("scroll");
  558. }
  559. }else{
  560. var mCSB_containerY=mCSB_container.position().top,
  561. focusedElemY=focusedElem.position().top,
  562. mCustomScrollBoxH=mCustomScrollBox.height(),
  563. focusedElemH=focusedElem.outerHeight();
  564. if(mCSB_containerY+focusedElemY>=0 && mCSB_containerY+focusedElemY<=mCustomScrollBoxH-focusedElemH){
  565. /*just focus...*/
  566. }else{ /*scroll, then focus*/
  567. var moveDragger=focusedElemY/$this.data("scrollAmount");
  568. if(moveDragger>=mCSB_draggerContainer.height()-mCSB_dragger.height()){ /*max dragger position is bottom*/
  569. moveDragger=mCSB_draggerContainer.height()-mCSB_dragger.height();
  570. }
  571. mCSB_dragger.css("top",moveDragger);
  572. $this.mCustomScrollbar("scroll");
  573. }
  574. }
  575. }
  576. });
  577. $this.data({"bindEvent_focusin":true});
  578. }
  579. }
  580. /*touch events*/
  581. if($(document).data("mCS-is-touch-device")){
  582. /*scrollbar touch-drag*/
  583. if(!$this.data("bindEvent_scrollbar_touch")){ /*bind once*/
  584. var mCSB_draggerTouchY,
  585. mCSB_draggerTouchX;
  586. mCSB_dragger.bind("touchstart onmsgesturestart",function(e){
  587. e.preventDefault();
  588. e.stopPropagation();
  589. var touch=e.originalEvent.touches[0] || e.originalEvent.changedTouches[0],
  590. elem=$(this),
  591. elemOffset=elem.offset(),
  592. x=touch.pageX-elemOffset.left,
  593. y=touch.pageY-elemOffset.top;
  594. if(x<elem.width() && x>0 && y<elem.height() && y>0){
  595. mCSB_draggerTouchY=y;
  596. mCSB_draggerTouchX=x;
  597. }
  598. });
  599. mCSB_dragger.bind("touchmove onmsgesturechange",function(e){
  600. e.preventDefault();
  601. e.stopPropagation();
  602. var touch=e.originalEvent.touches[0] || e.originalEvent.changedTouches[0],
  603. elem=$(this),
  604. elemOffset=elem.offset(),
  605. x=touch.pageX-elemOffset.left,
  606. y=touch.pageY-elemOffset.top;
  607. if($this.data("horizontalScroll")){
  608. $this.mCustomScrollbar("scrollTo",(mCSB_dragger.position().left-(mCSB_draggerTouchX))+x,{moveDragger:true});
  609. }else{
  610. $this.mCustomScrollbar("scrollTo",(mCSB_dragger.position().top-(mCSB_draggerTouchY))+y,{moveDragger:true});
  611. }
  612. });
  613. $this.data({"bindEvent_scrollbar_touch":true});
  614. }
  615. /*content touch-drag*/
  616. if(!$this.data("bindEvent_content_touch")){ /*bind once*/
  617. var touch,
  618. elem,
  619. elemOffset,
  620. x,
  621. y,
  622. mCSB_containerTouchY,
  623. mCSB_containerTouchX;
  624. mCSB_container.bind("touchstart onmsgesturestart",function(e){
  625. touch=e.originalEvent.touches[0] || e.originalEvent.changedTouches[0];
  626. elem=$(this);
  627. elemOffset=elem.offset();
  628. x=touch.pageX-elemOffset.left;
  629. y=touch.pageY-elemOffset.top;
  630. mCSB_containerTouchY=y;
  631. mCSB_containerTouchX=x;
  632. });
  633. mCSB_container.bind("touchmove onmsgesturechange",function(e){
  634. e.preventDefault();
  635. e.stopPropagation();
  636. touch=e.originalEvent.touches[0] || e.originalEvent.changedTouches[0];
  637. elem=$(this).parent();
  638. elemOffset=elem.offset();
  639. x=touch.pageX-elemOffset.left;
  640. y=touch.pageY-elemOffset.top;
  641. if($this.data("horizontalScroll")){
  642. $this.mCustomScrollbar("scrollTo",mCSB_containerTouchX-x);
  643. }else{
  644. $this.mCustomScrollbar("scrollTo",mCSB_containerTouchY-y);
  645. }
  646. });
  647. $this.data({"bindEvent_content_touch":true});
  648. }
  649. }
  650. },
  651. scroll:function(bypassCallbacks){
  652. var $this=$(this),
  653. mCSB_dragger=$this.find(".mCSB_dragger"),
  654. mCSB_container=$this.find(".mCSB_container"),
  655. mCustomScrollBox=$this.find(".mCustomScrollBox");
  656. if($this.data("horizontalScroll")){
  657. var draggerX=mCSB_dragger.position().left,
  658. targX=-draggerX*$this.data("scrollAmount"),
  659. thisX=mCSB_container.position().left,
  660. posX=Math.round(thisX-targX);
  661. }else{
  662. var draggerY=mCSB_dragger.position().top,
  663. targY=-draggerY*$this.data("scrollAmount"),
  664. thisY=mCSB_container.position().top,
  665. posY=Math.round(thisY-targY);
  666. }
  667. if($.browser.webkit){ /*fix webkit zoom and jquery animate*/
  668. var screenCssPixelRatio=(window.outerWidth-8)/window.innerWidth,
  669. isZoomed=(screenCssPixelRatio<.98 || screenCssPixelRatio>1.02);
  670. }
  671. if($this.data("scrollInertia")===0 || isZoomed){
  672. if(!bypassCallbacks){
  673. $this.mCustomScrollbar("callbacks","onScrollStart"); /*user custom callback functions*/
  674. }
  675. if($this.data("horizontalScroll")){
  676. mCSB_container.css("left",targX);
  677. }else{
  678. mCSB_container.css("top",targY);
  679. }
  680. if(!bypassCallbacks){
  681. /*user custom callback functions*/
  682. if($this.data("whileScrolling")){
  683. $this.data("whileScrolling_Callback").call();
  684. }
  685. $this.mCustomScrollbar("callbacks","onScroll");
  686. }
  687. $this.data({"mCS_Init":false});
  688. }else{
  689. if(!bypassCallbacks){
  690. $this.mCustomScrollbar("callbacks","onScrollStart"); /*user custom callback functions*/
  691. }
  692. if($this.data("horizontalScroll")){
  693. mCSB_container.stop().animate({left:"-="+posX},$this.data("scrollInertia"),$this.data("scrollEasing"),function(){
  694. if(!bypassCallbacks){
  695. $this.mCustomScrollbar("callbacks","onScroll"); /*user custom callback functions*/
  696. }
  697. $this.data({"mCS_Init":false});
  698. });
  699. }else{
  700. mCSB_container.stop().animate({top:"-="+posY},$this.data("scrollInertia"),$this.data("scrollEasing"),function(){
  701. if(!bypassCallbacks){
  702. $this.mCustomScrollbar("callbacks","onScroll"); /*user custom callback functions*/
  703. }
  704. $this.data({"mCS_Init":false});
  705. });
  706. }
  707. }
  708. },
  709. scrollTo:function(scrollTo,options){
  710. var defaults={
  711. moveDragger:false,
  712. callback:true
  713. },
  714. options=$.extend(defaults,options),
  715. $this=$(this),
  716. scrollToPos,
  717. mCustomScrollBox=$this.find(".mCustomScrollBox"),
  718. mCSB_container=mCustomScrollBox.children(".mCSB_container"),
  719. mCSB_draggerContainer=$this.find(".mCSB_draggerContainer"),
  720. mCSB_dragger=mCSB_draggerContainer.children(".mCSB_dragger"),
  721. targetPos;
  722. if(scrollTo || scrollTo===0){
  723. if(typeof(scrollTo)==="number"){ /*if integer, scroll by number of pixels*/
  724. if(options.moveDragger){ /*scroll dragger*/
  725. scrollToPos=scrollTo;
  726. }else{ /*scroll content by default*/
  727. targetPos=scrollTo;
  728. scrollToPos=Math.round(targetPos/$this.data("scrollAmount"));
  729. }
  730. }else if(typeof(scrollTo)==="string"){ /*if string, scroll by element position*/
  731. var target;
  732. if(scrollTo==="top"){ /*scroll to top*/
  733. target=0;
  734. }else if(scrollTo==="bottom" && !$this.data("horizontalScroll")){ /*scroll to bottom*/
  735. target=mCSB_container.outerHeight()-mCustomScrollBox.height();
  736. }else if(scrollTo==="left"){ /*scroll to left*/
  737. target=0;
  738. }else if(scrollTo==="right" && $this.data("horizontalScroll")){ /*scroll to right*/
  739. target=mCSB_container.outerWidth()-mCustomScrollBox.width();
  740. }else if(scrollTo==="first"){ /*scroll to first element position*/
  741. target=$this.find(".mCSB_container").find(":first");
  742. }else if(scrollTo==="last"){ /*scroll to last element position*/
  743. target=$this.find(".mCSB_container").find(":last");
  744. }else{ /*scroll to element position*/
  745. target=$this.find(scrollTo);
  746. }
  747. if(target.length===1){ /*if such unique element exists, scroll to it*/
  748. if($this.data("horizontalScroll")){
  749. targetPos=target.position().left;
  750. }else{
  751. targetPos=target.position().top;
  752. }
  753. scrollToPos=Math.ceil(targetPos/$this.data("scrollAmount"));
  754. }else{
  755. scrollToPos=target;
  756. }
  757. }
  758. /*scroll to*/
  759. if(scrollToPos<0){
  760. scrollToPos=0;
  761. }
  762. if($this.data("horizontalScroll")){
  763. if(scrollToPos>=mCSB_draggerContainer.width()-mCSB_dragger.width()){ /*max dragger position is bottom*/
  764. scrollToPos=mCSB_draggerContainer.width()-mCSB_dragger.width();
  765. }
  766. mCSB_dragger.css("left",scrollToPos);
  767. }else{
  768. if(scrollToPos>=mCSB_draggerContainer.height()-mCSB_dragger.height()){ /*max dragger position is bottom*/
  769. scrollToPos=mCSB_draggerContainer.height()-mCSB_dragger.height();
  770. }
  771. mCSB_dragger.css("top",scrollToPos);
  772. }
  773. if(options.callback){
  774. $this.mCustomScrollbar("scroll",false);
  775. }else{
  776. $this.mCustomScrollbar("scroll",true);
  777. }
  778. }
  779. },
  780. callbacks:function(callback){
  781. var $this=$(this),
  782. mCustomScrollBox=$this.find(".mCustomScrollBox"),
  783. mCSB_container=$this.find(".mCSB_container");
  784. switch(callback){
  785. /*start scrolling callback*/
  786. case "onScrollStart":
  787. if(!mCSB_container.is(":animated")){
  788. $this.data("onScrollStart_Callback").call();
  789. }
  790. break;
  791. /*end scrolling callback*/
  792. case "onScroll":
  793. if($this.data("horizontalScroll")){
  794. var mCSB_containerX=Math.round(mCSB_container.position().left);
  795. if(mCSB_containerX<0 && mCSB_containerX<=mCustomScrollBox.width()-mCSB_container.outerWidth()+$this.data("onTotalScroll_Offset")){
  796. $this.data("onTotalScroll_Callback").call();
  797. }else if(mCSB_containerX>=-$this.data("onTotalScroll_Offset")){
  798. $this.data("onTotalScrollBack_Callback").call();
  799. }else{
  800. $this.data("onScroll_Callback").call();
  801. }
  802. }else{
  803. var mCSB_containerY=Math.round(mCSB_container.position().top);
  804. if(mCSB_containerY<0 && mCSB_containerY<=mCustomScrollBox.height()-mCSB_container.outerHeight()+$this.data("onTotalScroll_Offset")){
  805. $this.data("onTotalScroll_Callback").call();
  806. }else if(mCSB_containerY>=-$this.data("onTotalScroll_Offset")){
  807. $this.data("onTotalScrollBack_Callback").call();
  808. }else{
  809. $this.data("onScroll_Callback").call();
  810. }
  811. }
  812. break;
  813. /*while scrolling callback*/
  814. case "whileScrolling":
  815. if($this.data("whileScrolling_Callback") && !$this.data("whileScrolling")){
  816. $this.data({"whileScrolling":setInterval(function(){
  817. if(mCSB_container.is(":animated") && !$this.data("mCS_Init")){
  818. $this.data("whileScrolling_Callback").call();
  819. }
  820. },$this.data("whileScrolling_Interval"))});
  821. }
  822. break;
  823. }
  824. },
  825. disable:function(resetScroll){
  826. var $this=$(this),
  827. mCustomScrollBox=$this.children(".mCustomScrollBox"),
  828. mCSB_container=mCustomScrollBox.children(".mCSB_container"),
  829. mCSB_scrollTools=mCustomScrollBox.children(".mCSB_scrollTools"),
  830. mCSB_dragger=mCSB_scrollTools.find(".mCSB_dragger");
  831. mCustomScrollBox.unbind("mousewheel focusin");
  832. if(resetScroll){
  833. if($this.data("horizontalScroll")){
  834. mCSB_dragger.add(mCSB_container).css("left",0);
  835. }else{
  836. mCSB_dragger.add(mCSB_container).css("top",0);
  837. }
  838. }
  839. mCSB_scrollTools.css("display","none");
  840. mCSB_container.addClass("mCS_no_scrollbar");
  841. $this.data({"bindEvent_mousewheel":false,"bindEvent_focusin":false}).addClass("mCS_disabled");
  842. },
  843. destroy:function(){
  844. var $this=$(this),
  845. content=$this.find(".mCSB_container").html();
  846. $this.find(".mCustomScrollBox").remove();
  847. $this.html(content).removeClass("mCustomScrollbar _mCS_"+$(document).data("mCustomScrollbar-index")).addClass("mCS_destroyed");
  848. }
  849. }
  850. $.fn.mCustomScrollbar=function(method){
  851. if(methods[method]){
  852. return methods[method].apply(this,Array.prototype.slice.call(arguments,1));
  853. }else if(typeof method==="object" || !method){
  854. return methods.init.apply(this,arguments);
  855. }else{
  856. $.error("Method "+method+" does not exist");
  857. }
  858. };
  859. })(jQuery);
  860. /*iOS 6 bug fix
  861. iOS 6 suffers from a bug that kills timers that are created while a page is scrolling.
  862. The following fixes that problem by recreating timers after scrolling finishes (with interval correction).*/
  863. var iOSVersion=iOSVersion();
  864. if(iOSVersion>=6){
  865. (function(h){var a={};var d={};var e=h.setTimeout;var f=h.setInterval;var i=h.clearTimeout;var c=h.clearInterval;if(!h.addEventListener){return false}function j(q,n,l){var p,k=l[0],m=(q===f);function o(){if(k){k.apply(h,arguments);if(!m){delete n[p];k=null}}}l[0]=o;p=q.apply(h,l);n[p]={args:l,created:Date.now(),cb:k,id:p};return p}function b(q,o,k,r,t){var l=k[r];if(!l){return}var m=(q===f);o(l.id);if(!m){var n=l.args[1];var p=Date.now()-l.created;if(p<0){p=0}n-=p;if(n<0){n=0}l.args[1]=n}function s(){if(l.cb){l.cb.apply(h,arguments);if(!m){delete k[r];l.cb=null}}}l.args[0]=s;l.created=Date.now();l.id=q.apply(h,l.args)}h.setTimeout=function(){return j(e,a,arguments)};h.setInterval=function(){return j(f,d,arguments)};h.clearTimeout=function(l){var k=a[l];if(k){delete a[l];i(k.id)}};h.clearInterval=function(l){var k=d[l];if(k){delete d[l];c(k.id)}};var g=h;while(g.location!=g.parent.location){g=g.parent}g.addEventListener("scroll",function(){var k;for(k in a){b(e,i,a,k)}for(k in d){b(f,c,d,k)}})}(window));
  866. }
  867. function iOSVersion(){
  868. var agent=window.navigator.userAgent,
  869. start=agent.indexOf('OS ');
  870. if((agent.indexOf('iPhone')>-1 || agent.indexOf('iPad')>-1) && start>-1){
  871. return window.Number(agent.substr(start+3,3).replace('_','.'));
  872. }
  873. return 0;
  874. }