word/edit: image container only needed for source
[sheet.git] / word / editor.js
index da403b2217ad31c75178ea6cb1cc958cf7f2d1f1..a4b8d8edab037f4923eef8bfc6d1338cb8c38cb3 100644 (file)
@@ -1,4 +1,17 @@
 document.addEventListener('DOMContentLoaded', () => {
+       document.querySelectorAll('#search').forEach(p => {
+               let [input, button] = p.children;
+               button.onclick = e => {
+                       if (input.value && input.offsetWidth > 50) {
+                               return true; // bubble to submit
+                       }
+                       // make visible first
+                       input.focus();
+                       e.preventDefault();
+                       return false;
+               };
+       });
+
        document.querySelectorAll('.multiinput > input[id]').forEach(el => {
                el.oninput = e => {
                        if (e.target.value == '') return;
@@ -31,7 +44,9 @@ document.addEventListener('DOMContentLoaded', () => {
                                let transrow = document.getElementById('trans-la');
                                if (transrow && !transrow.value && wptext) {
                                        const binom = wptext.match(/ class="binomial">.*?<i>(.*?)<\/i>/);
-                                       transrow.value = binom[1]
+                                       if (binom) {
+                                               transrow.value = binom[1]
+                                       }
                                }
 
                                // translations from language links
@@ -105,22 +120,102 @@ document.addEventListener('DOMContentLoaded', () => {
        let thumbpreview = document.getElementById('convertpreview');
        if (thumbpreview && imgpreview) {
                thumbpreview.onclick = e => {
-                       let imgselect = imgpreview; /* TODO clone */
-                       imgselect.hidden = false;
-                       imgselect.classList.add('popup');
-                       imgselect.onmousemove = e => {
-                               let border = imgselect.getBoundingClientRect();
-                               let pos = [
-                                       Math.round(1000 * (e.clientX - border.x) / border.width),
-                                       Math.round(1000 * (e.clientY - border.y) / border.height)
-                               ];
-                               return pos;
+                       thumbpreview.onclick = null; // setup once
+                       const cropinput = document.getElementById('crop32');
+                       const imgselect = thumbpreview.children[0];
+                       const border = [300,200];
+                       let crop = cropinput.value.split(/[^0-9]/).map(pos => pos / 1000);
+                       let scale = 1 / (crop[2] - crop[0]) || 1;
+                       crop.push(0); // defined y dimension
+                       crop.splice(2); // end coordinates applied to zoom
+                       crop = crop.map((rel, axis) => rel * border[axis % 2] * scale);
+
+                       let drag, pinch;
+                       function applydrag(e) {
+                               const touch = e.touches ? e.touches[0] : e;
+                               let pos = [touch.pageX, touch.pageY];
+                               if (e.type === 'touchmove' && e.touches.length > 1) {
+                                       // distance to second point
+                                       pos[0] -= e.touches[1].pageX;
+                                       pos[1] -= e.touches[1].pageY;
+                                       const span = Math.sqrt(pos[0]**2 + pos[1]**2);
+                                       if (pinch) {
+                                               cropzoom(.01 * (span - pinch));
+                                       }
+                                       pinch = span;
+                                       return;
+                               }
+                               if (drag) {
+                                       // apply drag delta to crop position
+                                       crop[0] += drag[0] - pos[0];
+                                       crop[1] += drag[1] - pos[1];
+                                       recrop();
+                               }
+                               drag = pos;
+                       }
+
+                       function recrop() {
+                               [0, 1].forEach(axis => {
+                                       if (crop[axis] > border[axis] * (scale - 1)) {
+                                               crop[axis] = border[axis] * (scale - 1);
+                                       }
+                                       if (crop[axis] < 0) {
+                                               crop[axis] = 0;
+                                       }
+                               });
+                               imgselect.style.left = -crop[0]+'px';
+                               imgselect.style.top  = -crop[1]+'px';
+                               imgselect.style.width = (scale * 100)+'%';
+                               cropinput.value = [
+                                       crop[0] / border[0],     crop[1] / border[1],
+                                       crop[0] / border[0] + 1, crop[1] / border[1] + 1,
+                               ].map(pos => Math.round(1000 * pos / scale));
+                       }
+
+                       function cropzoom(delta) {
+                               if (scale + delta < 1) {
+                                       delta = 1 - scale; // scale = 1
+                               }
+                               [0, 1].forEach(axis => {
+                                       // same area center at altered scale
+                                       crop[axis] += (crop[axis] + border[axis] / 2) / scale * delta;
+                               });
+                               scale += delta;
+                               recrop();
+                       }
+
+                       imgselect.src = imgpreview.src;
+                       imgselect.style.cursor = 'grab';
+                       imgselect.style.position = 'absolute';
+                       recrop();
+
+                       imgselect.ontouchstart =
+                       imgselect.onmousedown = e => {
+                               e.preventDefault();
+                               drag = pinch = false;
+                               applydrag(e);
+                               imgselect.style.cursor = 'grabbing';
+                               window.ontouchmove =
+                               window.onmousemove = e => {
+                                       e.preventDefault();
+                                       applydrag(e);
+                               };
+                               window.ontouchend =
+                               window.onmouseup = e => {
+                                       e.preventDefault();
+                                       imgselect.style.cursor = 'grab';
+                                       window.ontouchmove = window.ontouchend =
+                                       window.onmousemove = window.onmouseup = null;
+                               };
                        };
-                       imgselect.onclick = e => {
-                               let imgoption = document.getElementById('convert');
-                               imgoption.value += (imgoption.value && '-') + imgselect.onmousemove(e);
-                               imgselect.hidden = true;
-                               imgselect.classList.remove('popup');
+
+                       imgselect.onwheel = e => {
+                               e.preventDefault();
+                               let delta = (-e.deltaY || e.wheelDelta) * .001 * scale;
+                               if (e.deltaMode == 1) { // DOM_DELTA_LINE
+                                       delta *= 18; // convert number of lines to pixels
+                               }
+                               cropzoom(delta);
                        };
                };
        }