diff --git a/assets/js/jquery.mousewheel.min.js b/assets/js/jquery.mousewheel.min.js
new file mode 100755
index 0000000..930a8ac
--- /dev/null
+++ b/assets/js/jquery.mousewheel.min.js
@@ -0,0 +1,8 @@
+/*!
+ * jQuery Mousewheel 3.1.13
+ *
+ * Copyright 2015 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ */
+!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):"object"==typeof exports?module.exports=a:a(jQuery)}(function(a){function b(b){var g=b||window.event,h=i.call(arguments,1),j=0,l=0,m=0,n=0,o=0,p=0;if(b=a.event.fix(g),b.type="mousewheel","detail"in g&&(m=-1*g.detail),"wheelDelta"in g&&(m=g.wheelDelta),"wheelDeltaY"in g&&(m=g.wheelDeltaY),"wheelDeltaX"in g&&(l=-1*g.wheelDeltaX),"axis"in g&&g.axis===g.HORIZONTAL_AXIS&&(l=-1*m,m=0),j=0===m?l:m,"deltaY"in g&&(m=-1*g.deltaY,j=m),"deltaX"in g&&(l=g.deltaX,0===m&&(j=-1*l)),0!==m||0!==l){if(1===g.deltaMode){var q=a.data(this,"mousewheel-line-height");j*=q,m*=q,l*=q}else if(2===g.deltaMode){var r=a.data(this,"mousewheel-page-height");j*=r,m*=r,l*=r}if(n=Math.max(Math.abs(m),Math.abs(l)),(!f||f>n)&&(f=n,d(g,n)&&(f/=40)),d(g,n)&&(j/=40,l/=40,m/=40),j=Math[j>=1?"floor":"ceil"](j/f),l=Math[l>=1?"floor":"ceil"](l/f),m=Math[m>=1?"floor":"ceil"](m/f),k.settings.normalizeOffset&&this.getBoundingClientRect){var s=this.getBoundingClientRect();o=b.clientX-s.left,p=b.clientY-s.top}return b.deltaX=l,b.deltaY=m,b.deltaFactor=f,b.offsetX=o,b.offsetY=p,b.deltaMode=0,h.unshift(b,j,l,m),e&&clearTimeout(e),e=setTimeout(c,200),(a.event.dispatch||a.event.handle).apply(this,h)}}function c(){f=null}function d(a,b){return k.settings.adjustOldDeltas&&"mousewheel"===a.type&&b%120===0}var e,f,g=["wheel","mousewheel","DOMMouseScroll","MozMousePixelScroll"],h="onwheel"in document||document.documentMode>=9?["wheel"]:["mousewheel","DomMouseScroll","MozMousePixelScroll"],i=Array.prototype.slice;if(a.event.fixHooks)for(var j=g.length;j;)a.event.fixHooks[g[--j]]=a.event.mouseHooks;var k=a.event.special.mousewheel={version:"3.1.12",setup:function(){if(this.addEventListener)for(var c=h.length;c;)this.addEventListener(h[--c],b,!1);else this.onmousewheel=b;a.data(this,"mousewheel-line-height",k.getLineHeight(this)),a.data(this,"mousewheel-page-height",k.getPageHeight(this))},teardown:function(){if(this.removeEventListener)for(var c=h.length;c;)this.removeEventListener(h[--c],b,!1);else this.onmousewheel=null;a.removeData(this,"mousewheel-line-height"),a.removeData(this,"mousewheel-page-height")},getLineHeight:function(b){var c=a(b),d=c["offsetParent"in a.fn?"offsetParent":"parent"]();return d.length||(d=a("body")),parseInt(d.css("fontSize"),10)||parseInt(c.css("fontSize"),10)||16},getPageHeight:function(b){return a(b).height()},settings:{adjustOldDeltas:!0,normalizeOffset:!0}};a.fn.extend({mousewheel:function(a){return a?this.bind("mousewheel",a):this.trigger("mousewheel")},unmousewheel:function(a){return this.unbind("mousewheel",a)}})});
\ No newline at end of file
diff --git a/assets/js/photos.js b/assets/js/photos.js
new file mode 100755
index 0000000..d7d0a97
--- /dev/null
+++ b/assets/js/photos.js
@@ -0,0 +1,276 @@
+let showcase = $("#imgBig");
+let showcaseButtonContainer = $("#photoButtonsContainer");
+let showcaseDownload = $("#downloadButton");
+let photoOverlay = $("#photoOverlay");
+let headerTop = $("#header-top");
+let sideNav = $("#menuSidenav");
+let loading = $("#loadingIconContainer");
+let move_photo = false;
+let grab_offsetX = 0;
+let grab_offsetY = 0;
+
+let idle_time = 0;
+let isMobile = window.matchMedia("only screen and (max-width: 480px)").matches;
+let isMouseOverButtons = false;
+
+$(document).ready(
+ function () {
+ showcase.bind("mousewheel", function(event, delta) {
+ let min_width = $(window).width() / 5;
+ let min_height = $(window).height() / 5;
+ let max_width = $(window).width() * 5;
+ let max_height = $(window).height() * 5;
+
+ let scale = 150 / 100;
+ if (delta < 0)
+ scale = 1/scale;
+ let cursorY = event.pageY - $(window).scrollTop();
+ let offsetX = event.pageX - (showcase.position().left + showcase.width()/2);
+ let offsetY = cursorY - (showcase.position().top + showcase.height()/2);
+
+ let new_width = showcase.width() * scale;
+ let new_height = showcase.height() * scale;
+ if (new_width > max_width || new_width < min_width)
+ new_width = 0;
+ if (new_height > max_height || new_height < min_height)
+ new_height = 0;
+
+ if (new_width !== 0 && new_height !== 0){
+ let new_left = event.pageX - (offsetX * scale);
+ let new_top = cursorY - (offsetY * scale);
+
+ showcase.width(new_width);
+ showcase.height(new_height);
+
+ if (new_height > $(window).height() || new_width > $(window).width()){
+ showcase.css('left', new_left +'px');
+ showcase.css('top', new_top +'px');
+ showcase.css('cursor', 'move');
+ }
+ else{
+ showcase.css('left', $(window).width()/2 +'px');
+ showcase.css('top', $(window).height()/2 +'px');
+ showcase.css('cursor', 'default');
+ }
+ }
+ return false;
+ });
+ document.getElementById("photosTitle").scrollIntoView();
+ showcase.on('dragstart', function(event) { event.preventDefault(); }); // Stop image drag out of page
+ if (!isMobile)
+ setInterval(timerIncrement, 100);
+ }
+);
+
+$(document).mousemove(function (event) {
+ let cursorY = event.pageY - $(window).scrollTop();
+ let elem = document.elementFromPoint(event.pageX, cursorY);
+ isMouseOverButtons = !(elem.id === "closeBack" || elem.id === "loadingIconContainer" || elem.id === showcase.attr('id')); // Prevent entering fullscreen when cursor on control buttons
+ idle_time = 0;
+});
+
+showcase.mousemove(function(event){
+ if (showcase.height() > $(window).height() || showcase.width() > $(window).width) {
+ showcase.css('cursor', 'move');
+ if (move_photo){
+ let cursorY = event.pageY - $(window).scrollTop();
+ let offsetX = event.pageX - (showcase.position().left + showcase.width()/2);
+ let offsetY = cursorY - (showcase.position().top + showcase.height()/2);
+
+ let new_left = showcase.position().left + showcase.width()/2 + offsetX - grab_offsetX;
+ let new_top = showcase.position().top + showcase.height()/2 + offsetY - grab_offsetY;
+
+ showcase.css('left', new_left +'px');
+ showcase.css('top', new_top +'px');
+ }
+ }
+ else{
+ showcase.css('cursor', 'default');
+ }
+});
+
+showcase.mousedown(function(event){
+ move_photo = true;
+ let cursorY = event.pageY - $(window).scrollTop();
+ grab_offsetX = event.pageX - (showcase.position().left + showcase.width()/2);
+ grab_offsetY = cursorY - (showcase.position().top + showcase.height()/2);
+
+ if (isMobile)
+ toggleFullscreen();
+});
+
+showcase.mouseup(function(){
+ move_photo = false;
+});
+
+showcase.mouseleave(function(){
+ move_photo = false;
+});
+
+
+/*
+ * Display selected image in showcase
+ * When clicked, display image in full size
+ */
+function displayBig(elem) {
+ isMouseOverButtons = false; // Allow fullscreen when clicking on an image without mouving the mouse
+ changeImage($(elem).attr('src'));
+ hideTopBar();
+ disableFullscreen();
+ photoOverlay.fadeIn(500);
+ $('body').css('overflow', 'hidden');
+}
+
+function getSourceFromThumbnail(source) {
+ return source.replace("photos_thumb/", "photos/");
+}
+
+function getThumbnailFromSource(source) {
+ return source.replace("photos/", "photos_thumb/");
+}
+
+/*
+ * Hide showcase image
+ */
+function closeBig() {
+ showTopBar();
+ disableFullscreen();
+ photoOverlay.fadeOut(500);
+ $('body').css('overflow', 'auto');
+ scrollToShowcaseImage();
+}
+
+
+function scrollToShowcaseImage() {
+ let source = showcase.attr('src');
+ let image = $("img[src$='" + getThumbnailFromSource(source) + "']");
+ if (image !== undefined) {
+ image.get(0).scrollIntoView();
+ }
+}
+
+
+function enableFullscreen() {
+ showcaseButtonContainer.fadeOut(500);
+}
+
+function disableFullscreen() {
+ showcaseButtonContainer.fadeIn(500);
+}
+
+function toggleFullscreen() {
+ if (isFullscreen())
+ disableFullscreen();
+ else
+ enableFullscreen();
+}
+
+function hideTopBar() {
+ headerTop.fadeOut(500);
+ sideNav.fadeOut(500);
+}
+
+function showTopBar() {
+ headerTop.fadeIn(500);
+ sideNav.fadeIn(500);
+}
+
+function isFullscreen(){
+ return showcaseButtonContainer.css("display") === "none";
+}
+
+
+function timerIncrement() {
+ if (isMouseOverButtons)
+ idle_time = 0;
+ else
+ idle_time = idle_time+ 1;
+ if (idle_time > 10 && !isFullscreen()) { // 1 second
+ enableFullscreen();
+ } else if (idle_time <= 10 && isFullscreen()){
+ disableFullscreen();
+ }
+}
+
+/*
+ * Control images with keyboard arrows
+ */
+$(document).keydown(function (e) {
+ switch (e.keyCode) {
+ case 37: // left
+ displayNext(-1);
+ break;
+ case 39: // right
+ displayNext(1);
+ break;
+ case 27: // escape
+ closeBig();
+ break;
+ default:
+ return; // exit this handler for other keys
+ }
+ e.preventDefault(); // prevent the default action (scroll / move caret)
+});
+
+
+/*
+ * Display next/last image in showcase. When reaching end/start, loop back to start/end
+ */
+function displayNext(direction) {
+ let currentSrc = showcase.attr('src');
+ let photos = document.getElementsByClassName("photo");
+ let current = 0;
+ for (let i = 0; i < photos.length; i++) {
+ if (getSourceFromThumbnail($(photos[i]).attr('src')) === currentSrc) {
+ current = i;
+ }
+ }
+ let next = current + direction;
+ let nextId = "";
+ if (direction > 0) {
+ nextId = "#photo-0";
+ } else {
+ nextId = "#photo-" + (photos.length - 1);
+ }
+ if (document.getElementById("photo-" + next) != null) {
+ nextId = "#photo-" + next;
+ }
+ let nextSrc = $(nextId).attr('src');
+ changeImage(nextSrc);
+}
+
+/*
+ * Change image source, link and download
+ */
+function changeImage(thumb) {
+ displayLoading();
+ showcase.css('display', 'none');
+ showcase.on('load', function () {
+ hideLoading();
+ showcase.css('display', 'block');
+ if ($(showcase).width() > $(window).width()){ // prevent display problems on portait devices
+ let scale = $(window).width() * 0.9 / $(showcase).width();
+ $(showcase).width(scale*$(showcase).width());
+ $(showcase).height(scale*$(showcase).height());
+ }
+ });
+ let source = getSourceFromThumbnail(thumb);
+ showcase.attr("src", source);
+ showcase.css({
+ width: 'auto',
+ height: '90%',
+ });
+ showcase.css('left', $(window).width()/2 +'px');
+ showcase.css('top', $(window).height()/2 +'px');
+ showcaseDownload.attr("href", source);
+
+}
+
+
+function displayLoading() {
+ loading.show();
+}
+
+function hideLoading() {
+ loading.fadeOut(200);
+}
diff --git a/photos.php b/photos.php
index 1eb0ec0..1ba645d 100644
--- a/photos.php
+++ b/photos.php
@@ -1,9 +1,314 @@
$value) {
+ $path = realpath($dir . DIRECTORY_SEPARATOR . $value);
+ if (!is_dir($path)) {
+ $valid = pathinfo($path, PATHINFO_EXTENSION) == "zip";
+ if ($valid)
+ break;
+ }
+ }
+ return $valid;
+}
+
+/**
+ * Get all directories in the specified path and creates them on the page
+ * @param string $path path to search directories in
+ */
+function createDirectories($path)
+{
+ $path = photoRoot . $path;
+ $displayedItems = 0;
+ $folders = getDirectories($path);
+ foreach ($folders as $key => $value) {
+ $folderTitle = $value;
+ $photos = getTotalPhotoCount($path . DIRECTORY_SEPARATOR . $value);
+ $albums = getTotalAlbumCount($path . DIRECTORY_SEPARATOR . $value);
+ $folderLink = "?" . urlParam . "=" . getActivePath() . DIRECTORY_SEPARATOR . $value;
+ ?>
+
+ = $folderTitle ?>
+ 1): ?>
+ = $photos ?> photos
+
+ = $photos ?> photo
+
+ vide
+
+
+ 1): ?>
+ = $albums ?> albums
+
+ = $albums ?> album
+
+
+ $value) {
+ $realPath = realpath($path . DIRECTORY_SEPARATOR . $value);
+ if (isValidImage($realPath)) {
+ $imageSrc = $path . DIRECTORY_SEPARATOR . $value;
+ $imageId = "photo-" . $displayedItems;
+ ?> $value) {
+ $realPath = realpath($path . DIRECTORY_SEPARATOR . $value);
+ if (isValidDirectory($realPath, $value)) {
+ array_push($folders, $value);
+ }
+ }
+ return $folders;
+}
+
+/**
+ * Counts directories in the specified folder
+ * @param string $path path to search directories in
+ * @return int directories count
+ */
+function getDirectoriesCount($path)
+{
+ $files = scandir($path);
+ $dirCount = 0;
+ foreach ($files as $key => $value) {
+ $realPath = realpath($path . DIRECTORY_SEPARATOR . $value);
+ if (isValidDirectory($realPath, $value)) {
+ $dirCount++;
+ }
+ }
+ return $dirCount;
+}
+
+/**
+ * Counts images in the specified folder
+ * @param string $path path to search photos in
+ * @return int photo count
+ */
+function getPhotoCount($path)
+{
+ $files = scandir($path);
+ $fileCount = 0;
+ foreach ($files as $key => $value) {
+ $realPath = realpath($path . DIRECTORY_SEPARATOR . $value);
+ if (isValidImage($realPath)) {
+ $fileCount++;
+ }
+ }
+ return $fileCount;
+}
+
+/**
+ * Get the count of all directories, recursively from the path specified
+ * @param string $path root for search
+ * @return int total number of directories
+ */
+function getTotalAlbumCount($path)
+{
+ $folders = getDirectories($path);
+ $total = sizeof($folders);
+ foreach ($folders as $key => $value) {
+ $total += getTotalAlbumCount($path . DIRECTORY_SEPARATOR . $value);
+ }
+ return $total;
+ }
+
+function getTotalPhotoCount($path)
+{
+ $folders = getDirectories($path);
+ $total = getPhotoCount($path);
+ foreach ($folders as $key => $value) {
+ $total += getTotalPhotoCount($path . DIRECTORY_SEPARATOR . $value);
+ }
+ return $total;
+}
+
+/**
+ * Check if the given image is valid
+ * @param string $imagePath absolute path of the image
+ * @return bool True if the file is a jpg, jpeg or png, false otherwise
+ */
+function isValidImage($imagePath)
+{
+ $ext = pathinfo($imagePath, PATHINFO_EXTENSION);
+ return !is_dir($imagePath) && ($ext == "jpg" || $ext == "JPG" || $ext == "jpeg" || $ext == "JPEG" || $ext == "png" || $ext == "PNG");
+}
+
+/**
+ * Check if the given folder is valid (is not '.' or '..')
+ * @param string $directoryPath directory path
+ * @param string $directory directory name
+ * @return bool True if the directory is valid, false otherwise
+ */
+function isValidDirectory($directoryPath, $directory)
+{
+ return is_dir($directoryPath) && $directory != "." && $directory != ".." && substr($directory, 0, 1) !== ".";
+}
+
+
+/**
+ * Creates buttons representing the actual path for easier navigation
+ * @param string $path Actual Path
+ */
+function generatePath($path)
+{
+ $folders = explode(DIRECTORY_SEPARATOR, $path);
+ $currentPath = "";
+ $pathTitle = "Menu";
+ $pathLink = "?" . urlParam . "=";
+ echo '
Clique sur le dossier de ton choix pour afficher les photos. Il faut que tu sois inscrit à l'INSA pour pouvoir + les regarder (et oui, pas de spoiler). +
++ Si tu ne peux pas voir les photos (la fenêtre pour entrer le mot de passe ne s'affiche pas), ouvre cette page + avec + un autre navigateur. +
+Chemin :