Parcourir la source

Set cover/hide actions

Innocenty Enikeew il y a 10 ans
Parent
commit
c07ae8cc5b

BIN
assets/FontAwesome.otf


+ 6 - 0
assets/default-skin.css

@@ -481,3 +481,9 @@ a.pswp__share--download:hover {
 
 .pswp--minimal--dark .pswp__top-bar {
   background: none; }
+
+
+/* Enikesha's customization */
+.pswp__button--fa {
+  background: none;
+  color: white; }

Fichier diff supprimé car celui-ci est trop grand
+ 3 - 0
assets/font-awesome.min.css


BIN
assets/fontawesome-webfont.eot


Fichier diff supprimé car celui-ci est trop grand
+ 196 - 0
assets/fontawesome-webfont.svg


BIN
assets/fontawesome-webfont.ttf


BIN
assets/fontawesome-webfont.woff


BIN
assets/fontawesome-webfont.woff2


+ 875 - 0
assets/photoswipe-ui-default.js

@@ -0,0 +1,875 @@
+/*! PhotoSwipe Default UI - 4.1.0 - 2015-07-11
+* http://photoswipe.com
+* Copyright (c) 2015 Dmitry Semenov; */
+/**
+*
+* UI on top of main sliding area (caption, arrows, close button, etc.).
+* Built just using public methods/properties of PhotoSwipe.
+* 
+*/
+(function (root, factory) { 
+	if (typeof define === 'function' && define.amd) {
+		define(factory);
+	} else if (typeof exports === 'object') {
+		module.exports = factory();
+	} else {
+		root.PhotoSwipeUI_Default = factory();
+	}
+})(this, function () {
+
+	'use strict';
+
+
+
+var PhotoSwipeUI_Default =
+ function(pswp, framework) {
+
+	var ui = this;
+	var _overlayUIUpdated = false,
+		_controlsVisible = true,
+		_fullscrenAPI,
+		_controls,
+		_captionContainer,
+		_fakeCaptionContainer,
+		_indexIndicator,
+		_shareButton,
+		_shareModal,
+		_shareModalHidden = true,
+		_initalCloseOnScrollValue,
+		_isIdle,
+		_listen,
+
+		_loadingIndicator,
+		_loadingIndicatorHidden,
+		_loadingIndicatorTimeout,
+
+		_galleryHasOneSlide,
+
+		_options,
+		_defaultUIOptions = {
+			barsSize: {top:44, bottom:'auto'},
+			closeElClasses: ['item', 'caption', 'zoom-wrap', 'ui', 'top-bar'], 
+			timeToIdle: 4000, 
+			timeToIdleOutside: 1000,
+			loadingIndicatorDelay: 1000, // 2s
+			
+			addCaptionHTMLFn: function(item, captionEl /*, isFake */) {
+				if(!item.title) {
+					captionEl.children[0].innerHTML = '';
+					return false;
+				}
+				captionEl.children[0].innerHTML = item.title;
+				return true;
+			},
+
+			closeEl:true,
+			captionEl: true,
+			fullscreenEl: true,
+			zoomEl: true,
+			shareEl: true,
+			counterEl: true,
+			arrowEl: true,
+			preloaderEl: true,
+			coverEl: true,
+            hideEl: true,
+
+			tapToClose: false,
+			tapToToggleControls: true,
+
+			clickToCloseNonZoomable: true,
+
+			shareButtons: [
+				{id:'facebook', label:'Share on Facebook', url:'https://www.facebook.com/sharer/sharer.php?u={{url}}'},
+				{id:'twitter', label:'Tweet', url:'https://twitter.com/intent/tweet?text={{text}}&url={{url}}'},
+				{id:'pinterest', label:'Pin it', url:'http://www.pinterest.com/pin/create/button/'+
+													'?url={{url}}&media={{image_url}}&description={{text}}'},
+				{id:'download', label:'Download image', url:'{{raw_image_url}}', download:true}
+			],
+			getImageURLForShare: function( /* shareButtonData */ ) {
+				return pswp.currItem.src || '';
+			},
+			getPageURLForShare: function( /* shareButtonData */ ) {
+				return window.location.href;
+			},
+			getTextForShare: function( /* shareButtonData */ ) {
+				return pswp.currItem.title || '';
+			},
+				
+			indexIndicatorSep: ' / '
+
+		},
+		_blockControlsTap,
+		_blockControlsTapTimeout;
+
+
+
+	var _onControlsTap = function(e) {
+			if(_blockControlsTap) {
+				return true;
+			}
+
+
+			e = e || window.event;
+
+			if(_options.timeToIdle && _options.mouseUsed && !_isIdle) {
+				// reset idle timer
+				_onIdleMouseMove();
+			}
+
+
+			var target = e.target || e.srcElement,
+				uiElement,
+				clickedClass = target.className,
+				found;
+
+			for(var i = 0; i < _uiElements.length; i++) {
+				uiElement = _uiElements[i];
+				if(uiElement.onTap && clickedClass.indexOf('pswp__' + uiElement.name ) > -1 ) {
+					uiElement.onTap();
+					found = true;
+
+				}
+			}
+
+			if(found) {
+				if(e.stopPropagation) {
+					e.stopPropagation();
+				}
+				_blockControlsTap = true;
+
+				// Some versions of Android don't prevent ghost click event 
+				// when preventDefault() was called on touchstart and/or touchend.
+				// 
+				// This happens on v4.3, 4.2, 4.1, 
+				// older versions strangely work correctly, 
+				// but just in case we add delay on all of them)	
+				var tapDelay = framework.features.isOldAndroid ? 600 : 30;
+				_blockControlsTapTimeout = setTimeout(function() {
+					_blockControlsTap = false;
+				}, tapDelay);
+			}
+
+		},
+		_fitControlsInViewport = function() {
+			return !pswp.likelyTouchDevice || _options.mouseUsed || screen.width > 1200;
+		},
+		_togglePswpClass = function(el, cName, add) {
+			framework[ (add ? 'add' : 'remove') + 'Class' ](el, 'pswp__' + cName);
+		},
+
+		// add class when there is just one item in the gallery
+		// (by default it hides left/right arrows and 1ofX counter)
+		_countNumItems = function() {
+			var hasOneSlide = (_options.getNumItemsFn() === 1);
+
+			if(hasOneSlide !== _galleryHasOneSlide) {
+				_togglePswpClass(_controls, 'ui--one-slide', hasOneSlide);
+				_galleryHasOneSlide = hasOneSlide;
+			}
+		},
+		_toggleShareModalClass = function() {
+			_togglePswpClass(_shareModal, 'share-modal--hidden', _shareModalHidden);
+		},
+		_toggleShareModal = function() {
+
+			_shareModalHidden = !_shareModalHidden;
+			
+			
+			if(!_shareModalHidden) {
+				_toggleShareModalClass();
+				setTimeout(function() {
+					if(!_shareModalHidden) {
+						framework.addClass(_shareModal, 'pswp__share-modal--fade-in');
+					}
+				}, 30);
+			} else {
+				framework.removeClass(_shareModal, 'pswp__share-modal--fade-in');
+				setTimeout(function() {
+					if(_shareModalHidden) {
+						_toggleShareModalClass();
+					}
+				}, 300);
+			}
+			
+			if(!_shareModalHidden) {
+				_updateShareURLs();
+			}
+			return false;
+		},
+
+		_openWindowPopup = function(e) {
+			e = e || window.event;
+			var target = e.target || e.srcElement;
+
+			pswp.shout('shareLinkClick', e, target);
+
+			if(!target.href) {
+				return false;
+			}
+
+			if( target.hasAttribute('download') ) {
+				return true;
+			}
+
+			window.open(target.href, 'pswp_share', 'scrollbars=yes,resizable=yes,toolbar=no,'+
+										'location=yes,width=550,height=420,top=100,left=' + 
+										(window.screen ? Math.round(screen.width / 2 - 275) : 100)  );
+
+			if(!_shareModalHidden) {
+				_toggleShareModal();
+			}
+			
+			return false;
+		},
+		_updateShareURLs = function() {
+			var shareButtonOut = '',
+				shareButtonData,
+				shareURL,
+				image_url,
+				page_url,
+				share_text;
+
+			for(var i = 0; i < _options.shareButtons.length; i++) {
+				shareButtonData = _options.shareButtons[i];
+
+				image_url = _options.getImageURLForShare(shareButtonData);
+				page_url = _options.getPageURLForShare(shareButtonData);
+				share_text = _options.getTextForShare(shareButtonData);
+
+				shareURL = shareButtonData.url.replace('{{url}}', encodeURIComponent(page_url) )
+									.replace('{{image_url}}', encodeURIComponent(image_url) )
+									.replace('{{raw_image_url}}', image_url )
+									.replace('{{text}}', encodeURIComponent(share_text) );
+
+				shareButtonOut += '<a href="' + shareURL + '" target="_blank" '+
+									'class="pswp__share--' + shareButtonData.id + '"' +
+									(shareButtonData.download ? 'download' : '') + '>' + 
+									shareButtonData.label + '</a>';
+
+				if(_options.parseShareButtonOut) {
+					shareButtonOut = _options.parseShareButtonOut(shareButtonData, shareButtonOut);
+				}
+			}
+			_shareModal.children[0].innerHTML = shareButtonOut;
+			_shareModal.children[0].onclick = _openWindowPopup;
+
+		},
+		_hasCloseClass = function(target) {
+			for(var  i = 0; i < _options.closeElClasses.length; i++) {
+				if( framework.hasClass(target, 'pswp__' + _options.closeElClasses[i]) ) {
+					return true;
+				}
+			}
+		},
+		_idleInterval,
+		_idleTimer,
+		_idleIncrement = 0,
+		_onIdleMouseMove = function() {
+			clearTimeout(_idleTimer);
+			_idleIncrement = 0;
+			if(_isIdle) {
+				ui.setIdle(false);
+			}
+		},
+		_onMouseLeaveWindow = function(e) {
+			e = e ? e : window.event;
+			var from = e.relatedTarget || e.toElement;
+			if (!from || from.nodeName === 'HTML') {
+				clearTimeout(_idleTimer);
+				_idleTimer = setTimeout(function() {
+					ui.setIdle(true);
+				}, _options.timeToIdleOutside);
+			}
+		},
+		_setupFullscreenAPI = function() {
+			if(_options.fullscreenEl) {
+				if(!_fullscrenAPI) {
+					_fullscrenAPI = ui.getFullscreenAPI();
+				}
+				if(_fullscrenAPI) {
+					framework.bind(document, _fullscrenAPI.eventK, ui.updateFullscreen);
+					ui.updateFullscreen();
+					framework.addClass(pswp.template, 'pswp--supports-fs');
+				} else {
+					framework.removeClass(pswp.template, 'pswp--supports-fs');
+				}
+			}
+		},
+		_setupLoadingIndicator = function() {
+			// Setup loading indicator
+			if(_options.preloaderEl) {
+			
+				_toggleLoadingIndicator(true);
+
+				_listen('beforeChange', function() {
+
+					clearTimeout(_loadingIndicatorTimeout);
+
+					// display loading indicator with delay
+					_loadingIndicatorTimeout = setTimeout(function() {
+
+						if(pswp.currItem && pswp.currItem.loading) {
+
+							if( !pswp.allowProgressiveImg() || (pswp.currItem.img && !pswp.currItem.img.naturalWidth)  ) {
+								// show preloader if progressive loading is not enabled, 
+								// or image width is not defined yet (because of slow connection)
+								_toggleLoadingIndicator(false); 
+								// items-controller.js function allowProgressiveImg
+							}
+							
+						} else {
+							_toggleLoadingIndicator(true); // hide preloader
+						}
+
+					}, _options.loadingIndicatorDelay);
+					
+				});
+				_listen('imageLoadComplete', function(index, item) {
+					if(pswp.currItem === item) {
+						_toggleLoadingIndicator(true);
+					}
+				});
+
+			}
+		},
+		_toggleLoadingIndicator = function(hide) {
+			if( _loadingIndicatorHidden !== hide ) {
+				_togglePswpClass(_loadingIndicator, 'preloader--active', !hide);
+				_loadingIndicatorHidden = hide;
+			}
+		},
+		_applyNavBarGaps = function(item) {
+			var gap = item.vGap;
+
+			if( _fitControlsInViewport() ) {
+				
+				var bars = _options.barsSize; 
+				if(_options.captionEl && bars.bottom === 'auto') {
+					if(!_fakeCaptionContainer) {
+						_fakeCaptionContainer = framework.createEl('pswp__caption pswp__caption--fake');
+						_fakeCaptionContainer.appendChild( framework.createEl('pswp__caption__center') );
+						_controls.insertBefore(_fakeCaptionContainer, _captionContainer);
+						framework.addClass(_controls, 'pswp__ui--fit');
+					}
+					if( _options.addCaptionHTMLFn(item, _fakeCaptionContainer, true) ) {
+
+						var captionSize = _fakeCaptionContainer.clientHeight;
+						gap.bottom = parseInt(captionSize,10) || 44;
+					} else {
+						gap.bottom = bars.top; // if no caption, set size of bottom gap to size of top
+					}
+				} else {
+					gap.bottom = bars.bottom === 'auto' ? 0 : bars.bottom;
+				}
+				
+				// height of top bar is static, no need to calculate it
+				gap.top = bars.top;
+			} else {
+				gap.top = gap.bottom = 0;
+			}
+		},
+		_setupIdle = function() {
+			// Hide controls when mouse is used
+			if(_options.timeToIdle) {
+				_listen('mouseUsed', function() {
+					
+					framework.bind(document, 'mousemove', _onIdleMouseMove);
+					framework.bind(document, 'mouseout', _onMouseLeaveWindow);
+
+					_idleInterval = setInterval(function() {
+						_idleIncrement++;
+						if(_idleIncrement === 2) {
+							ui.setIdle(true);
+						}
+					}, _options.timeToIdle / 2);
+				});
+			}
+		},
+		_setupHidingControlsDuringGestures = function() {
+
+			// Hide controls on vertical drag
+			_listen('onVerticalDrag', function(now) {
+				if(_controlsVisible && now < 0.95) {
+					ui.hideControls();
+				} else if(!_controlsVisible && now >= 0.95) {
+					ui.showControls();
+				}
+			});
+
+			// Hide controls when pinching to close
+			var pinchControlsHidden;
+			_listen('onPinchClose' , function(now) {
+				if(_controlsVisible && now < 0.9) {
+					ui.hideControls();
+					pinchControlsHidden = true;
+				} else if(pinchControlsHidden && !_controlsVisible && now > 0.9) {
+					ui.showControls();
+				}
+			});
+
+			_listen('zoomGestureEnded', function() {
+				pinchControlsHidden = false;
+				if(pinchControlsHidden && !_controlsVisible) {
+					ui.showControls();
+				}
+			});
+
+		};
+
+
+
+	var _uiElements = [
+		{ 
+			name: 'caption', 
+			option: 'captionEl',
+			onInit: function(el) {  
+				_captionContainer = el; 
+			} 
+		},
+		{ 
+			name: 'share-modal', 
+			option: 'shareEl',
+			onInit: function(el) {  
+				_shareModal = el;
+			},
+			onTap: function() {
+				_toggleShareModal();
+			} 
+		},
+		{ 
+			name: 'button--share', 
+			option: 'shareEl',
+			onInit: function(el) { 
+				_shareButton = el;
+			},
+			onTap: function() {
+				_toggleShareModal();
+			} 
+		},
+		{ 
+			name: 'button--zoom', 
+			option: 'zoomEl',
+			onTap: pswp.toggleDesktopZoom
+		},
+		{ 
+			name: 'counter', 
+			option: 'counterEl',
+			onInit: function(el) {  
+				_indexIndicator = el;
+			} 
+		},
+		{ 
+			name: 'button--close', 
+			option: 'closeEl',
+			onTap: pswp.close
+		},
+		{ 
+			name: 'button--arrow--left', 
+			option: 'arrowEl',
+			onTap: pswp.prev
+		},
+		{ 
+			name: 'button--arrow--right', 
+			option: 'arrowEl',
+			onTap: pswp.next
+		},
+		{ 
+			name: 'button--fs', 
+			option: 'fullscreenEl',
+			onTap: function() {  
+				if(_fullscrenAPI.isFullscreen()) {
+					_fullscrenAPI.exit();
+				} else {
+					_fullscrenAPI.enter();
+				}
+			} 
+		},
+		{ 
+			name: 'preloader', 
+			option: 'preloaderEl',
+			onInit: function(el) {  
+				_loadingIndicator = el;
+			} 
+		},
+        {
+            name: 'button--cover',
+            option: 'coverEl',
+            onTap: function(e) {
+			    pswp.shout('setCoverClick', pswp.currItem);
+            }
+        },
+        {
+            name: 'button--hide',
+            option: 'hideEl',
+            onTap: function(e) {
+			    pswp.shout('hideClick', pswp.currItem);
+            }
+        }
+	];
+
+	var _setupUIElements = function() {
+		var item,
+			classAttr,
+			uiElement;
+
+		var loopThroughChildElements = function(sChildren) {
+			if(!sChildren) {
+				return;
+			}
+
+			var l = sChildren.length;
+			for(var i = 0; i < l; i++) {
+				item = sChildren[i];
+				classAttr = item.className;
+
+				for(var a = 0; a < _uiElements.length; a++) {
+					uiElement = _uiElements[a];
+
+					if(classAttr.indexOf('pswp__' + uiElement.name) > -1  ) {
+
+						if( _options[uiElement.option] ) { // if element is not disabled from options
+							
+							framework.removeClass(item, 'pswp__element--disabled');
+							if(uiElement.onInit) {
+								uiElement.onInit(item);
+							}
+							
+							//item.style.display = 'block';
+						} else {
+							framework.addClass(item, 'pswp__element--disabled');
+							//item.style.display = 'none';
+						}
+					}
+				}
+			}
+		};
+		loopThroughChildElements(_controls.children);
+
+		var topBar =  framework.getChildByClass(_controls, 'pswp__top-bar');
+		if(topBar) {
+			loopThroughChildElements( topBar.children );
+		}
+	};
+
+
+	
+
+	ui.init = function() {
+
+		// extend options
+		framework.extend(pswp.options, _defaultUIOptions, true);
+
+		// create local link for fast access
+		_options = pswp.options;
+
+		// find pswp__ui element
+		_controls = framework.getChildByClass(pswp.scrollWrap, 'pswp__ui');
+
+		// create local link
+		_listen = pswp.listen;
+
+
+		_setupHidingControlsDuringGestures();
+
+		// update controls when slides change
+		_listen('beforeChange', ui.update);
+
+		// toggle zoom on double-tap
+		_listen('doubleTap', function(point) {
+			var initialZoomLevel = pswp.currItem.initialZoomLevel;
+			if(pswp.getZoomLevel() !== initialZoomLevel) {
+				pswp.zoomTo(initialZoomLevel, point, 333);
+			} else {
+				pswp.zoomTo(_options.getDoubleTapZoom(false, pswp.currItem), point, 333);
+			}
+		});
+
+		// Allow text selection in caption
+		_listen('preventDragEvent', function(e, isDown, preventObj) {
+			var t = e.target || e.srcElement;
+			if(
+				t && 
+				t.className && e.type.indexOf('mouse') > -1 && 
+				( t.className.indexOf('__caption') > 0 || (/(SMALL|STRONG|EM)/i).test(t.tagName) ) 
+			) {
+				preventObj.prevent = false;
+			}
+		});
+
+		// bind events for UI
+		_listen('bindEvents', function() {
+			framework.bind(_controls, 'pswpTap click', _onControlsTap);
+			framework.bind(pswp.scrollWrap, 'pswpTap', ui.onGlobalTap);
+
+			if(!pswp.likelyTouchDevice) {
+				framework.bind(pswp.scrollWrap, 'mouseover', ui.onMouseOver);
+			}
+		});
+
+		// unbind events for UI
+		_listen('unbindEvents', function() {
+			if(!_shareModalHidden) {
+				_toggleShareModal();
+			}
+
+			if(_idleInterval) {
+				clearInterval(_idleInterval);
+			}
+			framework.unbind(document, 'mouseout', _onMouseLeaveWindow);
+			framework.unbind(document, 'mousemove', _onIdleMouseMove);
+			framework.unbind(_controls, 'pswpTap click', _onControlsTap);
+			framework.unbind(pswp.scrollWrap, 'pswpTap', ui.onGlobalTap);
+			framework.unbind(pswp.scrollWrap, 'mouseover', ui.onMouseOver);
+
+			if(_fullscrenAPI) {
+				framework.unbind(document, _fullscrenAPI.eventK, ui.updateFullscreen);
+				if(_fullscrenAPI.isFullscreen()) {
+					_options.hideAnimationDuration = 0;
+					_fullscrenAPI.exit();
+				}
+				_fullscrenAPI = null;
+			}
+		});
+
+
+		// clean up things when gallery is destroyed
+		_listen('destroy', function() {
+			if(_options.captionEl) {
+				if(_fakeCaptionContainer) {
+					_controls.removeChild(_fakeCaptionContainer);
+				}
+				framework.removeClass(_captionContainer, 'pswp__caption--empty');
+			}
+
+			if(_shareModal) {
+				_shareModal.children[0].onclick = null;
+			}
+			framework.removeClass(_controls, 'pswp__ui--over-close');
+			framework.addClass( _controls, 'pswp__ui--hidden');
+			ui.setIdle(false);
+		});
+		
+
+		if(!_options.showAnimationDuration) {
+			framework.removeClass( _controls, 'pswp__ui--hidden');
+		}
+		_listen('initialZoomIn', function() {
+			if(_options.showAnimationDuration) {
+				framework.removeClass( _controls, 'pswp__ui--hidden');
+			}
+		});
+		_listen('initialZoomOut', function() {
+			framework.addClass( _controls, 'pswp__ui--hidden');
+		});
+
+		_listen('parseVerticalMargin', _applyNavBarGaps);
+		
+		_setupUIElements();
+
+		if(_options.shareEl && _shareButton && _shareModal) {
+			_shareModalHidden = true;
+		}
+
+		_countNumItems();
+
+		_setupIdle();
+
+		_setupFullscreenAPI();
+
+		_setupLoadingIndicator();
+	};
+
+	ui.setIdle = function(isIdle) {
+		_isIdle = isIdle;
+		_togglePswpClass(_controls, 'ui--idle', isIdle);
+	};
+
+	ui.update = function() {
+		// Don't update UI if it's hidden
+		if(_controlsVisible && pswp.currItem) {
+			
+			ui.updateIndexIndicator();
+
+			if(_options.captionEl) {
+				_options.addCaptionHTMLFn(pswp.currItem, _captionContainer);
+
+				_togglePswpClass(_captionContainer, 'caption--empty', !pswp.currItem.title);
+			}
+
+			_overlayUIUpdated = true;
+
+		} else {
+			_overlayUIUpdated = false;
+		}
+
+		if(!_shareModalHidden) {
+			_toggleShareModal();
+		}
+
+		_countNumItems();
+	};
+
+	ui.updateFullscreen = function(e) {
+
+		if(e) {
+			// some browsers change window scroll position during the fullscreen
+			// so PhotoSwipe updates it just in case
+			setTimeout(function() {
+				pswp.setScrollOffset( 0, framework.getScrollY() );
+			}, 50);
+		}
+		
+		// toogle pswp--fs class on root element
+		framework[ (_fullscrenAPI.isFullscreen() ? 'add' : 'remove') + 'Class' ](pswp.template, 'pswp--fs');
+	};
+
+	ui.updateIndexIndicator = function() {
+		if(_options.counterEl) {
+			_indexIndicator.innerHTML = (pswp.getCurrentIndex()+1) + 
+										_options.indexIndicatorSep + 
+										_options.getNumItemsFn();
+		}
+	};
+	
+	ui.onGlobalTap = function(e) {
+		e = e || window.event;
+		var target = e.target || e.srcElement;
+
+		if(_blockControlsTap) {
+			return;
+		}
+
+		if(e.detail && e.detail.pointerType === 'mouse') {
+
+			// close gallery if clicked outside of the image
+			if(_hasCloseClass(target)) {
+				pswp.close();
+				return;
+			}
+
+			if(framework.hasClass(target, 'pswp__img')) {
+				if(pswp.getZoomLevel() === 1 && pswp.getZoomLevel() <= pswp.currItem.fitRatio) {
+					if(_options.clickToCloseNonZoomable) {
+						pswp.close();
+					}
+				} else {
+					pswp.toggleDesktopZoom(e.detail.releasePoint);
+				}
+			}
+			
+		} else {
+
+			// tap anywhere (except buttons) to toggle visibility of controls
+			if(_options.tapToToggleControls) {
+				if(_controlsVisible) {
+					ui.hideControls();
+				} else {
+					ui.showControls();
+				}
+			}
+
+			// tap to close gallery
+			if(_options.tapToClose && (framework.hasClass(target, 'pswp__img') || _hasCloseClass(target)) ) {
+				pswp.close();
+				return;
+			}
+			
+		}
+	};
+	ui.onMouseOver = function(e) {
+		e = e || window.event;
+		var target = e.target || e.srcElement;
+
+		// add class when mouse is over an element that should close the gallery
+		_togglePswpClass(_controls, 'ui--over-close', _hasCloseClass(target));
+	};
+
+	ui.hideControls = function() {
+		framework.addClass(_controls,'pswp__ui--hidden');
+		_controlsVisible = false;
+	};
+
+	ui.showControls = function() {
+		_controlsVisible = true;
+		if(!_overlayUIUpdated) {
+			ui.update();
+		}
+		framework.removeClass(_controls,'pswp__ui--hidden');
+	};
+
+	ui.supportsFullscreen = function() {
+		var d = document;
+		return !!(d.exitFullscreen || d.mozCancelFullScreen || d.webkitExitFullscreen || d.msExitFullscreen);
+	};
+
+	ui.getFullscreenAPI = function() {
+		var dE = document.documentElement,
+			api,
+			tF = 'fullscreenchange';
+
+		if (dE.requestFullscreen) {
+			api = {
+				enterK: 'requestFullscreen',
+				exitK: 'exitFullscreen',
+				elementK: 'fullscreenElement',
+				eventK: tF
+			};
+
+		} else if(dE.mozRequestFullScreen ) {
+			api = {
+				enterK: 'mozRequestFullScreen',
+				exitK: 'mozCancelFullScreen',
+				elementK: 'mozFullScreenElement',
+				eventK: 'moz' + tF
+			};
+
+			
+
+		} else if(dE.webkitRequestFullscreen) {
+			api = {
+				enterK: 'webkitRequestFullscreen',
+				exitK: 'webkitExitFullscreen',
+				elementK: 'webkitFullscreenElement',
+				eventK: 'webkit' + tF
+			};
+
+		} else if(dE.msRequestFullscreen) {
+			api = {
+				enterK: 'msRequestFullscreen',
+				exitK: 'msExitFullscreen',
+				elementK: 'msFullscreenElement',
+				eventK: 'MSFullscreenChange'
+			};
+		}
+
+		if(api) {
+			api.enter = function() { 
+				// disable close-on-scroll in fullscreen
+				_initalCloseOnScrollValue = _options.closeOnScroll; 
+				_options.closeOnScroll = false; 
+
+				if(this.enterK === 'webkitRequestFullscreen') {
+					pswp.template[this.enterK]( Element.ALLOW_KEYBOARD_INPUT );
+				} else {
+					return pswp.template[this.enterK](); 
+				}
+			};
+			api.exit = function() { 
+				_options.closeOnScroll = _initalCloseOnScrollValue;
+
+				return document[this.exitK](); 
+
+			};
+			api.isFullscreen = function() { return document[this.elementK]; };
+		}
+
+		return api;
+	};
+
+
+
+};
+return PhotoSwipeUI_Default;
+
+
+});

+ 99 - 102
assets/site.css

@@ -332,6 +332,7 @@ img.img--with_border {
   margin-left: 0;
   /*color: rgba(255, 255, 255, 0.8);*/
 }
+
 .row--modules span {
   font-wight:600;
   border-left:5px solid #FFF;
@@ -342,155 +343,151 @@ img.img--with_border {
 .block__ui-separated {
   position: relative;
 }
+
 .block__ui-separated .col-50 {
   position: absolute;
   left: 0;
   top:12px;
 }
+
 .block__ui-separated img {
   float: right;
   max-width: 450px;
 }
 
-
 .demo-gallery {
   width: 100%;
   height: auto;
   float: left;
 }
+
 .demo-gallery a {
-  -webkit-tap-highlight-color: rgba(0,0,0,0);
-  -webkit-touch-callout: none;
-  display: block;
-  float: left;
-  margin: 0 12px 12px 0;
-  width: 250px;
+    -webkit-tap-highlight-color: rgba(0,0,0,0);
+    -webkit-touch-callout: none;
+    display: block;
+    float: left;
+    margin: 0 12px 12px 0;
+    width: 250px;
 /*  line-height: 0; */
 }
+
 .demo-gallery figure {
-  font-size: 14px;
+    font-size: 14px;
 }
 
-
 a.demo-gallery__img--main {
-  width: auto;
-  height: auto;
+    width: auto;
+    height: auto;
 }
 
 .demo-gallery__title {
-  line-height: 14px;
-  font-size: 14px;
-  opacity: 0.8;
-  margin-top: 5px;
-  width: 100%;
-  float: left;
+    line-height: 14px;
+    font-size: 14px;
+    opacity: 0.8;
+    margin-top: 5px;
+    width: 100%;
+    float: left;
 }
 
 @media screen and (max-width: 1000px) {
-  .row--wide {
-    max-width: 800px;
-  }
-  .row--wide img {
-    float: none;
-  }
-  .img-desc {
-    margin-left: 0;
-  }
-  .section--head {
-    margin-top:0;
-    padding: 30px 0;
-  }
-  .row--nav {
-    font-size: 24px;
-    line-height: 1.1; 
-  }
-
+    .row--wide {
+        max-width: 800px;
+    }
+    .row--wide img {
+        float: none;
+    }
+    .img-desc {
+        margin-left: 0;
+    }
+    .section--head {
+        margin-top:0;
+        padding: 30px 0;
+    }
+    .row--nav {
+        font-size: 24px;
+        line-height: 1.1; 
+    }
 }
 
 @media screen and (max-width: 650px) {
-   h1 {
-    font-size: 40px;
-  }
-  .block__ui-separated .col-50 {
-    position: relative;
-    top: 0;
-  }
-  .block__ui-separated img {
-    max-width: 100%;
-    width: 100%;
-    float: left;
-  }
+    h1 {
+        font-size: 40px;
+    }
+    .block__ui-separated .col-50 {
+        position: relative;
+        top: 0;
+    }
+    .block__ui-separated img {
+        max-width: 100%;
+        width: 100%;
+        float: left;
+    }
 }
 
 @media screen and (max-width: 450px) {
-  
-
-  .col-50:nth-child(1) {
-    margin-right: 0;
-  }
-  .row--wide img {
-    margin-bottom: 6px;
-  }
-  .col-50 {
-    width: 100%;
-    margin-bottom: 12px;
-  }
-  .row {
-    padding: 0 18px;
-  }
-  .section--head {
-    margin-top:0;
-    padding: 24px 0;
-  }
-  .row--nav {
-    font-size: 18px;
-    line-height: 26px; 
-  }
-
-
+    .col-50:nth-child(1) {
+        margin-right: 0;
+    }
+    .row--wide img {
+        margin-bottom: 6px;
+    }
+    .col-50 {
+        width: 100%;
+        margin-bottom: 12px;
+    }
+    .row {
+        padding: 0 18px;
+    }
+    .section--head {
+        margin-top:0;
+        padding: 24px 0;
+    }
+    .row--nav {
+        font-size: 18px;
+        line-height: 26px; 
+    }
 }
 
 @media screen and (max-width: 700px) {
-
-  .row--nav {
-    font-size: 18px;
-    line-height: 26px; 
-  }
-
-  .demo-gallery {
-    max-width: 600px;
-  }
-  .demo-gallery a {
-    width: 275px;
-    margin: 0 15px 12px 0;
-  }
-  a.demo-gallery__img--main {
-    width: 164px;
-  }
-  .section--head p {
-    font-size: 18px;
-    line-height: 24px;
-  }
+    .row--nav {
+        font-size: 18px;
+        line-height: 26px; 
+    }
+
+    .demo-gallery {
+        max-width: 600px;
+    }
+    .demo-gallery a {
+        width: 275px;
+        margin: 0 15px 12px 0;
+    }
+    a.demo-gallery__img--main {
+        width: 164px;
+    }
+    .section--head p {
+        font-size: 18px;
+        line-height: 24px;
+    }
 }
 
 @media screen and (max-width: 450px) {
-  .demo-gallery a {
-    width: 324px;
-    margin: 0 0 12px 0;
-  }
-  a.demo-gallery__img--main {
-    width: 127px;
-  }
+    .demo-gallery a {
+        width: 324px;
+        margin: 0 0 12px 0;
+    }
+    a.demo-gallery__img--main {
+        width: 127px;
+    }
 }
 
 
 @media screen and (max-width: 350px) {
   .demo-gallery a {
-    width: 81px;
-margin: 0 1px 1px 0;
+      width: 81px;
+      margin: 0 1px 1px 0;
   }
   a.demo-gallery__img--main {
-    width: 109px;
+      width: 109px;
   }
 }
 

+ 12 - 5
assets/site.js

@@ -12,10 +12,17 @@ function setAlbums(albums) {
 
         var a = addAlbumDom(dAlbums, alb, true);
         a.setAttribute('data-id', alb.id);
-        a.setAttribute('title', alb.cover.src);
-        a.addEventListener('click', function() {
-            jsonGET('/api/albums/' + alb.id + '/', function (alb) {
-                startGallery(alb.photos, 0, alb.id);
+        a.setAttribute('title', alb.cover);
+        a.addEventListener('click', function(e) {
+            jsonGET('/api/albums/' + alb.id + '/' + (e.ctrlKey ? '?full=1' : ''), function (alb) {
+                var pswp = startGallery(alb.photos, 0, alb.id);
+                pswp.listen('setCoverClick', function(item) {
+                    jsonPOST('/api/albums/' + alb.id + '/cover/', JSON.stringify({id: item.id}));
+                });
+                pswp.listen('hideClick', function(item) {
+                    var data = JSON.stringify({id: item.id, hidden:item.hidden ? null : 1});
+                    jsonPOST('/api/albums/' + alb.id + '/hide/', data);
+                });
             });
         });
     });
@@ -55,7 +62,7 @@ function setIncoming(albums, parent) {
 function addAlbumDom(parent, alb, add_count) {
     var a = appendElement(parent, 'a');
     var img = appendElement(a, 'img');
-    img.src = alb.cover.src;
+    img.src = alb.cover;
     if (alb.title) {
         var fig = appendElement(a, 'figure');
         fig.textContent = alb.title;

+ 5 - 1
index.html

@@ -20,11 +20,13 @@
          - preloader.gif (for browsers that do not support CSS animations) -->
     <link rel="stylesheet" href="/css/default-skin.css"> 
 
+    <link rel="stylesheet" href="/css/font-awesome.min.css">
+
     <!-- Core JS file -->
     <script src="/js/photoswipe.min.js"></script> 
 
     <!-- UI JS file -->
-    <script src="/js/photoswipe-ui-default.min.js"></script> 
+    <script src="/js/photoswipe-ui-default.js"></script> 
 
     <!--[if lt IE 9]>
         <script>
@@ -62,6 +64,8 @@
 			<!--<button class="pswp__button pswp__button--share" title="Share"></button> -->
 			<button class="pswp__button pswp__button--fs" title="Toggle fullscreen"></button>
 			<button class="pswp__button pswp__button--zoom" title="Zoom in/out"></button>
+			<button class="pswp__button pswp__button--cover pswp__button--fa fa fa-bookmark-o" title="Set as cover"></button>
+			<button class="pswp__button pswp__button--hide pswp__button--fa fa fa-eye-slash" title="Hide"></button>
 			<div class="pswp__preloader">
 			  <div class="pswp__preloader__icn">
 				<div class="pswp__preloader__cut">

+ 1 - 1
package.lisp

@@ -2,5 +2,5 @@
 
 (defpackage #:photo-store
   (:nicknames #:ph-store)
-  (:use :cl)
+  (:use :cl :iter)
   (:export #:start))

+ 48 - 14
photo-store.lisp

@@ -1,5 +1,4 @@
 (in-package #:photo-store)
-(use-package :iter)
 
 (eval-when (:compile-toplevel :load-toplevel :execute)
   (restas::register-pkgmodule-traits 'photo-store)
@@ -48,19 +47,20 @@
    album-id photo-id description idx hidden))
 
 (defvar *photo-storage-url* nil "base url for photo storage")
-(defun db-load-album (album-id)
+(defun db-load-album (album-id &optional full)
   (with-db (db)
     (multiple-value-bind (name cover-id)
         (sqlite:execute-one-row-m-v db "select id, name, cover_id from albums where id = ?" album-id)
       (when name
-        (let ((photos (iter (for (id path title w h)
-                                 in-sqlite-query "select p.id, p.path, ap.description, p.width, p.height from photos p inner join album_photos ap on ap.photo_id = p.id where ap.album_id = ? order by ap.idx"
+        (let ((photos (iter (for (id path title w h hidden)
+                                 in-sqlite-query "select p.id, p.path, ap.description, p.width, p.height, ap.hidden from photos p inner join album_photos ap on ap.photo_id = p.id where ap.album_id = ? and (ap.hidden is null or ? is not null) order by ap.idx"
                                  on-database db
-                                 with-parameters (album-id))
+                                 with-parameters (album-id full))
                             (collect (list (cons :id id)
                                            (cons :src (concatenate 'string *photo-storage-url* path))
-                                           (cons :title title)
-                                           (cons :w w) (cons :h h))))))
+                                           (cons :title (format nil "~A~:[~; [hidden]~]" title hidden))
+                                           (cons :w w) (cons :h h)
+                                           (cons :hidden hidden))))))
           (list (cons :id album-id)
                 (cons :title name)
                 (cons :cover (find cover-id photos :key (agetter :id)))
@@ -68,16 +68,27 @@
 
 (defun db-load-albums (&optional parent-id)
   (with-db (db)
-    (iter (for (id title cover-path cover-w cover-h cover-taken count)
-               in-sqlite-query "select a.id, a.name, c.path, c.width, c.height, c.taken, (select count(photo_id) from album_photos where album_id=a.id) cnt from albums a left join photos c on a.cover_id=c.id where cnt > 0 and ((? is null and parent_id is null) or (parent_id=?)) order by c.taken desc" on-database db with-parameters (parent-id parent-id))
+    (iter (for (id title cover-path cover-taken count)
+               in-sqlite-query "select a.id, a.name, c.path, c.taken, (select count(photo_id) from album_photos where album_id=a.id) cnt from albums a left join photos c on a.cover_id=c.id where cnt > 0 and ((? is null and parent_id is null) or (parent_id=?)) order by c.taken desc" on-database db with-parameters (parent-id parent-id))
           (collect (list (cons :id id)
                          (cons :title title)
                          (cons :count count)
                          (cons :date cover-taken)
-                         (cons :cover (list (cons :src (concatenate 'string
-                                                                    *photo-storage-url* cover-path))
-                                            (cons :w cover-w)
-                                            (cons :h cover-h))))))))
+                         (cons :cover (concatenate 'string
+                                                   *photo-storage-url* cover-path)))))))
+
+(defun db-set-album-cover (album-id cover-id)
+  (with-db (db)
+    (sqlite:execute-non-query
+     db "update albums set cover_id = ? where id = ?"
+     cover-id album-id)))
+
+(defun db-set-album-photo-hidden (album-id photo-id hidden)
+  (with-db (db)
+    (sqlite:execute-non-query
+     db "update album_photos set hidden=? where album_id=? and photo_id=?"
+     hidden album-id photo-id)))
+
 
 (defun dirname (directory)
   (car (last (pathname-directory directory))))
@@ -196,6 +207,9 @@
 (restas:define-route assets/js ("js/:file" :content-type "application/x-javascript")
   (merge-pathnames file *assets-path*))
 
+(restas:define-route assets/fonts ("fonts/:file")
+  (merge-pathnames file *assets-path*))
+
 (defun json (object)
   (json:encode-json-to-string object))
 
@@ -223,7 +237,27 @@
 (restas:define-route api/album ("api/albums/:album-id/"
                                 :content-type "application/json")
   (:sift-variables (album-id 'integer))
-  (json (db-load-album album-id)))
+  (json (db-load-album album-id (hunchentoot:get-parameter "full"))))
+
+(restas:define-route api/album-set-cover ("api/albums/:album-id/cover/"
+                                          :method :post
+                                          :content-type "application/json")
+  (:sift-variables (album-id 'integer))
+  (let* ((data (json:decode-json-from-string (hunchentoot:raw-post-data :external-format :utf-8)))
+         (cover-id (aget :id data)))
+    (db-set-album-cover album-id cover-id)
+    "OK"))
+
+(restas:define-route api/album-hide ("api/albums/:album-id/hide/"
+                                     :method :post
+                                     :content-type "application/json")
+  (:sift-variables (album-id 'integer))
+  (let* ((data (json:decode-json-from-string (hunchentoot:raw-post-data :external-format :utf-8)))
+         (photo-id (aget :id data))
+         (hidden (aget :hidden data)))
+    (db-set-album-photo-hidden album-id photo-id hidden)
+    "OK"))
+
 
 (defvar *photo-storage-path* nil "Destination storage path")
 

Certains fichiers n'ont pas été affichés car il y a eu trop de fichiers modifiés dans ce diff