jquery.ad-gallery.js 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854
  1. /**
  2. * Copyright (c) 2010 Anders Ekdahl (http://coffeescripter.com/)
  3. * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
  4. * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
  5. *
  6. * Version: 1.2.4
  7. *
  8. * Demo and documentation: http://coffeescripter.com/code/ad-gallery/
  9. */
  10. (function($) {
  11. $.fn.adGallery = function(options) {
  12. var defaults = { loader_image: 'loading.gif',
  13. start_at_index: 0,
  14. description_wrapper: false,
  15. thumb_opacity: 0.7,
  16. animate_first_image: false,
  17. animation_speed: 400,
  18. width: false,
  19. height: false,
  20. display_next_and_prev: true,
  21. display_back_and_forward: true,
  22. scroll_jump: 0, // If 0, it jumps the width of the container
  23. slideshow: {
  24. enable: true,
  25. autostart: false,
  26. speed: 5000,
  27. start_label: 'autoplay',
  28. stop_label: 'suspend',
  29. stop_on_scroll: true,
  30. countdown_prefix: '(',
  31. countdown_sufix: ')',
  32. onStart: false,
  33. onStop: false
  34. },
  35. effect: 'slide-hori', // or 'slide-vert', 'fade', or 'resize', 'none'
  36. enable_keyboard_move: true,
  37. cycle: true,
  38. callbacks: {
  39. init: false,
  40. afterImageVisible: false,
  41. beforeImageVisible: false
  42. }
  43. };
  44. var settings = $.extend(false, defaults, options);
  45. if(options && options.slideshow) {
  46. settings.slideshow = $.extend(false, defaults.slideshow, options.slideshow);
  47. };
  48. if(!settings.slideshow.enable) {
  49. settings.slideshow.autostart = false;
  50. };
  51. var galleries = [];
  52. $(this).each(function() {
  53. var gallery = new AdGallery(this, settings);
  54. galleries[galleries.length] = gallery;
  55. });
  56. // Sorry, breaking the jQuery chain because the gallery instances
  57. // are returned so you can fiddle with them
  58. return galleries;
  59. };
  60. function VerticalSlideAnimation(img_container, direction, desc) {
  61. var current_top = parseInt(img_container.css('top'), 10);
  62. if(direction == 'left') {
  63. var old_image_top = '-'+ this.image_wrapper_height +'px';
  64. img_container.css('top', this.image_wrapper_height +'px');
  65. } else {
  66. var old_image_top = this.image_wrapper_height +'px';
  67. img_container.css('top', '-'+ this.image_wrapper_height +'px');
  68. };
  69. if(desc) {
  70. desc.css('bottom', '-'+ desc[0].offsetHeight +'px');
  71. desc.animate({bottom: 0}, this.settings.animation_speed * 2);
  72. };
  73. if(this.current_description) {
  74. this.current_description.animate({bottom: '-'+ this.current_description[0].offsetHeight +'px'}, this.settings.animation_speed * 2);
  75. };
  76. return {old_image: {top: old_image_top},
  77. new_image: {top: current_top}};
  78. };
  79. function HorizontalSlideAnimation(img_container, direction, desc) {
  80. var current_left = parseInt(img_container.css('left'), 10);
  81. if(direction == 'left') {
  82. var old_image_left = '-'+ this.image_wrapper_width +'px';
  83. img_container.css('left',this.image_wrapper_width +'px');
  84. } else {
  85. var old_image_left = this.image_wrapper_width +'px';
  86. img_container.css('left','-'+ this.image_wrapper_width +'px');
  87. };
  88. if(desc) {
  89. desc.css('bottom', '-'+ desc[0].offsetHeight +'px');
  90. desc.animate({bottom: 0}, this.settings.animation_speed * 2);
  91. };
  92. if(this.current_description) {
  93. this.current_description.animate({bottom: '-'+ this.current_description[0].offsetHeight +'px'}, this.settings.animation_speed * 2);
  94. };
  95. return {old_image: {left: old_image_left},
  96. new_image: {left: current_left}};
  97. };
  98. function ResizeAnimation(img_container, direction, desc) {
  99. var image_width = img_container.width();
  100. var image_height = img_container.height();
  101. var current_left = parseInt(img_container.css('left'), 10);
  102. var current_top = parseInt(img_container.css('top'), 10);
  103. img_container.css({width: 0, height: 0, top: this.image_wrapper_height / 2, left: this.image_wrapper_width / 2});
  104. return {old_image: {width: 0,
  105. height: 0,
  106. top: this.image_wrapper_height / 2,
  107. left: this.image_wrapper_width / 2},
  108. new_image: {width: image_width,
  109. height: image_height,
  110. top: current_top,
  111. left: current_left}};
  112. };
  113. function FadeAnimation(img_container, direction, desc) {
  114. img_container.css('opacity', 0);
  115. return {old_image: {opacity: 0},
  116. new_image: {opacity: 1}};
  117. };
  118. // Sort of a hack, will clean this up... eventually
  119. function NoneAnimation(img_container, direction, desc) {
  120. img_container.css('opacity', 0);
  121. return {old_image: {opacity: 0},
  122. new_image: {opacity: 1},
  123. speed: 0};
  124. };
  125. function AdGallery(wrapper, settings) {
  126. this.init(wrapper, settings);
  127. };
  128. AdGallery.prototype = {
  129. // Elements
  130. wrapper: false,
  131. image_wrapper: false,
  132. gallery_info: false,
  133. nav: false,
  134. loader: false,
  135. preloads: false,
  136. thumbs_wrapper: false,
  137. scroll_back: false,
  138. scroll_forward: false,
  139. next_link: false,
  140. prev_link: false,
  141. slideshow: false,
  142. image_wrapper_width: 0,
  143. image_wrapper_height: 0,
  144. current_index: 0,
  145. current_image: false,
  146. current_description: false,
  147. nav_display_width: 0,
  148. settings: false,
  149. images: false,
  150. in_transition: false,
  151. animations: false,
  152. init: function(wrapper, settings) {
  153. var context = this;
  154. this.wrapper = $(wrapper);
  155. this.settings = settings;
  156. this.setupElements();
  157. this.setupAnimations();
  158. if(this.settings.width) {
  159. this.image_wrapper_width = this.settings.width;
  160. this.image_wrapper.width(this.settings.width);
  161. this.wrapper.width(this.settings.width);
  162. } else {
  163. this.image_wrapper_width = this.image_wrapper.width();
  164. };
  165. if(this.settings.height) {
  166. this.image_wrapper_height = this.settings.height;
  167. this.image_wrapper.height(this.settings.height);
  168. } else {
  169. this.image_wrapper_height = this.image_wrapper.height();
  170. };
  171. this.nav_display_width = this.nav.width();
  172. this.current_index = 0;
  173. this.current_image = false;
  174. this.current_description = false;
  175. this.in_transition = false;
  176. this.findImages();
  177. if(this.settings.display_next_and_prev) {
  178. this.initNextAndPrev();
  179. };
  180. // The slideshow needs a callback to trigger the next image to be shown
  181. // but we don't want to give it access to the whole gallery instance
  182. var nextimage_callback = function(callback) {
  183. return context.nextImage(callback);
  184. };
  185. this.slideshow = new AdGallerySlideshow(nextimage_callback, this.settings.slideshow);
  186. this.controls.append(this.slideshow.create());
  187. if(this.settings.slideshow.enable) {
  188. this.slideshow.enable();
  189. } else {
  190. this.slideshow.disable();
  191. };
  192. if(this.settings.display_back_and_forward) {
  193. this.initBackAndForward();
  194. };
  195. if(this.settings.enable_keyboard_move) {
  196. this.initKeyEvents();
  197. };
  198. var start_at = parseInt(this.settings.start_at_index, 10);
  199. if(window.location.hash && window.location.hash.indexOf('#ad-image') === 0) {
  200. start_at = window.location.hash.replace(/[^0-9]+/g, '');
  201. // Check if it's a number
  202. if((start_at * 1) != start_at) {
  203. start_at = this.settings.start_at_index;
  204. };
  205. };
  206. this.loading(true);
  207. this.showImage(start_at,
  208. function() {
  209. // We don't want to start the slideshow before the image has been
  210. // displayed
  211. if(context.settings.slideshow.autostart) {
  212. context.preloadImage(start_at + 1);
  213. context.slideshow.start();
  214. };
  215. }
  216. );
  217. // window.setTimeout(function() {
  218. // $('.ad-thumb'+ start_at).trigger('click');
  219. // },
  220. // 500);
  221. this.fireCallback(this.settings.callbacks.init);
  222. },
  223. setupAnimations: function() {
  224. this.animations = {
  225. 'slide-vert': VerticalSlideAnimation,
  226. 'slide-hori': HorizontalSlideAnimation,
  227. 'resize': ResizeAnimation,
  228. 'fade': FadeAnimation,
  229. 'none': NoneAnimation
  230. };
  231. },
  232. setupElements: function() {
  233. this.controls = this.wrapper.find('.ad-controls');
  234. this.gallery_info = $('<p class="ad-info"></p>');
  235. // this.controls.append(this.gallery_info);
  236. this.image_wrapper = this.wrapper.find('.ad-image-wrapper');
  237. this.image_wrapper.empty();
  238. this.nav = this.wrapper.find('.ad-nav');
  239. this.thumbs_wrapper = this.nav.find('.ad-thumbs');
  240. this.preloads = $('<div class="ad-preloads"></div>');
  241. this.loader = $('<img class="ad-loader" src="'+ this.settings.loader_image +'">');
  242. this.image_wrapper.append(this.loader);
  243. this.loader.hide();
  244. $(document.body).append(this.preloads);
  245. },
  246. loading: function(bool) {
  247. if(bool) {
  248. this.loader.show();
  249. } else {
  250. this.loader.hide();
  251. };
  252. },
  253. addAnimation: function(name, fn) {
  254. if($.isFunction(fn)) {
  255. this.animations[name] = fn;
  256. };
  257. },
  258. findImages: function() {
  259. var context = this;
  260. this.images = [];
  261. var thumb_wrapper_width = 0;
  262. var thumbs_loaded = 0;
  263. var thumbs = this.thumbs_wrapper.find('a');
  264. var thumb_count = thumbs.length;
  265. if(this.settings.thumb_opacity < 1) {
  266. thumbs.find('img').css('opacity', this.settings.thumb_opacity);
  267. };
  268. thumbs.each(
  269. function(i) {
  270. var link = $(this);
  271. var image_src = link.attr('href');
  272. var thumb = link.find('img');
  273. // Check if the thumb has already loaded
  274. if(!context.isImageLoaded(thumb[0])) {
  275. thumb.load(
  276. function() {
  277. thumb_wrapper_width += this.parentNode.parentNode.parentNode.offsetWidth;
  278. thumbs_loaded++;
  279. }
  280. );
  281. } else{
  282. thumb_wrapper_width += thumb[0].parentNode.parentNode.parentNode.offsetWidth;
  283. thumbs_loaded++;
  284. };
  285. link.addClass('ad-thumb'+ i);
  286. link.click(
  287. function() {
  288. context.showImage(i);
  289. context.slideshow.stop();
  290. return false;
  291. }
  292. ).hover(
  293. function() {
  294. if(!$(this).is('.ad-active') && context.settings.thumb_opacity < 1) {
  295. $(this).find('img').fadeTo(300, 1);
  296. };
  297. context.preloadImage(i);
  298. },
  299. function() {
  300. if(!$(this).is('.ad-active') && context.settings.thumb_opacity < 1) {
  301. $(this).find('img').fadeTo(300, context.settings.thumb_opacity);
  302. };
  303. }
  304. );
  305. var link = false;
  306. if(thumb.data('ad-link')) {
  307. link = thumb.data('ad-link');
  308. } else if(thumb.attr('longdesc') && thumb.attr('longdesc').length) {
  309. link = thumb.attr('longdesc');
  310. };
  311. var desc = false;
  312. if(thumb.data('ad-desc')) {
  313. desc = thumb.data('ad-desc');
  314. } else if(thumb.attr('alt') && thumb.attr('alt').length) {
  315. desc = thumb.attr('alt');
  316. };
  317. var title = false;
  318. if(thumb.data('ad-title')) {
  319. title = thumb.data('ad-title');
  320. } else if(thumb.attr('title') && thumb.attr('title').length) {
  321. title = thumb.attr('title');
  322. };
  323. context.images[i] = { thumb: thumb.attr('src'), image: image_src, error: false,
  324. preloaded: false, desc: desc, title: title, size: false,
  325. link: link };
  326. }
  327. );
  328. // Wait until all thumbs are loaded, and then set the width of the ul
  329. var inter = setInterval(
  330. function() {
  331. if(thumb_count == thumbs_loaded) {
  332. thumb_wrapper_width -= 100;
  333. var list = context.nav.find('.ad-thumb-list');
  334. list.css('width', thumb_wrapper_width +'px');
  335. var i = 1;
  336. var last_height = list.height();
  337. while(i < 201) {
  338. list.css('width', (thumb_wrapper_width + i) +'px');
  339. if(last_height != list.height()) {
  340. break;
  341. }
  342. last_height = list.height();
  343. i++;
  344. }
  345. clearInterval(inter);
  346. };
  347. },
  348. 100
  349. );
  350. },
  351. initKeyEvents: function() {
  352. var context = this;
  353. $(document).keydown(
  354. function(e) {
  355. if(e.keyCode == 39) {
  356. // right arrow
  357. context.nextImage();
  358. context.slideshow.stop();
  359. } else if(e.keyCode == 37) {
  360. // left arrow
  361. context.prevImage();
  362. context.slideshow.stop();
  363. };
  364. }
  365. );
  366. },
  367. initNextAndPrev: function() {
  368. this.next_link = $('<div class="ad-next"><div class="ad-next-image"></div></div>');
  369. this.prev_link = $('<div class="ad-prev"><div class="ad-prev-image"></div></div>');
  370. this.image_wrapper.append(this.next_link);
  371. this.image_wrapper.append(this.prev_link);
  372. var context = this;
  373. this.prev_link.add(this.next_link).mouseover(
  374. function(e) {
  375. // IE 6 hides the wrapper div, so we have to set it's width
  376. $(this).css('height', context.image_wrapper_height);
  377. $(this).find('div').show();
  378. }
  379. ).mouseout(
  380. function(e) {
  381. $(this).find('div').hide();
  382. }
  383. ).click(
  384. function() {
  385. if($(this).is('.ad-next')) {
  386. context.nextImage();
  387. context.slideshow.stop();
  388. } else {
  389. context.prevImage();
  390. context.slideshow.stop();
  391. };
  392. }
  393. ).find('div').css('opacity', 0.7);
  394. },
  395. initBackAndForward: function() {
  396. var context = this;
  397. this.scroll_forward = $('<div class="ad-forward"></div>');
  398. this.scroll_back = $('<div class="ad-back"></div>');
  399. this.nav.append(this.scroll_forward);
  400. this.nav.prepend(this.scroll_back);
  401. var has_scrolled = 0;
  402. var thumbs_scroll_interval = false;
  403. // $(this.scroll_back).add(this.scroll_forward).click(
  404. // function() {
  405. // // We don't want to jump the whole width, since an image
  406. // // might be cut at the edge
  407. // var width = context.nav_display_width - 50;
  408. // if(context.settings.scroll_jump > 0) {
  409. // var width = context.settings.scroll_jump;
  410. // };
  411. // if($(this).is('.ad-forward')) {
  412. // var left = context.thumbs_wrapper.scrollLeft() + width;
  413. // } else {
  414. // var left = context.thumbs_wrapper.scrollLeft() - width;
  415. // };
  416. // if(context.settings.slideshow.stop_on_scroll) {
  417. // context.slideshow.stop();
  418. // };
  419. // context.thumbs_wrapper.animate({scrollLeft: left +'px'});
  420. // return false;
  421. // }
  422. // ).css('opacity', 0.6).hover(
  423. // function() {
  424. // var direction = 'left';
  425. // if($(this).is('.ad-forward')) {
  426. // direction = 'right';
  427. // };
  428. // thumbs_scroll_interval = setInterval(
  429. // function() {
  430. // has_scrolled++;
  431. // // Don't want to stop the slideshow just because we scrolled a pixel or two
  432. // if(has_scrolled > 30 && context.settings.slideshow.stop_on_scroll) {
  433. // context.slideshow.stop();
  434. // };
  435. // var left = context.thumbs_wrapper.scrollLeft() + 1;
  436. // if(direction == 'left') {
  437. // left = context.thumbs_wrapper.scrollLeft() - 1;
  438. // };
  439. // context.thumbs_wrapper.scrollLeft(left);
  440. // },
  441. // 10
  442. // );
  443. // $(this).css('opacity', 1);
  444. // },
  445. // function() {
  446. // has_scrolled = 0;
  447. // clearInterval(thumbs_scroll_interval);
  448. // $(this).css('opacity', 0.6);
  449. // }
  450. // );
  451. },
  452. _afterShow: function() {
  453. this.gallery_info.html((this.current_index + 1) +' / '+ this.images.length);
  454. if(!this.settings.cycle) {
  455. // Needed for IE
  456. this.prev_link.show().css('height', this.image_wrapper_height);
  457. this.next_link.show().css('height', this.image_wrapper_height);
  458. if(this.current_index == (this.images.length - 1)) {
  459. this.next_link.hide();
  460. };
  461. if(this.current_index == 0) {
  462. this.prev_link.hide();
  463. };
  464. };
  465. this.fireCallback(this.settings.callbacks.afterImageVisible);
  466. },
  467. /**
  468. * Checks if the image is small enough to fit inside the container
  469. * If it's not, shrink it proportionally
  470. */
  471. _getContainedImageSize: function(image_width, image_height) {
  472. if(image_height > this.image_wrapper_height) {
  473. var ratio = image_width / image_height;
  474. image_height = this.image_wrapper_height;
  475. image_width = this.image_wrapper_height * ratio;
  476. };
  477. if(image_width > this.image_wrapper_width) {
  478. var ratio = image_height / image_width;
  479. image_width = this.image_wrapper_width;
  480. image_height = this.image_wrapper_width * ratio;
  481. };
  482. return {width: image_width, height: image_height};
  483. },
  484. /**
  485. * If the image dimensions are smaller than the wrapper, we position
  486. * it in the middle anyway
  487. */
  488. _centerImage: function(img_container, image_width, image_height) {
  489. img_container.css('top', '0px');
  490. if(image_height < this.image_wrapper_height) {
  491. var dif = this.image_wrapper_height - image_height;
  492. img_container.css('top', (dif / 2) +'px');
  493. };
  494. img_container.css('left', '0px');
  495. if(image_width < this.image_wrapper_width) {
  496. var dif = this.image_wrapper_width - image_width;
  497. img_container.css('left', (dif / 2) +'px');
  498. };
  499. },
  500. _getDescription: function(image) {
  501. var desc = false;
  502. if(image.desc.length || image.title.length) {
  503. var title = '';
  504. if(image.title.length) {
  505. title = '<strong class="ad-description-title">'+ image.title +'</strong>';
  506. };
  507. var desc = '';
  508. if(image.desc.length) {
  509. desc = '<span>'+ image.desc +'</span>';
  510. };
  511. desc = $('<p class="ad-image-description">'+ title + desc +'</p>');
  512. };
  513. return desc;
  514. },
  515. /**
  516. * @param function callback Gets fired when the image has loaded, is displaying
  517. * and it's animation has finished
  518. */
  519. showImage: function(index, callback) {
  520. if(this.images[index] && !this.in_transition) {
  521. var context = this;
  522. var image = this.images[index];
  523. this.in_transition = true;
  524. if(!image.preloaded) {
  525. this.loading(true);
  526. this.preloadImage(index, function() {
  527. context.loading(false);
  528. context._showWhenLoaded(index, callback);
  529. });
  530. } else {
  531. this._showWhenLoaded(index, callback);
  532. };
  533. };
  534. },
  535. /**
  536. * @param function callback Gets fired when the image has loaded, is displaying
  537. * and it's animation has finished
  538. */
  539. _showWhenLoaded: function(index, callback) {
  540. if(this.images[index]) {
  541. var context = this;
  542. var image = this.images[index];
  543. var img_container = $(document.createElement('div')).addClass('ad-image');
  544. var img = $(new Image()).attr('src', image.image);
  545. if(image.link) {
  546. var link = $('<a href="'+ image.link +'" target="_blank"></a>');
  547. link.append(img);
  548. img_container.append(link);
  549. } else {
  550. img_container.append(img);
  551. }
  552. this.image_wrapper.prepend(img_container);
  553. var size = this._getContainedImageSize(image.size.width, image.size.height);
  554. img.attr('width', size.width);
  555. img.attr('height', size.height);
  556. img_container.css({width: size.width +'px', height: size.height +'px'});
  557. this._centerImage(img_container, size.width, size.height);
  558. var desc = this._getDescription(image, img_container);
  559. if(desc) {
  560. if(!this.settings.description_wrapper) {
  561. img_container.append(desc);
  562. var width = size.width - parseInt(desc.css('padding-left'), 10) - parseInt(desc.css('padding-right'), 10);
  563. desc.css('width', width +'px');
  564. } else {
  565. this.settings.description_wrapper.append(desc);
  566. }
  567. };
  568. this.highLightThumb(this.nav.find('.ad-thumb'+ index));
  569. var direction = 'right';
  570. if(this.current_index < index) {
  571. direction = 'left';
  572. };
  573. this.fireCallback(this.settings.callbacks.beforeImageVisible);
  574. if(this.current_image || this.settings.animate_first_image) {
  575. var animation_speed = this.settings.animation_speed;
  576. var easing = 'swing';
  577. var animation = this.animations[this.settings.effect].call(this, img_container, direction, desc);
  578. if(typeof animation.speed != 'undefined') {
  579. animation_speed = animation.speed;
  580. };
  581. if(typeof animation.easing != 'undefined') {
  582. easing = animation.easing;
  583. };
  584. if(this.current_image) {
  585. var old_image = this.current_image;
  586. var old_description = this.current_description;
  587. old_image.animate(animation.old_image, animation_speed, easing,
  588. function() {
  589. old_image.remove();
  590. if(old_description) old_description.remove();
  591. }
  592. );
  593. };
  594. img_container.animate(animation.new_image, animation_speed, easing,
  595. function() {
  596. context.current_index = index;
  597. context.current_image = img_container;
  598. context.current_description = desc;
  599. context.in_transition = false;
  600. context._afterShow();
  601. context.fireCallback(callback);
  602. }
  603. );
  604. } else {
  605. this.current_index = index;
  606. this.current_image = img_container;
  607. context.current_description = desc;
  608. this.in_transition = false;
  609. context._afterShow();
  610. this.fireCallback(callback);
  611. };
  612. };
  613. },
  614. nextIndex: function() {
  615. if(this.current_index == (this.images.length - 1)) {
  616. if(!this.settings.cycle) {
  617. return false;
  618. };
  619. var next = 0;
  620. } else {
  621. var next = this.current_index + 1;
  622. };
  623. return next;
  624. },
  625. nextImage: function(callback) {
  626. var next = this.nextIndex();
  627. if(next === false) return false;
  628. this.preloadImage(next + 1);
  629. this.showImage(next, callback);
  630. return true;
  631. },
  632. prevIndex: function() {
  633. if(this.current_index == 0) {
  634. if(!this.settings.cycle) {
  635. return false;
  636. };
  637. var prev = this.images.length - 1;
  638. } else {
  639. var prev = this.current_index - 1;
  640. };
  641. return prev;
  642. },
  643. prevImage: function(callback) {
  644. var prev = this.prevIndex();
  645. if(prev === false) return false;
  646. this.preloadImage(prev - 1);
  647. this.showImage(prev, callback);
  648. return true;
  649. },
  650. preloadAll: function() {
  651. var context = this;
  652. var i = 0;
  653. function preloadNext() {
  654. if(i < context.images.length) {
  655. i++;
  656. context.preloadImage(i, preloadNext);
  657. };
  658. };
  659. context.preloadImage(i, preloadNext);
  660. },
  661. preloadImage: function(index, callback) {
  662. if(this.images[index]) {
  663. var image = this.images[index];
  664. if(!this.images[index].preloaded) {
  665. var img = $(new Image());
  666. img.attr('src', image.image);
  667. if(!this.isImageLoaded(img[0])) {
  668. this.preloads.append(img);
  669. var context = this;
  670. img.load(
  671. function() {
  672. image.preloaded = true;
  673. image.size = { width: this.width, height: this.height };
  674. context.fireCallback(callback);
  675. }
  676. ).error(
  677. function() {
  678. image.error = true;
  679. image.preloaded = false;
  680. image.size = false;
  681. }
  682. );
  683. } else {
  684. image.preloaded = true;
  685. image.size = { width: img[0].width, height: img[0].height };
  686. this.fireCallback(callback);
  687. };
  688. } else {
  689. this.fireCallback(callback);
  690. };
  691. };
  692. },
  693. isImageLoaded: function(img) {
  694. if(typeof img.complete != 'undefined' && !img.complete) {
  695. return false;
  696. };
  697. if(typeof img.naturalWidth != 'undefined' && img.naturalWidth == 0) {
  698. return false;
  699. };
  700. return true;
  701. },
  702. highLightThumb: function(thumb) {
  703. this.thumbs_wrapper.find('.ad-active').removeClass('ad-active');
  704. thumb.addClass('ad-active');
  705. if(this.settings.thumb_opacity < 1) {
  706. this.thumbs_wrapper.find('a:not(.ad-active) img').fadeTo(300, this.settings.thumb_opacity);
  707. thumb.find('img').fadeTo(300, 1);
  708. };
  709. // var left = thumb[0].parentNode.offsetLeft;
  710. // left -= (this.nav_display_width / 2) - (thumb[0].offsetWidth / 2);
  711. // this.thumbs_wrapper.animate({scrollLeft: left +'px'});
  712. },
  713. fireCallback: function(fn) {
  714. if($.isFunction(fn)) {
  715. fn.call(this);
  716. };
  717. }
  718. };
  719. function AdGallerySlideshow(nextimage_callback, settings) {
  720. this.init(nextimage_callback, settings);
  721. };
  722. AdGallerySlideshow.prototype = {
  723. start_link: false,
  724. stop_link: false,
  725. countdown: false,
  726. controls: false,
  727. settings: false,
  728. nextimage_callback: false,
  729. enabled: false,
  730. running: false,
  731. countdown_interval: false,
  732. init: function(nextimage_callback, settings) {
  733. var context = this;
  734. this.nextimage_callback = nextimage_callback;
  735. this.settings = settings;
  736. },
  737. create: function() {
  738. this.start_link = $('<span class="ad-slideshow-start">'+ this.settings.start_label +'</span>');
  739. this.stop_link = $('<span class="ad-slideshow-stop">'+ this.settings.stop_label +'</span>');
  740. this.countdown = $('<span class="ad-slideshow-countdown"></span>');
  741. this.controls = $('<div class="ad-slideshow-controls"></div>');
  742. this.controls.append(this.start_link).append(this.stop_link).append(this.countdown);
  743. this.countdown.hide();
  744. var context = this;
  745. this.start_link.click(
  746. function() {
  747. context.start();
  748. }
  749. );
  750. this.stop_link.click(
  751. function() {
  752. context.stop();
  753. }
  754. );
  755. $(document).keydown(
  756. function(e) {
  757. if(e.keyCode == 83) {
  758. // 's'
  759. if(context.running) {
  760. context.stop();
  761. } else {
  762. context.start();
  763. };
  764. };
  765. }
  766. );
  767. return this.controls;
  768. },
  769. disable: function() {
  770. this.enabled = false;
  771. this.stop();
  772. this.controls.hide();
  773. },
  774. enable: function() {
  775. this.enabled = true;
  776. this.controls.show();
  777. },
  778. toggle: function() {
  779. if(this.enabled) {
  780. this.disable();
  781. } else {
  782. this.enable();
  783. };
  784. },
  785. start: function() {
  786. if(this.running || !this.enabled) return false;
  787. var context = this;
  788. this.running = true;
  789. this.controls.addClass('ad-slideshow-running');
  790. this._next();
  791. this.fireCallback(this.settings.onStart);
  792. return true;
  793. },
  794. stop: function() {
  795. if(!this.running) return false;
  796. this.running = false;
  797. this.countdown.hide();
  798. this.controls.removeClass('ad-slideshow-running');
  799. clearInterval(this.countdown_interval);
  800. this.fireCallback(this.settings.onStop);
  801. return true;
  802. },
  803. _next: function() {
  804. var context = this;
  805. var pre = this.settings.countdown_prefix;
  806. var su = this.settings.countdown_sufix;
  807. clearInterval(context.countdown_interval);
  808. this.countdown.show().html(pre + (this.settings.speed / 1000) + su);
  809. var slide_timer = 0;
  810. this.countdown_interval = setInterval(
  811. function() {
  812. slide_timer += 1000;
  813. if(slide_timer >= context.settings.speed) {
  814. var whenNextIsShown = function() {
  815. // A check so the user hasn't stoped the slideshow during the
  816. // animation
  817. if(context.running) {
  818. context._next();
  819. };
  820. slide_timer = 0;
  821. };
  822. if(!context.nextimage_callback(whenNextIsShown)) {
  823. context.stop();
  824. };
  825. slide_timer = 0;
  826. };
  827. var sec = parseInt(context.countdown.text().replace(/[^0-9]/g, ''), 10);
  828. sec--;
  829. if(sec > 0) {
  830. context.countdown.html(pre + sec + su);
  831. };
  832. },
  833. 1000
  834. );
  835. },
  836. fireCallback: function(fn) {
  837. if($.isFunction(fn)) {
  838. fn.call(this);
  839. };
  840. }
  841. };
  842. })(jQuery);