25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.
 
 
 
 

367 satır
11 KiB

  1. // import $ from 'jquery';
  2. import Slider from './slider';
  3. import Masonry from "./masonry";
  4. const $ = require('jquery');
  5. class Gallery {
  6. constructor(section) {
  7. this.section = section.addClass('initiated');
  8. this.wrapper = section.find('.gallery-wrapper');
  9. this.items = this.wrapper.children('.image');
  10. this.gridInitialized = false;
  11. this.currentPage = -1;
  12. this.visibleItems = [];
  13. this.type = section.attr('data-type');
  14. this.initPopup();
  15. if (this.type === 'first-image' || this.type === 'single-image') {
  16. this.initSingleThumb();
  17. } else if (this.type === 'grid') {
  18. this.initThumbs();
  19. this.initLoading();
  20. } else if (this.type === 'masonry') {
  21. this.initMasonry();
  22. }
  23. this.initScrollCheck();
  24. $('body').on('lazyload-gallery-image', () => {
  25. this.lazyLoadSingleImages.call(this);
  26. })
  27. }
  28. initScrollCheck() {
  29. window.addEventListener("scroll", () => {
  30. window.requestAnimationFrame(() => {
  31. this.scrollCheck();
  32. })
  33. }, {passive: true});
  34. this.scrollCheck();
  35. }
  36. scrollCheck() {
  37. const w = $(window);
  38. if (this.type === 'first-image' || this.type === 'single-image') {
  39. if (!this.isLoaded && w.scrollTop() + w.height() + 100 > this.section.offset().top) {
  40. const thumb = this.items.first();
  41. thumb.find('img').attr('src', thumb.data(this.type === 'first-image' ? 'thumb' : 'full'));
  42. this.isLoaded = true;
  43. }
  44. } else if (this.type === 'grid') {
  45. if (!this.gridInitialized && this.items.length > this.visibleItems.length && w.scrollTop() + w.height() + 300 > ($(this.section).offset().top + $(this.section).height())) {
  46. this.currentPage++;
  47. this.loadThumbs();
  48. this.gridInitialized = true;
  49. }
  50. }
  51. }
  52. lazyLoadSingleImages() {
  53. if (this.type === 'first-image' || this.type === 'single-image') {
  54. if (!this.isLoaded) {
  55. const thumb = this.items.first();
  56. thumb.find('img').attr('src', thumb.data(this.type === 'first-image' ? 'thumb' : 'full'));
  57. this.isLoaded = true;
  58. }
  59. }
  60. }
  61. initSingleThumb() {
  62. const first = this.items.first();
  63. const a = $('<a href="' + first.data('full') + '" />').attr('data-index', 0).appendTo(first);
  64. const img = $('<img alt="' + first.attr("alt") + '" />').appendTo(a);
  65. first.find('.image-description').appendTo(this.wrapper);
  66. this.isLoaded = false;
  67. img.one('load', () => {
  68. this.section.addClass('loaded');
  69. });
  70. if (this.items.length > 1) {
  71. a.append($('<span class="btn has-icon 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('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(this.wrapper, btnText, [
  95. {minWidth: 0, batchSize: 6},
  96. {minWidth: 0, batchSize: 6},
  97. {minWidth: 567, batchSize: 9},
  98. {minWidth: 1000, batchSize: 12}
  99. ]);
  100. }
  101. initLoading() {
  102. const imagesPerPage = this.section.data('per-page');
  103. const buttonWrapper = $('<div class="button-wrapper" />').appendTo(this.section);
  104. const buttonText = window.ihk.translations.loadMoreImages;
  105. if (this.items.length > imagesPerPage) {
  106. this.moreButton = $('<a href="#" class="btn load-more has-icon icon-laden icon-reload" />').text(buttonText).appendTo(buttonWrapper);
  107. }
  108. if (this.moreButton) {
  109. this.moreButton.on('click', (e) => {
  110. e.preventDefault();
  111. this.currentPage++;
  112. this.loadThumbs();
  113. })
  114. }
  115. }
  116. initTabIndex() {
  117. const focusable = 'a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, *[tabindex], *[contenteditable]';
  118. const unfocusable = '[tabindex=-1], [disabled], :hidden';
  119. const prevFocusable = this.section.prevAll().find(focusable).not(unfocusable).last();
  120. const nextFocusable = this.section.nextAll().find(focusable).not(unfocusable).first();
  121. this.items.find('a').focus((e) => {
  122. const focusElement = $(e.currentTarget);
  123. const currentIndex = parseInt(focusElement.attr('data-index'));
  124. prevFocusable.attr('tabindex', 1);
  125. this.items.eq(currentIndex - 1).find('a').attr('tabindex', 2);
  126. focusElement.attr('tabindex', 3);
  127. this.items.eq(currentIndex + 1).find('a').attr('tabindex', 4);
  128. nextFocusable.attr('tabindex', 5);
  129. })
  130. this.items.find('a').on('focusout', () => {
  131. this.items.find('a').removeAttr('tabindex');
  132. prevFocusable.removeAttr('tabindex');
  133. nextFocusable.removeAttr('tabindex');
  134. })
  135. nextFocusable.focus(() => {
  136. this.items.find('a').attr('tabindex', -1);
  137. this.visibleItems[this.visibleItems.length - 1].find('a').attr('tabindex', 0);
  138. })
  139. }
  140. loadThumbs() {
  141. const pp = this.section.data('per-page');
  142. const first = this.currentPage * pp;
  143. const last = first + pp < this.items.length ? first + pp : this.items.length;
  144. //const newItems = [];
  145. for (let i = first; i < last; i++) {
  146. const item = this.items.eq(i).addClass('loading');
  147. const img = $('<img />').one('load', function () {
  148. item.removeClass('loading').addClass('loaded');
  149. });
  150. img.attr('src', (this.section.data('type') === 'masonry' ? item.data('full') : item.data('thumb'))).appendTo(item.find('a'));
  151. img.attr('alt', item.attr('alt')).attr('title', item.attr("title")).appendTo(item.find('a'));
  152. this.visibleItems.push(item);
  153. //newItems.push(item);
  154. }
  155. if ( this.moreButton && last == this.items.length) {
  156. this.moreButton.hide();
  157. }
  158. /*
  159. if (this.cols) {
  160. this.addToCols(newItems);
  161. }
  162. */
  163. }
  164. /*
  165. handleResize() {
  166. this.width = this.section.outerWidth();
  167. this.timer = null;
  168. $(window).on('resize', () => {
  169. if (this.timer) {
  170. clearTimeout(this.timer);
  171. }
  172. setTimeout(() => {
  173. this.resetCols();
  174. },200);
  175. })
  176. }
  177. resetCols() {
  178. const w = this.section.width();
  179. let cols = 2;
  180. if (w > 500) { cols = 3 }
  181. if (w > 1000) { cols = 4 }
  182. if (this.cols && cols === this.cols.length) {
  183. return;
  184. }
  185. $.each(this.cols, function () {
  186. this.col.remove();
  187. })
  188. this.cols = [];
  189. this.section.attr('data-cols', cols);
  190. for (let i = 0; i < cols; i++) {
  191. const col = $('<div class="column" />').appendTo(this.wrapper);
  192. this.cols.push({
  193. col: col,
  194. index: i,
  195. height: 0
  196. })
  197. }
  198. this.addToCols(this.visibleItems);
  199. }
  200. addToCols(items) {
  201. $.each(items, (i, element) => {
  202. const item = $(element);
  203. this.cols[0].col.append(item);
  204. this.cols[0].height = Math.round(item.position().top + item.outerHeight());
  205. this.cols.sort( this.compareCols );
  206. })
  207. }
  208. compareCols(a, b) {
  209. if (a.height < b.height) {
  210. return -1;
  211. }
  212. else if (a.height > b.height) {
  213. return 1;
  214. }
  215. else {
  216. if (a.index < b.index) {
  217. return -1;
  218. }
  219. if (a.index > b.index) {
  220. return 1;
  221. }
  222. }
  223. return 0;
  224. }
  225. */
  226. initPopup() {
  227. this.popup = $('<div class="gallery-popup" tabindex="-1" />').appendTo($('body'));
  228. const slides = $('<div class="slider" />').appendTo(this.popup);
  229. const closer = $('<button class="closer" />').prependTo(this.popup);
  230. if (this.items.length === 1) {
  231. slides.addClass('single-slide');
  232. }
  233. this.items.each((i, element) => {
  234. const item = $(element);
  235. const slide = $('<div class="slide preload" />').appendTo(slides);
  236. const imgElement = $('<div class="image-box" />').attr('data-src', item.data('full')).attr("title", item.attr("title"));
  237. if (this.section.data("render-download") === true) {
  238. imgElement.attr('data-download', item.data('download'));
  239. }
  240. imgElement.appendTo(slide);
  241. if (item.find('span').length > 0) {
  242. $('<div class="text-box" />').appendTo(slide).append(item.find('span').clone());
  243. }
  244. })
  245. closer.on('click', (e) => {
  246. e.preventDefault();
  247. this.popup.removeClass('open');
  248. this.popup.find('button, a').attr('tabindex', -1);
  249. this.unbindPopupKeys();
  250. this.toggleContentScroll();
  251. })
  252. this.slider = new Slider(slides);
  253. this.popup.find('button, a').attr('tabindex', -1);
  254. this.wrapper.on('click', 'a', (e) => {
  255. e.preventDefault();
  256. const index = parseInt($(e.currentTarget).attr('data-index'));
  257. this.popup.addClass('open');
  258. this.bindPopupKeys();
  259. this.popup.find('button, a').attr('tabindex', 0);
  260. this.popup.focus();
  261. this.slider.goTo(index, false);
  262. this.toggleContentScroll();
  263. });
  264. if (this.section.data('render-download')) {
  265. const download = $('<a href="#" download class="download" />').prependTo(this.popup);
  266. $(download).attr('href', this.slider.slides.eq(this.slider.currentSlide).find('.image-box').attr('data-download'));
  267. }
  268. slides.on('slide-change', () => {
  269. this.slider.loadImage();
  270. const download = this.popup.find(".download");
  271. if (download.length) {
  272. $(download).attr('href', this.slider.slides.eq(this.slider.currentSlide).find('.image-box').attr('data-download'));
  273. }
  274. })
  275. }
  276. bindPopupKeys() {
  277. $('body').on('keydown.gallery', (e) => {
  278. if (e.keyCode === 27) {
  279. this.popup.find('.closer').trigger('click');
  280. } else if (e.keyCode === 37) {
  281. this.slider.onPrev();
  282. } else if (e.keyCode === 39) {
  283. this.slider.onNext();
  284. }
  285. })
  286. }
  287. unbindPopupKeys() {
  288. $('body').off('keydown.gallery');
  289. }
  290. toggleContentScroll() {
  291. const body = $('body');
  292. const win = $(window);
  293. if (this.popup.hasClass('open')) {
  294. body.css('top', (win.scrollTop() * -1) + 'px').addClass('nav-open');
  295. } else {
  296. const top = Math.abs(parseInt(body.css('top')));
  297. body.removeClass('nav-open').removeAttr('style');
  298. win.scrollTop(top);
  299. }
  300. }
  301. }
  302. $('body').on('ihk-init dynamic-component-loaded gfi-dynamic-init', function () {
  303. $('.gallery:not(.initiated)').each(function () {
  304. new Gallery($(this));
  305. });
  306. });