PageSourceSearch

https://normalcrafter.github.io/static/js/jquery.twentytwenty.js

js normalcrafter.github.io collected 2026-10-03 09:41:39 UTC 6,035 bytes, 171 lines download raw bytes

1(function($) {
2
3  $.fn.twentytwenty = function(options) {
4    var options = $.extend({
5      default_offset_pct: 0.5,
6      orientation: 'horizontal',
7      before_label: 'Before',
8      after_label: 'After',
9      no_overlay: false,
10      move_slider_on_hover: false,
11      move_with_handle_only: true,
12      click_to_move: false,
13    }, options);
14
15    return this.each(function() {
16      var container = $(this);
17      var sliderOrientation = options.orientation;
18      var beforeDirection = (sliderOrientation === 'vertical') ? 'down' : 'left';
19      var afterDirection = (sliderOrientation === 'vertical') ? 'up' : 'right';
20      var this_Offset_Pct = $(container).attr("default_offset_pct");
21      var sliderPct = this_Offset_Pct ? this_Offset_Pct : options.default_offset_pct;
22
23      container.wrap("<div class='twentytwenty-wrapper twentytwenty-" + sliderOrientation + "'></div>");
24      if(!options.no_overlay) {
25        container.append("<div class='twentytwenty-overlay'></div>");
26        var overlay = container.find(".twentytwenty-overlay");
27        overlay.append("<div class='twentytwenty-before-label' data-content='"+options.before_label+"'></div>");
28        overlay.append("<div class='twentytwenty-after-label' data-content='"+options.after_label+"'></div>");
29      }
30      var beforeImg = container.find(".cmpcontent:first");
31      var afterImg = container.find(".cmpcontent:last");
32      container.append("<div class='twentytwenty-handle'></div>");
33      var slider = container.find(".twentytwenty-handle");
34      slider.append("<span class='twentytwenty-" + beforeDirection + "-arrow'></span>");
35      slider.append("<span class='twentytwenty-" + afterDirection + "-arrow'></span>");
36      container.addClass("twentytwenty-container");
37      beforeImg.addClass("twentytwenty-before");
38      afterImg.addClass("twentytwenty-after");
39
40      var isBeforeVideo = beforeImg.is("video");
41      var isAfterVideo = afterImg.is("video");
42
43      if (isBeforeVideo && isAfterVideo) {
44        beforeImg.on("play", function() {
45          afterImg.get(0).currentTime = beforeImg.get(0).currentTime;
46          afterImg.get(0).play();
47        });
48
49        beforeImg.on("pause", function() {
50          afterImg.get(0).pause();
51        });
52
53        afterImg.on("play", function() {
54          beforeImg.get(0).currentTime = afterImg.get(0).currentTime;
55          beforeImg.get(0).play();
56        });
57
58        afterImg.on("pause", function() {
59          beforeImg.get(0).pause();
60        });
61      }
62
63      var calcOffset = function(dimensionPct) {
64        var w = $(container).width();
65        var h = $(container).height();
66
67        return {
68          w: w+"px",
69          h: h+"px",
70          cw: (dimensionPct*w)+"px",
71          ch: (dimensionPct*h)+"px"
72        };
73      };
74
75      var adjustContainer = function(offset) {
76        if (sliderOrientation === 'vertical') {
77          beforeImg.css("clip", "rect(0,"+offset.w+","+offset.ch+",0)");
78          afterImg.css("clip", "rect("+offset.ch+","+offset.w+","+offset.h+",0)");
79        }
80        else {
81          beforeImg.css("clip", "rect(0,"+offset.cw+","+offset.h+",0)");
82          afterImg.css("clip", "rect(0,"+offset.w+","+offset.h+","+offset.cw+")");
83        }
84        container.css("height", offset.h);
85      };
86
87      var adjustSlider = function(pct) {
88        var offset = calcOffset(pct);
89        slider.css((sliderOrientation==="vertical") ? "top" : "left", (sliderOrientation==="vertical") ? offset.ch : offset.cw);
90        adjustContainer(offset);
91      };
92
93      var minMaxNumber = function(num, min, max) {
94        return Math.max(min, Math.min(max, num));
95      };
96
97      var getSliderPercentage = function(positionX, positionY) {
98        var sliderPercentage = (sliderOrientation === 'vertical') ?
99            (positionY-offsetY)/imgHeight :
100            (positionX-offsetX)/imgWidth;
101
102        return minMaxNumber(sliderPercentage, 0, 1);
103      };
104
105      $(window).on("resize.twentytwenty", function(e) {
106        adjustSlider(sliderPct);
107      });
108
109      var offsetX = 0;
110      var offsetY = 0;
111      var imgWidth = 0;
112      var imgHeight = 0;
113      var onMoveStart = function(e) {
114        if (((e.distX > e.distY && e.distX < -e.distY) || (e.distX < e.distY && e.distX > -e.distY)) && sliderOrientation !== 'vertical') {
115          e.preventDefault();
116        }
117        else if (((e.distX < e.distY && e.distX < -e.distY) || (e.distX > e.distY && e.distX > -e.distY)) && sliderOrientation === 'vertical') {
118          e.preventDefault();
119        }
120        container.addClass("active");
121        offsetX = container.offset().left;
122        offsetY = container.offset().top;
123        imgWidth = beforeImg.width();
124        imgHeight = beforeImg.height();
125      };
126      var onMove = function(e) {
127        if (container.hasClass("active")) {
128          sliderPct = getSliderPercentage(e.pageX, e.pageY);
129          adjustSlider(sliderPct);
130        }
131      };
132      var onMoveEnd = function() {
133        container.removeClass("active");
134      };
135
136      var moveTarget = options.move_with_handle_only ? slider : container;
137      moveTarget.on("movestart", onMoveStart);
138      moveTarget.on("move", onMove);
139      moveTarget.on("moveend", onMoveEnd);
140
141      if (options.move_slider_on_hover) {
142        container.on("mouseenter", onMoveStart);
143        container.on("mousemove", onMove);
144        container.on("mouseleave", onMoveEnd);
145      }
146
147      slider.on("touchmove", function(e) {
148        e.preventDefault();
149      });
150
151      container.find("cmpcontent").on("mousedown", function(event) {
152        event.preventDefault();
153      });
154
155      if (options.click_to_move) {
156        container.on('click', function(e) {
157          offsetX = container.offset().left;
158          offsetY = container.offset().top;
159          imgWidth = beforeImg.width();
160          imgHeight = beforeImg.height();
161
162          sliderPct = getSliderPercentage(e.pageX, e.pageY);
163          adjustSlider(sliderPct);
164        });
165      }
166
167      $(window).trigger("resize.twentytwenty");
168    });
169  };
170
171})(jQuery);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.