]> git.sesse.net Git - pr0n/blobdiff - files/pr0n-fullscreen.js
Fix centering of text again.
[pr0n] / files / pr0n-fullscreen.js
index 2601aa14c3c8693183ca96331b7d5574a4fc5cf5..d9d37c6131b8226a952e95677f2991d9e404f2d2 100644 (file)
@@ -1,9 +1,9 @@
-var req;
+(function() {
 
-function init_ajax()
-{
-       req = new XMLHttpRequest();
-}
+var global_disabled_opacity = 0.1;
+var global_default_opacity = 0.7;
+var global_highlight_opacity = 1.0;
+var global_infobox = true;
 
 function find_width()
 {
@@ -26,6 +26,9 @@ function find_dpr()
  * pick_image_size, below.
  */
 var fixed_sizes = [
+       [ 3840, 2880 ],
+       [ 3200, 2400 ],
+       [ 2800, 2100 ],
        [ 2304, 1728 ],
        [ 2048, 1536 ],
        [ 1920, 1440 ],
@@ -86,24 +89,6 @@ function pick_image_size(screen_size, image_size)
        return [ 80, 64 ];
 }
 
-function replace_image_element(url, element_id, parent_node)
-{
-       var img = document.getElementById(element_id);
-       if (img !== null) {
-               if (img.src === url) {
-                       return img;
-               }
-               img.parentNode.removeChild(img);
-       }
-
-       img = document.createElement("img");
-       img.id = element_id;
-       img.alt = "";
-       img.src = url;
-       parent_node.appendChild(img);
-       return img;
-}
-
 function rename_element(old_name, new_name)
 {
        // Remove any element that's in the way.
@@ -119,55 +104,41 @@ function rename_element(old_name, new_name)
        return elem;
 }
 
-function display_image(width, height, evt, filename, element_id)
+function display_image(url, backend_width, backend_height, elem_id, offset, preload)
 {
-       var url = window.location.origin + "/" + evt + "/" + width + "x" + height + "/" + filename;
-       var main = document.getElementById("iehack");
-       var preload = document.getElementById("preload");
-       var dpr = find_dpr();
-       var img;
-       // See if we have a preload going on that we can reuse.
-       if (element_id == "image" && preload !== null && preload.src == url) {
-               rename_element("preload_box", "image_box");
-               img = rename_element("preload", "image");
-       } else {
-               img = replace_image_element(url, element_id, main);
+       // See if this image already exists in the DOM; if not, add it.
+       var img = document.getElementById(elem_id);
+       if (img === null) {
+               img = document.createElement("img");
+               img.id = elem_id;
+               img.alt = "";
+               img.className = preload ? "fsbox" : "fsimg";
        }
        img.style.position = "absolute";
-       img.style.left = "0px";
-       img.style.top = "0px";
        img.style.transformOrigin = "top left";
-       img.style.transform = "scale(" + (1.0 / dpr) + ")";
-
-       // Update the "download original" link.
-       var original_url = window.location.origin + "/" + evt + "/original/" + filename;
-       document.getElementById("origdownload").href = original_url;
+       document.getElementById("main").appendChild(img);
 
-       if (global_infobox) {
-               var url;
-               if (dpr == 1) {
-                       url = window.location.origin + "/" + evt + "/" + width + "x" + height + "/box/" + filename;
+       if (offset === 0) {
+               img.src = url;
+               position_image(img, backend_width, backend_height, offset, preload);
+       } else {
+               // This is a preload, so wait for the main image to be ready.
+               // The test for .complete is an old IE hack, which I don't know if is relevant anymore.
+               var main_img = document.getElementById(global_image_num);
+               if (main_img === null || main_img.complete) {
+                       img.src = url;
                } else {
-                       url = window.location.origin + "/" + evt + "/" + width + "x" + height + "@" + dpr.toFixed(2) + "/box/" + filename;
+                       main_img.addEventListener('load', function() { img.src = url; }, false);
                }
-               var boximg = replace_image_element(url, element_id + "_box", main);
 
-               boximg.style.position = "absolute";
-               boximg.style.left = "0px";
-               boximg.style.bottom = "-1px";
-               boximg.style.transformOrigin = "bottom left";
-               boximg.style.transform = "scale(" + (1.0 / dpr) + ")";
-       } else {
-               var boximg = document.getElementById(element_id + "_box");
-               if (boximg !== null) {
-                       boximg.parentNode.removeChild(boximg);
-               }
+               // Seemingly one needs to delay position_image(), or Firefox will set the initial
+               // scroll offset completely off.
+               img.style.display = 'none';
+               setTimeout(function() { position_image(img, backend_width, backend_height, offset, preload); img.style.display = null; }, 1);
        }
-
-       return img;
 }
 
-function display_image_num(num, element_id)
+function display_image_num(num, offset)
 {
        var screen_size = find_width();
        var adjusted_size;
@@ -179,40 +150,48 @@ function display_image_num(num, element_id)
                adjusted_size = pick_image_size(screen_size, [ global_image_list[num][2], global_image_list[num][3] ]);
        }
 
-       var img = display_image(adjusted_size[0], adjusted_size[1], global_image_list[num][0], global_image_list[num][1], element_id);
-       
-       if (element_id == "image") {
-               // we want to shrink the box as much as possible if we know the true
-               // size of the image
-               center_image(num);
-               
-               // replace the anchor part (if any) with the image number
-               window.location.hash = "#" + (num+1);
-       }
+       var evt = global_image_list[num][0];
+       var filename = global_image_list[num][1];
+       var backend_width = adjusted_size[0];
+       var backend_height = adjusted_size[1];
+       var url = window.location.origin + "/" + evt + "/" + backend_width + "x" + backend_height + "/" + filename;
+       var elem_id = num;
 
-       return img;
-}
+       display_image(url, adjusted_size[2], adjusted_size[3], elem_id, offset, false);
 
-function prepare_preload(img, num)
-{
-       // cancel any pending preload
-       var preload = document.getElementById("preload");
-       if (preload !== null) {
-               preload.parentNode.removeChild(preload);
-       }
-       
-       var preload_box = document.getElementById("preload_box");
-       if (preload_box !== null) {
-               preload_box.parentNode.removeChild(preload_box);
+       if (global_infobox) {
+               var url;
+               var dpr = find_dpr();
+               var elem_id = num + "_box";
+               if (dpr == 1) {
+                       url = window.location.origin + "/" + evt + "/" + backend_width + "x" + backend_height + "/box/" + filename;
+               } else {
+                       url = window.location.origin + "/" + evt + "/" + backend_width + "x" + backend_height + "@" + dpr.toFixed(2) + "/box/" + filename;
+               }
+               display_image(url, adjusted_size[2], adjusted_size[3], elem_id, offset, true);
+               document.getElementById(elem_id).style.transform += " scale(" + (1.0 / dpr) + ")";
        }
 
-       // grmf -- IE doesn't fire onload if the image was loaded from cache, so check for
-       // completeness first; should at least be _somewhat_ better
-       if (img.complete) {
-               display_image_num(num, "preload");
-       } else {
-               img.onload = function() { display_image_num(num, "preload"); };
-       }       
+       if (offset === 0) {
+               // Update the "download original" link.
+               var original_url = window.location.origin + "/" + evt + "/original/" + filename;
+               document.getElementById("origdownload").href = original_url;
+
+               // If it's a raw image, show a JPEG link.
+               var fulldownload = document.getElementById("fulldownload");
+               if (filename.match(/\.(nef|cr2)$/i)) {
+                       fulldownload.style.display = "block";
+                       var full_url = window.location.origin + "/" + evt + "/" + filename;
+                       document.getElementById("fulldownloadlink").href = full_url;
+                       origdownload.innerHTML = "Download original image (RAW)";
+               } else {
+                       fulldownload.style.display = "none";
+                       origdownload.innerHTML = "Download original image";
+               }
+
+               // replace the anchor part (if any) with the image number
+               window.location.hash = "#" + (num+1);
+       }
 }
 
 function can_go_next()
@@ -239,40 +218,93 @@ function set_opacity(id, amount)
        elem.style.opacity = amount;
 }
 
-function center_image(num)
+function position_image(img, backend_width, backend_height, offset, preload)
 {
        var screen_size = find_width();
        var dpr = find_dpr();
        var width, height;
-       
-       if (global_image_list[num][2] == -1) {
+
+       if (backend_width == -1) {
                // no size information, use our pessimal guess
                var adjusted_size = max_image_size(screen_size);
                width = adjusted_size[0];
                height = adjusted_size[1];
        } else {
                // use the exact information
-               var adjusted_size = pick_image_size(screen_size, [ global_image_list[num][2], global_image_list[num][3] ]);
+               var adjusted_size = pick_image_size(screen_size, [ backend_width, backend_height ]);
                width = adjusted_size[2];
                height = adjusted_size[3];
        }
 
+       var extra_x_offset = find_width()[0] * offset;
+       var left = (screen_size[0] - width) / 2;
+       var top = (screen_size[1] - height) / 2;
+
+       if (global_infobox) top -= dpr * (24/2);
+
        // center the image on-screen
-       var main = document.getElementById("main");
-       main.style.position = "absolute";
-       main.style.left = (((screen_size[0] - width) / 2) / dpr) + "px";
-       main.style.top = (((screen_size[1] - height) / 2) / dpr) + "px";
-       main.style.width = (width / dpr) + "px";
-       main.style.height = (height / dpr) + "px";
-       main.style.lineHeight = (height / dpr) + "px";
+       img.style.position = "absolute";
+       img.style.left = (left / dpr) + "px";
+       img.style.transform = "translate(" + extra_x_offset + "px,0px)";
+
+       if (preload) {
+               img.style.top = (top + height) / dpr + "px";
+       } else {
+               img.style.top = (top / dpr) + "px";
+               img.style.lineHeight = (height / dpr) + "px";
+               img.style.width = (width / dpr) + "px";
+               img.style.height = (height / dpr) + "px";
+       }
 }
 
-function relayout()
+function update_shown_images()
 {
-       var img = display_image_num(global_image_num, "image");
+       // Go through and remove all the elements that are not supposed to be there.
+       var main = document.getElementById("main");
+       var children = main.children;
+       var to_remove = [];
+       for (var i = 0; i < children.length; i++) {
+               var child = children[i];
+               var inum = null;
+               if (child.className === "fsimg") {
+                       inum = parseInt(child.id);
+               } else if (child.className === "fsbox") {
+                       inum = parseInt(child.id.replace("_box", ""));
+               } else {
+                       continue;
+               }
+
+               // FIXME: For whatever reason, if we don't actually remove an item
+               // and then scroll it out of view, Chrome scrolls to it.
+               // So don't keep anything that's going to be a preload;
+               // we'll have to recreate the element entirely.
+               //if (inum !== global_image_num - 1 &&
+               //    inum !== global_image_num &&
+               //    inum !== global_image_num + 1) {
+               //      to_remove.push(child);
+               //}
+               if (inum !== global_image_num) {
+                       to_remove.push(child);
+               }
+       }
+       for (let child of to_remove) {
+               child.parentNode.removeChild(child);
+       }
+
+       // Add any missing elements. Note that we add the main one first,
+       // so that the preloads have an element to fire onload off of.
+       display_image_num(global_image_num, 0);
+       if (can_go_previous()) {
+               display_image_num(global_image_num - 1, -1);
+       }
        if (can_go_next()) {
-               prepare_preload(img, global_image_num + 1);
+               display_image_num(global_image_num + 1, 1);
        }
+}
+
+function relayout()
+{
+       update_shown_images();
 
        set_opacity("previous", can_go_previous() ? global_default_opacity : global_disabled_opacity);
        set_opacity("next", can_go_next() ? global_default_opacity : global_disabled_opacity);
@@ -286,10 +318,10 @@ function go_previous()
                return;
        }
 
-       var img = display_image_num(--global_image_num, "image");
+       --global_image_num;
+       update_shown_images();
        if (can_go_previous()) {
                set_opacity("previous", global_default_opacity);
-               prepare_preload(img, global_image_num - 1);
        } else {
                set_opacity("previous", global_disabled_opacity);
        }
@@ -302,10 +334,10 @@ function go_next()
                return;
        }
 
-       var img = display_image_num(++global_image_num, "image");
+       ++global_image_num;
+       update_shown_images();
        if (can_go_next()) {
                set_opacity("next", global_default_opacity);
-               prepare_preload(img, global_image_num + 1);
        } else {
                set_opacity("next", global_disabled_opacity);
        }
@@ -331,6 +363,7 @@ function toggle_optionmenu()
                set_opacity("options", 0.7);
        }
 }
+window['toggle_optionmenu'] = toggle_optionmenu;
 
 function draw_text(msg)
 {
@@ -348,11 +381,11 @@ function draw_text(msg)
        text.style.font = "24px verdana, arial, sans-serif";
        text.innerHTML = msg;
 
-       var main = document.getElementById("main");
-       main.appendChild(text);
+       document.getElementById("main").appendChild(text);
 
-       text.style.left = (main.clientWidth - text.clientWidth) / 2 + "px";
-       text.style.top = (main.clientHeight - text.clientHeight) / 2 + "px";
+       var screen_size = find_width();
+       text.style.left = (screen_size[0] - text.clientWidth) / 2 + "px";
+       text.style.top = (screen_size[1] - text.clientHeight) / 2 + "px";
 }
 
 function fade_text(opacity)
@@ -363,7 +396,7 @@ function fade_text(opacity)
                if (opacity < 0.0) {
                        opacity = 0.0;
                }
-               setTimeout("fade_text(" + opacity + ")", 30);
+               setTimeout(function() { fade_text(opacity); }, 30);
        } else {
                var text = document.getElementById("text");
                if (text !== null) {
@@ -374,21 +407,18 @@ function fade_text(opacity)
 
 function select_image(evt, filename, selected)
 {
-       if (!req) {
-               return;
-       }
-
        if (selected) {
                draw_text("Selecting " + filename + "...");
        } else {
                draw_text("Unselecting " + filename + "...");
        }
        
-       req.open("POST", window.location.origin + "/select", false);
+       var req = new XMLHttpRequest();
+       req.open("POST", window.location.origin + "/select", true);
        req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
        req.send("event=" + evt + "&filename=" + filename + "&selected=" + selected);
 
-       setTimeout("fade_text(0.99)", 30);
+       setTimeout(function() { fade_text(0.99); }, 30);
 }
 
 function key_down(which)
@@ -439,6 +469,7 @@ function parse_image_num(default_value) {
                return default_value;
        }
 }
+window['parse_image_num'] = parse_image_num;
 
 function check_for_hash_change() {
        var num = parse_image_num(-1);
@@ -464,3 +495,107 @@ function toggle_immersive() {
        }
        relayout();
 }
+window['toggle_immersive'] = toggle_immersive;
+
+var swiping = false;
+var swipe_start_x = 0;
+
+function set_swipe_pos(x, transition)
+{
+       x = Math.max(x, -window.innerWidth);
+       x = Math.min(x,  window.innerWidth);
+       if (!can_go_previous()) {
+               x = Math.min(x, window.innerWidth / 8);
+       }
+       if (!can_go_next()) {
+               x = Math.max(x, -window.innerWidth / 8);
+       }
+
+       var dpr = find_dpr();
+       var main = document.getElementById("main");
+       var children = main.children;
+       var to_remove = [];
+       for (var i = 0; i < children.length; i++) {
+               var child = children[i];
+               if (child.className === "fsimg") {
+                       var inum = parseInt(child.id);
+                       var offset = inum - global_image_num;
+                       child.style.transition = transition;
+                       child.style.transform = "translate(" + (x + find_width()[0] * offset / dpr) + "px,0px)";
+               } else if (child.className === "fsbox") {
+                       var inum = parseInt(child.id.replace("_box", ""));
+                       var offset = inum - global_image_num;
+                       child.style.transition = transition;
+                       child.style.transform = "translate(" + (x + find_width()[0] * offset / dpr) + "px,0px) scale(" + (1.0 / dpr) + ")";
+               }
+       }
+}
+
+function start_swipe(e)
+{
+       swiping = true;
+       swipe_start_x = e.changedTouches[0].pageX;
+}
+
+function end_swipe(e)
+{
+       if (swiping) {
+               var new_x = (e.changedTouches[0].pageX - swipe_start_x);
+               if (new_x < -window.innerWidth / 4 && can_go_next()) {
+                       set_swipe_pos(-window.innerWidth, "transform 0.1s ease-out");
+                       setTimeout(function() { go_next(); }, 100);
+               } else if (new_x > window.innerWidth / 4 && can_go_previous()) {
+                       set_swipe_pos(window.innerWidth, "transform 0.1s ease-out");
+                       setTimeout(function() { go_previous(); }, 100);
+               } else {
+                       set_swipe_pos(0, "transform 0.1s ease-out");
+               }
+               swiping = false;
+       }
+}
+
+function swipe(e)
+{
+       if (swiping) {
+               var new_x = (e.changedTouches[0].pageX - swipe_start_x);
+               set_swipe_pos(new_x, null);
+       }
+}
+
+window.onload = function() {
+       relayout();
+       setInterval(check_for_hash_change, 1000);
+
+       document.addEventListener('touchstart', start_swipe, false);
+       document.addEventListener('touchend', end_swipe, false);
+       document.addEventListener('touchmove', swipe, false)
+
+       var body = document.body;
+       body.onresize = function() { relayout(); };
+       body.onkeydown = function(evt) { key_down(evt.keyCode); };
+       body.onkeyup = function(evt) { key_up(evt.keyCode); };
+       body.onhashchange = function() { check_for_hash_change(); };
+       body.onclick = function() { check_for_hash_change(); };
+
+       var previous = document.getElementById('previous');
+       previous.onmousedown = function() { if (can_go_previous()) { set_opacity('previous', global_highlight_opacity); } };
+       previous.onmouseup = function() { if (can_go_previous()) { set_opacity('previous', global_default_opacity); go_previous(); } };
+       previous.onmouseout = function() { if (can_go_previous()) { set_opacity('previous', global_default_opacity); } };
+
+       var next = document.getElementById('next');
+       next.onmousedown = function() { if (can_go_next()) { set_opacity('next', global_highlight_opacity); } };
+       next.onmouseup = function() { if (can_go_next()) { set_opacity('next', global_default_opacity); go_next(); } };
+       next.onmouseout = function() { if (can_go_next()) { set_opacity('next', global_default_opacity); } };
+
+       var close = document.getElementById('close');
+       close.onmousedown = function() { set_opacity('close', global_highlight_opacity); };
+       close.onmouseup = function() { set_opacity('close', global_default_opacity); do_close(); };
+       close.onmouseout = function() { set_opacity('close', global_default_opacity); };
+
+       var options = document.getElementById('options');
+       options.onmousedown = function() { set_opacity('options', global_highlight_opacity); };
+       options.onmouseup = function() { set_opacity('options', global_default_opacity); toggle_optionmenu(); };
+       options.onmouseout = function() { set_opacity('options', global_default_opacity); };
+};
+
+})();