From a6b949e31a4c511f25dcf7f0fc0dda2bab862739 Mon Sep 17 00:00:00 2001 From: Victor Häggqvist Date: Wed, 13 Jan 2016 17:05:44 +0100 Subject: basic working click on image --- js/touch-imagelightbox.js | 334 ----------------------------------------- package.json | 21 ++- sass/_variables.scss | 2 - sass/touch-imagelightbox.scss | 214 -------------------------- src/CSSUtil.js | 55 +++++++ src/LightBox.js | 193 ++++++++++++++++++++++++ src/Log/Log.js | 52 +++++++ src/Log/LogLevel.js | 9 ++ src/touch-imagelightbox.js | 334 +++++++++++++++++++++++++++++++++++++++++ style/_variables.scss | 2 + style/touch-imagelightbox.scss | 214 ++++++++++++++++++++++++++ 11 files changed, 872 insertions(+), 558 deletions(-) delete mode 100644 js/touch-imagelightbox.js delete mode 100644 sass/_variables.scss delete mode 100644 sass/touch-imagelightbox.scss create mode 100644 src/CSSUtil.js create mode 100644 src/LightBox.js create mode 100644 src/Log/Log.js create mode 100644 src/Log/LogLevel.js create mode 100644 src/touch-imagelightbox.js create mode 100644 style/_variables.scss create mode 100644 style/touch-imagelightbox.scss diff --git a/js/touch-imagelightbox.js b/js/touch-imagelightbox.js deleted file mode 100644 index f5bbe2f..0000000 --- a/js/touch-imagelightbox.js +++ /dev/null @@ -1,334 +0,0 @@ -/*jslint browser: true*/ -;( function( $, window, document, undefined ) { - 'use strict'; - var options, - cssTransitionSupport = function() { - var d = document.body || document.documentElement, s = d.style; - if ( s.WebkitTransition === '' ) - return '-webkit-'; - if ( s.MozTransition === '' ) - return '-moz-'; - if ( s.OTransition === '' ) - return '-o-'; - if ( s.transition === '' ) - return ''; - return false; - }, - - isCssTransitionSupport = cssTransitionSupport() === false ? false : true, - - cssTransitionTranslateX = function( element, positionX, speed ) { - options = {}; - var prefix = cssTransitionSupport(); - options[ prefix + 'transform' ] = 'translateX(' + positionX + ')'; - options[ prefix + 'transition' ] = prefix + 'transform ' + speed + 's linear'; - element.css( options ); - }, - - hasTouch = ( 'ontouchstart' in window ), - hasPointers = window.navigator.pointerEnabled || window.navigator.msPointerEnabled, - wasTouched = function( event ) { - if( hasTouch ) - return true; - - if( !hasPointers || typeof event === 'undefined' || typeof event.pointerType === 'undefined' ) - return false; - - if( typeof event.MSPOINTER_TYPE_MOUSE !== 'undefined' ) { - if( event.MSPOINTER_TYPE_MOUSE !== event.pointerType ) - return true; - } else { - if( event.pointerType !== 'mouse' ) - return true; - } - - return false; - }; - - $.fn.imageLightbox = function( options ) { - options = $.extend( - { - selector: 'id="imagelightbox"', - allowedTypes: 'png|jpg|jpeg|gif', - animationSpeed: 250, - preloadNext: true, - enableKeyboard: true, - quitOnEnd: false, - quitOnImgClick: false, - quitOnDocClick: true, - onStart: false, - onEnd: false, - onLoadStart: false, - onLoadEnd: false - }, - options); - - var targets = $([]), - target = $(), - image = $(), - imageWidth = 0, - imageHeight = 0, - swipeDiff = 0, - inProgress = false, - - isTargetValid = function( element ) { - /*jshint -W044*/ - options.regexValidObject = new RegExp("(\.("+options.allowedTypes+")$)"); - /*jshint +W044*/ - return $( element ).prop( 'tagName' ).toLowerCase() === 'a' && options.regexValidObject.test($(element).attr('href') ); - }, - - setImage = function() { - if( !image.length ) return false; - - var screenWidth = $( window ).width() * 0.8, - screenHeight = $( window ).height() * 0.9, - tmpImage = new Image(); - - tmpImage.src = image.attr( 'src' ); - tmpImage.onload = function() { - imageWidth = tmpImage.width; - imageHeight = tmpImage.height; - - if( imageWidth > screenWidth || imageHeight > screenHeight ) { - var ratio = imageWidth / imageHeight > screenWidth / screenHeight ? imageWidth / screenWidth : imageHeight / screenHeight; - imageWidth /= ratio; - imageHeight /= ratio; - } - - image.css( - { - 'width': imageWidth + 'px', - 'height': imageHeight + 'px', - 'top': ( $( window ).height() - imageHeight ) / 2 + 'px', - 'left': ( $( window ).width() - imageWidth ) / 2 + 'px' - } - ); - }; - }, - - loadImage = function( direction ) { - if( inProgress ) return false; - - direction = typeof direction === 'undefined' ? false : direction === 'left' ? 1 : -1; - - // BIG if - if( image.length ) { - if( direction !== false && - ( targets.length < 2 || - ( options.quitOnEnd === true && - ( - ( direction === -1 && - targets.index( target ) === 0 - ) || - ( direction === 1 && - targets.index( target ) === targets.length - 1 - ) ) ) ) - ) - { - quitLightbox(); - return false; - } - var params = { 'opacity': 0 }; - if( isCssTransitionSupport ){ - cssTransitionTranslateX( image, ( 100 * direction ) - swipeDiff + 'px', options.animationSpeed / 1000 ); - } else { - params.left = parseInt( image.css( 'left' ) ) + 100 * direction + 'px'; - } - image.animate( params, options.animationSpeed, function(){ removeImage(); }); - swipeDiff = 0; - } - - inProgress = true; - if( options.onLoadStart !== false ) options.onLoadStart(); - - setTimeout( function() { - image = $( '' ) - .attr( 'src', target.attr( 'href' ) ) - .load( function() - { - image.appendTo( 'body' ); - setImage(); - - var params = { 'opacity': 1 }; - - image.css( 'opacity', 0 ); - if( isCssTransitionSupport ) - { - cssTransitionTranslateX( image, -100 * direction + 'px', 0 ); - setTimeout( function(){ - cssTransitionTranslateX( image, 0 + 'px', options.animationSpeed / 1000 ); - }, 50 ); - } - else - { - var imagePosLeft = parseInt( image.css( 'left' ) ); - params.left = imagePosLeft + 'px'; - image.css( 'left', imagePosLeft - 100 * direction + 'px' ); - } - - image.animate( params, options.animationSpeed, function() - { - inProgress = false; - if( options.onLoadEnd !== false ) options.onLoadEnd(); - }); - if( options.preloadNext ) - { - var nextTarget = targets.eq( targets.index( target ) + 1 ); - if( !nextTarget.length ) nextTarget = targets.eq( 0 ); - $( '' ).attr( 'src', nextTarget.attr( 'href' ) ).load(); - } - }) - .error( function() { - if( options.onLoadEnd !== false ) - options.onLoadEnd(); - }); - - var swipeStart = 0, - swipeEnd = 0, - imagePosLeft = 0; - - image.on( hasPointers ? 'pointerup MSPointerUp' : 'click', function( e ) { - e.preventDefault(); - if( options.quitOnImgClick ) { - quitLightbox(); - return false; - } - - if( wasTouched( e.originalEvent ) ) - return true; - - var posX = ( e.pageX || e.originalEvent.pageX ) - e.target.offsetLeft; - target = targets.eq( targets.index( target ) - ( imageWidth / 2 > posX ? 1 : -1 ) ); - - if( !target.length ) - target = targets.eq( imageWidth / 2 > posX ? targets.length : 0 ); - - loadImage( imageWidth / 2 > posX ? 'left' : 'right' ); - }) - .on( 'touchstart pointerdown MSPointerDown', function( e ) { - if( !wasTouched( e.originalEvent ) || options.quitOnImgClick ) - return true; - if( isCssTransitionSupport ) - imagePosLeft = parseInt( image.css( 'left' ) ); - - swipeStart = e.originalEvent.pageX || e.originalEvent.touches[ 0 ].pageX; - }) - .on( 'touchmove pointermove MSPointerMove', function( e ) { - if( !wasTouched( e.originalEvent ) || options.quitOnImgClick ) - return true; - - e.preventDefault(); - swipeEnd = e.originalEvent.pageX || e.originalEvent.touches[ 0 ].pageX; - swipeDiff = swipeStart - swipeEnd; - - if( isCssTransitionSupport ) - cssTransitionTranslateX( image, -swipeDiff + 'px', 0 ); - else - image.css( 'left', imagePosLeft - swipeDiff + 'px' ); - }) - .on( 'touchend touchcancel pointerup MSPointerUp', function( e ) { - if( !wasTouched( e.originalEvent ) || options.quitOnImgClick ) - return true; - if( Math.abs( swipeDiff ) > 50 ) { - target = targets.eq( targets.index( target ) - ( swipeDiff < 0 ? 1 : -1 ) ); - - if( !target.length ) - target = targets.eq( swipeDiff < 0 ? targets.length : 0 ); - loadImage( swipeDiff > 0 ? 'right' : 'left' ); - } else { - if( isCssTransitionSupport ) - cssTransitionTranslateX( image, 0 + 'px', options.animationSpeed / 1000 ); - else - image.animate({ 'left': imagePosLeft + 'px' }, options.animationSpeed / 2 ); - } - }); - - }, options.animationSpeed + 100 ); - }, - - removeImage = function() { - if( !image.length ) - return false; - image.remove(); - image = $(); - }, - - quitLightbox = function() { - if( !image.length ) - return false; - image.animate({ 'opacity': 0 }, options.animationSpeed, function() { - removeImage(); - inProgress = false; - if( options.onEnd !== false ) - options.onEnd(); - }); - }; - - $( window ).on( 'resize', setImage ); - - if( options.quitOnDocClick ) { - $( document ).on( hasTouch ? 'touchend' : 'click', function( e ) { - if( image.length && !$( e.target ).is( image ) ) quitLightbox(); - }); - } - - if( options.enableKeyboard ) { - $( document ).on( 'keyup', function( e ) { - if( !image.length ) - return true; - - e.preventDefault(); - - if( e.keyCode === 27 ) - quitLightbox(); - - if( e.keyCode === 37 || e.keyCode === 39 ) { - target = targets.eq( targets.index( target ) - ( e.keyCode === 37 ? 1 : -1 ) ); - - if( !target.length ) - target = targets.eq( e.keyCode === 37 ? targets.length : 0 ); - - loadImage( e.keyCode === 37 ? 'left' : 'right' ); - } - }); - } - - $( document ).on( 'click', this.selector, function( e ) { - if( !isTargetValid( this ) ) - return true; - e.preventDefault(); - - if( inProgress ) - return false; - inProgress = false; - - if( options.onStart !== false ) - options.onStart(); - target = $( this ); - loadImage(); - }); - - this.each( function() { - if( !isTargetValid( this ) ) return true; - targets = targets.add( $( this ) ); - }); - - this.switchImageLightbox = function( index ) { - var tmpTarget = targets.eq( index ); - if( tmpTarget.length ) { - var currentIndex = targets.index( target ); - target = tmpTarget; - loadImage( index < currentIndex ? 'left' : 'right' ); - } - return this; - }; - - this.quitImageLightbox = function() { - quitLightbox(); - return this; - }; - - return this; - }; -})( jQuery, window, document ); diff --git a/package.json b/package.json index ca64d21..959af42 100644 --- a/package.json +++ b/package.json @@ -24,13 +24,18 @@ }, "homepage": "https://github.com/victorhaggqvist/touch-imagelightbox", "devDependencies": { - "grunt": "~0.4.2", - "grunt-contrib-clean": "^0.5.0", - "grunt-contrib-concat": "~0.4.0", - "grunt-contrib-copy": "^0.5.0", - "grunt-contrib-jshint": "~0.10.0", - "grunt-contrib-sass": "^0.7.3", - "grunt-contrib-uglify": "~0.5.0", - "grunt-contrib-watch": "~0.6.1" + "babel-eslint": "^5.0.0-beta6", + "babel-loader": "^6.2.1", + "babel-preset-es2015": "^6.3.13", + "gulp": "^3.9.0", + "gulp-autoprefixer": "^3.1.0", + "gulp-babel": "^6.1.1", + "gulp-csso": "^1.0.1", + "gulp-eslint": "^1.1.1", + "gulp-rename": "^1.2.2", + "gulp-sass": "^2.1.1", + "gulp-size": "^2.0.0", + "gulp-uglify": "^1.5.1", + "webpack-stream": "^3.1.0" } } diff --git a/sass/_variables.scss b/sass/_variables.scss deleted file mode 100644 index d2deae5..0000000 --- a/sass/_variables.scss +++ /dev/null @@ -1,2 +0,0 @@ -$closebutton-size: 40px; -$loadingbox-size: 20px; diff --git a/sass/touch-imagelightbox.scss b/sass/touch-imagelightbox.scss deleted file mode 100644 index c9df56f..0000000 --- a/sass/touch-imagelightbox.scss +++ /dev/null @@ -1,214 +0,0 @@ -@import 'compass/css3'; -@import 'variables'; - -@mixin touch-action($value) { - -ms-touch-action: $value; - touch-action: $value; -} - -html { - // killing 300ms touch delay in IE - @include touch-action(manipulation); -} - -#imagelightbox { - @include touch-action(none); - @include box-shadow(rgba(0, 0, 0, .75) 0 0 50px); - cursor: pointer; - position: fixed; - z-index: 10000; -} - -// Loading Indication -#imagelightbox-loading, -#imagelightbox-loading div { - @include border-radius(50%); -} - -#imagelightbox-loading { - @include box-shadow(rgba(0, 0, 0, .75) 0 0 $loadingbox-size*2); - - background: #444; // Fallback - background: rgba(0, 0, 0, .5); - height: $loadingbox-size; - left: 50%; - margin: -20px 0 0 -20px; - padding: 10px; - position: fixed; - top: 50%; - width: $loadingbox-size; - z-index: 10003; - - div { - -moz-animation: imagelightbox-loading .5s ease infinite; - -o-animation: imagelightbox-loading .5s ease infinite; - -webkit-animation: imagelightbox-loading .5s ease infinite; - animation: imagelightbox-loading .5s ease infinite; - - background-color: #fff; - height: 20px; - width: 20px; - } -} - -@-webkit-keyframes imagelightbox-loading { - 0% { opacity: .5; -webkit-transform: scale(.75); } - 50% { opacity: 1; -webkit-transform: scale(1); } - 100% { opacity: .5; -webkit-transform: scale(.75); } -} - -@-moz-keyframes imagelightbox-loading { - 0% { opacity: .5; -moz-transform: scale(.75); } - 50% { opacity: 1; -moz-transform: scale(1); } - 100% { opacity: .5; -moz-transform: scale(.75); } -} - -@-o-keyframes imagelightbox-loading { - 0% { opacity: .5; -o-transform: scale(.75); } - 50% { opacity: 1; -o-transform: scale(1); } - 100% { opacity: .5; -o-transform: scale(.75); } -} - -@keyframes imagelightbox-loading { - 0% { opacity: .5; transform: scale(.75); } - 50% { opacity: 1; transform: scale(1); } - 100% { opacity: .5; transform: scale(.75); } -} - -#imagelightbox-overlay { - background: #fff; - background: rgba(255, 255, 255, .9); - bottom: 0; - left: 0; - position: fixed; - right: 0; - top: 0; - z-index: 9998; -} - - -// Close button -#imagelightbox-close { - @include border-radius(50%); - - - background-color: #666; - height: $closebutton-size; - position: fixed; - right: $closebutton-size; - text-align: left; - text-indent: -9999px; - top: $closebutton-size; - -moz-transition: color .3s ease; - -ms-transition: color .3s ease; - -o-transition: color .3s ease; - -webkit-transition: color .3s ease; - transition: color .3s ease; - width: $closebutton-size; - z-index: 10002; - - &:hover { - background-color: #111; - } - - &:before, - &:after { - background-color: #fff; - bottom: 20%; - content: ''; - left: 50%; - margin-left: -1px; - position: absolute; - top: 20%; - width: 2px; - } - - &:before { - @include rotate(45deg); - } - - &:after { - @include rotate(-45deg); - } -} - -#imagelightbox-caption { - background-color: #666; - bottom: 0; - color: #fff; - left: 0; - padding: 10px; - position: fixed; - right: 0; - text-align: center; - z-index: 10001; -} - -// The nav bubbles -#imagelightbox-nav { - @include border-radius(20px); - @include translateX(-50%); - - background-color: #444; - background-color: rgba(0, 0, 0, .5); - bottom: 60px; // 60 - left: 50%; - padding: 5px 2px 1px; - position: fixed; - z-index: 10001; - - a { - @include border-radius(50%); - border: 1px solid #fff; - display: inline-block; - height: 20px; - margin: 0 5px; - width: 20px; - } - - .active { - background-color: #fff; - } -} - -#imagelightbox-loading, -#imagelightbox-overlay, -#imagelightbox-close, -#imagelightbox-caption, -#imagelightbox-nav { - -moz-animation: fade-in .25s linear; - -o-animation: fade-in .25s linear; - -webkit-animation: fade-in .25s linear; - animation: fade-in .25s linear; -} - -@-webkit-keyframes fade-in { - 0% { opacity: 0; } - 100% { opacity: 1; } -} - -@-moz-keyframes fade-in { - 0% { opacity: 0; } - 100% { opacity: 1; } -} - -@-o-keyframes fade-in { - 0% { opacity: 0; } - 100% { opacity: 1; } -} - -@keyframes fade-in { - 0% { opacity: 0; } - 100% { opacity: 1; } -} - -@media only screen and (max-width: 660px) { - #imagelightbox-close { - right: 20px; - top: 20px; - } - - #imagelightbox-nav { - bottom: 20px; - } -} diff --git a/src/CSSUtil.js b/src/CSSUtil.js new file mode 100644 index 0000000..f08a0da --- /dev/null +++ b/src/CSSUtil.js @@ -0,0 +1,55 @@ +/** + * Created by Victor Häggqvist on 1/12/16. + */ + +export class CSSUtil { + + /** + * transion need to be set on property + * + * using key-value dont work + * + * @param ele + * @param value + */ + static setTransitionProperty(ele, value) { + if (ele.transition === '') { + ele.transition = value; + return; + } + if (ele.WebkitTransition === '') { + ele.WebkitTransition = value; + return; + } + if (ele.MozTransition === '') { + ele.MozTransition = value; + return; + } + if (ele.OTransition === '') { + ele.OTransition = value; + } + } + + static cssTransitionSupport() { + let d = document.body || document.documentElement, s = d.style; + if (s.WebkitTransition === '') + return '-webkit-'; + if (s.MozTransition === '') + return '-moz-'; + if (s.OTransition === '') + return '-o-'; + if (s.transition === '') + return ''; + return false; + } + + static cssTransitionTranslateX(element, positionX, speed) { + let options = {}; + let prefix = CSSUtil.cssTransitionSupport(); + element.style[prefix + 'transform'] = 'translateX(' + positionX + ')'; + element.style[prefix + 'transition'] = prefix + 'transform ' + speed + 's linear'; + //element.style = Object.assign(options, element.style); + } + +} +CSSUtil.isCssTransitionSupport = CSSUtil.cssTransitionSupport() !== false; diff --git a/src/LightBox.js b/src/LightBox.js new file mode 100644 index 0000000..15d2cdd --- /dev/null +++ b/src/LightBox.js @@ -0,0 +1,193 @@ +/** + * Created by Victor Häggqvist on 1/12/16. + */ + +import {CSSUtil} from './CSSUtil' +import {Log as L} from './Log/Log' +import {animate} from './animate' +import {FetchImage} from './FetchImage' + + +export class LightBox { + + constructor(targetSelector, options = {}) { + this.targets = document.querySelectorAll(targetSelector); + + const defaultOptions = { + allowedTypes: 'png|jpg|jpeg|gif', + animationSpeed: 250, + preloadNext: true, + enableKeyboard: true, + quitOnEnd: false, + quitOnImgClick: false, + quitOnDocClick: true, + onStart: false, + onEnd: false, + onLoadStart: false, + onLoadEnd: false + }; + + this.options = Object.assign(options, defaultOptions); + console.log(this.options); + + this.target = null; + this.image = document.createElement('img'); + this.imageWidth = 0; + this.imageHeight = 0; + this.swipeDiff = 0; + this.inProgress = false; + + this.bindEvents(); + } + + bindEvents() { + console.log(this.targets); + + Array.prototype.forEach.call(this.targets, ele => { + ele.onclick = this.onImageClick.bind(this) + }); + window.addEventListener('resize', this.windowResizeListener.bind(this)); + } + + onImageClick(event) { + console.log(event); + let element = event.srcElement.parentElement; + //console.log(this.isTargetValid(element)); + if (!this.isTargetValid(element)) return true; + + event.preventDefault(); + + if (this.inProgress) return; + + this.inProgress = false; + + if (this.options.onStart !== false ) this.options.onStart(); + + this.target = element; + + this.loadImage(); + } + + isTargetValid(element) { + let validTypes = new RegExp("(\.("+this.options.allowedTypes+")$)"); + + //console.log(element.tagName.toLowerCase()); + return element.tagName.toLowerCase() === 'a' && validTypes.test(element.href); + + //return $( element ).prop( 'tagName' ).toLowerCase() === 'a' && options.regexValidObject.test($(element).attr('href') ); + } + + loadImage(direction = false) { + L.l('loadImage'); + L.l(this.inProgress); + if (this.inProgress) return false; + L.l('not progress'); + // if image.length + //if () + + this.inProgress = true; + if (this.options.onLoadStart !== false) this.options.onLoadStart(); + + setTimeout(() => { + L.l('loadImage in'); + FetchImage(this.target.href).then(image => { + this.image = image; + image.id='imagelightbox'; + console.log(image); + + //let image = new Image(); + //image.src = this.target.href; + + L.l(image); + document.body.appendChild(image); + //image.appendTo('body'); + L.d('setImage'); + this.setImage(); + + var params = {opacity: 1}; + image.style.opacity = 0; + + let prefix = CSSUtil.cssTransitionSupport(); + CSSUtil.setTransitionProperty(image.style, 'opacity .3s linear'); + //image.style[prefix + 'transform'] = 'opacity 25s linear'; + //image.style.transition = 'opacity .3s linear'; + image.style.transform = 'translateX(0px)'; + + setTimeout(() => { + // without timeout it's to fast to make it fade and just jumps to 1 instant + image.style.opacity = 1; + }, 5); + + if (this.options.preloadNext) { + console.log(this.options.preloadNext); + Array.prototype.forEach.call(this.targets, (t) => { + if (t == this.target) { + console.log(t); + console.log('match'); + } + }); + // + ////this.targets. + //let nextTarget = targets.eq(targets.index(target) + 1); + //if (!nextTarget.length) nextTarget = targets.eq(0); + //$('').attr('src', nextTarget.attr('href')).load(); + } + + + this.image = image; + }); + }, this.options.animationSpeed + 100) + } + + //static animate(elem,style,unit,from,to,time) { + // if( !elem) return; + // var start = new Date().getTime(), + // timer = setInterval(function() { + // var step = Math.min(1,(new Date().getTime()-start)/time); + // elem.style[style] = (from+step*(to-from))+unit; + // if( step == 1) clearInterval(timer); + // },25); + // elem.style[style] = from+unit; + //} + + //animate(id, direction, value, end, speed) { + // var div = document.getElementById(id); + // interval = setInterval(function() { + // if (+(div.style) === end) { + // clearInterval(interval); + // return false; + // } + // div.style[direction] += value; // or -= as per your needs + // }, speed); + //} + + setImage() { + L.l(this.image); + if (!this.image) return false; + + let screenWidth = window.innerWidth * 0.8; + let screenHeight = window.innerHeight * 0.9; + + let tmpImage = new Image(); + tmpImage.src = this.image.src; + tmpImage.onload = () => { + this.imageWidth = tmpImage.width; + this.imageHeight = tmpImage.height; + + if (this.imageWidth > screenWidth || this.imageHeight > screenHeight) { + let ratio = this.imageWidth / this.imageHeight > screenWidth / screenHeight ? this.imageWidth / screenWidth : this.imageHeight / screenHeight; + this.imageWidth /= ratio; + this.imageHeight /= ratio; + } + + this.image.style.width = this.imageWidth + 'px'; + this.image.style.height = this.imageHeight + 'px'; + this.image.style.top = (window.innerHeight - this.imageHeight) / 2 + 'px'; + this.image.style.left = (window.innerWidth - this.imageWidth) / 2 + 'px'; + }; + } + + windowResizeListener() { + console.log('resized') + } +} diff --git a/src/Log/Log.js b/src/Log/Log.js new file mode 100644 index 0000000..e01d9dc --- /dev/null +++ b/src/Log/Log.js @@ -0,0 +1,52 @@ +/** + * Created by Victor Häggqvist on 1/12/16. + */ + +import {LogLevel} from './LogLevel' + +export class Log { + + //var instance = null; + static init() { + Log.level = LogLevel.DEBUG; + } + + static silence() { + Log.level = LogLevel.SILENT; + } + + static l(msg) { + Log.log(msg, 'log'); + } + + static w(msg) { + Log.log(msg, 'warn'); + } + + static d(msg) { + Log.log(msg, 'debug'); + //console.debug(Log.explode(msg)); + } + + static log(args, type='log') { + let baked = Log.explode(args); + + if (Log.level === LogLevel.SILENT) return; + + switch (type) { + case 'info': return console.info(baked); + case 'log': return console.log(baked); + case 'warn': return console.warn(baked); + case 'debug': return console.debug(baked); + } + + } + + static explode(args) { + if (!Array.isArray(args)) { + return args; + } + + return args; + } +} diff --git a/src/Log/LogLevel.js b/src/Log/LogLevel.js new file mode 100644 index 0000000..23ba8f9 --- /dev/null +++ b/src/Log/LogLevel.js @@ -0,0 +1,9 @@ +/** + * Created by Victor Häggqvist on 1/12/16. + */ + +export class LogLevel {} +LogLevel.SILENT = 0; +LogLevel.INFO = 1; +LogLevel.VERBOSE = 1; +LogLevel.DEBUG = 1; diff --git a/src/touch-imagelightbox.js b/src/touch-imagelightbox.js new file mode 100644 index 0000000..f5bbe2f --- /dev/null +++ b/src/touch-imagelightbox.js @@ -0,0 +1,334 @@ +/*jslint browser: true*/ +;( function( $, window, document, undefined ) { + 'use strict'; + var options, + cssTransitionSupport = function() { + var d = document.body || document.documentElement, s = d.style; + if ( s.WebkitTransition === '' ) + return '-webkit-'; + if ( s.MozTransition === '' ) + return '-moz-'; + if ( s.OTransition === '' ) + return '-o-'; + if ( s.transition === '' ) + return ''; + return false; + }, + + isCssTransitionSupport = cssTransitionSupport() === false ? false : true, + + cssTransitionTranslateX = function( element, positionX, speed ) { + options = {}; + var prefix = cssTransitionSupport(); + options[ prefix + 'transform' ] = 'translateX(' + positionX + ')'; + options[ prefix + 'transition' ] = prefix + 'transform ' + speed + 's linear'; + element.css( options ); + }, + + hasTouch = ( 'ontouchstart' in window ), + hasPointers = window.navigator.pointerEnabled || window.navigator.msPointerEnabled, + wasTouched = function( event ) { + if( hasTouch ) + return true; + + if( !hasPointers || typeof event === 'undefined' || typeof event.pointerType === 'undefined' ) + return false; + + if( typeof event.MSPOINTER_TYPE_MOUSE !== 'undefined' ) { + if( event.MSPOINTER_TYPE_MOUSE !== event.pointerType ) + return true; + } else { + if( event.pointerType !== 'mouse' ) + return true; + } + + return false; + }; + + $.fn.imageLightbox = function( options ) { + options = $.extend( + { + selector: 'id="imagelightbox"', + allowedTypes: 'png|jpg|jpeg|gif', + animationSpeed: 250, + preloadNext: true, + enableKeyboard: true, + quitOnEnd: false, + quitOnImgClick: false, + quitOnDocClick: true, + onStart: false, + onEnd: false, + onLoadStart: false, + onLoadEnd: false + }, + options); + + var targets = $([]), + target = $(), + image = $(), + imageWidth = 0, + imageHeight = 0, + swipeDiff = 0, + inProgress = false, + + isTargetValid = function( element ) { + /*jshint -W044*/ + options.regexValidObject = new RegExp("(\.("+options.allowedTypes+")$)"); + /*jshint +W044*/ + return $( element ).prop( 'tagName' ).toLowerCase() === 'a' && options.regexValidObject.test($(element).attr('href') ); + }, + + setImage = function() { + if( !image.length ) return false; + + var screenWidth = $( window ).width() * 0.8, + screenHeight = $( window ).height() * 0.9, + tmpImage = new Image(); + + tmpImage.src = image.attr( 'src' ); + tmpImage.onload = function() { + imageWidth = tmpImage.width; + imageHeight = tmpImage.height; + + if( imageWidth > screenWidth || imageHeight > screenHeight ) { + var ratio = imageWidth / imageHeight > screenWidth / screenHeight ? imageWidth / screenWidth : imageHeight / screenHeight; + imageWidth /= ratio; + imageHeight /= ratio; + } + + image.css( + { + 'width': imageWidth + 'px', + 'height': imageHeight + 'px', + 'top': ( $( window ).height() - imageHeight ) / 2 + 'px', + 'left': ( $( window ).width() - imageWidth ) / 2 + 'px' + } + ); + }; + }, + + loadImage = function( direction ) { + if( inProgress ) return false; + + direction = typeof direction === 'undefined' ? false : direction === 'left' ? 1 : -1; + + // BIG if + if( image.length ) { + if( direction !== false && + ( targets.length < 2 || + ( options.quitOnEnd === true && + ( + ( direction === -1 && + targets.index( target ) === 0 + ) || + ( direction === 1 && + targets.index( target ) === targets.length - 1 + ) ) ) ) + ) + { + quitLightbox(); + return false; + } + var params = { 'opacity': 0 }; + if( isCssTransitionSupport ){ + cssTransitionTranslateX( image, ( 100 * direction ) - swipeDiff + 'px', options.animationSpeed / 1000 ); + } else { + params.left = parseInt( image.css( 'left' ) ) + 100 * direction + 'px'; + } + image.animate( params, options.animationSpeed, function(){ removeImage(); }); + swipeDiff = 0; + } + + inProgress = true; + if( options.onLoadStart !== false ) options.onLoadStart(); + + setTimeout( function() { + image = $( '' ) + .attr( 'src', target.attr( 'href' ) ) + .load( function() + { + image.appendTo( 'body' ); + setImage(); + + var params = { 'opacity': 1 }; + + image.css( 'opacity', 0 ); + if( isCssTransitionSupport ) + { + cssTransitionTranslateX( image, -100 * direction + 'px', 0 ); + setTimeout( function(){ + cssTransitionTranslateX( image, 0 + 'px', options.animationSpeed / 1000 ); + }, 50 ); + } + else + { + var imagePosLeft = parseInt( image.css( 'left' ) ); + params.left = imagePosLeft + 'px'; + image.css( 'left', imagePosLeft - 100 * direction + 'px' ); + } + + image.animate( params, options.animationSpeed, function() + { + inProgress = false; + if( options.onLoadEnd !== false ) options.onLoadEnd(); + }); + if( options.preloadNext ) + { + var nextTarget = targets.eq( targets.index( target ) + 1 ); + if( !nextTarget.length ) nextTarget = targets.eq( 0 ); + $( '' ).attr( 'src', nextTarget.attr( 'href' ) ).load(); + } + }) + .error( function() { + if( options.onLoadEnd !== false ) + options.onLoadEnd(); + }); + + var swipeStart = 0, + swipeEnd = 0, + imagePosLeft = 0; + + image.on( hasPointers ? 'pointerup MSPointerUp' : 'click', function( e ) { + e.preventDefault(); + if( options.quitOnImgClick ) { + quitLightbox(); + return false; + } + + if( wasTouched( e.originalEvent ) ) + return true; + + var posX = ( e.pageX || e.originalEvent.pageX ) - e.target.offsetLeft; + target = targets.eq( targets.index( target ) - ( imageWidth / 2 > posX ? 1 : -1 ) ); + + if( !target.length ) + target = targets.eq( imageWidth / 2 > posX ? targets.length : 0 ); + + loadImage( imageWidth / 2 > posX ? 'left' : 'right' ); + }) + .on( 'touchstart pointerdown MSPointerDown', function( e ) { + if( !wasTouched( e.originalEvent ) || options.quitOnImgClick ) + return true; + if( isCssTransitionSupport ) + imagePosLeft = parseInt( image.css( 'left' ) ); + + swipeStart = e.originalEvent.pageX || e.originalEvent.touches[ 0 ].pageX; + }) + .on( 'touchmove pointermove MSPointerMove', function( e ) { + if( !wasTouched( e.originalEvent ) || options.quitOnImgClick ) + return true; + + e.preventDefault(); + swipeEnd = e.originalEvent.pageX || e.originalEvent.touches[ 0 ].pageX; + swipeDiff = swipeStart - swipeEnd; + + if( isCssTransitionSupport ) + cssTransitionTranslateX( image, -swipeDiff + 'px', 0 ); + else + image.css( 'left', imagePosLeft - swipeDiff + 'px' ); + }) + .on( 'touchend touchcancel pointerup MSPointerUp', function( e ) { + if( !wasTouched( e.originalEvent ) || options.quitOnImgClick ) + return true; + if( Math.abs( swipeDiff ) > 50 ) { + target = targets.eq( targets.index( target ) - ( swipeDiff < 0 ? 1 : -1 ) ); + + if( !target.length ) + target = targets.eq( swipeDiff < 0 ? targets.length : 0 ); + loadImage( swipeDiff > 0 ? 'right' : 'left' ); + } else { + if( isCssTransitionSupport ) + cssTransitionTranslateX( image, 0 + 'px', options.animationSpeed / 1000 ); + else + image.animate({ 'left': imagePosLeft + 'px' }, options.animationSpeed / 2 ); + } + }); + + }, options.animationSpeed + 100 ); + }, + + removeImage = function() { + if( !image.length ) + return false; + image.remove(); + image = $(); + }, + + quitLightbox = function() { + if( !image.length ) + return false; + image.animate({ 'opacity': 0 }, options.animationSpeed, function() { + removeImage(); + inProgress = false; + if( options.onEnd !== false ) + options.onEnd(); + }); + }; + + $( window ).on( 'resize', setImage ); + + if( options.quitOnDocClick ) { + $( document ).on( hasTouch ? 'touchend' : 'click', function( e ) { + if( image.length && !$( e.target ).is( image ) ) quitLightbox(); + }); + } + + if( options.enableKeyboard ) { + $( document ).on( 'keyup', function( e ) { + if( !image.length ) + return true; + + e.preventDefault(); + + if( e.keyCode === 27 ) + quitLightbox(); + + if( e.keyCode === 37 || e.keyCode === 39 ) { + target = targets.eq( targets.index( target ) - ( e.keyCode === 37 ? 1 : -1 ) ); + + if( !target.length ) + target = targets.eq( e.keyCode === 37 ? targets.length : 0 ); + + loadImage( e.keyCode === 37 ? 'left' : 'right' ); + } + }); + } + + $( document ).on( 'click', this.selector, function( e ) { + if( !isTargetValid( this ) ) + return true; + e.preventDefault(); + + if( inProgress ) + return false; + inProgress = false; + + if( options.onStart !== false ) + options.onStart(); + target = $( this ); + loadImage(); + }); + + this.each( function() { + if( !isTargetValid( this ) ) return true; + targets = targets.add( $( this ) ); + }); + + this.switchImageLightbox = function( index ) { + var tmpTarget = targets.eq( index ); + if( tmpTarget.length ) { + var currentIndex = targets.index( target ); + target = tmpTarget; + loadImage( index < currentIndex ? 'left' : 'right' ); + } + return this; + }; + + this.quitImageLightbox = function() { + quitLightbox(); + return this; + }; + + return this; + }; +})( jQuery, window, document ); diff --git a/style/_variables.scss b/style/_variables.scss new file mode 100644 index 0000000..d2deae5 --- /dev/null +++ b/style/_variables.scss @@ -0,0 +1,2 @@ +$closebutton-size: 40px; +$loadingbox-size: 20px; diff --git a/style/touch-imagelightbox.scss b/style/touch-imagelightbox.scss new file mode 100644 index 0000000..c9df56f --- /dev/null +++ b/style/touch-imagelightbox.scss @@ -0,0 +1,214 @@ +@import 'compass/css3'; +@import 'variables'; + +@mixin touch-action($value) { + -ms-touch-action: $value; + touch-action: $value; +} + +html { + // killing 300ms touch delay in IE + @include touch-action(manipulation); +} + +#imagelightbox { + @include touch-action(none); + @include box-shadow(rgba(0, 0, 0, .75) 0 0 50px); + cursor: pointer; + position: fixed; + z-index: 10000; +} + +// Loading Indication +#imagelightbox-loading, +#imagelightbox-loading div { + @include border-radius(50%); +} + +#imagelightbox-loading { + @include box-shadow(rgba(0, 0, 0, .75) 0 0 $loadingbox-size*2); + + background: #444; // Fallback + background: rgba(0, 0, 0, .5); + height: $loadingbox-size; + left: 50%; + margin: -20px 0 0 -20px; + padding: 10px; + position: fixed; + top: 50%; + width: $loadingbox-size; + z-index: 10003; + + div { + -moz-animation: imagelightbox-loading .5s ease infinite; + -o-animation: imagelightbox-loading .5s ease infinite; + -webkit-animation: imagelightbox-loading .5s ease infinite; + animation: imagelightbox-loading .5s ease infinite; + + background-color: #fff; + height: 20px; + width: 20px; + } +} + +@-webkit-keyframes imagelightbox-loading { + 0% { opacity: .5; -webkit-transform: scale(.75); } + 50% { opacity: 1; -webkit-transform: scale(1); } + 100% { opacity: .5; -webkit-transform: scale(.75); } +} + +@-moz-keyframes imagelightbox-loading { + 0% { opacity: .5; -moz-transform: scale(.75); } + 50% { opacity: 1; -moz-transform: scale(1); } + 100% { opacity: .5; -moz-transform: scale(.75); } +} + +@-o-keyframes imagelightbox-loading { + 0% { opacity: .5; -o-transform: scale(.75); } + 50% { opacity: 1; -o-transform: scale(1); } + 100% { opacity: .5; -o-transform: scale(.75); } +} + +@keyframes imagelightbox-loading { + 0% { opacity: .5; transform: scale(.75); } + 50% { opacity: 1; transform: scale(1); } + 100% { opacity: .5; transform: scale(.75); } +} + +#imagelightbox-overlay { + background: #fff; + background: rgba(255, 255, 255, .9); + bottom: 0; + left: 0; + position: fixed; + right: 0; + top: 0; + z-index: 9998; +} + + +// Close button +#imagelightbox-close { + @include border-radius(50%); + + + background-color: #666; + height: $closebutton-size; + position: fixed; + right: $closebutton-size; + text-align: left; + text-indent: -9999px; + top: $closebutton-size; + -moz-transition: color .3s ease; + -ms-transition: color .3s ease; + -o-transition: color .3s ease; + -webkit-transition: color .3s ease; + transition: color .3s ease; + width: $closebutton-size; + z-index: 10002; + + &:hover { + background-color: #111; + } + + &:before, + &:after { + background-color: #fff; + bottom: 20%; + content: ''; + left: 50%; + margin-left: -1px; + position: absolute; + top: 20%; + width: 2px; + } + + &:before { + @include rotate(45deg); + } + + &:after { + @include rotate(-45deg); + } +} + +#imagelightbox-caption { + background-color: #666; + bottom: 0; + color: #fff; + left: 0; + padding: 10px; + position: fixed; + right: 0; + text-align: center; + z-index: 10001; +} + +// The nav bubbles +#imagelightbox-nav { + @include border-radius(20px); + @include translateX(-50%); + + background-color: #444; + background-color: rgba(0, 0, 0, .5); + bottom: 60px; // 60 + left: 50%; + padding: 5px 2px 1px; + position: fixed; + z-index: 10001; + + a { + @include border-radius(50%); + border: 1px solid #fff; + display: inline-block; + height: 20px; + margin: 0 5px; + width: 20px; + } + + .active { + background-color: #fff; + } +} + +#imagelightbox-loading, +#imagelightbox-overlay, +#imagelightbox-close, +#imagelightbox-caption, +#imagelightbox-nav { + -moz-animation: fade-in .25s linear; + -o-animation: fade-in .25s linear; + -webkit-animation: fade-in .25s linear; + animation: fade-in .25s linear; +} + +@-webkit-keyframes fade-in { + 0% { opacity: 0; } + 100% { opacity: 1; } +} + +@-moz-keyframes fade-in { + 0% { opacity: 0; } + 100% { opacity: 1; } +} + +@-o-keyframes fade-in { + 0% { opacity: 0; } + 100% { opacity: 1; } +} + +@keyframes fade-in { + 0% { opacity: 0; } + 100% { opacity: 1; } +} + +@media only screen and (max-width: 660px) { + #imagelightbox-close { + right: 20px; + top: 20px; + } + + #imagelightbox-nav { + bottom: 20px; + } +} -- cgit v1.2.3