|
3 | 3 | <link rel="stylesheet" type="text/css" href="/static/css/bootstrap.min.css"/> |
4 | 4 | <script src="/static/js/bootstrap.min.js"></script> |
5 | 5 |
|
6 | | -## Quirks 0: |
7 | | -## |
8 | | -## Need to add this block buffer so that the question circle does not overlap with the image. The |
9 | | -## height will be set if zoom feature is enabled for the give image. The height is set to be 38px, |
10 | | -## which includes 10px each for top and bottom margin, and 18px for the question circle icon. |
11 | | -## |
| 6 | +## The block to hold the question circle, which prevents it from overlapping with the image and |
| 7 | +## of which the style will be updated if zoom is enabled |
12 | 8 | <div id="popover-buffer" style="display: none"></div> |
13 | 9 | <a id="popover-content" style="display: none" data-toggle="popover" |
14 | 10 | data-trigger="hover" data-placement="left" data-html="true" |
|
17 | 13 | <p><b> Zoom:</b> Click on the image and use the mouse wheel to zoom in and out</p> |
18 | 14 | <p><b> Navigate:</b> Move the mouse cursor to navigate through the magnified image</p> |
19 | 15 | " |
20 | | -> |
21 | | - <img src="${base}/images/question-circle.png"> |
22 | | -</a> |
| 16 | +><img src="${base}/images/question-circle.png"></a> |
23 | 17 |
|
| 18 | +## The image to render, which will be wrapped accordingly if zoom is enabled |
24 | 19 | <img id="base-image" style="max-width: 100%" class="baseImage" src="${url}"> |
25 | 20 |
|
| 21 | +## MFR scripts |
26 | 22 | <script src="/static/js/mfr.js"></script> |
27 | 23 | <script src="/static/js/mfr.child.js"></script> |
28 | 24 |
|
29 | | -<script src="${base}/js/jquery.detectmobile.js"></script> |
| 25 | +## JQuery Zoom and Mouse Wheel scripts |
30 | 26 | <script src="${base}/js/jquery.mousewheel.min.js"></script> |
31 | 27 | <script src="${base}/js/jquery.zoom.js"></script> |
32 | 28 |
|
| 29 | +## The main script for enable Hi-Res and Zoom for rendered images |
33 | 30 | <script> |
34 | | -
|
| 31 | + ## Enforces strict mode |
35 | 32 | "use strict"; |
36 | 33 |
|
| 34 | + ## Magnifiation parameters |
37 | 35 | var magScale = 1; |
38 | 36 | var magStep = 0.1; |
39 | 37 | var maxScale = 3; |
40 | 38 | var minScale = 1; |
41 | | -
|
42 | 39 | var magHeight = null; |
43 | 40 | var magWidth = null; |
44 | 41 |
|
| 42 | + ## The height and width for the displaying part of the image |
45 | 43 | var heightLimit = null; |
46 | 44 | var widthLimit = null; |
47 | 45 |
|
48 | | - var heightThreshold = 200; |
| 46 | + ## The minimal height requirement to enable the zoom feature for a image |
| 47 | + ## For more information, refer to the line where it is used in this file |
| 48 | + var minHeightToZoom = 200; |
49 | 49 |
|
| 50 | + ## A flag indicating whether the image is already wrapped or not |
50 | 51 | var wrapped = false; |
51 | 52 |
|
52 | | - ## Enable the zoom feature only for desktop browsers |
53 | | - if (!$.browser.mobile) { |
| 53 | + $(document).ready(function() { |
54 | 54 |
|
55 | | - var popoverBuffer = $("#popover-buffer"); |
56 | | - var popoverContent = $("#popover-content"); |
| 55 | + ## Reference on how mobile is detected: https://stackoverflow.com/a/10364620 |
| 56 | + var isMobile = window.matchMedia("only screen and (max-width: 760px)"); |
57 | 57 |
|
58 | | - popoverBuffer.css({ |
59 | | - "height": "38px" |
60 | | - }); |
| 58 | + ## Enable the zoom feature only for desktop browsers |
| 59 | + if (!isMobile.matches) { |
61 | 60 |
|
62 | | - popoverContent.css({ |
63 | | - "position": "absolute", |
64 | | - "top": "10px", |
65 | | - "right": "10px", |
66 | | - "cursor": "pointer" |
67 | | - }); |
| 61 | + ## Update the style for instruction popover and enable it |
| 62 | + var popoverBuffer = $("#popover-buffer"); |
| 63 | + var popoverContent = $("#popover-content"); |
| 64 | + popoverBuffer.css({"height": "38px"}); |
| 65 | + popoverContent.css({ |
| 66 | + "position": "absolute", |
| 67 | + "top": "10px", |
| 68 | + "right": "10px", |
| 69 | + "cursor": "pointer" |
| 70 | + }); |
| 71 | + $('[data-toggle="popover"]').popover(); |
| 72 | +
|
| 73 | + var baseImage = $("#base-image"); |
68 | 74 |
|
69 | | - $('[data-toggle="popover"]').popover(); |
| 75 | + ## Quirks: the base image must be wrapped, see http://www.jacklmoore.com/zoom/ |
| 76 | + ## |
| 77 | + ## The BASE image must be wrapped with a parent "container" and it must be the only (or |
| 78 | + ## the first) image in it. The `jquery.zoom` library performs the zoom on the parent |
| 79 | + ## and grabs the first image it finds to create the zoom image. |
| 80 | + ## |
| 81 | + ## `addSpan()` performs the "wrap" accordingly to cater for most cases |
| 82 | + var addSpan = function () { |
| 83 | +
|
| 84 | + ## Only wrap the image once |
| 85 | + if (wrapped) { |
| 86 | + return; |
| 87 | + } |
70 | 88 |
|
71 | | - $(document).ready(function() { |
| 89 | + ## Obtain the original height and width for the image loaded |
| 90 | + var baseImageHeight = parseInt(baseImage.css("height"), 10); |
| 91 | + var baseImageWidth = parseInt(baseImage.css("width"), 10); |
72 | 92 |
|
73 | | - var is_chrome = !!window.chrome; |
| 93 | + ## Detect the Google Chrome browser |
| 94 | + var isChrome = !!window.chrome; |
74 | 95 |
|
75 | | - var baseImage = $("#base-image"); |
| 96 | + ## Detect if the image is downsized due to screen size |
| 97 | + var isActualSize = heightLimit === baseImageHeight || widthLimit === baseImageWidth; |
76 | 98 |
|
77 | | - var addSpan = function() { |
78 | | -
|
79 | | - if (!wrapped) { |
80 | | -
|
81 | | - var baseImageHeight = parseInt(baseImage.css("height")); |
82 | | - var baseImageWidth = parseInt(baseImage.css("width")); |
83 | | -
|
84 | | - ## Quirk 1 |
85 | | - ## |
86 | | - ## The BASE image must be wrapped with a parent "container" and it must be the |
87 | | - ## only image in this parent. The "JQuery Zoom" library performs the zoom |
88 | | - ## function on the parent, in which it uses the first image it finds to create |
89 | | - ## the ZOOM image. |
90 | | - ## |
91 | | - ## There are two issues if it is not wrapped. First, the ZOOM image will be the |
92 | | - ## question cirle, which is the first image we have in the iframe. Second, the |
93 | | - ## ZOOM image will take over the full space of the iframe. |
94 | | - ## |
95 | | - ## Quirk 2 |
96 | | - ## |
97 | | - ## Wrapping <img> with <div> or <span> in Google Chrome makes the scroll bar in |
98 | | - ## the <iframe> flickering when zoom is active. However, wrap it with <p> does |
99 | | - ## not have the problem for most of the time. |
100 | | - ## |
101 | | - ## Quirk 3 |
102 | | - ## |
103 | | - ## Weird behaviors SOMETIMES occur when the image is downsized due to smaller |
104 | | - ## screen size. Thus, different wrapping are used. |
105 | | - ## |
106 | | - ## Quirk 4 |
107 | | - ## |
108 | | - ## Werid behaviors ALWAYS occur when the image's height is less than 150. This |
109 | | - ## number is obtained by experiments. Thus, zoom are disabled for such images. |
110 | | - ## |
111 | | - if (heightLimit === baseImageHeight || widthLimit === baseImageWidth) { |
112 | | - baseImage.wrap("<div></div>").parent().css({ |
113 | | - "display": "block", |
114 | | - "position": "relative", |
115 | | - "overflow": "hidden" |
116 | | - }); |
117 | | - baseImage.parent().wrap("<span></span>").parent().css("display", "inline-block"); |
118 | | - } else if (!is_chrome) { |
119 | | - baseImage.wrap("<div></div>").parent().css("display", "inline-block"); |
120 | | - } else { |
121 | | - baseImage.wrap("<p></p>") |
122 | | - } |
123 | | -
|
124 | | - wrapped = true; |
| 99 | + if (isActualSize || !isChrome) { |
| 100 | + ## Use the default wrapping suggested by http://www.jacklmoore.com/zoom/ if |
| 101 | + ## either of the two conditions below holds: |
| 102 | + ## 1. Images are downsized but not in Google Chrome. Please see the flickering |
| 103 | + ## issue mentioned below. |
| 104 | + ## 2. Images are displayed in its actual size. No issue for all supported |
| 105 | + ## browsers. |
| 106 | + baseImage.wrap("<div></div>").parent().css("display", "inline-block"); |
| 107 | + } else { |
| 108 | + ## Quirks: Chrome has a flickering bug when images are wrapped with `<div>` or |
| 109 | + ## `<span>`. During zoom the scroll bar keeps appearing and disappearing which |
| 110 | + ## causes the image to keep resizing. Wrapping with `<p>` instead to solve this |
| 111 | + ## annoying issue. |
| 112 | + baseImage.wrap("<p></p>") |
125 | 113 | } |
| 114 | +
|
| 115 | + wrapped = true; |
126 | 116 | }; |
127 | 117 |
|
128 | | - var mouseZoom = function(event, delta) { |
| 118 | + var mouseZoom = function (event, delta) { |
129 | 119 |
|
130 | 120 | ## Disable page scroll when the mouse cursor are above the image |
131 | 121 | event.preventDefault(); |
|
139 | 129 | } |
140 | 130 |
|
141 | 131 | var image = $(".zoomImage"); |
142 | | - magHeight = magHeight === null ? parseInt(image.css("height")) : magHeight; |
143 | | - magWidth = magWidth === null ? parseInt(image.css("width")) : magWidth; |
| 132 | + magHeight = magHeight === null ? parseInt(image.css("height"), 10) : magHeight; |
| 133 | + magWidth = magWidth === null ? parseInt(image.css("width"), 10) : magWidth; |
144 | 134 |
|
145 | 135 | image.css({ |
146 | 136 | width: magWidth * magScale, |
147 | 137 | height: magHeight * magScale |
148 | 138 | }); |
149 | 139 | }; |
150 | 140 |
|
151 | | - ## Create an in memory copy of the image to avoid CSS issues, TODO: double check |
152 | | - $("<img>").attr("src", $(baseImage[0]).attr("src")).load(function() { |
| 141 | + ## Quirks: Need to use an in-memory copy of the image to prevent the zoom image from |
| 142 | + ## moving around. Without this in-memoery copy, the zoom image moves around |
| 143 | + ## horizontally and "centers" wherever the mouse cursor is. |
| 144 | + $("<img>").attr("src", $(baseImage[0]).attr("src")).load(function () { |
153 | 145 |
|
154 | 146 | widthLimit = this.width; |
155 | 147 | heightLimit = this.height; |
156 | 148 |
|
157 | | - ## Enable zoom and display popover instructions only when images are eligible |
158 | | - if (heightLimit >= heightThreshold) { |
159 | | - $(window).resize(addSpan); |
160 | | - $("#popover-buffer").css("display", "block"); |
161 | | - $("#popover-content").css("display", "block"); |
162 | | - addSpan(); |
163 | | - baseImage.parent().zoom({magnify: magScale}).on("mousewheel", mouseZoom); |
| 149 | + ## Quirks: Disable zoom and display instructions for images of height less than 200. |
| 150 | + ## 1. The original issue was when the height is less than 150 (not 200), the zoom |
| 151 | + ## image moves around and thus does not cover the base image fully. However, |
| 152 | + ## I cannot trigger this any more. |
| 153 | + ## 2. When the height is less than around 200 (a little bit less than 200), which |
| 154 | + ## is close to the height of the popover instruction when shown, the bottom |
| 155 | + ## part of the instruction block is cut off. Users need to scroll down to see |
| 156 | + ## the full message. In addition, the scroll bar overlaps with the question |
| 157 | + ## circle. |
| 158 | + ## 3. Images of height less than 200 are not worth zooming anyway. |
| 159 | + if (heightLimit < minHeightToZoom) { |
| 160 | + return; |
164 | 161 | } |
| 162 | +
|
| 163 | + ## For images that are eligible to zoom: |
| 164 | + ## 1. Display the question circle for popover zoom instructions |
| 165 | + ## 2. Wrap the base image accordingly by calling `addSpan()` |
| 166 | + ## 3. Call zoom on its parent with customized configs (scale and mouse click) |
| 167 | + ## 4. Enable further zoom on mouse wheel |
| 168 | + $(window).resize(addSpan); |
| 169 | + $("#popover-buffer").css("display", "block"); |
| 170 | + $("#popover-content").css("display", "block"); |
| 171 | + addSpan(); |
| 172 | + baseImage.parent().zoom({magnify: magScale, on: 'click'}).on("mousewheel", mouseZoom); |
165 | 173 | }); |
166 | | - }); |
167 | | - } |
| 174 | + } |
| 175 | + }); |
168 | 176 | </script> |
0 commit comments