Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 
 

306 lignes
10 KiB

  1. import $ from 'jquery';
  2. import Slider from "../../sections/slider/slider";
  3. import Masonry from "../../_global/scripts/masonry";
  4. class IHKGallery {
  5. constructor(section) {
  6. this.section = section.addClass('initiated');
  7. this.wrapper = section.find('.gallery-wrapper');
  8. this.items = this.wrapper.children('.image');
  9. this.gridInitialized = false;
  10. this.currentPage = -1;
  11. this.visibleItems = [];
  12. this.type = section.attr('data-type');
  13. this.initPopup();
  14. if (this.type === 'first-image' || this.type === 'single-image') {
  15. this.initSingleThumb();
  16. } else if (this.type === 'grid') {
  17. this.initThumbs();
  18. this.initLoading();
  19. } else if (this.type === 'masonry') {
  20. this.initMasonry();
  21. }
  22. this.initScrollCheck();
  23. $('body').on('lazyload-gallery-image', () => {
  24. this.lazyLoadSingleImages.call(this);
  25. })
  26. }
  27. initScrollCheck() {
  28. window.addEventListener("scroll", () => {
  29. window.requestAnimationFrame(() => {
  30. this.scrollCheck();
  31. })
  32. }, {passive: true});
  33. this.scrollCheck();
  34. }
  35. scrollCheck() {
  36. const w = $(window);
  37. if (this.type === 'first-image' || this.type === 'single-image') {
  38. if (!this.isLoaded && w.scrollTop() + w.height() + 100 > this.section.offset().top) {
  39. const thumb = this.items.first();
  40. thumb.find('img').attr('src', thumb.data(this.type === 'first-image' ? 'thumb' : 'full'));
  41. this.isLoaded = true;
  42. }
  43. } else if (this.type === 'grid') {
  44. if (!this.gridInitialized && this.items.length > this.visibleItems.length && w.scrollTop() + w.height() + 300 > ($(this.section).offset().top + $(this.section).height())) {
  45. this.currentPage++;
  46. this.loadThumbs();
  47. this.gridInitialized = true;
  48. }
  49. }
  50. }
  51. lazyLoadSingleImages() {
  52. if (this.type === 'first-image' || this.type === 'single-image') {
  53. if (!this.isLoaded) {
  54. const thumb = this.items.first();
  55. thumb.find('img').attr('src', thumb.data(this.type === 'first-image' ? 'thumb' : 'full'));
  56. this.isLoaded = true;
  57. }
  58. }
  59. }
  60. initSingleThumb() {
  61. const first = this.items.first().addClass('loading');
  62. const a = $('<a href="' + first.data('full') + '" />').attr('data-index', 0).appendTo(first);
  63. const img = $('<img alt="' + first.attr("alt") + '" />').appendTo(a);
  64. if (first.data('copyright')) {
  65. $('<span class="copyright">' + first.data('copyright') + '</span>').appendTo(a);
  66. }
  67. first.find('.image-description').appendTo(this.wrapper);
  68. this.isLoaded = false;
  69. img.one('load', () => {
  70. this.section.addClass('loaded');
  71. first.removeClass('loading');
  72. });
  73. if (this.items.length > 1) {
  74. a.append($('<span class="btn has-icon icon-right icon-galerie" />').text(this.items.length + ' Bilder'));
  75. first.find('.image-description').hide();
  76. }
  77. if (this.section.data('type') === 'single-image') {
  78. const ratio = (Math.round(first.data('height') / first.data('width') * 1000) / 10) + '%';
  79. a.css('padding-top', ratio);
  80. first.find('.copyright').appendTo(a).css('max-width', ratio);
  81. }
  82. this.section.closest('.main-col').addClass('clearfix');
  83. }
  84. initThumbs() {
  85. this.items.each(function (i) {
  86. const item = $(this);
  87. $('<a href="' + item.data('full') + '" />').attr('tabindex', '-1').attr('data-index', i).appendTo(item);
  88. })
  89. }
  90. initMasonry() {
  91. this.items.each(function (i) {
  92. const item = $(this);
  93. const a = $('<a href="' + item.data('full') + '" />').attr('data-index', i).appendTo(item);
  94. a.css('padding-top', Math.round(item.data('height') / item.data('width') * 10000) / 100 + '%');
  95. // Copyright für Masonry-Element vorbereiten
  96. if (item.data('copyright')) {
  97. a.append('<span class="copyright">' + item.data('copyright') + '</span>');
  98. }
  99. })
  100. const btnText = window.ihk.translations.loadMoreImages;
  101. new Masonry(
  102. this.wrapper,
  103. btnText,
  104. [
  105. {minWidth: 0, batchSize: 6},
  106. {minWidth: 0, batchSize: 6},
  107. {minWidth: 567, batchSize: 9},
  108. {minWidth: 1000, batchSize: 12}
  109. ],
  110. 'primary-light');
  111. }
  112. initLoading() {
  113. const imagesPerPage = this.section.data('per-page');
  114. const buttonWrapper = $('<div class="button-wrapper" />').appendTo(this.section);
  115. const buttonText = window.ihk.translations.loadMoreImages;
  116. if (this.items.length > imagesPerPage) {
  117. this.moreButton = $('<button href="#" class="btn primary-light btn-regular icon-right icon-laden" />').text(buttonText).appendTo(buttonWrapper);
  118. }
  119. if (this.moreButton) {
  120. this.moreButton.on('click', (e) => {
  121. e.preventDefault();
  122. this.currentPage++;
  123. this.loadThumbs();
  124. })
  125. }
  126. }
  127. initTabIndex() {
  128. const focusable = 'a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, *[tabindex], *[contenteditable]';
  129. const unfocusable = '[tabindex=-1], [disabled], :hidden';
  130. const prevFocusable = this.section.prevAll().find(focusable).not(unfocusable).last();
  131. const nextFocusable = this.section.nextAll().find(focusable).not(unfocusable).first();
  132. this.items.find('a').focus((e) => {
  133. const focusElement = $(e.currentTarget);
  134. const currentIndex = parseInt(focusElement.attr('data-index'));
  135. prevFocusable.attr('tabindex', 1);
  136. this.items.eq(currentIndex - 1).find('a').attr('tabindex', 2);
  137. focusElement.attr('tabindex', 3);
  138. this.items.eq(currentIndex + 1).find('a').attr('tabindex', 4);
  139. nextFocusable.attr('tabindex', 5);
  140. })
  141. this.items.find('a').on('focusout', () => {
  142. this.items.find('a').removeAttr('tabindex');
  143. prevFocusable.removeAttr('tabindex');
  144. nextFocusable.removeAttr('tabindex');
  145. })
  146. nextFocusable.focus(() => {
  147. this.items.find('a').attr('tabindex', -1);
  148. this.visibleItems[this.visibleItems.length - 1].find('a').attr('tabindex', 0);
  149. })
  150. }
  151. loadThumbs() {
  152. const pp = this.section.data('per-page');
  153. const first = this.currentPage * pp;
  154. const last = first + pp < this.items.length ? first + pp : this.items.length;
  155. //const newItems = [];
  156. for (let i = first; i < last; i++) {
  157. const item = this.items.eq(i).addClass('loading');
  158. const img = $('<img />').one('load', function () {
  159. item.removeClass('loading').addClass('loaded');
  160. });
  161. img.attr('src', (this.section.data('type') === 'masonry' ? item.data('full') : item.data('thumb'))).appendTo(item.find('a'));
  162. img.attr('alt', item.attr('alt')).attr('title', item.attr("title"));
  163. if (item.data('copyright')) {
  164. $('<span class="copyright">').html(item.data('copyright')).appendTo(item.find('a'));
  165. }
  166. this.visibleItems.push(item);
  167. item.find('a').removeAttr('tabindex');
  168. //newItems.push(item);
  169. }
  170. if ( this.moreButton && last === this.items.length) {
  171. this.moreButton.hide();
  172. }
  173. }
  174. initPopup() {
  175. this.popup = $('<div class="gallery-popup" tabindex="-1" />').appendTo($('body'));
  176. const slides = $('<div class="slider" />').appendTo(this.popup);
  177. const closer = $('<button class="closer" />').prependTo(this.popup);
  178. if (this.items.length === 1) {
  179. slides.addClass('single-slide');
  180. }
  181. this.items.each((i, element) => {
  182. const item = $(element);
  183. const slide = $('<div class="slide preload" />').appendTo(slides);
  184. const imgElement = $('<div class="image-box" />').attr('data-src', item.data('full')).attr('data-copyright', item.data('copyright')).attr("title", item.attr("title"));
  185. if (this.section.data("render-download") === true) {
  186. imgElement.attr('data-download', item.data('download'));
  187. }
  188. imgElement.appendTo(slide);
  189. if (item.find('span').length > 0) {
  190. $('<div class="text-box" />').appendTo(slide).append(item.find('span.image-description,span.copyright').clone());
  191. }
  192. })
  193. closer.on('click', (e) => {
  194. e.preventDefault();
  195. this.popup.removeClass('open');
  196. this.popup.find('button, a').attr('tabindex', -1);
  197. this.unbindPopupKeys();
  198. this.toggleContentScroll();
  199. })
  200. this.slider = new Slider(slides);
  201. this.popup.find('button, a').attr('tabindex', -1);
  202. this.wrapper.on('click', 'a', (e) => {
  203. e.preventDefault();
  204. const index = parseInt($(e.currentTarget).attr('data-index'));
  205. this.popup.addClass('open');
  206. this.bindPopupKeys();
  207. this.popup.find('button, a').attr('tabindex', 0);
  208. this.popup.focus();
  209. this.slider.goTo(index, false);
  210. this.toggleContentScroll();
  211. });
  212. if (this.section.data('render-download')) {
  213. const download = $('<a href="#" download class="download" />').prependTo(this.popup);
  214. $(download).attr('href', this.slider.slides.eq(this.slider.currentSlide).find('.image-box').attr('data-download'));
  215. }
  216. slides.on('slide-change', () => {
  217. this.slider.loadImage();
  218. const download = this.popup.find(".download");
  219. if (download.length) {
  220. $(download).attr('href', this.slider.slides.eq(this.slider.currentSlide).find('.image-box').attr('data-download'));
  221. }
  222. })
  223. }
  224. bindPopupKeys() {
  225. $('body').on('keydown.gallery', (e) => {
  226. if (e.keyCode === 27) {
  227. this.popup.find('.closer').trigger('click');
  228. } else if (e.keyCode === 37) {
  229. this.slider.onPrev();
  230. } else if (e.keyCode === 39) {
  231. this.slider.onNext();
  232. }
  233. })
  234. }
  235. unbindPopupKeys() {
  236. $('body').off('keydown.gallery');
  237. }
  238. toggleContentScroll() {
  239. const body = $('body');
  240. const win = $(window);
  241. if (this.popup.hasClass('open')) {
  242. body.css('top', (win.scrollTop() * -1) + 'px').addClass('nav-open');
  243. } else {
  244. const top = Math.abs(parseInt(body.css('top')));
  245. body.removeClass('nav-open').removeAttr('style');
  246. win.scrollTop(top);
  247. }
  248. }
  249. }
  250. export default IHKGallery;
  251. $('body').on('ihk-init dynamic-component-loaded gfi-dynamic-init', () => {
  252. $('.gallery:not(.initiated)').each(function () {
  253. new IHKGallery($(this));
  254. });
  255. });