ScrollBar.js 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510
  1. o2.widget = o2.widget || {};
  2. o2.require("o2.widget.Common", null, false);
  3. o2.widget.ScrollBar = new Class({
  4. Implements : [ Options, Events],
  5. Extends: o2.widget.Common,
  6. options : {
  7. "distance" : 50,
  8. "style": "default",
  9. "isShow": false,
  10. "where": "before",
  11. "indent": true,
  12. "offset": {
  13. "V": {
  14. "x": 0,
  15. "y": 0
  16. },
  17. "H": {
  18. "x": 0,
  19. "y": 0
  20. }
  21. }
  22. },
  23. scrollEvent: function(node){
  24. var scrollTop = node.scrollTop.toFloat();
  25. var scrollLeft = node.scrollLeft.toFloat();
  26. this.fireEvent("scroll", [scrollTop, scrollLeft]);
  27. },
  28. initialize : function(node, options) {
  29. if (COMMON.Browser.Platform.isMobile){
  30. node.setStyle("overflow", "auto");
  31. node.addEvent("scroll", function(){
  32. this.scrollEvent(node);
  33. }.bind(this));
  34. // node.addEvent("touchstart", function(e){ this.checkScroll()}.bind(this));
  35. // node.addEvent("touchmove", function(e){
  36. // e.preventDefault();
  37. // // this.fireEvent("scroll", [1]);
  38. // // e.preventDefault();
  39. // //
  40. // // var scrollTop = node.scrollTop.toFloat();
  41. // // var scrollLeft = node.scrollLeft.toFloat();
  42. // // //this.fireEvent("scroll", [scrollTop, scrollLeft]);
  43. // e.stopPropagation();
  44. // }.bind(this));
  45. // node.addEvent("touchend", function(e){
  46. // this.scrollEvent(node);
  47. // }.bind(this));
  48. return true;
  49. }
  50. this.node = $(node);
  51. this.setOptions(options);
  52. this.path = o2.session.path+"/widget/$ScrollBar/";
  53. this.cssPath = o2.session.path+"/widget/$ScrollBar/"+this.options.style+"/css.wcss";
  54. this._loadCss();
  55. // document.body.onresize = function(e){
  56. // this.checkScroll();
  57. // }.bind(this);
  58. // this.node.onresize = function(e){
  59. // this.checkScroll();
  60. // }.bind(this);
  61. this.checkScrollFun = function(e){
  62. this.checkScroll();
  63. }.bind(this);
  64. this.checkScrollStopFun = function(e){
  65. this.checkScroll();
  66. e.stopPropagation();
  67. }.bind(this);
  68. if(layout.desktop && layout.desktop.addEvent)layout.desktop.addEvent("resize", this.checkScrollFun);
  69. //layout.desktop.addEvent("onresize", this.checkScrollFun);
  70. this.node.addEvent("mouseover", this.checkScrollStopFun);
  71. this.node.addEvent("mouseout", this.checkScrollStopFun);
  72. // this.node.addEvent("click", function(e){
  73. // this.checkScrollShow(e);
  74. // }.bind(this));
  75. this.checkScrollShow();
  76. this.checkScrollShowFun = function(e){
  77. this.checkScrollShow(e);
  78. }.bind(this);
  79. document.body.addEvent("mousemove", this.checkScrollShowFun);
  80. // this.node.getChildren().each(function(node){
  81. // node.onresize = function(e){
  82. // this.checkScroll();
  83. // }.bind(this);
  84. // }.bind(this));
  85. // this.node.onpropertychange = function(e){
  86. // this.checkScroll();
  87. // }.bind(this);
  88. },
  89. checkScrollShow: function(e){
  90. if (!this.node.isPointIn) return false;
  91. //if (this.node.isPointIn(e.event.clientX, e.event.clientY, this.scrollVWidth)){
  92. if (this.scrollVAreaNode){
  93. var opacity = this.scrollVAreaNode.getStyle("opacity");
  94. if (opacity==0){
  95. if (!this.scrollAreaOverLock && !this.scrollAreaOutLock){
  96. this.scrollAreaOverLock = true;
  97. var margin = this.node.getStyle("margin-right").toFloat();
  98. if (this.options.indent){
  99. var marginFx = new Fx.Tween(this.node, {property: "margin-right", duration: "100"});
  100. marginFx.start(margin+this.scrollVWidth).chain(function(){
  101. this.scrollVAreaNode.setStyle("display", "block");
  102. var scrollFx = new Fx.Tween(this.scrollVAreaNode, {property: "opacity", duration: "100"});
  103. scrollFx.start(0,1).chain(function(){
  104. this.scrollAreaOverLock = false;
  105. }.bind(this));
  106. //this.scrollVAreaNode.fade("in");
  107. }.bind(this));
  108. }else{
  109. this.scrollVAreaNode.setStyle("display", "block");
  110. var scrollFx = new Fx.Tween(this.scrollVAreaNode, {property: "opacity", duration: "100"});
  111. scrollFx.start(0,1).chain(function(){
  112. this.scrollAreaOverLock = false;
  113. }.bind(this));
  114. }
  115. }
  116. }
  117. }
  118. // }else{
  119. // if (this.scrollVAreaNode){
  120. // var opacity = this.scrollVAreaNode.getStyle("opacity");
  121. // // if (!this.options.isShow){
  122. // if (opacity==1){
  123. // if (!this.scrollAreaOutLock && !this.scrollAreaOverLock){
  124. // if (!this.showScrollBar){
  125. // this.scrollAreaOutLock = true;
  126. // var scrollFx = new Fx.Tween(this.scrollVAreaNode, {property: "opacity", duration: "100"});
  127. // scrollFx.start(0).chain(function(){
  128. // var margin = this.node.getStyle("margin-right").toFloat();
  129. // this.scrollVAreaNode.setStyle("display", "none");
  130. // if (this.options.indent){
  131. // var marginFx = new Fx.Tween(this.node, {property: "margin-right", duration: "100"});
  132. // marginFx.start(margin-this.scrollVWidth).chain(function(){
  133. // this.scrollAreaOutLock = false;
  134. // }.bind(this));
  135. // }else{
  136. // this.scrollAreaOutLock = false;
  137. // }
  138. // }.bind(this));
  139. // }
  140. // }
  141. // }
  142. // // }
  143. // }
  144. // }
  145. },
  146. // checkScrollShow: function(e){
  147. // if (!this.node.isPointIn) return false;
  148. // if (this.node.isPointIn(e.event.clientX, e.event.clientY, this.scrollVWidth)){
  149. // if (this.scrollVAreaNode){
  150. // var opacity = this.scrollVAreaNode.getStyle("opacity");
  151. // if (opacity==0){
  152. // if (!this.scrollAreaOverLock && !this.scrollAreaOutLock){
  153. // this.scrollAreaOverLock = true;
  154. // var margin = this.node.getStyle("margin-right").toFloat();
  155. // if (this.options.indent){
  156. // var marginFx = new Fx.Tween(this.node, {property: "margin-right", duration: "100"});
  157. // marginFx.start(margin+this.scrollVWidth).chain(function(){
  158. // this.scrollVAreaNode.setStyle("display", "block");
  159. //
  160. // var scrollFx = new Fx.Tween(this.scrollVAreaNode, {property: "opacity", duration: "100"});
  161. // scrollFx.start(0,1).chain(function(){
  162. // this.scrollAreaOverLock = false;
  163. // }.bind(this));
  164. //
  165. // //this.scrollVAreaNode.fade("in");
  166. //
  167. // }.bind(this));
  168. // }else{
  169. // this.scrollVAreaNode.setStyle("display", "block");
  170. //
  171. // var scrollFx = new Fx.Tween(this.scrollVAreaNode, {property: "opacity", duration: "100"});
  172. // scrollFx.start(0,1).chain(function(){
  173. // this.scrollAreaOverLock = false;
  174. // }.bind(this));
  175. // }
  176. // }
  177. // }
  178. // }
  179. // }else{
  180. // if (this.scrollVAreaNode){
  181. // var opacity = this.scrollVAreaNode.getStyle("opacity");
  182. // // if (!this.options.isShow){
  183. // if (opacity==1){
  184. // if (!this.scrollAreaOutLock && !this.scrollAreaOverLock){
  185. // if (!this.showScrollBar){
  186. // this.scrollAreaOutLock = true;
  187. // var scrollFx = new Fx.Tween(this.scrollVAreaNode, {property: "opacity", duration: "100"});
  188. // scrollFx.start(0).chain(function(){
  189. // var margin = this.node.getStyle("margin-right").toFloat();
  190. // this.scrollVAreaNode.setStyle("display", "none");
  191. // if (this.options.indent){
  192. // var marginFx = new Fx.Tween(this.node, {property: "margin-right", duration: "100"});
  193. // marginFx.start(margin-this.scrollVWidth).chain(function(){
  194. // this.scrollAreaOutLock = false;
  195. // }.bind(this));
  196. // }else{
  197. // this.scrollAreaOutLock = false;
  198. // }
  199. // }.bind(this));
  200. // }
  201. // }
  202. // }
  203. // // }
  204. // }
  205. // }
  206. // },
  207. setScrollNodePosition: function(){
  208. this.node.scrollTo(0,0);
  209. if (this.scrollVNode){
  210. // var x = (this.clientSize.x.toFloat()) - (this.scrollVNodeSize.x.toFloat()) + this.options.offset.V.x;
  211. // var y = 0-(this.scrollSize.y.toFloat()) + this.options.offset.V.y;
  212. // this.scrollVNode.setStyle("margin-left", ""+x+"px");
  213. this.scrollVNode.setStyle("margin-top", "0px");
  214. // this.scrollVNode.setStyle("margin-left", "100px");
  215. // this.scrollVNode.setStyle("margin-top", ""+y+"px");
  216. this.setScrollVNodeMoveLimit();
  217. }
  218. if (this.scrollHNode){
  219. // var x = (this.nodePosition.x.toFloat());
  220. // //var y = (this.nodePosition.y.toFloat())+(this.clientSize.y.toFloat())-(this.scrollVNodeSize.y.toFloat());
  221. // var y = (this.nodePosition.y.toFloat())+(this.clientSize.y.toFloat());
  222. // this.scrollHNode.setStyle("top", ""+y+"px");
  223. // this.scrollHNode.setStyle("left", ""+x+"px");
  224. var y = this.scrollHNode.getSize().y;
  225. y = 0-y + this.options.offset.H.y;
  226. var x = 0 + this.options.offset.H.x;
  227. this.scrollHNode.setStyle("margin-left", ""+x+"px");
  228. this.scrollHNode.setStyle("margin-top", ""+y+"px");
  229. }
  230. },
  231. setScrollVNodeMove: function(){
  232. this.scrollVAreaNode.addEvent("click", function(e){e.stopPropagation();});
  233. this.scrollVNodeMove = new Drag(this.scrollVNode,{
  234. "onStart": function(el, e){
  235. this.fireEvent("scrollStart");
  236. var x = e.event.clientX;
  237. var y = e.event.clientY;
  238. el.store("position", {"x": x, "y": y});
  239. el.store("margin", el.getStyle("margin-top"));
  240. this.showScrollBar = true;
  241. }.bind(this),
  242. "onComplete": function(e){
  243. this.showScrollBar = false;
  244. this.fireEvent("scrollComplete");
  245. }.bind(this),
  246. "onDrag": function(el, e){
  247. var p = el.retrieve("position");
  248. var margin = el.retrieve("margin").toFloat();
  249. // var dx = (e.event.clientX.toFloat()) - (p.x.toFloat());
  250. var dy = (e.event.clientY.toFloat()) - (p.y.toFloat());
  251. var dmargin = margin+dy;
  252. var scrollSize = this.node.getScrollSize();
  253. var clientSize = this.node.getSize();
  254. var scrollVNodeSize = this.scrollVNode.getSize();
  255. //var marginTop = this.node.getStyle("margin-top").toFloat();
  256. var maxY = (clientSize.y.toFloat())-(scrollVNodeSize.y.toFloat());
  257. var minY = 0;
  258. if (dmargin<minY) dmargin = minY;
  259. if (dmargin>maxY) dmargin = maxY;
  260. this.scrollVNode.setStyle("margin-top", ""+dmargin+"px");
  261. this.scroll(null, dmargin);
  262. // var vPosition = this.scrollVNode.getPosition();
  263. // this.scroll(null, (vPosition.y.toFloat())-(this.nodePosition.y.toFloat()));
  264. }.bind(this)
  265. });
  266. },
  267. setScrollVNodeMoveLimit: function(){
  268. //var x = (this.nodePosition.x.toFloat())+(this.clientSize.x.toFloat())-(this.scrollVNodeSize.x.toFloat());
  269. var x = (this.nodePosition.x.toFloat())+(this.clientSize.x.toFloat());
  270. var y = (this.nodePosition.y.toFloat());
  271. var maxY = y+(this.clientSize.y.toFloat()) - (this.scrollVNodeSize.y.toFloat());
  272. this.scrollVNodeMove.detach();
  273. this.scrollVNodeMove.setOptions({"limit": {"x": [x, x], "y": [y, maxY]}});
  274. this.scrollVNodeMove.attach();
  275. },
  276. scroll: function(nodeDelta, scrollDelta){
  277. var scrollSize = this.node.getScrollSize();
  278. var clientSize = this.node.getSize();
  279. var scrollVNodeSize = this.scrollVNode.getSize();
  280. // var marginTop = this.node.getStyle("margin-top").toFloat();
  281. var scrollHeight = scrollSize.y-clientSize.y;
  282. var maxY = (clientSize.y.toFloat())-(scrollVNodeSize.y.toFloat());
  283. var minY = 0;
  284. if (nodeDelta){
  285. var scroll = this.node.getScroll();
  286. var scrollTo = (scroll.y.toFloat())+(nodeDelta.toFloat());
  287. if (scrollTo<0) scrollTo = 0;
  288. if (scrollTo>scrollHeight) scrollTo = scrollHeight;
  289. //this.node.scrollTo(0, scrollTo);
  290. this.fireEvent("scroll", [scrollTo]);
  291. this.node.tweenScroll(scrollTo, 1);
  292. //this.node.tween("margin-top", -100);
  293. var y = (scrollTo/(scrollHeight.toFloat()))*(maxY.toFloat());
  294. if (y<minY) y = minY;
  295. if (y>maxY) y = maxY;
  296. // this.scrollVNode.set("tween", {"duration": "1", "transition": Fx.Transitions.Expo.easeOut});
  297. // this.scrollVNode.tween("margin-top", ""+y+"px");
  298. this.scrollVNode.setStyle("margin-top", ""+y+"px");
  299. }
  300. if (scrollDelta){
  301. if (scrollDelta>maxY) scrollDelta = maxY;
  302. var y = (scrollDelta/maxY)*scrollHeight;
  303. var scroll = this.node.getScroll();
  304. //this.node.scrollTo(0, y);
  305. this.node.tweenScroll(y, 1);
  306. this.fireEvent("scroll", [y]);
  307. }
  308. },
  309. checkScroll: function(){
  310. var scrollSize = this.node.getScrollSize();
  311. var clientSize = this.node.getSize();
  312. var nodePosition = this.node.getPosition(this.node.getOffsetParent());
  313. if (!this.mousewheel) this.mousewheel = function(e){
  314. var delta = 1-e.event.wheelDelta;
  315. var step = ((this.options.distance.toFloat())/100)*(clientSize.y.toFloat());
  316. delta = (delta/(clientSize.y.toFloat()))*step;
  317. this.scroll(delta, null);
  318. e.stopPropagation();
  319. }.bind(this);
  320. if (!this.domMousewheel) this.domMousewheel = function(e){
  321. var delta = e.detail;
  322. var step = ((this.options.distance.toFloat())/100)*(clientSize.y.toFloat());
  323. delta = (delta/6)*step;
  324. this.scroll(delta, null);
  325. e.stopPropagation();
  326. }.bind(this);
  327. if (!this.touchmove) this.touchmove = function(e){
  328. var delta = e.event.detail;
  329. var step = ((this.options.distance.toFloat())/100)*(clientSize.y.toFloat());
  330. delta = (delta/(clientSize.y.toFloat()))*step;
  331. this.scroll(delta, null);
  332. e.preventDefault();
  333. e.stopPropagation();
  334. }.bind(this);
  335. if (scrollSize.y>clientSize.y){
  336. if (!this.scrollVNode){
  337. // this.scrollVAreaNode = new Element("div", {
  338. // "styles": this.css.scrollVAreaNode
  339. // }).inject(this.node, "before");
  340. this.scrollVAreaNode = new Element("div", {
  341. "styles": this.css.scrollVAreaNode
  342. }).inject(this.node, this.options.where);
  343. //if (this.scrollVAreaNode.getStyle("position")=="absolute"){
  344. // this.scrollVAreaNode.position({
  345. // relativeTo: this.node,
  346. // position: "topright",
  347. // edge: "topleft"
  348. // });
  349. //}
  350. this.scrollVNode = new Element("div", {
  351. "styles": this.css.scrollVNode
  352. }).inject(this.scrollVAreaNode);
  353. var margin = this.node.getStyle("margin-right").toFloat();
  354. var marginTop = this.node.getStyle("margin-top").toFloat();
  355. var marginBottom = this.node.getStyle("margin-bottom").toFloat();
  356. var scrollVNodeSize = this.scrollVAreaNode.getSize();
  357. // this.node.tween("margin-right", margin+scrollVNodeSize.x);
  358. if (this.options.indent) this.scrollVAreaNode.setStyle("margin-right", margin);
  359. this.scrollVAreaNode.setStyle("margin-top", marginTop);
  360. this.scrollVAreaNode.setStyle("display", "none");
  361. this.scrollVWidth = this.scrollVAreaNode.getStyle("width").toFloat();
  362. this.setScrollVNodeMove();
  363. if (!this.isAddEvent){
  364. this.node.addEvent("mousewheel", this.mousewheel);
  365. this.node.addEvent("touchmove", this.touchmove);
  366. if (Browser.name=="firefox"){
  367. this.node.addEventListener("DOMMouseScroll", this.domMousewheel, false);
  368. }
  369. this.isAddEvent = true
  370. }
  371. // this.node DOMMouseScroll
  372. }
  373. if (this.scrollVAreaNode.getStyle("position")=="absolute"){
  374. this.scrollVAreaNode.position({
  375. relativeTo: this.node,
  376. position: "topright",
  377. edge: "topleft"
  378. });
  379. }
  380. this.scrollVAreaNode.setStyle("height", clientSize.y);
  381. // this.setScrollNodePosition();
  382. }else{
  383. if (this.scrollVNode){
  384. if (!this.scrollAreaOutLock && !this.scrollAreaOverLock){
  385. if (!this.showScrollBar){
  386. this.scrollAreaOutLock = true;
  387. var scrollFx = new Fx.Tween(this.scrollVAreaNode, {property: "opacity", duration: "100"});
  388. scrollFx.start(0).chain(function(){
  389. var margin = this.node.getStyle("margin-right").toFloat();
  390. this.scrollVAreaNode.setStyle("display", "none");
  391. //var marginFx = new Fx.Tween(this.node, {property: "margin-right", duration: "100"});
  392. if (this.options.indent){
  393. var marginFx = new Fx.Tween(this.node, {property: "margin-right", duration: "100"});
  394. marginFx.start(margin-this.scrollVWidth).chain(function(){
  395. this.scrollAreaOutLock = false;
  396. this.scrollVAreaNode.destroy();
  397. this.scrollVNode = null;
  398. this.scrollVAreaNode = null;
  399. }.bind(this));
  400. }else{
  401. this.scrollAreaOutLock = false;
  402. this.scrollVAreaNode.destroy();
  403. this.scrollVNode = null;
  404. this.scrollVAreaNode = null;
  405. }
  406. }.bind(this));
  407. };
  408. };
  409. // var scrollVNodeSize = this.scrollVAreaNode.getSize();
  410. // var margin = this.node.getStyle("margin-right").toFloat();
  411. //
  412. // this.scrollVAreaNode.destroy();
  413. // this.scrollVNode = null;
  414. // this.scrollVAreaNode = null;
  415. // this.node.tween("margin-right", margin-scrollVNodeSize.x);
  416. }
  417. //this.node.removeEvent("mousewheel", this.mousewheel);
  418. this.node.removeEvent("touchmove", this.touchmove);
  419. if (Browser.name=="firefox"){
  420. this.node.removeEventListener("DOMMouseScroll", this.domMousewheel, false);
  421. }
  422. }
  423. // if (scrollSize.x>scrollSize.x){
  424. // alert("ddd");
  425. // var scrollNode = node.retrieve("scrollbarH");
  426. // if (!scrollNode){
  427. // var scrollNode = new Element("div", {
  428. // "styles": css
  429. // }).inject(node, "after");
  430. // alerrt("ddd");
  431. // var scrollNodeMove = new Drag.Move(scrollNode);
  432. // node.store("scrollbarH", scrollNode);
  433. // }
  434. // }
  435. },
  436. destroy: function(){
  437. if (this.checkScrollFun) layout.desktop.removeEvent("resize", this.checkScrollFun);
  438. //if (this.checkScrollFun) layout.desktop.removeEvent("onresize", this.checkScrollFun);
  439. if (this.checkScrollStopFun) this.node.removeEvent("mouseover", this.checkScrollStopFun);
  440. if (this.checkScrollStopFun) this.node.removeEvent("mouseout", this.checkScrollStopFun);
  441. if (this.checkScrollShowFun) document.body.removeEvent("mousemove", this.checkScrollShowFun);
  442. if (this.mousewheel) this.node.removeEvent("mousewheel", this.mousewheel);
  443. if (this.touchmove) this.node.removeEvent("touchmove", this.touchmove);
  444. if (Browser.name=="firefox"){
  445. if (this.domMousewheel) this.node.removeEventListener("DOMMouseScroll", this.domMousewheel, false);
  446. }
  447. if (this.scrollVAreaNode) this.scrollVAreaNode.destroy();
  448. if (this.scrollVNode) this.scrollVNode.destroy();
  449. o2.release(this);
  450. }
  451. });