Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.
 
 
 
 

294 řádky
9.5 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. first.find('.image-description').appendTo(this.wrapper);
  65. this.isLoaded = false;
  66. img.one('load', () => {
  67. this.section.addClass('loaded');
  68. first.removeClass('loading');
  69. });
  70. if (this.items.length > 1) {
  71. a.append($('<span class="btn has-icon icon-right icon-galerie" />').text(this.items.length + ' Bilder'));
  72. first.find('.image-description').hide();
  73. }
  74. if (this.section.data('type') === 'single-image') {
  75. const ratio = (Math.round(first.data('height') / first.data('width') * 1000) / 10) + '%';
  76. a.css('padding-top', ratio);
  77. first.find('.copyright').appendTo(a).css('max-width', ratio);
  78. }
  79. this.section.closest('.main-col').addClass('clearfix');
  80. }
  81. initThumbs() {
  82. this.items.each(function (i) {
  83. const item = $(this);
  84. $('<a href="' + item.data('full') + '" />').attr('tabindex', '-1').attr('data-index', i).appendTo(item);
  85. })
  86. }
  87. initMasonry() {
  88. this.items.each(function (i) {
  89. const item = $(this);
  90. const a = $('<a href="' + item.data('full') + '" />').attr('data-index', i).appendTo(item);
  91. a.css('padding-top', Math.round(item.data('height') / item.data('width') * 10000) / 100 + '%');
  92. })
  93. const btnText = window.ihk.translations.loadMoreImages;
  94. new Masonry(
  95. this.wrapper,
  96. btnText,
  97. [
  98. {minWidth: 0, batchSize: 6},
  99. {minWidth: 0, batchSize: 6},
  100. {minWidth: 567, batchSize: 9},
  101. {minWidth: 1000, batchSize: 12}
  102. ],
  103. 'primary-light');
  104. }
  105. initLoading() {
  106. const imagesPerPage = this.section.data('per-page');
  107. const buttonWrapper = $('<div class="button-wrapper" />').appendTo(this.section);
  108. const buttonText = window.ihk.translations.loadMoreImages;
  109. if (this.items.length > imagesPerPage) {
  110. this.moreButton = $('<button href="#" class="btn primary-light btn-regular icon-right icon-laden" />').text(buttonText).appendTo(buttonWrapper);
  111. }
  112. if (this.moreButton) {
  113. this.moreButton.on('click', (e) => {
  114. e.preventDefault();
  115. this.currentPage++;
  116. this.loadThumbs();
  117. })
  118. }
  119. }
  120. initTabIndex() {
  121. const focusable = 'a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, *[tabindex], *[contenteditable]';
  122. const unfocusable = '[tabindex=-1], [disabled], :hidden';
  123. const prevFocusable = this.section.prevAll().find(focusable).not(unfocusable).last();
  124. const nextFocusable = this.section.nextAll().find(focusable).not(unfocusable).first();
  125. this.items.find('a').focus((e) => {
  126. const focusElement = $(e.currentTarget);
  127. const currentIndex = parseInt(focusElement.attr('data-index'));
  128. prevFocusable.attr('tabindex', 1);
  129. this.items.eq(currentIndex - 1).find('a').attr('tabindex', 2);
  130. focusElement.attr('tabindex', 3);
  131. this.items.eq(currentIndex + 1).find('a').attr('tabindex', 4);
  132. nextFocusable.attr('tabindex', 5);
  133. })
  134. this.items.find('a').on('focusout', () => {
  135. this.items.find('a').removeAttr('tabindex');
  136. prevFocusable.removeAttr('tabindex');
  137. nextFocusable.removeAttr('tabindex');
  138. })
  139. nextFocusable.focus(() => {
  140. this.items.find('a').attr('tabindex', -1);
  141. this.visibleItems[this.visibleItems.length - 1].find('a').attr('tabindex', 0);
  142. })
  143. }
  144. loadThumbs() {
  145. const pp = this.section.data('per-page');
  146. const first = this.currentPage * pp;
  147. const last = first + pp < this.items.length ? first + pp : this.items.length;
  148. //const newItems = [];
  149. for (let i = first; i < last; i++) {
  150. const item = this.items.eq(i).addClass('loading');
  151. const img = $('<img />').one('load', function () {
  152. item.removeClass('loading').addClass('loaded');
  153. });
  154. img.attr('src', (this.section.data('type') === 'masonry' ? item.data('full') : item.data('thumb'))).appendTo(item.find('a'));
  155. img.attr('alt', item.attr('alt')).attr('title', item.attr("title")).appendTo(item.find('a'));
  156. this.visibleItems.push(item);
  157. item.find('a').removeAttr('tabindex');
  158. //newItems.push(item);
  159. }
  160. if ( this.moreButton && last == this.items.length) {
  161. this.moreButton.hide();
  162. }
  163. }
  164. initPopup() {
  165. this.popup = $('<div class="gallery-popup" tabindex="-1" />').appendTo($('body'));
  166. const slides = $('<div class="slider" />').appendTo(this.popup);
  167. const closer = $('<button class="closer" />').prependTo(this.popup);
  168. if (this.items.length === 1) {
  169. slides.addClass('single-slide');
  170. }
  171. this.items.each((i, element) => {
  172. const item = $(element);
  173. const slide = $('<div class="slide preload" />').appendTo(slides);
  174. const imgElement = $('<div class="image-box" />').attr('data-src', item.data('full')).attr("title", item.attr("title"));
  175. if (this.section.data("render-download") === true) {
  176. imgElement.attr('data-download', item.data('download'));
  177. }
  178. imgElement.appendTo(slide);
  179. if (item.find('span').length > 0) {
  180. $('<div class="text-box" />').appendTo(slide).append(item.find('span').clone());
  181. }
  182. })
  183. closer.on('click', (e) => {
  184. e.preventDefault();
  185. this.popup.removeClass('open');
  186. this.popup.find('button, a').attr('tabindex', -1);
  187. this.unbindPopupKeys();
  188. this.toggleContentScroll();
  189. })
  190. this.slider = new Slider(slides);
  191. this.popup.find('button, a').attr('tabindex', -1);
  192. this.wrapper.on('click', 'a', (e) => {
  193. e.preventDefault();
  194. const index = parseInt($(e.currentTarget).attr('data-index'));
  195. this.popup.addClass('open');
  196. this.bindPopupKeys();
  197. this.popup.find('button, a').attr('tabindex', 0);
  198. this.popup.focus();
  199. this.slider.goTo(index, false);
  200. this.toggleContentScroll();
  201. });
  202. if (this.section.data('render-download')) {
  203. const download = $('<a href="#" download class="download" />').prependTo(this.popup);
  204. $(download).attr('href', this.slider.slides.eq(this.slider.currentSlide).find('.image-box').attr('data-download'));
  205. }
  206. slides.on('slide-change', () => {
  207. this.slider.loadImage();
  208. const download = this.popup.find(".download");
  209. if (download.length) {
  210. $(download).attr('href', this.slider.slides.eq(this.slider.currentSlide).find('.image-box').attr('data-download'));
  211. }
  212. })
  213. }
  214. bindPopupKeys() {
  215. $('body').on('keydown.gallery', (e) => {
  216. if (e.keyCode === 27) {
  217. this.popup.find('.closer').trigger('click');
  218. } else if (e.keyCode === 37) {
  219. this.slider.onPrev();
  220. } else if (e.keyCode === 39) {
  221. this.slider.onNext();
  222. }
  223. })
  224. }
  225. unbindPopupKeys() {
  226. $('body').off('keydown.gallery');
  227. }
  228. toggleContentScroll() {
  229. const body = $('body');
  230. const win = $(window);
  231. if (this.popup.hasClass('open')) {
  232. body.css('top', (win.scrollTop() * -1) + 'px').addClass('nav-open');
  233. } else {
  234. const top = Math.abs(parseInt(body.css('top')));
  235. body.removeClass('nav-open').removeAttr('style');
  236. win.scrollTop(top);
  237. }
  238. }
  239. }
  240. export default IHKGallery;
  241. $('body').on('ihk-init dynamic-component-loaded gfi-dynamic-init', () => {
  242. $('.gallery:not(.initiated)').each(function () {
  243. new IHKGallery($(this));
  244. });
  245. });