Prototype Carousel


/ Published in: JavaScript
Save to your folder(s)

Prototype Carousel Slider


Copy this code and paste it in your HTML
  1. /*
  2.  
  3. *********************************The Markup*************************************
  4.  
  5. <script type="text/javascript" src="prototype.js"></script>
  6. <script type="text/javascript" src="scriptaculous.js"></script>
  7. <script type="text/javascript" src="carousel.js"></script>
  8.  
  9. <div id="carousel-wrapper">
  10.   <div id="carousel-content">
  11.   <div class="slide"></div>
  12.   <div class="slide"></div>
  13.   ...
  14.   <div class="slide"></div>
  15.   </div>
  16. </div>
  17.  
  18. #carousel-wrapper {
  19.   width: 500px;
  20.   height: 500px;
  21.   overflow: hidden;
  22. }
  23. #carousel-content {
  24.   width: 2500px;
  25. }
  26. #carousel-content .slide {
  27.   float: left;
  28.   width: 500px;
  29.   height: 500px;
  30. }
  31.  
  32. new Carousel(wrapper, slides, triggers, {options});
  33.  
  34. new Carousel('carousel-wrapper', $$('#carousel-content .slide'), $$('a.carousel-control', 'a.carousel-jumper'));
  35.  
  36. <a href="javascript:" class="carousel-jumper" rel="slide-1">Jump to slide 1</a>
  37. <a href="javascript:" class="carousel-control" rel="prev">Previous slide</a>
  38.  
  39.  
  40.  
  41. Copyright (c) 2009 Victor Stanciu - http://www.victorstanciu.ro
  42.  
  43. Permission is hereby granted, free of charge, to any person
  44. obtaining a copy of this software and associated documentation
  45. files (the "Software"), to deal in the Software without
  46. restriction, including without limitation the rights to use,
  47. copy, modify, merge, publish, distribute, sublicense, and/or sell
  48. copies of the Software, and to permit persons to whom the
  49. Software is furnished to do so, subject to the following
  50. conditions:
  51.  
  52. The above copyright notice and this permission notice shall be
  53. included in all copies or substantial portions of the Software.
  54.  
  55. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  56. EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  57. OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  58. NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  59. HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  60. WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  61. FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  62. OTHER DEALINGS IN THE SOFTWARE.
  63. */
  64.  
  65. Carousel = Class.create(Abstract, {
  66. initialize: function (scroller, slides, controls, options) {
  67. this.scrolling = false;
  68. this.scroller = $(scroller);
  69. this.slides = slides;
  70. this.controls = controls;
  71.  
  72. this.options = Object.extend({
  73. duration: 1,
  74. auto: false,
  75. frequency: 3,
  76. visibleSlides: 1,
  77. controlClassName: 'carousel-control',
  78. jumperClassName: 'carousel-jumper',
  79. disabledClassName: 'carousel-disabled',
  80. selectedClassName: 'carousel-selected',
  81. circular: false,
  82. wheel: true,
  83. effect: 'scroll',
  84. transition: 'sinoidal'
  85. }, options || {});
  86.  
  87. if (this.options.effect == 'fade') {
  88. this.options.circular = true;
  89. }
  90.  
  91. this.slides.each(function(slide, index) {
  92. slide._index = index;
  93. });
  94.  
  95. if (this.controls) {
  96. this.controls.invoke('observe', 'click', this.click.bind(this));
  97. }
  98.  
  99. if (this.options.wheel) {
  100. this.scroller.observe('mousewheel', this.wheel.bindAsEventListener(this)).observe('DOMMouseScroll', this.wheel.bindAsEventListener(this));;
  101. }
  102.  
  103. if (this.options.auto) {
  104. this.start();
  105. }
  106.  
  107. if (this.options.initial) {
  108. var initialIndex = this.slides.indexOf($(this.options.initial));
  109. if (initialIndex > (this.options.visibleSlides - 1) && this.options.visibleSlides > 1) {
  110. if (initialIndex > this.slides.length - (this.options.visibleSlides + 1)) {
  111. initialIndex = this.slides.length - this.options.visibleSlides;
  112. }
  113. }
  114. this.moveTo(this.slides[initialIndex]);
  115. }
  116. },
  117.  
  118. click: function (event) {
  119. this.stop();
  120.  
  121. var element = event.findElement('a');
  122.  
  123. if (!element.hasClassName(this.options.disabledClassName)) {
  124. if (element.hasClassName(this.options.controlClassName)) {
  125. eval("this." + element.rel + "()");
  126. } else if (element.hasClassName(this.options.jumperClassName)) {
  127. this.moveTo(element.rel);
  128. if (this.options.selectedClassName) {
  129. this.controls.invoke('removeClassName', this.options.selectedClassName);
  130. element.addClassName(this.options.selectedClassName);
  131. }
  132. }
  133. }
  134.  
  135. this.deactivateControls();
  136.  
  137. event.stop();
  138. },
  139.  
  140. moveTo: function (element) {
  141. if (this.options.beforeMove && (typeof this.options.beforeMove == 'function')) {
  142. this.options.beforeMove();
  143. }
  144.  
  145. this.previous = this.current ? this.current : this.slides[0];
  146. this.current = $(element);
  147.  
  148. var scrollerOffset = this.scroller.cumulativeOffset();
  149. var elementOffset = this.current.cumulativeOffset();
  150.  
  151. if (this.scrolling) {
  152. this.scrolling.cancel();
  153. }
  154.  
  155. switch (this.options.effect) {
  156. case 'fade':
  157. this.scrolling = new Effect.Opacity(this.scroller, {
  158. from: 1.0,
  159. to: 0,
  160. duration: this.options.duration,
  161. afterFinish: (function () {
  162. this.scroller.scrollLeft = elementOffset[0] - scrollerOffset[0];
  163. this.scroller.scrollTop = elementOffset[1] - scrollerOffset[1];
  164.  
  165. new Effect.Opacity(this.scroller, {
  166. from: 0,
  167. to: 1.0,
  168. duration: this.options.duration,
  169. afterFinish: (function () {
  170. if (this.controls) {
  171. this.activateControls();
  172. }
  173. if (this.options.afterMove && (typeof this.options.afterMove == 'function')) {
  174. this.options.afterMove();
  175. }
  176. }).bind(this)
  177. });
  178. }
  179. ).bind(this)});
  180. break;
  181. case 'scroll':
  182. default:
  183. var transition;
  184. switch (this.options.transition) {
  185. case 'spring':
  186. transition = Effect.Transitions.spring;
  187. break;
  188. case 'sinoidal':
  189. default:
  190. transition = Effect.Transitions.sinoidal;
  191. break;
  192. }
  193.  
  194. this.scrolling = new Effect.SmoothScroll(this.scroller, {
  195. duration: this.options.duration,
  196. x: (elementOffset[0] - scrollerOffset[0]),
  197. y: (elementOffset[1] - scrollerOffset[1]),
  198. transition: transition,
  199. afterFinish: (function () {
  200. if (this.controls) {
  201. this.activateControls();
  202. }
  203. if (this.options.afterMove && (typeof this.options.afterMove == 'function')) {
  204. this.options.afterMove();
  205. }
  206. this.scrolling = false;
  207. }).bind(this)});
  208. break;
  209. }
  210.  
  211. return false;
  212. },
  213.  
  214. prev: function () {
  215. if (this.current) {
  216. var currentIndex = this.current._index;
  217. var prevIndex = (currentIndex == 0) ? (this.options.circular ? this.slides.length - 1 : 0) : currentIndex - 1;
  218. } else {
  219. var prevIndex = (this.options.circular ? this.slides.length - 1 : 0);
  220. }
  221.  
  222. if (prevIndex == (this.slides.length - 1) && this.options.circular && this.options.effect != 'fade') {
  223. this.scroller.scrollLeft = (this.slides.length - 1) * this.slides.first().getWidth();
  224. this.scroller.scrollTop = (this.slides.length - 1) * this.slides.first().getHeight();
  225. prevIndex = this.slides.length - 2;
  226. }
  227.  
  228. this.moveTo(this.slides[prevIndex]);
  229. },
  230.  
  231. next: function () {
  232. if (this.current) {
  233. var currentIndex = this.current._index;
  234. var nextIndex = (this.slides.length - 1 == currentIndex) ? (this.options.circular ? 0 : currentIndex) : currentIndex + 1;
  235. } else {
  236. var nextIndex = 1;
  237. }
  238.  
  239. if (nextIndex == 0 && this.options.circular && this.options.effect != 'fade') {
  240. this.scroller.scrollLeft = 0;
  241. this.scroller.scrollTop = 0;
  242. nextIndex = 1;
  243. }
  244.  
  245. if (nextIndex > this.slides.length - (this.options.visibleSlides + 1)) {
  246. nextIndex = this.slides.length - this.options.visibleSlides;
  247. }
  248.  
  249. this.moveTo(this.slides[nextIndex]);
  250. },
  251.  
  252. first: function () {
  253. this.moveTo(this.slides[0]);
  254. },
  255.  
  256. last: function () {
  257. this.moveTo(this.slides[this.slides.length - 1]);
  258. },
  259.  
  260. toggle: function () {
  261. if (this.previous) {
  262. this.moveTo(this.slides[this.previous._index]);
  263. } else {
  264. return false;
  265. }
  266. },
  267.  
  268. stop: function () {
  269. if (this.timer) {
  270. clearTimeout(this.timer);
  271. }
  272. },
  273.  
  274. start: function () {
  275. this.periodicallyUpdate();
  276. },
  277.  
  278. pause: function () {
  279. this.stop();
  280. this.activateControls();
  281. },
  282.  
  283. resume: function (event) {
  284. if (event) {
  285. var related = event.relatedTarget || event.toElement;
  286. if (!related || (!this.slides.include(related) && !this.slides.any(function (slide) { return related.descendantOf(slide); }))) {
  287. this.start();
  288. }
  289. } else {
  290. this.start();
  291. }
  292. },
  293.  
  294. periodicallyUpdate: function () {
  295. if (this.timer != null) {
  296. clearTimeout(this.timer);
  297. this.next();
  298. }
  299. this.timer = setTimeout(this.periodicallyUpdate.bind(this), this.options.frequency * 1000);
  300. },
  301.  
  302. wheel: function (event) {
  303. event.cancelBubble = true;
  304. event.stop();
  305.  
  306. var delta = 0;
  307. if (!event) {
  308. event = window.event;
  309. }
  310. if (event.wheelDelta) {
  311. delta = event.wheelDelta / 120;
  312. } else if (event.detail) {
  313. delta = -event.detail / 3;
  314. }
  315.  
  316. if (!this.scrolling) {
  317. this.deactivateControls();
  318. if (delta > 0) {
  319. this.prev();
  320. } else {
  321. this.next();
  322. }
  323. }
  324.  
  325. return Math.round(delta); //Safari Round
  326. },
  327.  
  328. deactivateControls: function () {
  329. this.controls.invoke('addClassName', this.options.disabledClassName);
  330. },
  331.  
  332. activateControls: function () {
  333. this.controls.invoke('removeClassName', this.options.disabledClassName);
  334. }
  335. });
  336.  
  337.  
  338. Effect.SmoothScroll = Class.create();
  339. Object.extend(Object.extend(Effect.SmoothScroll.prototype, Effect.Base.prototype), {
  340. initialize: function (element) {
  341. this.element = $(element);
  342. var options = Object.extend({ x: 0, y: 0, mode: 'absolute' } , arguments[1] || {});
  343. this.start(options);
  344. },
  345.  
  346. setup: function () {
  347. if (this.options.continuous && !this.element._ext) {
  348. this.element.cleanWhitespace();
  349. this.element._ext = true;
  350. this.element.appendChild(this.element.firstChild);
  351. }
  352.  
  353. this.originalLeft = this.element.scrollLeft;
  354. this.originalTop = this.element.scrollTop;
  355.  
  356. if (this.options.mode == 'absolute') {
  357. this.options.x -= this.originalLeft;
  358. this.options.y -= this.originalTop;
  359. }
  360. },
  361.  
  362. update: function (position) {
  363. this.element.scrollLeft = this.options.x * position + this.originalLeft;
  364. this.element.scrollTop = this.options.y * position + this.originalTop;
  365. }
  366. });

URL: http://code.google.com/p/prototype-carousel/

Report this snippet


Comments

RSS Icon Subscribe to comments

You need to login to post a comment.