File: /home/hanode/public_html/wp-content/plugins/sw_core/js/photobox.js
/*!
photobox v1.8.0
(c) 2013 Yair Even Or <http://dropthebit.com>
Uses jQuery-mousewheel Version: 3.0.6 by:
(c) 2009 Brandon Aaron <http://brandonaaron.net>
MIT-style license.
*/
(function($, doc, win){
"use strict";
var Photobox, photoboxes = [], photobox, options, images=[], imageLinks, activeImage = -1, activeURL, lastActive, activeType, prevImage, nextImage, thumbsStripe, docElm, APControl,
transitionend = "transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd",
isOldIE = !('placeholder' in doc.createElement('input')),
noPointerEvents = (function(){ var el = $('<p>')[0]; el.style.cssText = 'pointer-events:auto'; return !el.style.pointerEvents})(),
isMobile = 'ontouchend' in doc,
thumbsContainerWidth, thumbsTotalWidth, activeThumb = $(),
blankImg = "data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==",
transformOrigin = getPrefixed('transformOrigin'),
transition = getPrefixed('transition'),
// Preload images
preload = {}, preloadPrev = new Image(), preloadNext = new Image(),
// DOM elements
closeBtn, image, video, prevBtn, nextBtn, caption, captionText, pbLoader, autoplayBtn, thumbs, wrapper,
defaults = {
loop: true, // Allows to navigate between first and last images
thumbs: true, // Show gallery thumbnails below the presented photo
counter: true, // Counter text (example [24/62])
title: true, // show the original alt or title attribute of the image's thumbnail
autoplay: false, // should autoplay on first time or not
time: 3000, // autoplay interna, in miliseconds (less than 1000 will hide the autoplay button)
history: true, // should use history hashing if possible (HTML5 API)
hideFlash: true, // Hides flash elements on the page when photobox is activated. NOTE: flash elements must have wmode parameter set to "opaque" or "transparent" if this is set to false
zoomable: true, // disable/enable mousewheel image zooming
keys: {
close: '27, 88, 67', // keycodes to close Picbox, default: Esc (27), 'x' (88), 'c' (67)
prev: '37, 80', // keycodes to navigate to the previous image, default: Left arrow (37), 'p' (80)
next: '39, 78' // keycodes to navigate to the next image, default: Right arrow (39), 'n' (78)
}
},
// DOM structure
overlay = $('<div id="pbOverlay">').append(
pbLoader = $('<div class="pbLoader"><b></b><b></b><b></b></div>'),
prevBtn = $('<div id="pbPrevBtn" class="prevNext"><b></b></div>').on('click', next_prev),
nextBtn = $('<div id="pbNextBtn" class="prevNext"><b></b></div>').on('click', next_prev),
wrapper = $('<div class="wrapper">').append( // gives Perspective
image = $('<img>'),
video = $('<div>')
),
closeBtn = $('<div id="pbCloseBtn">').on('click', close)[0],
autoplayBtn = $('<div id="pbAutoplayBtn">').append(
$('<div class="pbProgress">')
),
caption = $('<div id="pbCaption">').append(
captionText = $('<div class="pbCaptionText">').append('<div class="title"></div><div class="counter">'),
thumbs = $('<div>').addClass('pbThumbs')
)
);
/*---------------------------------------------------------------
Initialization (on DOM ready)
*/
function prepareDOM(){
// if useragent is IE < 10 (user deserves a slap on the face, but I gotta support them still...)
isOldIE && overlay.addClass('msie');
noPointerEvents && overlay.hide();
autoplayBtn.on('click', APControl.toggle);
// attach a delegated event on the thumbs container
thumbs.on('click', 'a', thumbsStripe.click);
// enable scrolling gesture on mobile
isMobile && thumbs.css('overflow', 'auto');
// cancel prppogation up to the overlay container so it won't close
overlay.on('click', 'img', function(e){
e.stopPropagation();
});
$(doc.body).prepend( $(overlay) );
// need this for later:
docElm = doc.documentElement;
}
// @param [List of elements to work on, Custom settings, Callback after image is loaded]
$.fn.photobox = function(target, settings, callback){
if( $(this).data('_photobox') ) // don't initiate the plugin more than once on the same element
return this;
if( typeof target != 'string' )
target = 'a';
if( target === 'prepareDOM' ){
prepareDOM();
return this;
}
var _options = $.extend({}, defaults, settings || {}),
pb = new Photobox(_options, this, target);
// Saves the insance on the gallery's target element
$(this).data('_photobox', pb);
// add a callback to the specific gallery
pb.callback = callback;
// save every created gallery pointer
photoboxes.push( pb );
return this;
}
Photobox = function(_options, object, target){
this.options = $.extend({}, _options);
this.target = target;
this.selector = $(object || doc);
this.thumbsList = null;
// filter the links which actually HAS an image as a child
var filtered = this.imageLinksFilter( object.find(target) );
this.imageLinks = filtered[0]; // Array of jQuery links
this.images = filtered[1]; // 2D Array of image url & title
this.init();
};
Photobox.prototype = {
init : function(){
var that = this;
// only generates the thumbStripe once, and listen for any DOM changes on the selector element, if so, re-generate
if( this.options.thumbs )
// generate gallery thumbnails every time (cause links might have been changed dynamicly)
this.thumbsList = thumbsStripe.generate(this.imageLinks);
this.selector.on('click.photobox', this.target, function(e){
e.preventDefault();
that.open(this);
});
// if any node was added or removed from the Selector of the gallery
this.observerTimeout = null;
if( this.selector[0].nodeType == 1 ) // observe normal nodes
that.observeDOM( that.selector[0] ,function(){
// use a timeout to prevent more than one DOM change event fireing at once, and also to overcome the fact that IE's DOMNodeRemoved is fired BEFORE elements were actually removed
clearTimeout(that.observerTimeout);
that.observerTimeout = setTimeout( function(){
var filtered = that.imageLinksFilter( that.selector.find(that.target) );
that.imageLinks = filtered[0];
that.images = filtered[1];
that.thumbsList = thumbsStripe.generate(that.imageLinks);
}, 50);
});
},
open : function(link){
var startImage = $.inArray(link, this.imageLinks);
// if image link does not exist in the imageLinks array (probably means it's not a valid part of the galery)
if( startImage == -1 ) return false;
// load the right gallery selector...
options = this.options;
images = this.images;
imageLinks = this.imageLinks;
photobox = this;
this.setup(1);
overlay.on(transitionend, function(){
overlay.off(transitionend).addClass('on'); // class 'on' is set when the initial fade-in of the overlay is done
changeImage(startImage, true);
}).addClass('show');
if( isOldIE )
overlay.trigger('MSTransitionEnd');
return false;
},
imageLinksFilter : function(obj){
var images = [];
return [obj.filter(function(i){
var link = this, img = $(link).find('img')[0];
// if no img child found in the link
if( !img ) return false;
images.push([link.href, img.getAttribute('alt') || img.getAttribute('title') || '']);
return true;
}), images];
},
//check if DOM nodes were added or removed, to re-build the imageLinks and thumbnails
observeDOM : (function(){
var MutationObserver = win.MutationObserver || win.WebKitMutationObserver,
eventListenerSupported = win.addEventListener;
return function(obj, callback){
if( MutationObserver ){
// define a new observer
var obs = new MutationObserver(function(mutations, observer){
if( mutations[0].addedNodes.length || mutations[0].removedNodes.length )
callback();
});
// have the observer observe foo for changes in children
obs.observe( obj, { childList:true, subtree:true });
}
else if( eventListenerSupported ){
obj.addEventListener('DOMNodeInserted', callback, false);
obj.addEventListener('DOMNodeRemoved', callback, false);
}
}
})(),
// things that should happend everytime the gallery opens or closes (some messed up code below..)
setup : function (open){
var fn = open ? "on" : "off";
// a hack to change the image src to nothing, because you can't do that in CHROME
image[0].src = blankImg;
if( open ){
image.css({'transition':'0s'}).removeAttr('style'); // reset any transition that might be on the element (yes it's ugly)
overlay.show();
// Clean up if another gallery was veiwed before, which had a thumbsList
thumbs.html( this.thumbsList );
overlay[options.thumbs ? 'addClass' : 'removeClass']('thumbs');
if( options.thumbs ){
activeThumb.removeAttr('class');
$(win).on('resize.photobox', thumbsStripe.calc);
thumbsStripe.calc(); // initiate the function for the first time without any window resize
}
// things to hide if there are less than 2 images
if( this.images.length < 2 )
overlay.removeClass('thumbs hasArrows hasCounter hasAutoplay');
else{
overlay.addClass('hasArrows hasCounter')
// check is the autoplay button should be visible (per gallery) and if so, should it autoplay or not.
if( options.time > 1000 ){
overlay.addClass('hasAutoplay');
if( options.autoplay )
APControl.progress.start();
else
APControl.pause();
}
else
overlay.removeClass('hasAutoplay');
}
} else {
$(win).off('resize.photobox');
}
if( options.hideFlash ){
$.each(["object", "embed"], function(i, val){
$(val).each(function(){
if (open) this._photobox = this.style.visibility;
this.style.visibility = open ? "hidden" : this._photobox;
});
});
}
$(doc)[fn]({ "keydown.photobox": keyDown });
if( 'ontouchstart' in document.documentElement ){
overlay.removeClass('hasArrows'); // no need for Arros on touch-enabled
wrapper[fn]('swipe', onSwipe);
}
if( options.zoomable ){
overlay[fn]({"mousewheel.photobox": scrollZoom });
if( !isOldIE) thumbs[fn]({"mousewheel.photobox": thumbsResize });
}
},
destroy : function(){
this.selector
.off('click.photobox', this.target)
.removeData('_photobox');
close();
return this.selector;
}
}
// on touch-devices only
function onSwipe(e, Dx, Dy){
if( Dx == 1 ){
image.css({transform:'translateX(25%)', transition:'.7s', opacity:0});
setTimeout(function(){ changeImage(prevImage) }, 200);
}
else if( Dx == -1 ){
image.css({transform:'translateX(-25%)', transition:'.7s', opacity:0});
setTimeout(function(){ changeImage(nextImage) }, 200);
}
if( Dy == 1 )
thumbs.addClass('show');
else if( Dy == -1 )
thumbs.removeClass('show');
}
// manage the (bottom) thumbs strip
thumbsStripe = {
// returns a <ul> element which is populated with all the gallery links and thumbs
generate : function(imageLinks){
var thumbsList = $('<ul>'), link, elements = [], i, len = imageLinks.size(), title, image, type;
for( i = 0; i < len; i++ ){
link = imageLinks[i];
image = $(link).find('img');
title = image[0].title || image[0].alt || '';
type = link.rel ? " class='" + link.rel +"'" : '';
elements.push('<li'+ type +'><a href="'+ link.href +'"><img src="'+ image[0].src +'" alt="" title="'+ title +'" /></a></li>');
};
thumbsList.html( elements.join('') );
return thumbsList;
},
click : function(e){
e.preventDefault();
activeThumb.removeClass('active');
activeThumb = $(this).parent().addClass('active');
var imageIndex = $(this.parentNode).index();
return changeImage(imageIndex, 0, 1);
},
changeActiveTimeout : null,
/** Highlights the thumb which represents the photo and centers the thumbs viewer on it.
** @thumbClick - if a user clicked on a thumbnail, don't center on it
*/
changeActive : function(index, delay, thumbClick){
var lastIndex = activeThumb.index();
activeThumb.removeClass('active');
activeThumb = thumbs.find('li').eq(index).addClass('active');
if( thumbClick ) return;
// set the scrollLeft position of the thumbs list to show the active thumb
clearTimeout(this.changeActiveTimeout);
// give the images time to to settle on their new sizes (because of css transition) and then calculate the center...
this.changeActiveTimeout = setTimeout(
function(){
var pos = activeThumb[0].offsetLeft + activeThumb[0].clientWidth/2 - docElm.clientWidth/2;
delay ? thumbs.delay(800) : thumbs.stop();
thumbs.animate({scrollLeft: pos}, 500, 'swing');
}, 200);
},
// claculate the thumbs container width is the window has been resized
calc : function(){
thumbsContainerWidth = thumbs[0].clientWidth;
thumbsTotalWidth = thumbs[0].firstChild.clientWidth;
var state = thumbsTotalWidth > thumbsContainerWidth ? 'on' : 'off';
!isMobile && thumbs[state]('mousemove', thumbsStripe.move);
return this;
},
// move the stipe left or right acording to mouse position
move : function(e){
var ratio = thumbsTotalWidth / thumbsContainerWidth;
thumbs[0].scrollLeft = e.pageX * ratio - 500;
}
};
// Autoplay controller
APControl = {
autoPlayTimer : false,
play : function(){
APControl.autoPlayTimer = setTimeout(function(){ changeImage(nextImage) }, options.time);
APControl.progress.start();
autoplayBtn.removeClass('play');
APControl.setTitle('Click to stop autoplay');
options.autoplay = true;
},
pause : function(){
clearTimeout(APControl.autoPlayTimer);
APControl.progress.reset();
autoplayBtn.addClass('play');
APControl.setTitle('Click to resume autoplay');
options.autoplay = false;
},
progress : {
reset : function(){
autoplayBtn.find('div').removeAttr('style');
setTimeout(function(){ autoplayBtn.removeClass('playing') },200);
},
start : function(){
if( !isOldIE)
autoplayBtn.find('div').css(transition, options.time+'ms');
autoplayBtn.addClass('playing');
}
},
// sets the button Title property
setTitle : function(text){
if(text)
autoplayBtn.prop('title', text + ' (every ' + options.time/1000 + ' seconds)' );
},
// the button onClick handler
toggle : function(e){
e.stopPropagation();
APControl[ options.autoplay ? 'pause' : 'play']();
}
}
function getPrefixed(prop){
var i, s = doc.createElement('p').style, v = ['ms','O','Moz','Webkit'];
if( s[prop] == '' ) return prop;
prop = prop.charAt(0).toUpperCase() + prop.slice(1);
for( i = v.length; i--; )
if( s[v[i] + prop] == '' )
return (v[i] + prop);
}
function keyDown(event){
var code = event.keyCode, ok = options.keys, result;
// Prevent default keyboard action (like navigating inside the page)
return ok.close.indexOf(code) >= 0 && close() ||
ok.next.indexOf(code) >= 0 && changeImage(nextImage) ||
ok.prev.indexOf(code) >= 0 && changeImage(prevImage) || true;
}
// serves as a callback for pbPrevBtn / pbNextBtn buttons but also is called on keypress events
function next_prev(){
// don't get crazy when user clicks next or prev buttons rapidly
//if( !image.hasClass('zoomable') )
// return false;
var img = (this.id == 'pbPrevBtn') ? prevImage : nextImage;
changeImage(img);
return false;
}
function changeImage(imageIndex, firstTime, thumbClick){
if( !imageIndex || imageIndex < 0 )
imageIndex = 0;
overlay.removeClass('error').addClass( imageIndex > activeImage ? 'next' : 'prev' );
lastActive = activeImage;
activeImage = imageIndex;
activeURL = images[imageIndex][0];
prevImage = (activeImage || (options.loop ? images.length : 0)) - 1;
nextImage = ((activeImage + 1) % images.length) || (options.loop ? 0 : -1);
// reset things
stop();
video.empty();
preload.onerror = null;
image.add(video).data('zoom', 1);
activeType = imageLinks[imageIndex].rel == 'video' ? 'video' : 'image';
// check if corrent link is a video
if( activeType == 'video' ){
video.html( newVideo() ).addClass('hide');
showContent(firstTime);
}
else{
// give a tiny delay to the preloader, so it won't be showed when images are already cached
var loaderTimeout = setTimeout(function(){ overlay.addClass('pbLoading'); },50);
// hide/show next-prev buttons
if( !options.loop ){
nextBtn[ imageIndex == images.length-1 ? 'addClass' : 'removeClass' ]('hide');
prevBtn[ imageIndex == 0 ? 'addClass' : 'removeClass' ]('hide');
}
if( prevImage >= 0 ) preloadPrev.src = images[prevImage][0];
if( nextImage >= 0 ) preloadNext.src = images[nextImage][0];
if( isOldIE ) overlay.addClass('hide'); // should wait for the image onload. just hide the image while old ie display the preloader
options.autoplay && APControl.progress.reset();
preload = new Image();
preload.onload = function(){ clearTimeout(loaderTimeout); showContent(firstTime); };
preload.onerror = imageError;
preload.src = activeURL;
}
// Show Caption text
captionText.on(transitionend, captionTextChange).addClass('change');
if( firstTime || isOldIE ) captionTextChange();
if( options.thumbs )
thumbsStripe.changeActive(imageIndex, firstTime, thumbClick);
// Save url hash for current image
history.save();
}
function newVideo(){
var url = images[activeImage][0],
sign = $('<a>').prop('href',images[activeImage][0])[0].search ? '&' : '?';
url += sign + 'vq=hd720&wmode=opaque';
return $("<iframe>").prop({ scrolling:'no', frameborder:0, allowTransparency:true, src:url }).attr({webkitAllowFullScreen:true, mozallowfullscreen:true, allowFullScreen:true});
}
// show the item's Title & Counter
function captionTextChange(){
captionText.off(transitionend).removeClass('change');
// change caption's text
options.counter && caption.find('.counter').text('(' + (activeImage + 1) + ' / ' + images.length + ')');
options.title && caption.find('.title').text( images[activeImage][1] );
}
// Handles the history states when changing images
var history = {
save : function(){
// only save to history urls which are not already in the hash
if('pushState' in window.history && decodeURIComponent(window.location.hash.slice(1)) != activeURL && options.history ){
window.history.pushState( 'photobox', doc.title + '-' + images[activeImage][1], window.location.pathname + window.location.search + '#' + encodeURIComponent(activeURL) );
}
},
load : function(){
if( options && !options.history ) return false;
var hash = decodeURIComponent( window.location.hash.slice(1) ), i, j;
if( !hash && overlay.hasClass('show') )
close();
else
// Scan all galleries for the image link (open the first gallery that has the link's image)
for( i = 0; i < photoboxes.length; i++ )
for( j in photoboxes[i].images )
if( photoboxes[i].images[j][0] == hash ){
photoboxes[i].open( photoboxes[i].imageLinks[j] );
return true;
}
},
clear : function(){
if( options.history && 'pushState' in window.history )
window.history.pushState('photobox', doc.title, window.location.pathname + window.location.search);
}
};
// Add Photobox special `onpopstate` to the `onpopstate` function
window.onpopstate = (function(){
var cached = window.onpopstate;
return function(event){
cached && cached.apply(this, arguments);
if( event.state == 'photobox' )
history.load();
}
})();
// handles all image loading error (if image is dead)
function imageError(){
overlay.addClass('error');
image[0].src = blankImg; // set the source to a blank image
preload.onerror = null;
}
// Shows the content (image/video) on the screen
function showContent(firstTime){
var out, showSaftyTimer;
showSaftyTimer = setTimeout(show, 2000);
overlay.removeClass("pbLoading").addClass('hide');
image.add(video).removeAttr('style').removeClass('zoomable'); // while transitioning an image, do not apply the 'zoomable' class
// check which element needs to transition-out:
if( !firstTime && imageLinks[lastActive].rel == 'video' ){
out = video;
image.addClass('prepare');
}
else
out = image;
if( firstTime || isOldIE )
show();
else
out.on(transitionend, show);
// in case the 'transitionend' didn't fire
// after hiding the last seen image, show the new one
function show(){
clearTimeout(showSaftyTimer);
out.off(transitionend).css({'transition':'none'});
overlay.removeClass('video');
if( activeType == 'video' ){
image[0].src = blankImg;
video.addClass('prepare');
overlay.addClass('video');
}
else
image.prop({ 'src':activeURL, 'class':'prepare' });
// filthy hack for the transitionend event, but cannot work without it:
setTimeout(function(){
image.add(video).removeAttr('style').removeClass('prepare');
overlay.removeClass('hide next prev');
setTimeout(function(){
image.add(video).on(transitionend, showDone);
if(isOldIE) showDone(); // IE9 and below don't support transitionEnd...
}, 0);
},50);
}
}
// a callback whenever a transition of an image or a video is done
function showDone(){
image.add(video).off(transitionend).addClass('zoomable');
if( activeType == 'video' )
video.removeClass('hide');
else
autoplayBtn && options.autoplay && APControl.play();
if( typeof photobox.callback == 'function' )
photobox.callback.apply(imageLinks[activeImage]);
}
function scrollZoom(e, delta){
if( activeType == 'video' ){
var zoomLevel = video.data('zoom') || 1;
zoomLevel += (delta / 10);
if( zoomLevel < 0.5 )
return false;
video.data('zoom', zoomLevel).css({width:624*zoomLevel, height:351*zoomLevel});
}
else{
var zoomLevel = image.data('zoom') || 1,
getSize = image[0].getBoundingClientRect();
zoomLevel += (delta / 10);
if( zoomLevel < 0.1 )
zoomLevel = 0.1;
image.data('zoom', zoomLevel).css({'transform':'scale('+ zoomLevel +')'});
// check if dragging should take effect (if image is larger than the window
if( getSize.height > docElm.clientHeight || getSize.width > docElm.clientWidth ){
$(doc).on('mousemove.photobox', imageReposition);
}
else{
$(doc).off('mousemove.photobox');
image[0].style[transformOrigin] = '50% 50%';
}
}
return false;
}
function thumbsResize(e, delta){
e.preventDefault();
e.stopPropagation(); // stop the event from bubbling up to the Overlay and enlarge the content itself
var thumbList = photobox.thumbsList;
thumbList.css('height', thumbList[0].clientHeight + (delta * 10) );
var h = caption[0].clientHeight / 2;
wrapper[0].style.cssText = "margin-top: -"+ h +"px; padding: "+ h +"px 0;";
thumbs.hide().show(0);
thumbsStripe.calc();
}
// moves the image around during zoom mode on mousemove event
function imageReposition(e){
var y = (e.clientY / docElm.clientHeight) * (docElm.clientHeight + 200) - 100, // extend the range of the Y axis by 100 each side
yDelta = y / docElm.clientHeight * 100,
xDelta = e.clientX / docElm.clientWidth * 100,
origin = xDelta.toFixed(2)+'% ' + yDelta.toFixed(2) +'%';
image[0].style[transformOrigin] = origin;
}
function stop(){
clearTimeout(APControl.autoPlayTimer);
$(doc).off('mousemove.photobox');
preload.onload = function(){};
preload.src = preloadPrev.src = preloadNext.src = activeURL;
}
function close(){
stop();
video.find('iframe').prop('src','').empty();
Photobox.prototype.setup();
history.clear();
overlay.removeClass('on video').addClass('hide');
image.on(transitionend, hide);
isOldIE && hide();
function hide(){
if( overlay[0].className == '' ) return; // if already hidden
overlay.removeClass('show hide error pbLoading');
image.removeAttr('class').removeAttr('style').off().data('zoom',1);
if(noPointerEvents) // pointer-events lack support in IE, so just hide the overlay
setTimeout(function(){ overlay.hide(); }, 200);
}
// fallback if the 'transitionend' event didn't fire
setTimeout(hide, 500);
}
/*! Copyright (c) 2011 Brandon Aaron (http://brandonaaron.net)
* Licensed under the MIT License (LICENSE.txt).
*
* Version: 3.0.6
*/
var types = ['DOMMouseScroll', 'mousewheel'];
if ($.event.fixHooks){
for ( var i=types.length; i; )
$.event.fixHooks[ types[--i] ] = $.event.mouseHooks;
}
$.event.special.mousewheel = {
setup: function(){
if( this.addEventListener ){
for ( var i=types.length; i; )
this.addEventListener( types[--i], handler, false );
}else
this.onmousewheel = handler;
},
teardown: function(){
if ( this.removeEventListener ){
for ( var i=types.length; i; )
this.removeEventListener( types[--i], handler, false );
}else
this.onmousewheel = null;
}
};
$.fn.extend({
mousewheel: function(fn){
return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel");
},
unmousewheel: function(fn){
return this.unbind("mousewheel", fn);
}
});
function handler(event){
var orgEvent = event || win.event, args = [].slice.call( arguments, 1 ), delta = 0, returnValue = true, deltaX = 0, deltaY = 0;
event = $.event.fix(orgEvent);
event.type = "mousewheel";
// Old school scrollwheel delta
if( orgEvent.wheelDelta ){ delta = orgEvent.wheelDelta/120; }
if( orgEvent.detail ){ delta = -orgEvent.detail/3; }
// New school multidimensional scroll (touchpads) deltas
deltaY = delta;
// Gecko
if( orgEvent.axis !== undefined && orgEvent.axis === orgEvent.HORIZONTAL_AXIS ){
deltaY = 0;
deltaX = -1*delta;
}
// Webkit
if( orgEvent.wheelDeltaY !== undefined ){ deltaY = orgEvent.wheelDeltaY/120; }
if( orgEvent.wheelDeltaX !== undefined ){ deltaX = -1*orgEvent.wheelDeltaX/120; }
// Add event and delta to the front of the arguments
args.unshift(event, delta, deltaX, deltaY);
return ($.event.dispatch || $.event.handle).apply(this, args);
}
/**
* jQuery Plugin to add basic "swipe" support on touch-enabled devices
*
* @author Yair Even Or
* @version 1.0.0 (March 20, 2013)
*/
$.event.special.swipe = {
setup: function(){
$(this).bind('touchstart', $.event.special.swipe.handler);
},
teardown: function(){
$(this).unbind('touchstart', $.event.special.swipe.handler);
},
handler: function(event){
var args = [].slice.call( arguments, 1 ), // clone arguments array, remove original event from cloned array
touches = event.originalEvent.touches,
startX, startY,
deltaX = 0, deltaY = 0,
that = this;
event = $.event.fix(event);
if( touches.length == 1 ){
startX = touches[0].pageX;
startY = touches[0].pageY;
this.addEventListener('touchmove', onTouchMove, false);
}
function cancelTouch(){
that.removeEventListener('touchmove', onTouchMove);
startX = startY = null;
}
function onTouchMove(e){
e.preventDefault();
var Dx = startX - e.touches[0].pageX,
Dy = startY - e.touches[0].pageY;
if( Math.abs(Dx) >= 20 ){
cancelTouch();
deltaX = (Dx > 0) ? -1 : 1;
}
else if( Math.abs(Dy) >= 20 ){
cancelTouch();
deltaY = (Dy > 0) ? 1 : -1;
}
event.type = 'swipe';
args.unshift(event, deltaX, deltaY); // add back the new event to the front of the arguments with the delatas
return ($.event.dispatch || $.event.handle).apply(that, args);
}
}
};
$(doc).ready(prepareDOM);
// expose outside
window._photobox = {
history : history
};
})(jQuery, document, window);