summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorVictor Häggqvist <[email protected]>2016-01-13 17:05:44 +0100
committerVictor Häggqvist <[email protected]>2016-01-13 17:05:44 +0100
commita6b949e31a4c511f25dcf7f0fc0dda2bab862739 (patch)
treeda3d13a5c6b341a5501d0108a999cdb11c27d1b5 /src
parent489015e2558f528e1d6f988f3f03c8f3633c0256 (diff)
basic working click on image
Diffstat (limited to 'src')
-rw-r--r--src/CSSUtil.js55
-rw-r--r--src/LightBox.js193
-rw-r--r--src/Log/Log.js52
-rw-r--r--src/Log/LogLevel.js9
-rw-r--r--src/touch-imagelightbox.js334
5 files changed, 643 insertions, 0 deletions
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);
+ //$('<img />').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 = $( '<img ' + options.selector + ' />' )
+ .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 );
+ $( '<img />' ).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 );