Guest User

Untitled

a guest
Apr 25th, 2018
82
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.21 KB | None | 0 0
  1. /*
  2.  
  3. Copyright (c) 2009 Rob Bast
  4.  
  5. Permission is hereby granted, free of charge, to any person
  6. obtaining a copy of this software and associated documentation
  7. files (the "Software"), to deal in the Software without
  8. restriction, including without limitation the rights to use,
  9. copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. copies of the Software, and to permit persons to whom the Software
  11. is furnished to do so, subject to the following condition:
  12.  
  13. The above copyright notice and this permission notice shall be
  14. included in all copies or substantial portions of the Software.
  15.  
  16.  
  17. slider.js
  18.  
  19. Simple class for sliding elements within a container.
  20.  
  21. Container should be as wide as the total width of slides you
  22. intend to show at once (overflow hidden). Slides should be wide
  23. enough to fill the container. Slides should have no margin or
  24. padding! If you need these, simply add a child element to the
  25. slide with desired padding or margin.
  26.  
  27. */
  28. var Slider = new Class({
  29.  
  30. Implements: [Options, Events, Chain],
  31.  
  32. options: {
  33. childSelector: 'div', // used to grab sliding children of container
  34. endless: false, // endless implies next() or previous() always works
  35. direction: 'horizontal', // direction of sliding, horizontal or vertical
  36. show: 1, // how many items to show at once
  37. slideToSlide: 1, // how many items to slide at once
  38. auto: false, // delay between each auto slide action (set to false for off)
  39. fxOptions: {
  40. duration: 500 // duration of the slide effect
  41. },
  42. onStart: function(){
  43. this.next();
  44. },
  45. onFirst: function(){
  46. this.next();
  47. },
  48. onLast: function(){
  49. this.previous();
  50. },
  51. onNext: $empty,
  52. onPrevious: $empty,
  53. onStop: $empty,
  54. onPause: $empty,
  55. onResume: $empty
  56. },
  57.  
  58. slides: {
  59. next: [],
  60. previous: []
  61. },
  62. fx: null,
  63. timeoutId: null,
  64.  
  65. initialize: function(container, options){
  66. // grab container element
  67. this.container = this.parent = document.id(container);
  68. // check if container exists
  69. if(!this.container){
  70. console.error('You failed the internet, do not pass start and do not collect awesome fx effects.');
  71. return;
  72. }
  73. // process any passed options
  74. this.setOptions(options);
  75. // grab all children of our container, based on childSelector given && also apply style float:left
  76. var slides = this.container.getElements(this.options.childSelector).setStyle('float', 'left');
  77. // check if we have enough child elements to work with
  78. if(slides.length < this.options.show + 1){
  79. console.error('Failure is imminent, need more items to slide anything.');
  80. return;
  81. }
  82. // grab all excess children and loop through them
  83. slides.slice(this.options.show, slides.length).each(
  84. function(slide){
  85. // remove each element from the DOM and push them onto the 'next' slides stack
  86. this.slides.next.push(slide.dispose());
  87. // I bind 'this', because otherwise this.slides is not accessible
  88. }.bind(this)
  89. );
  90. // if auto slide option is on
  91. if(this.options.auto){
  92. // start sliding! durrr
  93. this.start.delay(this.options.auto, this);
  94. }
  95. },
  96.  
  97. start: function(){
  98. this.fireEvent('start');
  99. },
  100.  
  101. stop: function(){
  102. if(this.timeoutId){
  103. $clear(this.timeoutId);
  104. }
  105. this.fireEvent('stop');
  106. },
  107.  
  108. pause: function(){
  109. if(this.fx){
  110. this.fx.pause();
  111. }
  112. this.fireEvent('pause');
  113. },
  114.  
  115. resume: function(){
  116. if(this.fx){
  117. this.fx.resume();
  118. }
  119. this.fireEvent('resume');
  120. },
  121.  
  122. previous: function(slides){
  123. var slides = slides || this.options.slidesToSlide;
  124. this.slide(-slides);
  125. },
  126.  
  127. next: function(slides){
  128. var slides = slides || this.options.slidesToSlide;
  129. this.slide(slides);
  130. },
  131.  
  132. slide: function(slides){
  133. // check if we're moving in next direction, are out of slides and have endless mode on
  134. if(slides > 0 && !this.slides.next.length && this.options.endless){
  135. // grab the last slide from the 'previous' slides stack and push it onto the 'next' slides stack
  136. this.slides.next.push(this.slides.previous.pop());
  137. }
  138. // check if we're moving in previous direction, are out of slides and have endless mode on
  139. if(slides < 0 && !this.slides.previous.length && this.options.endless){
  140. // grab the last slide from the 'next' slides stack and push it onto the 'previous' slides stack
  141. this.slides.previous.push(this.slides.next.pop());
  142. }
  143. // get the current child about to be removed
  144. var curChild = (slides > 0
  145. ? this.container.getFirst(this.options.childSelector)
  146. : this.container.getLast(this.options.childSelector)
  147. );
  148. // get the next child we want to slide in
  149. var newChild = (slides > 0
  150. ? this.slides.next.shift()
  151. : this.slides.previous.shift()
  152. );
  153. // generate the options object
  154. var opts = {'0': {}, '1': {}};
  155. // figure out which direction we are sliding in
  156. switch(this.options.direction){
  157. // vertical!
  158. case 'vertical':
  159. // figure out which margin to adjust depending on next or previous direction
  160. opts['0'][(slides > 0 ? 'margin-top' : 'margin-bottom')] = [0, -curChild.getStyle('height').toInt()];
  161. opts['1'][(slides > 0 ? 'margin-bottom' : 'margin-top')] = [-curChild.getStyle('height').toInt(), 0];
  162. // inject element into appropriate dom location after having adjusted style
  163. newChild.setStyle((slides > 0 ? 'margin-bottom' : 'margin-top'), -curChild.getStyle('height').toInt())
  164. .inject(this.container, (slides > 0 ? 'bottom' : 'top'));
  165. break;
  166. // horizontal!
  167. case 'horizontal':
  168. default:
  169. // figure out which margin to adjust depending on next or previous direction
  170. opts['0'][(slides > 0 ? 'margin-left' : 'margin-right')] = [0, -curChild.getStyle('width').toInt()];
  171. opts['1'][(slides > 0 ? 'margin-right' : 'margin-left')] = [-curChild.getStyle('width').toInt(), 0];
  172. // inject element into appropriate dom location after having adjusted style
  173. newChild.setStyle((slides > 0 ? 'margin-right' : 'margin-left'), -curChild.getStyle('width').toInt())
  174. .inject(this.container, (slides > 0 ? 'bottom' : 'top'));
  175. break;
  176. }
  177. }
  178.  
  179.  
  180.  
  181.  
  182.  
  183.  
  184.  
  185. // are we in auto slide mode?
  186. if(this.options.auto){
  187. // is there a timer active?
  188. if(this.timeoutId){
  189. // clear it
  190. $clear(this.timeoutId);
  191. }
  192. // generate the fxOptions object by merging default with some extra options
  193. var fxOptions = $merge(this.options.fxOptions, {
  194. // add a onComplete event
  195. onComplete: function(e){
  196. // when we're done, set a timer again, cause this is like, auto slide mode, mkay
  197. this.timeoutId = this.next.delay(this.options.auto, this);
  198. // binding 'this' cause otherwise this.next and such are not accessible
  199. }.bind(this)
  200. });
  201. // no autoslide mode
  202. }else{
  203. // default options are sufficient
  204. var fxOptions = this.options.fxOptions;
  205. }
  206. // are we sliding multiple elements at once?
  207. if(this.options.slidePer > 1){
  208. // set slide duration to duration divided by amount of slides to process
  209. var fxOptions = $merge(this.options.fxOptions, {duration: this.options.fxOptions.duration / this.options.slidePer});
  210. }
  211. // create the fx instance with the custom options, and add a chained function
  212. this.fx = new Fx.Elements($$(currChild, nextChild), fxOptions).start(opts).chain(
  213. function(){
  214. // unset the existing fx instance when we're done
  215. this.fx = null;
  216. // When we are done, dispose of the current child and put it on the 'previous' slides
  217. this.slides.previous.unshift(currChild.dispose().setStyles({'margin-top':0,'margin-bottom':0,'margin-left':0,'margin-right':0}));
  218. // check if it's a multislide action
  219. if(this.slidePerCurrent <= this.options.slidePer){
  220. // adjust counter
  221. this.slidePerCurrent = this.slidePerCurrent + 1;
  222. if(this.slidePerCurrent > this.options.slidePer){
  223. this.slidePerCurrent = 1;
  224. }else{
  225. // slide to next
  226. this.next();
  227. }
  228. }
  229. // again, binding 'this' for accessibility
  230. }.bind(this)
  231. );
  232. // we've moved to the next element, fire event!
  233. this.fireEvent('next', nextChild);
  234. // no more elements and no endless mode :(
  235. }else{
  236. // since there are no more elements, fire the last event
  237. this.fireEvent('last');
  238. }
  239. }
  240. return this;
  241. },
  242.  
  243. previous: function(){
  244. // check if an fx instance isn't currently active
  245. if(!this.fx){
  246. // check if we still have elements in the 'previous' slides stack OR if endless mode is set
  247. if(this.slides.previous.length || this.options.endless){
  248. // If we have no more elements on the 'previous' slides stack, we assume endless mode is true
  249. if(!this.slides.previous.length){
  250. // grab the last slide from the 'next' slides and push it onto the 'previous' slides stack
  251. this.slides.previous.push(this.slides.next.pop());
  252. }
  253. // get the current child, use childSelector given just to be sure we get the right one
  254. var currChild = this.container.getLast(this.options.childSelector);
  255. // get the previous child we want
  256. var prevChild = this.slides.previous.shift();
  257. // generate the options object
  258. var opts = {'0': {}, '1': {}};
  259. // figure out which direction we are running in
  260. switch (this.options.direction){
  261. // vertical is ^ v
  262. case 'vertical':
  263. // so we mess with bottom margin of current child
  264. opts['0']['margin-bottom'] = [0, -currChild.getStyle('height').toInt()],
  265. // and with top margin of the previous child
  266. opts['1']['margin-top'] = [-currChild.getStyle('height').toInt(), 0];
  267. // apply the top margin to the to be inserted child and inject it into the dom
  268. prevChild.setStyle('margin-top', -currChild.getStyle('height').toInt()).inject(this.container, 'top');
  269. break;
  270. // horizontal is < >
  271. case 'horizontal':
  272. default:
  273. // so we mess with right margin of current child
  274. opts['0']['margin-right'] = [0, -currChild.getStyle('width').toInt()],
  275. // and with left margin of the next child
  276. opts['1']['margin-left'] = [-currChild.getStyle('width').toInt(), 0];
  277. // apply the left margin to the to be inserted child and inject it into the dom
  278. prevChild.setStyle('margin-left', -currChild.getStyle('width').toInt()).inject(this.container, 'top');
  279. break;
  280. }
  281. // are we in auto slide mode?
  282. if(this.options.auto){
  283. // is there a timer active?
  284. if(this.timeoutId){
  285. // clear it
  286. $clear(this.timeoutId);
  287. }
  288. // generate the fxOptions object by merging default with some extra options
  289. var fxOptions = $merge(this.options.fxOptions, {
  290. // add a onComplete event
  291. onComplete: function(e){
  292. // when we're done, set a timer again, cause this is like, auto slide mode, mkay
  293. this.timeoutId = this.previous.delay(this.options.auto, this);
  294. // binding 'this' cause otherwise this.previous and such are not accessible
  295. }.bind(this)
  296. });
  297. // not in auto slide mode
  298. }else{
  299. // default options are sufficient
  300. var fxOptions = this.options.fxOptions;
  301. }
  302. // are we sliding multiple elements at once?
  303. if(this.options.slidePer > 1){
  304. // set the duration of each slide effect to duration divided by amount of slides to be processed
  305. var fxOptions = $merge(this.options.fxOptions, {duration: this.options.fxOptions.duration / this.options.slidePer});
  306. }
  307. // create the fx instance with the custom options, and add a chained function
  308. this.fx = new Fx.Elements($$(currChild, prevChild), fxOptions).start(opts).chain(
  309. function(){
  310. // unset the fx instance
  311. this.fx = null;
  312. // when we are done, dispose of the current child and put it on the 'next' slides
  313. this.slides.next.unshift(currChild.dispose().setStyles({'margin-top':0,'margin-bottom':0,'margin-left':0,'margin-right':0}));
  314. // check if it's a multislide action
  315. if(this.slidePerCurrent <= this.options.slidePer){
  316. // adjust counter
  317. this.slidePerCurrent = this.slidePerCurrent + 1;
  318. if(this.slidePerCurrent > this.options.slidePer){
  319. this.slidePerCurrent = 1;
  320. }else{
  321. // slide to next
  322. this.previous();
  323. }
  324. }
  325. // again, binding 'this' for accessibility
  326. }.bind(this)
  327. );
  328. // we've moved to the previous element, fire event!
  329. this.fireEvent('previous', prevChild);
  330. // no more elements and no endless mode :(
  331. }else{
  332. // since there are no more elements, fire the first event
  333. this.fireEvent('first');
  334. }
  335. }
  336. return this;
  337. }
  338.  
  339. });
Add Comment
Please, Sign In to add comment