0

I know it's not good practice, but I made a page with almost entirely fixed sizing.

Also, there is a lot of JavaScript and interactive parts dealing with the coordinates of your cursor etc.

If I wanted to increase everything by a certain size, I could manually change every number to multiply or divide by a "zoom" variable. However, in addition to that being incredibly time consuming while using regex with find and replace, there is still a lot that could possibly go wrong.

Is there some CSS (or HTML or JavaScript) attribute/function that would allow me to scale up the entire thing? I know I can use transform: scale(x) in CSS, along with some other similar things, but is there a way everything can be scaled including the cursor coordinates?

Thank you!

Edit: Refer to the comments for more info.

$(document).ready(main);
function main(){

"use strict";

var popup = window;
var doc = document;
var $body = $('body', doc)[0];
var $inputs = doc.getElementsByClassName('note');
var $paragraphs = doc.getElementsByTagName('p');

doc.title = "Assignment Notebook";

$body.innerHTML = "<canvas></canvas>";

var images = {
  left : "https://i.imgur.com/xlnvl6M.png",
  right : "https://i.imgur.com/o8XT5X1.png"
}

var snapPoints = [62,84,106,128,150,172,194,216,238,261,283,305,327,349,371,393,415,438,462,484,506,528,550,572,594,616];

var inputs = {};

var d = new Date();
var week;
function setWeek() {
  week = [];
  for (var i = 1; i < 8; i++) {
    var _d = new Date(d);
    week[i-1] = new Date(_d.setDate(_d.getDate() - _d.getDay()+i));
  }
}
setWeek();
var months = {0: 'January',1: 'February',2: 'March',3: 'April',4: 'May',5: 'June',6: 'July',7: 'August',8: 'September',9: 'October',10: 'November',11: 'December'};
var df;
function updateFormat(n) {
  df = formatDate(week[n].getDay()-1, '');
}
function checkArr() {
  var start = left ? 0 : 3;
  var end = left ? 3 : 7;
  for (var i = start; i < end; i++) {
    updateFormat(i);
    if (!inputs[df]) {
      inputs[df] = [];
    } else if (JSON.stringify(inputs[df]) != "[]") {
      for (var j = 0; j < inputs[df].length; j++) {
        let data = inputs[df][j];
        createInput(data.x, data.y, data.fontFamily, data.fontSize, data.width, data.bg, data.txt);
      }
    }
  }
}
var left = (d.getDay() == 0 || d.getDay() > 3) ? false : true;
$body.style.backgroundImage = left ? "url("+images.left+")" : "url("+images.right+")";
$body.style.backgroundSize = "480px 680px";
$body.style.backgroundRepeat = "no-repeat";
$body.style.margin = "0";
checkArr();
var ctx = $('canvas', doc)[0].getContext('2d');
var fontFamily = 'sans-serif';
var fontSize = 14;
ctx.font = fontSize+' '+fontFamily;
function createP (text, family, weight, size, x, y) {
  var p = doc.createElement("P");
  p.setAttribute("type", "text");
  p.style.position = 'fixed';
  p.style.fontFamily = family;
  p.style.fontWeight = weight;
  p.innerHTML = text;
  p.style.top = y;
  p.style.left = x;
  p.style.fontSize = size;
  p.style.userSelect = 'none';
  $body.appendChild(p);
}
function formatDate(dayIndex, join) {
  if (dayIndex == -1) dayIndex = 6;
  return months[week[dayIndex].getMonth()]+join+week[dayIndex].getDate();
}
left ? (
  createP(formatDate(0, ' '), 'Helvetica', '300', '11px', '114px', '36px'),
  createP(formatDate(1, ' '), 'Helvetica', '300', '11px', '116px', '235px'),
  createP(formatDate(2, ' '), 'Helvetica', '300', '11px', '140px', '436px')
) : (
  createP(formatDate(3, ' '), 'Helvetica', '300', '11px', '126px', '36px'),
  createP(formatDate(4, ' '), 'Helvetica', '300', '11px', '102px', '235px'),
  createP(formatDate(5, ' '), 'Helvetica', '300', '11px', '72px', '436px'),
  createP(formatDate(6, ' '), 'Helvetica', '300', '11px', '276px', '436px')
);
function createInput(x, y, ff, fs, width, bg, txt) {
  fs = parseInt(fs);
  var input = doc.createElement("INPUT");
  input.setAttribute("type", "text");
  input.setAttribute("placeholder", "Type here!");
  input.style.position = 'fixed';
  input.classList.add('note');
  $body.appendChild(input);
  input.style.left = x;
  input.style.top = snap ? getClosest(y+fs)-fs : y;
  input = $inputs[$inputs.length-1];
  typeof txt != "string" ? input.focus() : input.value = txt;
  input.style.backgroundColor = bg;
  input.style.border = 'none';
  input.style.outline = 'none';
  input.style.width = width;
  input.style.fontFamily = ff;
  input.style.fontSize = fs;
  input.style.backgroundColor = bg;
  input.draggable = true;
  input.addEventListener('keyup', e => {
    ctx.font = window.getComputedStyle(input).getPropertyValue('font-size')+' '+window.getComputedStyle(input).getPropertyValue('font-family');
    e.path[0].style.width = !!e.path[0].value ? ctx.measureText(e.path[0].value).width+3 : 86;
  });
}

var diff = {
  x : null,
  y : null
}

doc.addEventListener('dragstart', e => {
  diff.x = e.clientX - parseInt(e.target.style.left);
  diff.y = e.clientY - parseInt(e.target.style.top);
});
doc.addEventListener('dragend', e => {
  let height = parseInt(window.getComputedStyle(e.target).getPropertyValue('font-size'));
  e.target.style.left = e.clientX-diff.x;
  e.target.style.top = snap ? getClosest(e.clientY-diff.y+height)-height : e.clientY-diff.y;
});

doc.addEventListener('keyup', e => {
  if (doc.activeElement.tagName != "INPUT" && e.keyCode == 37 || e.keyCode == 39) {
    var inpLen = $inputs.length;
    var pLen = $paragraphs.length;
    for (var i = 0; i < inpLen; i++) {
      $inputs[0].remove();
    }
    for (var i = 0; i < pLen; i++) {
      $paragraphs[0].remove();
    }
    if (e.keyCode == 37) {
      if (d.getDay() > 0 && d.getDay() < 4) {
        d = new Date(week[0].setDate(week[0].getDate() - week[0].getDay()-3));
      } else {
        d = new Date(week[0].setDate(week[0].getDate() - week[0].getDay()+1));
      }
    } else {
      if (d.getDay() > 0 && d.getDay() < 4) {
        d = new Date(week[0].setDate(week[0].getDate() - week[0].getDay()+4));
      } else {
        d = new Date(week[0].setDate(week[0].getDate() - week[0].getDay()+8));
      }
    }
    setWeek();
    left = (d.getDay() == 0 || d.getDay() > 3) ? false : true;
    $body.style.backgroundImage = left ? "url("+images.left+")" : "url("+images.right+")";
    left ? (
      createP(formatDate(0, ' '), 'Helvetica', '300', '11px', '114px', '36px'),
      createP(formatDate(1, ' '), 'Helvetica', '300', '11px', '116px', '235px'),
      createP(formatDate(2, ' '), 'Helvetica', '300', '11px', '140px', '436px')
    ) : (
      createP(formatDate(3, ' '), 'Helvetica', '300', '11px', '126px', '36px'),
      createP(formatDate(4, ' '), 'Helvetica', '300', '11px', '102px', '235px'),
      createP(formatDate(5, ' '), 'Helvetica', '300', '11px', '72px', '436px'),
      createP(formatDate(6, ' '), 'Helvetica', '300', '11px', '276px', '436px')
    );
    checkArr();
  }
});

doc.addEventListener('dblclick', e => {
  if (doc.activeElement.tagName != "INPUT" && !deleteMode) {
    createInput(e.clientX, parseInt(e.clientY)-9.5, fontFamily, fontSize, 86, "transparent", true);
  }
});
var snap = false;
var deleteMode = false;
function getClosest(n) {
  if (isNaN(n) || typeof n != 'number') err('Number isn\'t of type "number", or it is NaN');
  return snapPoints.reduce((a, b) => Math.abs(b - n) < Math.abs(a - n) ? b : a);
}

function err(error) {
  console.log(new Error(error));
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Andrew
  • 119
  • 1
  • 7
  • You need to show a fully working example. – antfuentes87 Jun 29 '18 at 00:49
  • 2
    That's the thing, I don't have a working example. And this is a generic idea, so the answer I'm looking for would work with any page – Andrew Jun 29 '18 at 00:51
  • For me at least I would no way of helping you. I do not fully understand what your asking. Plus when you mention scaling the cursor coordinates, that makes no sense to me. Hopefully someone else can help you but I am pretty sure your going to need to provide some kind of demo. – antfuentes87 Jun 29 '18 at 00:53
  • Post edited to include demo. – Andrew Jun 29 '18 at 01:24
  • I understand, but there are too many characters to put it in a snippet, and snippets/jsfiddle block pop-ups (the main page is a popup) – Andrew Jun 29 '18 at 01:28
  • In question:`"I made a page with almost entirely fixed sizing."` and then…In comment:`"That's the thing, I don't have a working example."` — It sounds like you do, but if not...make one? – vol7ron Jun 29 '18 at 01:31
  • I have a demo of the page, which is at the bottom of the post. I just don't have a working demo using a function to try to adjust the size other than one where I manually changed everything, but that is irrelevant – Andrew Jun 29 '18 at 01:32
  • Can you transition your demo to the Code Snippet that Stack Overflow provides? – vol7ron Jun 29 '18 at 01:33
  • I'm not able to. `there are too many characters to put it in a snippet, and snippets/jsfiddle block pop-ups (the main page is a popup)` – Andrew Jun 29 '18 at 01:33
  • Ahh, have you tried removing those two Base64 images? A working demo just has to work conceptually so that others can understand/debug more quickly. It's better for their time and for yours if you're after a quick solution. Pastebin is next to no good, JSFiddle is better than nothing, but the Code Snippet is the recommended feature so that others may copy/paste your example quickly – vol7ron Jun 29 '18 at 01:36
  • 1
    Give me a bit to remove the popup, local storage use, and base64 images, then I'll post a snippet – Andrew Jun 29 '18 at 01:37
  • Alright, so, I don't have enough time to make the snippet work perfectly, but it sorta works? If you use the same code inside an html document it'll work, it's just the snippet. But I hope that gives you an idea. – Andrew Jun 29 '18 at 01:59
  • Basically, when you double click it creates an input element where you clicked (which is the part not working on the snippet, but you get the idea). The goal is to make the input exactly where you clicked regardless of the size (which I would change using the css `zoom` property on the body). You could easily achieve this by dividing the coordinates by the scale, but there are a variety of other factors in this code that rely on the coordinates, so is there another way to do it? – Andrew Jun 29 '18 at 02:02
  • Not especially relevant (?) But your demo shows the wrong day/date. I'm in Melbourne, Aus and it's currently 12:07pm on Friday the 29th. Your demo says Thurs June 28 (and seemingly, does nothing else) – enhzflep Jun 29 '18 at 02:07
  • @enhzflep yeah that's not relevant. @Andrew thanks for the example. Why have you decided to use fixed sizing? It seems like everything inside the container you want to size should be an `em`, which would allow you to change the size of the container and automatically affect all else. Also, why can't you use `zoom` on the container? – vol7ron Jun 29 '18 at 02:11
  • Many people have solved the problem of scaling in the past by way of an SVGMatrix. An example of use (in this case, with a scaled canvas) can be found in the answer supplied by Phrogz, here: https://stackoverflow.com/questions/5526486/clear-entire-transformed-html5-canvas-while-preserving-context-transform – enhzflep Jun 29 '18 at 02:13
  • I just completely disagree with your implementation of using fixed coordinates for mouse events. At most they should be relative, but even that, they should be container-sniffing. This would be a maintenance nightmare and I would feel uncomfortable offering any other suggestions before you take care of that. Note that pixels on one screen are not equivalent on another. Some screens/browsers even handle partial pixels, which could cause unexpected behavior based on what you may want to do with the mouse. – vol7ron Jul 06 '18 at 17:12

1 Answers1

1

One work around you can use to scale the whole document since you made the whole page fixed scaling, would be to include the whole page into an iframe (https://www.w3schools.com/html/html_iframe.asp) which spans the whole page. This way you can play around with scaling/zoom of the iframe but the user will only see that page inside the iframe.

You can play around with the css of iframe to get the correct way to display the inner page.

  • Thank you! This is exactly the type of answer I was looking for. And thank you to everyone else who helped! – Andrew Jun 29 '18 at 23:56