summaryrefslogtreecommitdiffstats
path: root/src/main/java/com
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com')
-rw-r--r--src/main/java/com/gitblit/wicket/pages/ImageDiffHandler.java13
-rw-r--r--src/main/java/com/gitblit/wicket/pages/scripts/imgdiff.js143
2 files changed, 136 insertions, 20 deletions
diff --git a/src/main/java/com/gitblit/wicket/pages/ImageDiffHandler.java b/src/main/java/com/gitblit/wicket/pages/ImageDiffHandler.java
index 1232e990..52bf13b9 100644
--- a/src/main/java/com/gitblit/wicket/pages/ImageDiffHandler.java
+++ b/src/main/java/com/gitblit/wicket/pages/ImageDiffHandler.java
@@ -67,8 +67,9 @@ public class ImageDiffHandler implements DiffUtils.BinaryDiffHandler {
imgDiffCount++;
String id = "imgdiff" + imgDiffCount;
HtmlBuilder builder = new HtmlBuilder("div");
- Element container = builder.root().attr("align", "center").appendElement("div").attr("class", "imgdiff");
- Element resizeable = container.appendElement("div").attr("class", "imgdiff-left");
+ Element wrapper = builder.root().attr("class", "imgdiff-container").attr("id", "imgdiff-" + id);
+ Element container = wrapper.appendElement("div").attr("class", "imgdiff-ovr-slider").appendElement("div").attr("class", "imgdiff");
+ Element old = container.appendElement("div").attr("class", "imgdiff-left");
// style='max-width:640px;' is necessary for ensuring that the browser limits large images
// to some reasonable width, and to override the "img { max-width: 100%; }" from bootstrap.css,
// which would scale the left image to the width of its resizeable container, which isn't what
@@ -77,12 +78,10 @@ public class ImageDiffHandler implements DiffUtils.BinaryDiffHandler {
// is too wide.
// XXX: Maybe add a max-height, too, to limit portrait-oriented images to some reasonable height?
// (Like a 300x10000px image...)
- resizeable.appendElement("img").attr("class", "imgdiff-left").attr("id", id).attr("style", "max-width:640px;").attr("src", oldUrl);
+ old.appendElement("img").attr("class", "imgdiff-old").attr("id", id).attr("style", "max-width:640px;").attr("src", oldUrl);
container.appendElement("img").attr("class", "imgdiff").attr("style", "max-width:640px;").attr("src", newUrl);
- builder.root().appendElement("br");
- Element slider = builder.root().appendElement("div").attr("class", "imgdiff-slider");
- slider.appendElement("div").attr("class", "imgdiff-slider-resizeable").attr("id", "slider-" + id)
- .appendElement("div").attr("class", "imgdiff-slider-left");
+ wrapper.appendElement("br");
+ wrapper.appendElement("div").attr("class", "imgdiff-opa-container").appendElement("div").attr("class", "imgdiff-opa-slider");
return builder.toString();
}
break;
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 bfde435d..2b2f4f9f 100644
--- a/src/main/java/com/gitblit/wicket/pages/scripts/imgdiff.js
+++ b/src/main/java/com/gitblit/wicket/pages/scripts/imgdiff.js
@@ -13,18 +13,135 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-jQuery(function () {
- // Runs on jQuery's document.ready and sets up the scroll event handlers for all image diffs.
- jQuery(".imgdiff-slider-resizeable").each(function () {
- var $el = jQuery(this);
- var $img = jQuery('#' + this.id.substr(this.id.indexOf('-') + 1));
- function fade() {
- var w = Math.max(0, $el.width() - 18); // Must correspond to CSS: 18 px is handle width, 400 px is slider width
- w = Math.max(0, 1.0 - w / 400.0);
- $img.css("opacity", w);
+(function($) {
+
+/**
+ * Sets up elem as a slider; returns an access object. Elem must be positioned!
+ * Note that the element may contain other elements; this is used for instance
+ * for the image diff overlay slider.
+ *
+ * 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.
+ * If no handleClass is specified, a very plain default style is assigned.
+ */
+function rangeSlider(elem, options) {
+ options = $.extend({ initial : 0 }, options || {});
+ 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 $root = $(document.documentElement);
+ var $doc = $(document);
+ var lastRatio = options.initial;
+
+ /** 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 range = width - handleWidth;
+ if (range <= 0) return;
+ var delta = Math.min(range, Math.max (0, e.pageX - pos - handleWidth / 2));
+ lastRatio = delta / range;
+ $handle.css('left', "" + (delta * 100 / width) + '%');
+ $elem.trigger('slider:pos', { ratio: lastRatio, handle: $handle[0] });
+ }
+
+ /** Mouseup event handler to stop mouse tracking. */
+ function end(e) {
+ $doc.off('mousemove', track);
+ $doc.off('mouseup', end);
+ $root.removeClass('no-select');
+ }
+
+ /** Snaps the slider to the given ratio and generates a slider:pos event with the new ratio. */
+ function setTo(ratio) {
+ var w = $elem.width();
+ 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) + '%');
+ $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.
+ */
+ function moveTo(ratio, duration) {
+ ratio = Math.min(1.0, Math.max(0, ratio));
+ if (ratio === lastRatio) return;
+ if (typeof duration == 'undefined') duration = 500;
+ if (duration === 0) {
+ setTo(ratio);
+ } else {
+ var target = ratio * ($elem.width() - $handle.width());
+ if (ratio > lastRatio) target--; else target++;
+ $handle.animate({left: target},
+ { 'duration' : duration,
+ 'step' : function() {
+ lastRatio = Math.min(1.0, Math.max(0, $handle.offset().left / ($elem.width() - $handle.width())));
+ $elem.trigger('slider:pos', { ratio : lastRatio, handle : $handle[0] });
+ },
+ 'complete' : function() { setTo(ratio); } // Last step gives us a % value again.
+ }
+ );
}
- // Unfortunately, not even jQuery triggers resize events for our resizeable... so let's track the mouse.
- $el.on('mousedown', function() { $el.on('mousemove', fade); });
- $el.on('mouseup', function() { $el.off('mousemove', fade); fade(); });
+ }
+
+ /** Returns the current ratio. */
+ function getValue() {
+ return lastRatio;
+ }
+
+ $elem.append($handle);
+ if (options.handleClass) {
+ $handle.addClass(options.handleClass);
+ } else { // Provide a default style so that it is at least visible
+ $handle.css({ width: '10px', height: '10px', background: 'white', border: '1px solid black' });
+ }
+ if (options.initial) setTo(options.initial);
+
+ /** Install mousedown handler to start mouse tracking. */
+ $handle.on('mousedown', function(e) {
+ $root.addClass('no-select');
+ $doc.on('mousemove', track);
+ $doc.on('mouseup', end);
+ });
+
+ return { setRatio: setTo, moveRatio: moveTo, getRatio: getValue, handle: $handle[0] };
+}
+
+function setup() {
+ $('.imgdiff-container').each(function() {
+ var $this = $(this);
+ 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 $img = $('#' + this.id.substr(this.id.indexOf('-')+1)); // Here we change opacity
+ var $div = $img.parent(); // This controls visibility: here we change width.
+
+ $overlaySlider.on('slider:pos', function(e, data) {
+ var pos = $(data.handle).offset().left;
+ var imgLeft = $img.offset().left; // Global
+ var imgW = $img.width() + $img.position().left; // From left edge of $div
+ if (pos <= imgLeft) {
+ $div.width(0);
+ } else if (pos <= imgLeft + imgW) {
+ $div.width(pos - imgLeft);
+ } else if ($div.width() < imgW) {
+ $div.width(imgW);
+ }
+ });
+ $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);
+ });
});
-});
+}
+
+$(setup); // Run on jQuery's dom-ready
+
+})(jQuery); \ No newline at end of file