add files
This commit is contained in:
471
assets/js/vendor/images-compare/jquery.images-compare.js
vendored
Normal file
471
assets/js/vendor/images-compare/jquery.images-compare.js
vendored
Normal file
@@ -0,0 +1,471 @@
|
||||
/** global: Hammer */
|
||||
;(function ($, window) {
|
||||
"use strict";
|
||||
|
||||
function stringRepeat(s, precision) {
|
||||
// String repeat polyfill
|
||||
if (!String.prototype.repeat) {
|
||||
precision = precision || 1;
|
||||
return new Array(precision + 1).join(s);
|
||||
}
|
||||
return s.repeat(precision);
|
||||
}
|
||||
|
||||
var pluginName = 'imagesCompare',
|
||||
defaults = {
|
||||
initVisibleRatio: 0.5,
|
||||
interactionMode: "drag", // "drag", "mousemove", "click"
|
||||
animationDuration: 400, // default animation duration in ms
|
||||
animationEasing: "swing",
|
||||
addSeparator: true, // add a html element on the separation
|
||||
addDragHandle: true, // add a html drag handle element on the separation
|
||||
precision: 4
|
||||
};
|
||||
|
||||
// Our object, using revealing module pattern
|
||||
function ImagesCompare(element, options) {
|
||||
element = $(element);
|
||||
options = $.extend({}, defaults, options);
|
||||
options.roundFactor = parseInt('1' + stringRepeat('0', options.precision));
|
||||
|
||||
this._name = pluginName;
|
||||
|
||||
var frontElement, backElement, separator, dragHandle, lastRatio = 1, size = {
|
||||
width: 0,
|
||||
height: 0,
|
||||
maxWidth: 0,
|
||||
maxHeight: 0
|
||||
}, events = {
|
||||
initialised: "imagesCompare:initialised",
|
||||
changed: "imagesCompare:changed",
|
||||
resized: "imagesCompare:resized"
|
||||
};
|
||||
|
||||
function onImagesLoaded() {
|
||||
var images = element.find('img'),
|
||||
totalImagesCount= images.length,
|
||||
elementsLoaded = 0;
|
||||
|
||||
function onImageLoaded(){
|
||||
if (elementsLoaded >= totalImagesCount) {
|
||||
init();
|
||||
}
|
||||
}
|
||||
|
||||
images.each(function() {
|
||||
// Image already loaded (cached)
|
||||
if ($(this)[0].complete) {
|
||||
totalImagesCount--;
|
||||
onImageLoaded();
|
||||
} else {
|
||||
// Image loading / error
|
||||
$(this).on('load', function() {
|
||||
elementsLoaded++;
|
||||
onImageLoaded();
|
||||
});
|
||||
$(this).on('error', function() {
|
||||
elementsLoaded++;
|
||||
onImageLoaded();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onImagesLoaded();
|
||||
|
||||
function init() {
|
||||
updateDom();
|
||||
patchSize();
|
||||
initInteractions();
|
||||
|
||||
$(frontElement).attr('ratio', options.initVisibleRatio);
|
||||
setVisibleRatio(options.initVisibleRatio);
|
||||
|
||||
// Let the world know we have done the init
|
||||
element.trigger({
|
||||
type: events.initialised
|
||||
});
|
||||
}
|
||||
|
||||
function addResize() {
|
||||
$(window).on('resize', function (event) {
|
||||
frontElement.css('clip', '');
|
||||
patchSize();
|
||||
setVisibleRatio(lastRatio);
|
||||
|
||||
// Let the world know we have done some resize updates
|
||||
element.trigger({
|
||||
type: events.resized,
|
||||
originalEvent: event
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function initInteractions() {
|
||||
options.interactionMode = options.interactionMode.toLowerCase();
|
||||
|
||||
if (options.interactionMode != "drag" && options.interactionMode != "mousemove" && options.interactionMode != "click") {
|
||||
console.warn('No valid interactionMode found, valid values are "drag", "mousemove", "click"');
|
||||
}
|
||||
|
||||
switch (options.interactionMode) {
|
||||
case "drag":
|
||||
initDrag();
|
||||
break;
|
||||
case "mousemove":
|
||||
initMouseMove();
|
||||
break;
|
||||
case "click":
|
||||
initClick();
|
||||
break;
|
||||
default:
|
||||
initDrag();
|
||||
}
|
||||
}
|
||||
|
||||
function initDrag() {
|
||||
if (typeof Hammer == 'undefined') {
|
||||
console.error('Please include the hammerjs library for drag support');
|
||||
}
|
||||
addDrag();
|
||||
addResize();
|
||||
}
|
||||
|
||||
function initMouseMove() {
|
||||
addMouseMove();
|
||||
addResize();
|
||||
}
|
||||
|
||||
function initClick() {
|
||||
addClick();
|
||||
addResize();
|
||||
}
|
||||
|
||||
function addClick() {
|
||||
element.on('click', function (event) {
|
||||
var ratio = getElementRatio(event.pageX);
|
||||
setVisibleRatio(ratio);
|
||||
});
|
||||
}
|
||||
|
||||
function addMouseMove() {
|
||||
var lastMove = 0;
|
||||
var eventThrottle = 1;
|
||||
element.on('mousemove', function (event) {
|
||||
event.preventDefault();
|
||||
var now = Date.now();
|
||||
if (now > lastMove + eventThrottle) {
|
||||
lastMove = now;
|
||||
var ratio = getElementRatio(event.pageX);
|
||||
setVisibleRatio(ratio);
|
||||
}
|
||||
});
|
||||
|
||||
element.on('mouseout', function (event) {
|
||||
var ratio = getElementRatio(event.pageX);
|
||||
setVisibleRatio(ratio);
|
||||
});
|
||||
}
|
||||
|
||||
function addDrag() {
|
||||
var hammertime = new Hammer(element[0]);
|
||||
hammertime.get('pan').set({direction: Hammer.DIRECTION_HORIZONTAL});
|
||||
hammertime.on('pan', function (event) {
|
||||
var ratio = getElementRatio(event.srcEvent.pageX);
|
||||
setVisibleRatio(ratio);
|
||||
});
|
||||
}
|
||||
|
||||
function updateDom() {
|
||||
element.addClass('images-compare-container');
|
||||
element.css('display', 'inline-block');
|
||||
|
||||
frontElement = element.find('> *:nth-child(1)');
|
||||
backElement = element.find('> *:nth-child(2)');
|
||||
|
||||
frontElement.addClass("images-compare-before");
|
||||
frontElement.css('display', 'block');
|
||||
backElement.addClass("images-compare-after");
|
||||
backElement.css('display', 'block');
|
||||
|
||||
if (options.addDragHandle) {
|
||||
buildDragHandle();
|
||||
}
|
||||
|
||||
if (options.addSeparator) {
|
||||
buildSeparator();
|
||||
}
|
||||
}
|
||||
|
||||
function buildSeparator() {
|
||||
element.prepend("<div class='images-compare-separator'></div>");
|
||||
separator = element.find(".images-compare-separator");
|
||||
|
||||
}
|
||||
|
||||
function buildDragHandle() {
|
||||
element.prepend("<div class='images-compare-handle'></div>");
|
||||
dragHandle = element.find(".images-compare-handle");
|
||||
dragHandle.append("<span class='images-compare-left-arrow'></span>");
|
||||
dragHandle.append("<span class='images-compare-right-arrow'></span>");
|
||||
}
|
||||
|
||||
function patchSize() {
|
||||
var imgRef = backElement.find('img').first();
|
||||
setSize(imgRef.width(), imgRef.height(), imgRef.naturalWidth(), imgRef.naturalHeight());
|
||||
element.css('max-width', size.maxWidth + 'px');
|
||||
element.css('max-height', size.maxHeight + 'px');
|
||||
frontElement.width(size.width);
|
||||
frontElement.height(size.height);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param x
|
||||
* @return float
|
||||
*/
|
||||
function getElementRatio(x) {
|
||||
return roundRatio((x - element.offset().left) / frontElement.width());
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param ratio
|
||||
* @return float
|
||||
*/
|
||||
function roundRatio(ratio) {
|
||||
ratio = Math.round((ratio * options.roundFactor)) / options.roundFactor;
|
||||
if (ratio > 1) {
|
||||
ratio = 1;
|
||||
}
|
||||
|
||||
if (ratio < 0) {
|
||||
ratio = 0;
|
||||
}
|
||||
|
||||
return ratio;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Animation request
|
||||
*
|
||||
* @param startValue float
|
||||
* @param endValue float
|
||||
* @param duration value in ms
|
||||
* @param easing linear or swing
|
||||
*/
|
||||
function launchAnimation(startValue, endValue, duration, easing) {
|
||||
$(frontElement).attr('ratio', startValue).animate({ratio: startValue}, {
|
||||
duration: 0
|
||||
});
|
||||
|
||||
$(frontElement).stop().attr('ratio', startValue).animate({ratio: endValue}, {
|
||||
duration: duration,
|
||||
easing: easing,
|
||||
step: function (now) {
|
||||
var width = getRatioValue(now);
|
||||
lastRatio = now;
|
||||
frontElement.attr('ratio', now).css('clip', 'rect(0, ' + width + 'px, ' + size.height + 'px, 0)');
|
||||
|
||||
if (options.addSeparator) {
|
||||
separator.css('left', width + 'px');
|
||||
}
|
||||
|
||||
if (options.addDragHandle) {
|
||||
dragHandle.css('left', width + 'px');
|
||||
}
|
||||
},
|
||||
done: function (animation, jumpedToEnd) {
|
||||
var ratio = $(frontElement).attr('ratio');
|
||||
// Let the world know something has changed
|
||||
element.trigger({
|
||||
type: events.changed,
|
||||
ratio: ratio,
|
||||
value: getRatioValue(ratio),
|
||||
animate: true,
|
||||
animation : animation,
|
||||
jumpedToEnd: jumpedToEnd
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get value to reach, based on a ratio
|
||||
*
|
||||
* @param ratio float
|
||||
* @return {number}
|
||||
*/
|
||||
function getRatioValue(ratio) {
|
||||
ratio = Math.round((ratio * options.roundFactor)) / options.roundFactor;
|
||||
return Math.round(frontElement.width() * ratio);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change visible ratio
|
||||
*
|
||||
* @param ratio float
|
||||
* @param animate boolean Do we want an animation ?
|
||||
* @param duration in ms
|
||||
* @param easing 'swing', 'linear'
|
||||
*/
|
||||
function setVisibleRatio(ratio, animate, duration, easing) {
|
||||
if (typeof animate == 'undefined') {
|
||||
animate = false;
|
||||
}
|
||||
|
||||
var width = getRatioValue(ratio);
|
||||
|
||||
if (animate) {
|
||||
var finalDuration = duration ? duration : options.animationDuration;
|
||||
var finalEasing = easing ? easing : options.animationEasing;
|
||||
|
||||
launchAnimation(lastRatio, ratio, finalDuration, finalEasing);
|
||||
|
||||
// Let the world know something has changed
|
||||
if (lastRatio != ratio) {
|
||||
element.trigger({
|
||||
type: events.changed,
|
||||
ratio: lastRatio,
|
||||
value: width,
|
||||
animate: animate
|
||||
});
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
} else {
|
||||
frontElement.stop().css('clip', 'rect(0, ' + width + 'px, ' + size.height + 'px, 0)');
|
||||
|
||||
if (options.addSeparator) {
|
||||
$(separator).stop().css('left', width + 'px');
|
||||
}
|
||||
|
||||
if (options.addDragHandle) {
|
||||
dragHandle.css('left', width + 'px');
|
||||
}
|
||||
}
|
||||
|
||||
// Let the world know something has changed
|
||||
if (lastRatio != ratio) {
|
||||
element.trigger({
|
||||
type: events.changed,
|
||||
ratio: ratio,
|
||||
value: width,
|
||||
animate: animate
|
||||
});
|
||||
}
|
||||
|
||||
lastRatio = ratio;
|
||||
}
|
||||
|
||||
function setSize(width, height, maxWidth, maxHeight) {
|
||||
if (typeof width != 'undefined') {
|
||||
setWidth(width);
|
||||
}
|
||||
if (typeof height != 'undefined') {
|
||||
setHeight(height);
|
||||
}
|
||||
if (typeof maxWidth != 'undefined') {
|
||||
setMaxWidth(maxWidth);
|
||||
}
|
||||
if (typeof maxHeight != 'undefined') {
|
||||
setMaxHeight(maxHeight);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
function setWidth(width) {
|
||||
size.width = width;
|
||||
return size;
|
||||
}
|
||||
|
||||
function setMaxWidth(maxWidth) {
|
||||
size.maxWidth = maxWidth;
|
||||
return size;
|
||||
}
|
||||
|
||||
function setHeight(height) {
|
||||
size.height = height;
|
||||
return size;
|
||||
}
|
||||
|
||||
function setMaxHeight(maxHeight) {
|
||||
size.maxHeight = maxHeight;
|
||||
return size;
|
||||
}
|
||||
|
||||
// public function declaration
|
||||
// returning element to preserve chaining
|
||||
return {
|
||||
"setValue": function (ratio, animate, duration, easing) {
|
||||
setVisibleRatio(ratio, animate, duration, easing);
|
||||
return element;
|
||||
},
|
||||
"getValue": function () {
|
||||
return lastRatio;
|
||||
},
|
||||
"on": function (eventName, callback) {
|
||||
element.on(eventName, callback);
|
||||
return element;
|
||||
},
|
||||
"off": function (eventName, callback) {
|
||||
element.off(eventName, callback);
|
||||
return element;
|
||||
},
|
||||
"events": function () {
|
||||
return events;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Plugin declaration
|
||||
*
|
||||
* @param userOptions
|
||||
* @return {*}
|
||||
*/
|
||||
$.fn.imagesCompare = function (userOptions) {
|
||||
var options = $.extend(defaults, userOptions);
|
||||
return this.each(function () {
|
||||
if (!$.data(this, pluginName)) {
|
||||
$.data(this, pluginName, new ImagesCompare(this, options));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
})(jQuery, window, document);
|
||||
|
||||
// http://www.jacklmoore.com/notes/naturalwidth-and-naturalheight-in-ie/
|
||||
(function ($) {
|
||||
var props = ['Width', 'Height'], prop, propsLength;
|
||||
|
||||
propsLength = props.length;
|
||||
|
||||
for (var index = 0; index < propsLength; index++) {
|
||||
prop = props[index];
|
||||
/*jslint loopfunc: true */
|
||||
(function (natural, prop) {
|
||||
$.fn[natural] = (natural in document.createElement('img')) ?
|
||||
function () {
|
||||
return this[0][natural];
|
||||
} :
|
||||
function () {
|
||||
var
|
||||
node = this[0],
|
||||
img,
|
||||
value = 0;
|
||||
|
||||
if (node.tagName.toLowerCase() === 'img') {
|
||||
img = document.createElement('img');
|
||||
img.src = node.src;
|
||||
value = img[prop];
|
||||
}
|
||||
return value;
|
||||
};
|
||||
}('natural' + prop, prop.toLowerCase()));
|
||||
/*jslint loopfunc: false */
|
||||
}
|
||||
}(jQuery));
|
||||
Reference in New Issue
Block a user