From fbc7a7dd5fa61486610cf11c09e0007f2900a3e1 Mon Sep 17 00:00:00 2001
From: James Moger <james.moger@gitblit.com>
Date: Wed, 03 Dec 2014 15:05:49 -0500
Subject: [PATCH] Add support for specifying the `Proxy-Authorization` header for the PluginManager
---
src/main/java/com/gitblit/wicket/pages/scripts/imgdiff.js | 157 +++++++++++++++++++++++++++++++++++++++++++++-------
1 files changed, 136 insertions(+), 21 deletions(-)
diff --git a/src/main/java/com/gitblit/wicket/pages/scripts/imgdiff.js b/src/main/java/com/gitblit/wicket/pages/scripts/imgdiff.js
index 27cca8c..6157513 100644
--- a/src/main/java/com/gitblit/wicket/pages/scripts/imgdiff.js
+++ b/src/main/java/com/gitblit/wicket/pages/scripts/imgdiff.js
@@ -22,7 +22,7 @@
*
* The styling of the slider is to be done in CSS. Currently recognized options:
* - initial: <float> clipped to [0..1], default 0
- * - handleClass: <string> to assign to the handle div element created.
+ * - handleClass: <string> to assign to the handle span element created.
* If no handleClass is specified, a very plain default style is assigned.
*/
function rangeSlider(elem, options) {
@@ -30,7 +30,7 @@
options.initial = Math.min(1.0, Math.max(0, options.initial));
var $elem = $(elem);
- var $handle = $('<div></div>').css({ position: 'absolute', left: 0, cursor: 'ew-resize' });
+ var $handle = $('<span></span>').css({ position: 'absolute', left: 0, cursor: 'ew-resize' });
var $root = $(document.documentElement);
var $doc = $(document);
var lastRatio = options.initial;
@@ -38,8 +38,8 @@
/** Mousemove event handler to track the mouse and move the slider. Generates slider:pos events. */
function track(e) {
var pos = $elem.offset().left;
- var width = $elem.width();
- var handleWidth = $handle.width();
+ var width = $elem.innerWidth();
+ var handleWidth = $handle.outerWidth(false);
var range = width - handleWidth;
if (range <= 0) return;
var delta = Math.min(range, Math.max (0, e.pageX - pos - handleWidth / 2));
@@ -57,44 +57,64 @@
/** Snaps the slider to the given ratio and generates a slider:pos event with the new ratio. */
function setTo(ratio) {
- var w = $elem.width();
+ var w = $elem.innerWidth();
if (w <= 0 || $elem.is(':hidden')) return;
lastRatio = Math.min( 1.0, Math.max(0, ratio));
- $handle.css('left', "" + Math.max(0, 100 * (lastRatio * (w - $handle.width())) / w) + '%');
+ $handle.css('left', "" + Math.max(0, 100 * (lastRatio * (w - $handle.outerWidth(false))) / w) + '%');
$elem.trigger('slider:pos', { ratio: lastRatio, handle: $handle[0] });
}
/**
* Moves the slider to the given ratio, clipped to [0..1], in duration milliseconds.
- * Generates slider:pos events during the animation. If duration === 0, same as setTo.
- * Default duration is 500ms.
+ * Generates slider:pos events during the animation. If duration <= 30, same as setTo.
+ * Default duration is 500ms. If a callback is given, it's called once the animation
+ * has completed.
*/
- function moveTo(ratio, duration) {
+ function moveTo(ratio, duration, callback) {
ratio = Math.min(1.0, Math.max(0, ratio));
- if (ratio === lastRatio) return;
+ if (ratio === lastRatio) {
+ if (typeof callback == 'function') callback();
+ return;
+ }
if (typeof duration == 'undefined') duration = 500;
- if (duration === 0) {
+ if (duration <= 30) {
+ // Cinema is 24 or 48 frames/sec, so 20-40ms per frame. Makes no sense to animate for such a short duration.
setTo(ratio);
+ if (typeof callback == 'function') callback();
} else {
- var target = ratio * ($elem.width() - $handle.width());
+ var target = ratio * ($elem.innerWidth() - $handle.outerWidth(false));
if (ratio > lastRatio) target--; else target++;
$handle.stop().animate({left: target},
{ 'duration' : duration,
'step' : function() {
- lastRatio = Math.min(1.0, Math.max(0, $handle.position().left / ($elem.width() - $handle.width())));
+ lastRatio = Math.min(1.0, Math.max(0, $handle.position().left / ($elem.innerWidth() - $handle.outerWidth(false))));
$elem.trigger('slider:pos', { ratio : lastRatio, handle : $handle[0] });
},
- 'complete' : function() { setTo(ratio); } // Last step gives us a % value again.
+ 'complete' : function() { setTo(ratio); if (typeof callback == 'function') callback(); } // Ensure we have again a % value
}
);
}
}
+ /**
+ * As moveTo, but determines an appropriate duration in the range [0..maxDuration] on its own,
+ * depending on the distance the handle would move. If no maxDuration is given it defaults
+ * to 1500ms.
+ */
+ function moveAuto(ratio, maxDuration, callback) {
+ if (typeof maxDuration == 'undefined') maxDuration = 1500;
+ var delta = ratio - lastRatio;
+ if (delta < 0) delta = -delta;
+ var speed = $elem.innerWidth() * delta * 2;
+ if (speed > maxDuration) speed = maxDuration;
+ moveTo(ratio, speed, callback);
+ }
+
/** Returns the current ratio. */
function getValue() {
return lastRatio;
}
-
+
$elem.append($handle);
if (options.handleClass) {
$handle.addClass(options.handleClass);
@@ -108,9 +128,11 @@
$root.addClass('no-select');
$doc.on('mousemove', track);
$doc.on('mouseup', end);
+ e.stopPropagation();
+ e.preventDefault();
});
- return { setRatio: setTo, moveRatio: moveTo, getRatio: getValue, handle: $handle[0] };
+ return { setRatio: setTo, moveRatio: moveTo, 'moveAuto': moveAuto, getRatio: getValue, handle: $handle[0] };
}
function setup() {
@@ -119,14 +141,15 @@
var $overlaySlider = $this.find('.imgdiff-ovr-slider').first();
var $opacitySlider = $this.find('.imgdiff-opa-slider').first();
var overlayAccess = rangeSlider($overlaySlider, {handleClass: 'imgdiff-ovr-handle'});
- rangeSlider($opacitySlider, {handleClass: 'imgdiff-opa-handle'});
+ var opacityAccess = rangeSlider($opacitySlider, {handleClass: 'imgdiff-opa-handle'});
var $img = $('#' + this.id.substr(this.id.indexOf('-')+1)); // Here we change opacity
var $div = $img.parent(); // This controls visibility: here we change width.
+ var blinking = false;
$overlaySlider.on('slider:pos', function(e, data) {
var pos = $(data.handle).offset().left;
var imgLeft = $img.offset().left; // Global
- var imgW = $img.outerWidth();
+ var imgW = $img.outerWidth(true);
var imgOff = $img.position().left; // From left edge of $div
if (pos <= imgLeft) {
$div.width(0);
@@ -136,10 +159,102 @@
$div.width(imgW + imgOff);
}
});
- $opacitySlider.on('slider:pos', function(e, data) {
- if ($div.width() <= 0) overlayAccess.moveRatio(1.0, 500); // Make old image visible in a nice way
- $img.css('opacity', 1.0 - data.ratio);
+ $overlaySlider.css('cursor', 'pointer');
+ $overlaySlider.on('mousedown', function(e) {
+ var newRatio = (e.pageX - $overlaySlider.offset().left) / $overlaySlider.innerWidth();
+ var oldRatio = overlayAccess.getRatio();
+ if (newRatio !== oldRatio) {
+ overlayAccess.moveAuto(newRatio);
+ }
});
+
+ var autoShowing = false;
+ $opacitySlider.on('slider:pos', function(e, data) {
+ if ($div.width() <= 0 && !blinking) {
+ // Make old image visible in a nice way, *then* adjust opacity
+ autoShowing = true;
+ overlayAccess.moveAuto(1.0, 500, function() {
+ $img.stop().animate(
+ {opacity: 1.0 - opacityAccess.getRatio()},
+ {duration: 400,
+ complete: function () {
+ // In case the opacity handle was moved while we were trying to catch up
+ $img.css('opacity', 1.0 - opacityAccess.getRatio());
+ autoShowing = false;
+ }
+ }
+ );
+ });
+ } else if (!autoShowing) {
+ $img.css('opacity', 1.0 - data.ratio);
+ }
+ });
+ $opacitySlider.on('click', function(e) {
+ var newRatio = (e.pageX - $opacitySlider.offset().left) / $opacitySlider.innerWidth();
+ var oldRatio = opacityAccess.getRatio();
+ if (newRatio !== oldRatio) {
+ if ($div.width() <= 0) {
+ overlayAccess.moveRatio(1.0, 500, function() {opacityAccess.moveAuto(newRatio);}); // Make old image visible in a nice way
+ } else {
+ opacityAccess.moveAuto(newRatio)
+ }
+ }
+ e.preventDefault();
+ });
+
+ // Blinking before and after images is a good way for the human eye to catch differences.
+ var $blinker = $this.find('.imgdiff-blink');
+ var initialOpacity = null;
+ $blinker.on('click', function(e) {
+ if (blinking) {
+ window.clearTimeout(blinking);
+ $blinker.children('img').first().css('border', '1px solid transparent');
+ opacityAccess.setRatio(initialOpacity);
+ blinking = null;
+ } else {
+ $blinker.children('img').first().css('border', '1px solid #AAA');
+ initialOpacity = opacityAccess.getRatio();
+ var currentOpacity = 1.0;
+ function blink() {
+ opacityAccess.setRatio(currentOpacity);
+ currentOpacity = 1.0 - currentOpacity;
+ // Keep frequeny below 2Hz (i.e., delay above 500ms)
+ blinking = window.setTimeout(blink, 600);
+ }
+ if ($div.width() <= 0) {
+ overlayAccess.moveRatio(1.0, 500, blink);
+ } else {
+ blink();
+ }
+ }
+ e.preventDefault();
+ });
+
+ // Subtracting before and after images is another good way to detect differences. Result will be
+ // black where identical.
+ if (typeof $img[0].style.mixBlendMode != 'undefined') {
+ // Feature test: does the browser support the mix-blend-mode CSS property from the Compositing
+ // and Blending Level 1 spec (http://dev.w3.org/fxtf/compositing-1/#mix-blend-mode )?
+ // As of 2014-11, only Firefox >= 32 and Safari >= 7.1 support this. Other browsers will have to
+ // make do with the blink comparator only.
+ var $sub = $this.find('.imgdiff-subtract');
+ $sub.css('display', 'inline-block');
+ $sub.on('click', function (e) {
+ var curr = $img.css('mix-blend-mode');
+ if (curr != 'difference') {
+ curr = 'difference';
+ $sub.children('img').first().css('border', '1px solid #AAA');
+ if ($div.width() <= 0) overlayAccess.moveRatio(1.0, 500);
+ opacityAccess.setRatio(0);
+ } else {
+ curr = 'normal';
+ $sub.children('img').first().css('border', '1px solid transparent');
+
+ }
+ $img.css('mix-blend-mode', curr);
+ e.preventDefault();
+ });
+ }
});
}
--
Gitblit v1.9.1