photoswipe-ui-default.js 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861
  1. /*! PhotoSwipe Default UI - 4.1.1 - 2015-12-24
  2. * http://photoswipe.com
  3. * Copyright (c) 2015 Dmitry Semenov; */
  4. /**
  5. *
  6. * UI on top of main sliding area (caption, arrows, close button, etc.).
  7. * Built just using public methods/properties of PhotoSwipe.
  8. *
  9. */
  10. (function (root, factory) {
  11. if (typeof define === 'function' && define.amd) {
  12. define(factory);
  13. } else if (typeof exports === 'object') {
  14. module.exports = factory();
  15. } else {
  16. root.PhotoSwipeUI_Default = factory();
  17. }
  18. })(this, function () {
  19. 'use strict';
  20. var PhotoSwipeUI_Default =
  21. function(pswp, framework) {
  22. var ui = this;
  23. var _overlayUIUpdated = false,
  24. _controlsVisible = true,
  25. _fullscrenAPI,
  26. _controls,
  27. _captionContainer,
  28. _fakeCaptionContainer,
  29. _indexIndicator,
  30. _shareButton,
  31. _shareModal,
  32. _shareModalHidden = true,
  33. _initalCloseOnScrollValue,
  34. _isIdle,
  35. _listen,
  36. _loadingIndicator,
  37. _loadingIndicatorHidden,
  38. _loadingIndicatorTimeout,
  39. _galleryHasOneSlide,
  40. _options,
  41. _defaultUIOptions = {
  42. barsSize: {top:44, bottom:'auto'},
  43. closeElClasses: ['item', 'caption', 'zoom-wrap', 'ui', 'top-bar'],
  44. timeToIdle: 4000,
  45. timeToIdleOutside: 1000,
  46. loadingIndicatorDelay: 1000, // 2s
  47. addCaptionHTMLFn: function(item, captionEl /*, isFake */) {
  48. if(!item.title) {
  49. captionEl.children[0].innerHTML = '';
  50. return false;
  51. }
  52. captionEl.children[0].innerHTML = item.title;
  53. return true;
  54. },
  55. closeEl:true,
  56. captionEl: true,
  57. fullscreenEl: true,
  58. zoomEl: true,
  59. shareEl: true,
  60. counterEl: true,
  61. arrowEl: true,
  62. preloaderEl: true,
  63. tapToClose: false,
  64. tapToToggleControls: true,
  65. clickToCloseNonZoomable: true,
  66. shareButtons: [
  67. {id:'facebook', label:'Share on Facebook', url:'https://www.facebook.com/sharer/sharer.php?u={{url}}'},
  68. {id:'twitter', label:'Tweet', url:'https://twitter.com/intent/tweet?text={{text}}&url={{url}}'},
  69. {id:'pinterest', label:'Pin it', url:'http://www.pinterest.com/pin/create/button/'+
  70. '?url={{url}}&media={{image_url}}&description={{text}}'},
  71. {id:'download', label:'Download image', url:'{{raw_image_url}}', download:true}
  72. ],
  73. getImageURLForShare: function( /* shareButtonData */ ) {
  74. return pswp.currItem.src || '';
  75. },
  76. getPageURLForShare: function( /* shareButtonData */ ) {
  77. return window.location.href;
  78. },
  79. getTextForShare: function( /* shareButtonData */ ) {
  80. return pswp.currItem.title || '';
  81. },
  82. indexIndicatorSep: ' / ',
  83. fitControlsWidth: 1200
  84. },
  85. _blockControlsTap,
  86. _blockControlsTapTimeout;
  87. var _onControlsTap = function(e) {
  88. if(_blockControlsTap) {
  89. return true;
  90. }
  91. e = e || window.event;
  92. if(_options.timeToIdle && _options.mouseUsed && !_isIdle) {
  93. // reset idle timer
  94. _onIdleMouseMove();
  95. }
  96. var target = e.target || e.srcElement,
  97. uiElement,
  98. clickedClass = target.getAttribute('class') || '',
  99. found;
  100. for(var i = 0; i < _uiElements.length; i++) {
  101. uiElement = _uiElements[i];
  102. if(uiElement.onTap && clickedClass.indexOf('pswp__' + uiElement.name ) > -1 ) {
  103. uiElement.onTap();
  104. found = true;
  105. }
  106. }
  107. if(found) {
  108. if(e.stopPropagation) {
  109. e.stopPropagation();
  110. }
  111. _blockControlsTap = true;
  112. // Some versions of Android don't prevent ghost click event
  113. // when preventDefault() was called on touchstart and/or touchend.
  114. //
  115. // This happens on v4.3, 4.2, 4.1,
  116. // older versions strangely work correctly,
  117. // but just in case we add delay on all of them)
  118. var tapDelay = framework.features.isOldAndroid ? 600 : 30;
  119. _blockControlsTapTimeout = setTimeout(function() {
  120. _blockControlsTap = false;
  121. }, tapDelay);
  122. }
  123. },
  124. _fitControlsInViewport = function() {
  125. return !pswp.likelyTouchDevice || _options.mouseUsed || screen.width > _options.fitControlsWidth;
  126. },
  127. _togglePswpClass = function(el, cName, add) {
  128. framework[ (add ? 'add' : 'remove') + 'Class' ](el, 'pswp__' + cName);
  129. },
  130. // add class when there is just one item in the gallery
  131. // (by default it hides left/right arrows and 1ofX counter)
  132. _countNumItems = function() {
  133. var hasOneSlide = (_options.getNumItemsFn() === 1);
  134. if(hasOneSlide !== _galleryHasOneSlide) {
  135. _togglePswpClass(_controls, 'ui--one-slide', hasOneSlide);
  136. _galleryHasOneSlide = hasOneSlide;
  137. }
  138. },
  139. _toggleShareModalClass = function() {
  140. _togglePswpClass(_shareModal, 'share-modal--hidden', _shareModalHidden);
  141. },
  142. _toggleShareModal = function() {
  143. _shareModalHidden = !_shareModalHidden;
  144. if(!_shareModalHidden) {
  145. _toggleShareModalClass();
  146. setTimeout(function() {
  147. if(!_shareModalHidden) {
  148. framework.addClass(_shareModal, 'pswp__share-modal--fade-in');
  149. }
  150. }, 30);
  151. } else {
  152. framework.removeClass(_shareModal, 'pswp__share-modal--fade-in');
  153. setTimeout(function() {
  154. if(_shareModalHidden) {
  155. _toggleShareModalClass();
  156. }
  157. }, 300);
  158. }
  159. if(!_shareModalHidden) {
  160. _updateShareURLs();
  161. }
  162. return false;
  163. },
  164. _openWindowPopup = function(e) {
  165. e = e || window.event;
  166. var target = e.target || e.srcElement;
  167. pswp.shout('shareLinkClick', e, target);
  168. if(!target.href) {
  169. return false;
  170. }
  171. if( target.hasAttribute('download') ) {
  172. return true;
  173. }
  174. window.open(target.href, 'pswp_share', 'scrollbars=yes,resizable=yes,toolbar=no,'+
  175. 'location=yes,width=550,height=420,top=100,left=' +
  176. (window.screen ? Math.round(screen.width / 2 - 275) : 100) );
  177. if(!_shareModalHidden) {
  178. _toggleShareModal();
  179. }
  180. return false;
  181. },
  182. _updateShareURLs = function() {
  183. var shareButtonOut = '',
  184. shareButtonData,
  185. shareURL,
  186. image_url,
  187. page_url,
  188. share_text;
  189. for(var i = 0; i < _options.shareButtons.length; i++) {
  190. shareButtonData = _options.shareButtons[i];
  191. image_url = _options.getImageURLForShare(shareButtonData);
  192. page_url = _options.getPageURLForShare(shareButtonData);
  193. share_text = _options.getTextForShare(shareButtonData);
  194. shareURL = shareButtonData.url.replace('{{url}}', encodeURIComponent(page_url) )
  195. .replace('{{image_url}}', encodeURIComponent(image_url) )
  196. .replace('{{raw_image_url}}', image_url )
  197. .replace('{{text}}', encodeURIComponent(share_text) );
  198. shareButtonOut += '<a href="' + shareURL + '" target="_blank" '+
  199. 'class="pswp__share--' + shareButtonData.id + '"' +
  200. (shareButtonData.download ? 'download' : '') + '>' +
  201. shareButtonData.label + '</a>';
  202. if(_options.parseShareButtonOut) {
  203. shareButtonOut = _options.parseShareButtonOut(shareButtonData, shareButtonOut);
  204. }
  205. }
  206. _shareModal.children[0].innerHTML = shareButtonOut;
  207. _shareModal.children[0].onclick = _openWindowPopup;
  208. },
  209. _hasCloseClass = function(target) {
  210. for(var i = 0; i < _options.closeElClasses.length; i++) {
  211. if( framework.hasClass(target, 'pswp__' + _options.closeElClasses[i]) ) {
  212. return true;
  213. }
  214. }
  215. },
  216. _idleInterval,
  217. _idleTimer,
  218. _idleIncrement = 0,
  219. _onIdleMouseMove = function() {
  220. clearTimeout(_idleTimer);
  221. _idleIncrement = 0;
  222. if(_isIdle) {
  223. ui.setIdle(false);
  224. }
  225. },
  226. _onMouseLeaveWindow = function(e) {
  227. e = e ? e : window.event;
  228. var from = e.relatedTarget || e.toElement;
  229. if (!from || from.nodeName === 'HTML') {
  230. clearTimeout(_idleTimer);
  231. _idleTimer = setTimeout(function() {
  232. ui.setIdle(true);
  233. }, _options.timeToIdleOutside);
  234. }
  235. },
  236. _setupFullscreenAPI = function() {
  237. if(_options.fullscreenEl && !framework.features.isOldAndroid) {
  238. if(!_fullscrenAPI) {
  239. _fullscrenAPI = ui.getFullscreenAPI();
  240. }
  241. if(_fullscrenAPI) {
  242. framework.bind(document, _fullscrenAPI.eventK, ui.updateFullscreen);
  243. ui.updateFullscreen();
  244. framework.addClass(pswp.template, 'pswp--supports-fs');
  245. } else {
  246. framework.removeClass(pswp.template, 'pswp--supports-fs');
  247. }
  248. }
  249. },
  250. _setupLoadingIndicator = function() {
  251. // Setup loading indicator
  252. if(_options.preloaderEl) {
  253. _toggleLoadingIndicator(true);
  254. _listen('beforeChange', function() {
  255. clearTimeout(_loadingIndicatorTimeout);
  256. // display loading indicator with delay
  257. _loadingIndicatorTimeout = setTimeout(function() {
  258. if(pswp.currItem && pswp.currItem.loading) {
  259. if( !pswp.allowProgressiveImg() || (pswp.currItem.img && !pswp.currItem.img.naturalWidth) ) {
  260. // show preloader if progressive loading is not enabled,
  261. // or image width is not defined yet (because of slow connection)
  262. _toggleLoadingIndicator(false);
  263. // items-controller.js function allowProgressiveImg
  264. }
  265. } else {
  266. _toggleLoadingIndicator(true); // hide preloader
  267. }
  268. }, _options.loadingIndicatorDelay);
  269. });
  270. _listen('imageLoadComplete', function(index, item) {
  271. if(pswp.currItem === item) {
  272. _toggleLoadingIndicator(true);
  273. }
  274. });
  275. }
  276. },
  277. _toggleLoadingIndicator = function(hide) {
  278. if( _loadingIndicatorHidden !== hide ) {
  279. _togglePswpClass(_loadingIndicator, 'preloader--active', !hide);
  280. _loadingIndicatorHidden = hide;
  281. }
  282. },
  283. _applyNavBarGaps = function(item) {
  284. var gap = item.vGap;
  285. if( _fitControlsInViewport() ) {
  286. var bars = _options.barsSize;
  287. if(_options.captionEl && bars.bottom === 'auto') {
  288. if(!_fakeCaptionContainer) {
  289. _fakeCaptionContainer = framework.createEl('pswp__caption pswp__caption--fake');
  290. _fakeCaptionContainer.appendChild( framework.createEl('pswp__caption__center') );
  291. _controls.insertBefore(_fakeCaptionContainer, _captionContainer);
  292. framework.addClass(_controls, 'pswp__ui--fit');
  293. }
  294. if( _options.addCaptionHTMLFn(item, _fakeCaptionContainer, true) ) {
  295. var captionSize = _fakeCaptionContainer.clientHeight;
  296. gap.bottom = parseInt(captionSize,10) || 44;
  297. } else {
  298. gap.bottom = bars.top; // if no caption, set size of bottom gap to size of top
  299. }
  300. } else {
  301. gap.bottom = bars.bottom === 'auto' ? 0 : bars.bottom;
  302. }
  303. // height of top bar is static, no need to calculate it
  304. gap.top = bars.top;
  305. } else {
  306. gap.top = gap.bottom = 0;
  307. }
  308. },
  309. _setupIdle = function() {
  310. // Hide controls when mouse is used
  311. if(_options.timeToIdle) {
  312. _listen('mouseUsed', function() {
  313. framework.bind(document, 'mousemove', _onIdleMouseMove);
  314. framework.bind(document, 'mouseout', _onMouseLeaveWindow);
  315. _idleInterval = setInterval(function() {
  316. _idleIncrement++;
  317. if(_idleIncrement === 2) {
  318. ui.setIdle(true);
  319. }
  320. }, _options.timeToIdle / 2);
  321. });
  322. }
  323. },
  324. _setupHidingControlsDuringGestures = function() {
  325. // Hide controls on vertical drag
  326. _listen('onVerticalDrag', function(now) {
  327. if(_controlsVisible && now < 0.95) {
  328. ui.hideControls();
  329. } else if(!_controlsVisible && now >= 0.95) {
  330. ui.showControls();
  331. }
  332. });
  333. // Hide controls when pinching to close
  334. var pinchControlsHidden;
  335. _listen('onPinchClose' , function(now) {
  336. if(_controlsVisible && now < 0.9) {
  337. ui.hideControls();
  338. pinchControlsHidden = true;
  339. } else if(pinchControlsHidden && !_controlsVisible && now > 0.9) {
  340. ui.showControls();
  341. }
  342. });
  343. _listen('zoomGestureEnded', function() {
  344. pinchControlsHidden = false;
  345. if(pinchControlsHidden && !_controlsVisible) {
  346. ui.showControls();
  347. }
  348. });
  349. };
  350. var _uiElements = [
  351. {
  352. name: 'caption',
  353. option: 'captionEl',
  354. onInit: function(el) {
  355. _captionContainer = el;
  356. }
  357. },
  358. {
  359. name: 'share-modal',
  360. option: 'shareEl',
  361. onInit: function(el) {
  362. _shareModal = el;
  363. },
  364. onTap: function() {
  365. _toggleShareModal();
  366. }
  367. },
  368. {
  369. name: 'button--share',
  370. option: 'shareEl',
  371. onInit: function(el) {
  372. _shareButton = el;
  373. },
  374. onTap: function() {
  375. _toggleShareModal();
  376. }
  377. },
  378. {
  379. name: 'button--zoom',
  380. option: 'zoomEl',
  381. onTap: pswp.toggleDesktopZoom
  382. },
  383. {
  384. name: 'counter',
  385. option: 'counterEl',
  386. onInit: function(el) {
  387. _indexIndicator = el;
  388. }
  389. },
  390. {
  391. name: 'button--close',
  392. option: 'closeEl',
  393. onTap: pswp.close
  394. },
  395. {
  396. name: 'button--arrow--left',
  397. option: 'arrowEl',
  398. onTap: pswp.prev
  399. },
  400. {
  401. name: 'button--arrow--right',
  402. option: 'arrowEl',
  403. onTap: pswp.next
  404. },
  405. {
  406. name: 'button--fs',
  407. option: 'fullscreenEl',
  408. onTap: function() {
  409. if(_fullscrenAPI.isFullscreen()) {
  410. _fullscrenAPI.exit();
  411. } else {
  412. _fullscrenAPI.enter();
  413. }
  414. }
  415. },
  416. {
  417. name: 'preloader',
  418. option: 'preloaderEl',
  419. onInit: function(el) {
  420. _loadingIndicator = el;
  421. }
  422. }
  423. ];
  424. var _setupUIElements = function() {
  425. var item,
  426. classAttr,
  427. uiElement;
  428. var loopThroughChildElements = function(sChildren) {
  429. if(!sChildren) {
  430. return;
  431. }
  432. var l = sChildren.length;
  433. for(var i = 0; i < l; i++) {
  434. item = sChildren[i];
  435. classAttr = item.className;
  436. for(var a = 0; a < _uiElements.length; a++) {
  437. uiElement = _uiElements[a];
  438. if(classAttr.indexOf('pswp__' + uiElement.name) > -1 ) {
  439. if( _options[uiElement.option] ) { // if element is not disabled from options
  440. framework.removeClass(item, 'pswp__element--disabled');
  441. if(uiElement.onInit) {
  442. uiElement.onInit(item);
  443. }
  444. //item.style.display = 'block';
  445. } else {
  446. framework.addClass(item, 'pswp__element--disabled');
  447. //item.style.display = 'none';
  448. }
  449. }
  450. }
  451. }
  452. };
  453. loopThroughChildElements(_controls.children);
  454. var topBar = framework.getChildByClass(_controls, 'pswp__top-bar');
  455. if(topBar) {
  456. loopThroughChildElements( topBar.children );
  457. }
  458. };
  459. ui.init = function() {
  460. // extend options
  461. framework.extend(pswp.options, _defaultUIOptions, true);
  462. // create local link for fast access
  463. _options = pswp.options;
  464. // find pswp__ui element
  465. _controls = framework.getChildByClass(pswp.scrollWrap, 'pswp__ui');
  466. // create local link
  467. _listen = pswp.listen;
  468. _setupHidingControlsDuringGestures();
  469. // update controls when slides change
  470. _listen('beforeChange', ui.update);
  471. // toggle zoom on double-tap
  472. _listen('doubleTap', function(point) {
  473. var initialZoomLevel = pswp.currItem.initialZoomLevel;
  474. if(pswp.getZoomLevel() !== initialZoomLevel) {
  475. pswp.zoomTo(initialZoomLevel, point, 333);
  476. } else {
  477. pswp.zoomTo(_options.getDoubleTapZoom(false, pswp.currItem), point, 333);
  478. }
  479. });
  480. // Allow text selection in caption
  481. _listen('preventDragEvent', function(e, isDown, preventObj) {
  482. var t = e.target || e.srcElement;
  483. if(
  484. t &&
  485. t.getAttribute('class') && e.type.indexOf('mouse') > -1 &&
  486. ( t.getAttribute('class').indexOf('__caption') > 0 || (/(SMALL|STRONG|EM)/i).test(t.tagName) )
  487. ) {
  488. preventObj.prevent = false;
  489. }
  490. });
  491. // bind events for UI
  492. _listen('bindEvents', function() {
  493. framework.bind(_controls, 'pswpTap click', _onControlsTap);
  494. framework.bind(pswp.scrollWrap, 'pswpTap', ui.onGlobalTap);
  495. if(!pswp.likelyTouchDevice) {
  496. framework.bind(pswp.scrollWrap, 'mouseover', ui.onMouseOver);
  497. }
  498. });
  499. // unbind events for UI
  500. _listen('unbindEvents', function() {
  501. if(!_shareModalHidden) {
  502. _toggleShareModal();
  503. }
  504. if(_idleInterval) {
  505. clearInterval(_idleInterval);
  506. }
  507. framework.unbind(document, 'mouseout', _onMouseLeaveWindow);
  508. framework.unbind(document, 'mousemove', _onIdleMouseMove);
  509. framework.unbind(_controls, 'pswpTap click', _onControlsTap);
  510. framework.unbind(pswp.scrollWrap, 'pswpTap', ui.onGlobalTap);
  511. framework.unbind(pswp.scrollWrap, 'mouseover', ui.onMouseOver);
  512. if(_fullscrenAPI) {
  513. framework.unbind(document, _fullscrenAPI.eventK, ui.updateFullscreen);
  514. if(_fullscrenAPI.isFullscreen()) {
  515. _options.hideAnimationDuration = 0;
  516. _fullscrenAPI.exit();
  517. }
  518. _fullscrenAPI = null;
  519. }
  520. });
  521. // clean up things when gallery is destroyed
  522. _listen('destroy', function() {
  523. if(_options.captionEl) {
  524. if(_fakeCaptionContainer) {
  525. _controls.removeChild(_fakeCaptionContainer);
  526. }
  527. framework.removeClass(_captionContainer, 'pswp__caption--empty');
  528. }
  529. if(_shareModal) {
  530. _shareModal.children[0].onclick = null;
  531. }
  532. framework.removeClass(_controls, 'pswp__ui--over-close');
  533. framework.addClass( _controls, 'pswp__ui--hidden');
  534. ui.setIdle(false);
  535. });
  536. if(!_options.showAnimationDuration) {
  537. framework.removeClass( _controls, 'pswp__ui--hidden');
  538. }
  539. _listen('initialZoomIn', function() {
  540. if(_options.showAnimationDuration) {
  541. framework.removeClass( _controls, 'pswp__ui--hidden');
  542. }
  543. });
  544. _listen('initialZoomOut', function() {
  545. framework.addClass( _controls, 'pswp__ui--hidden');
  546. });
  547. _listen('parseVerticalMargin', _applyNavBarGaps);
  548. _setupUIElements();
  549. if(_options.shareEl && _shareButton && _shareModal) {
  550. _shareModalHidden = true;
  551. }
  552. _countNumItems();
  553. _setupIdle();
  554. _setupFullscreenAPI();
  555. _setupLoadingIndicator();
  556. };
  557. ui.setIdle = function(isIdle) {
  558. _isIdle = isIdle;
  559. _togglePswpClass(_controls, 'ui--idle', isIdle);
  560. };
  561. ui.update = function() {
  562. // Don't update UI if it's hidden
  563. if(_controlsVisible && pswp.currItem) {
  564. ui.updateIndexIndicator();
  565. if(_options.captionEl) {
  566. _options.addCaptionHTMLFn(pswp.currItem, _captionContainer);
  567. _togglePswpClass(_captionContainer, 'caption--empty', !pswp.currItem.title);
  568. }
  569. _overlayUIUpdated = true;
  570. } else {
  571. _overlayUIUpdated = false;
  572. }
  573. if(!_shareModalHidden) {
  574. _toggleShareModal();
  575. }
  576. _countNumItems();
  577. };
  578. ui.updateFullscreen = function(e) {
  579. if(e) {
  580. // some browsers change window scroll position during the fullscreen
  581. // so PhotoSwipe updates it just in case
  582. setTimeout(function() {
  583. pswp.setScrollOffset( 0, framework.getScrollY() );
  584. }, 50);
  585. }
  586. // toogle pswp--fs class on root element
  587. framework[ (_fullscrenAPI.isFullscreen() ? 'add' : 'remove') + 'Class' ](pswp.template, 'pswp--fs');
  588. };
  589. ui.updateIndexIndicator = function() {
  590. if(_options.counterEl) {
  591. _indexIndicator.innerHTML = (pswp.getCurrentIndex()+1) +
  592. _options.indexIndicatorSep +
  593. _options.getNumItemsFn();
  594. }
  595. };
  596. ui.onGlobalTap = function(e) {
  597. e = e || window.event;
  598. var target = e.target || e.srcElement;
  599. if(_blockControlsTap) {
  600. return;
  601. }
  602. if(e.detail && e.detail.pointerType === 'mouse') {
  603. // close gallery if clicked outside of the image
  604. if(_hasCloseClass(target)) {
  605. pswp.close();
  606. return;
  607. }
  608. if(framework.hasClass(target, 'pswp__img')) {
  609. if(pswp.getZoomLevel() === 1 && pswp.getZoomLevel() <= pswp.currItem.fitRatio) {
  610. if(_options.clickToCloseNonZoomable) {
  611. pswp.close();
  612. }
  613. } else {
  614. pswp.toggleDesktopZoom(e.detail.releasePoint);
  615. }
  616. }
  617. } else {
  618. // tap anywhere (except buttons) to toggle visibility of controls
  619. if(_options.tapToToggleControls) {
  620. if(_controlsVisible) {
  621. ui.hideControls();
  622. } else {
  623. ui.showControls();
  624. }
  625. }
  626. // tap to close gallery
  627. if(_options.tapToClose && (framework.hasClass(target, 'pswp__img') || _hasCloseClass(target)) ) {
  628. pswp.close();
  629. return;
  630. }
  631. }
  632. };
  633. ui.onMouseOver = function(e) {
  634. e = e || window.event;
  635. var target = e.target || e.srcElement;
  636. // add class when mouse is over an element that should close the gallery
  637. _togglePswpClass(_controls, 'ui--over-close', _hasCloseClass(target));
  638. };
  639. ui.hideControls = function() {
  640. framework.addClass(_controls,'pswp__ui--hidden');
  641. _controlsVisible = false;
  642. };
  643. ui.showControls = function() {
  644. _controlsVisible = true;
  645. if(!_overlayUIUpdated) {
  646. ui.update();
  647. }
  648. framework.removeClass(_controls,'pswp__ui--hidden');
  649. };
  650. ui.supportsFullscreen = function() {
  651. var d = document;
  652. return !!(d.exitFullscreen || d.mozCancelFullScreen || d.webkitExitFullscreen || d.msExitFullscreen);
  653. };
  654. ui.getFullscreenAPI = function() {
  655. var dE = document.documentElement,
  656. api,
  657. tF = 'fullscreenchange';
  658. if (dE.requestFullscreen) {
  659. api = {
  660. enterK: 'requestFullscreen',
  661. exitK: 'exitFullscreen',
  662. elementK: 'fullscreenElement',
  663. eventK: tF
  664. };
  665. } else if(dE.mozRequestFullScreen ) {
  666. api = {
  667. enterK: 'mozRequestFullScreen',
  668. exitK: 'mozCancelFullScreen',
  669. elementK: 'mozFullScreenElement',
  670. eventK: 'moz' + tF
  671. };
  672. } else if(dE.webkitRequestFullscreen) {
  673. api = {
  674. enterK: 'webkitRequestFullscreen',
  675. exitK: 'webkitExitFullscreen',
  676. elementK: 'webkitFullscreenElement',
  677. eventK: 'webkit' + tF
  678. };
  679. } else if(dE.msRequestFullscreen) {
  680. api = {
  681. enterK: 'msRequestFullscreen',
  682. exitK: 'msExitFullscreen',
  683. elementK: 'msFullscreenElement',
  684. eventK: 'MSFullscreenChange'
  685. };
  686. }
  687. if(api) {
  688. api.enter = function() {
  689. // disable close-on-scroll in fullscreen
  690. _initalCloseOnScrollValue = _options.closeOnScroll;
  691. _options.closeOnScroll = false;
  692. if(this.enterK === 'webkitRequestFullscreen') {
  693. pswp.template[this.enterK]( Element.ALLOW_KEYBOARD_INPUT );
  694. } else {
  695. return pswp.template[this.enterK]();
  696. }
  697. };
  698. api.exit = function() {
  699. _options.closeOnScroll = _initalCloseOnScrollValue;
  700. return document[this.exitK]();
  701. };
  702. api.isFullscreen = function() { return document[this.elementK]; };
  703. }
  704. return api;
  705. };
  706. };
  707. return PhotoSwipeUI_Default;
  708. });