6

I been working on a code which was showing how to resize a div dynamically. However code was stuck on 1 element and I worked on a little to convert into multiple div resizer.

Now there is a space appears between mouse and the div while being resized, my goal is to make sure every single element seperately being resized with exact mouse location depending on parent position. Any approach that would change my perspective is appriciated. Not bound to the resize nodes instead directly holding div borders also possible.

Things I ve achived so far :

-Made multiple divs resizable by mouse location.

-Holded first location info in a function.

-Calgulated difference betweeen child and parent.

Things I would like to achieve:

-To make sure holders stays under mouse location while resizing without any space between mouse and div.

After couple attempts to resize I see there is a space appears caused by parent elements margins, paddings...etc. and div starts resizing with a space between div and the mouse location.

I need a recursive solution in calgulation to correctly resize and relocate divs.

May be another approach could be used to calgulate only x,y,w,h inside parent but I need some explanation about how to achive that with mouse...

function resizeable() {
  var resizers = document.querySelectorAll('.n, .s, .w, .e, .nw, .ne, .se, .sw');
  const min = 40;
  for (let i = 0; i < resizers.length; i++) {
    const currentResizer = resizers[i];
    const element = currentResizer.parentElement;
    const parent = currentResizer.parentElement.parentElement;
    let p;
    let c;
    let original_w = 0;
    let original_h = 0;
    let parent_x = 0;
    let parent_y = 0;
    let child_x = 0;
    let child_y = 0;
    let mouse_x = 0;
    let mouse_y = 0;
    let scale_x = 0;
    let scale_y = 0;
    // Mouse events
    currentResizer.addEventListener('mousedown', function(e) {
      first(e);
      document.addEventListener('mousemove', resize);
      document.addEventListener('mouseup', stopResize);
      e.preventDefault();
    });
    // Log
    function log(e){
      var str = 'original_w['+original_w+'] original_h['+original_h+'] \n'+
                'parent_x['+parent_x+'] parent_y['+parent_y+'] \n'+
                'child_x['+child_x+'] child_y['+child_y+'] \n'+
                'scale_x['+scale_x+'] scale_y['+scale_y+'] \n'+
                'mouse_x['+mouse_x+'] mouse_y['+mouse_y+'] \n'+
                'e.pageX['+e.pageX+'] e.pageY['+e.pageY+'] \n'+
                'obj.left['+element.style.left+'] obj.top['+element.style.top+']';
      console.log(str);
      /**/
      str = '<table>'+
          '<tr>'+
            '<th colspan="2">First Locations:</td>'+
          '</tr>'+
          '<tr>'+
            '<td>original_w['+original_w+']</td>'+
            '<td>original_h['+original_h+']</td>'+
          '</tr>'+
          '<tr>'+
            '<td>parent_x['+parent_x+']</td>'+
            '<td>parent_y['+parent_y+']</td>'+
          '</tr>'+
          '<tr>'+
            '<td>child_x['+child_x+']</td>'+
            '<td>child_y['+child_y+']</td>'+
          '</tr>'+
          '<tr>'+
            '<td>scale_x['+scale_x+']</td>'+
            '<td>scale_y['+scale_y+']</td>'+
          '</tr>'+
          '<tr>'+
            '<td>mouse_x['+mouse_x+']</td>'+
            '<td>mouse_y['+mouse_y+']</td>'+
          '</tr>'+
          '<tr>'+
            '<td>e.pageX['+e.pageX+']</td>'+
            '<td>e.pageY['+e.pageY+']</td>'+
          '</tr>'+
          '<tr>'+
            '<td>obj.left['+element.style.left+']</td>'+
            '<td>obj.top['+element.style.top+']</td>'+
          '</tr>'
      '</table>';
      var m = document.getElementById("nfo"); // Debug element
      m.innerHTML = str;
    }
    // First location & width
    function first(e) {
      c = element.getBoundingClientRect();
      child_y = c.top;
      child_x = c.left;
      p = parent.getBoundingClientRect();
      parent_y = p.top;
      parent_x = p.left;
      original_w = parseFloat(c.width).toFixed(2);
      original_h = parseFloat(c.height).toFixed(2);
      scale_y = parseFloat(c.height / element.offsetHeight).toFixed(2);
      scale_x = parseFloat(c.width / element.offsetWidth).toFixed(2);
      mouse_y = e.pageY;
      mouse_x = e.pageX;
      log(e);
    }
    // Resize process
    function resize(e) {
      element.style.position = "absolute";
      if (currentResizer.classList.contains('se')) {
        const width = e.pageX - child_x;
        const height = e.pageY - child_y;
        if (width > min) {
          element.style.width = (width / scale_x) + 'px';
        }
        if (height > min) {
          element.style.height = (height / scale_y) + 'px';
        }
      }
      else if (currentResizer.classList.contains('sw')) {
        const width = original_w - (e.pageX - child_x);
        const height = e.pageY - child_y;
        if (height > min) {
          element.style.height = (height / scale_y) + 'px';
        }
        if (width > min) {
          element.style.left = e.pageX - parent_x + 'px';
          element.style.width = (width / scale_x) + 'px';
        }
      }
      else if (currentResizer.classList.contains('ne')) {
        const width = e.pageX - child_x;
        const height = original_h - (e.pageY - mouse_y);
        if (width > min) {
          element.style.width = (width / scale_x) + 'px';
        }
        if (height > min) {
          element.style.height = (height / scale_y) + 'px';
          element.style.top =  e.pageY - parent_y + 'px';
        }
      }
      else if (currentResizer.classList.contains('nw')) {
        const width = original_w - (e.pageX - child_x);
        const height = original_h - (e.pageY - mouse_y);
        if (width > min) {
          element.style.left = e.pageX - parent_x + 'px';
          element.style.width = (width / scale_x) + 'px';
        }
        if (height > min) {
          element.style.height = (height / scale_y) + 'px';
          element.style.top = e.pageY - parent_y + 'px';
        }
      }
      else if (currentResizer.classList.contains('e')) {
        const width = e.pageX - child_x;
        if (width > min) {
          element.style.width = (width / scale_x) + 'px';
        }
      }
      else if (currentResizer.classList.contains('s')) {
        const height = e.pageY - child_y;
        if (height > min) {
          element.style.height = (height / scale_y) + 'px';
        }
      }
      else if (currentResizer.classList.contains('w')) {
        const width = original_w - (e.pageX - child_x);
        if (width > min) {
          element.style.width = (width / scale_x) + 'px';
          element.style.left = (e.pageX - parent_x) + 'px';
        }
      }
      else if (currentResizer.classList.contains('n')) {
        const height = original_h - (e.pageY - mouse_y);
        if (height > min) {
          element.style.height = (height / scale_y) + 'px';
          element.style.top = e.pageY - parent_y + 'px';
        }
      }
      log(e);
    }
    // When mouse released stop
    function stopResize(e) {
      first(e);
      document.removeEventListener('mousemove', resize);
    }
  }
}
resizeable();
.another_element_on_the_way {
  position: relative;
  width: 100px;
  height: 100px;
  float: left;
}
#nfo {
  position: relative;
  float: left;
}
div {
  position: absolute;
  background-color: grey;
}
.holder {
  float: left;
  clear: left;
  position: relative;
  margin: 20px;
  width: 550px;
  height: 600px;
}
.scaled:hover:before, .regular:hover:before {
  content: '';
  position: absolute;
  top: -3px;
  left: -3px;
  width: calc(100% - 6px);
  height: calc(100% - 6px);
  border: 6px solid #ccc;
}
.regular:nth-child(1){
  top: 5px;
  left: 5px;
  width: 120px;
  height: 120px;
  background-color: red;
}
.regular:nth-child(3){
  top: 270px;
  left: 60px;
  width: 240px;
  height: 180px;
  background-color: blue;
}
.scaled {
  top: 150px;
  left: 25px;
  width: 160px;
  height: 160px;
  transform: scale(0.6) translate(0, 0);
  transform-origin: top left 0px;
  background-color: green;
  overflow: visible;
}
.previewHeader {
  position: absolute;
  top: 10px;
  left: 10px;
  background-color: #eee;
  border: 1px solid #dedede;
}
.n, .s, .w, .e, .nw, .ne, .se, .sw {
  position: absolute;
  width: 18px;
  height: 18px;
  border: 1px solid grey;
  border-radius: 20px;
  background-color: #fff;
}
.n:hover, .s:hover, .w:hover, .e:hover,
.nw:hover, .ne:hover, .se:hover, .sw:hover {
  background-color: red;
}
.nw {
  top: -10px;
  left: -10px;
  cursor: nw-resize;
}
.ne {
  top: -10px;
  left: calc(100% - 10px);
  cursor: ne-resize;
}
.sw {
  top: calc(100% - 10px);
  left: -10px;
  cursor: sw-resize;
}
.se {
  top: calc(100% - 10px);
  left: calc(100% - 10px);
  cursor: se-resize;
}
.n {
  top: -10px;
  left: calc(50% - 10px);
  cursor: n-resize;
}
.w {
  top: calc(50% - 10px);
  left: -10px;
  cursor: w-resize;
}
.e {
  top: calc(50% - 10px);
  left:  calc(100% - 10px);
  cursor: e-resize;
}
.s {
  top: calc(100% - 10px);
  left: calc(50% - 10px);
  cursor: s-resize;
}
<div class="another_element_on_the_way">
</div>
<div class="another_element_on_the_way">
</div>
<div class="another_element_on_the_way">
</div>
<div class="another_element_on_the_way">
</div>
<div class="another_element_on_the_way">
</div>
<div class="another_element_on_the_way">
</div>
<div class="holder">
  <div class="regular">
      <div class="previewHeader">Resizable</div>
      <div class="nw"></div>
      <div class="ne"></div>
      <div class="sw"></div>
      <div class="se"></div>
      <div class="n"></div>
      <div class="s"></div>
      <div class="w"></div>
      <div class="e"></div>
  </div>
  <div class="scaled">
    <div class="previewHeader">Scaled</div>
    <div class="nw"></div>
    <div class="ne"></div>
    <div class="sw"></div>
    <div class="se"></div>
    <div class="n"></div>
    <div class="s"></div>
    <div class="w"></div>
    <div class="e"></div>
  </div>
  <div class="regular">
    <div class="previewHeader">Resizable</div>
    <div class="nw"></div>
    <div class="ne"></div>
    <div class="sw"></div>
    <div class="se"></div>
    <div class="n"></div>
    <div class="s"></div>
    <div class="w"></div>
    <div class="e"></div>
  </div>
</div>
<div id="nfo"> X & Y</div>

Also a codepen to show it more clear: https://codepen.io/BerkerYuceer/pen/gOYwqdb

Berker Yüceer
  • 7,026
  • 18
  • 68
  • 102
  • Also for debug help: check the `.ne` or `.nw` holders to see how top calc fails. – Berker Yüceer Aug 23 '19 at 07:37
  • I think you may have to calculate the scaling and the conditional code to when it is scaled `let match = getComputedStyle(element).transform.match(/matrix\((-?\d*\.?\d+),\s*0,\s*0,\s*(-?\d*\.?\d+),\s*0,\s*0\)/); if (match && match[1] != 0 && match[2] != 0)` and multiply `+match[1]` or `+match[2]` accordingly based on x,y – shrys Aug 23 '19 at 08:00
  • Could you please send it as an answer and with explanation. Cause I found many questions like this but none was curing this issue so if you can post a quality answer it may be usefull for future reference and would be a helpfull topic for all. – Berker Yüceer Aug 23 '19 at 08:08
  • sure, I'll try to solve the issue too – shrys Aug 23 '19 at 08:17
  • Do you want the resizer handle centers to snap to the mouse position, or would you like the offset between mousedown and handle center to remain the same so that it doesn't resize until dragging the mouse? – George Aug 31 '19 at 17:07
  • What are the requirements? For example: //requirements: //ability to create new boxes with x,y,w,h //ability to resize and reposition boxes //boxes must never intersect //the boxes are bounded by the top,right,bottom, and left of their container or the screen //when resizing or moving boxes, they can push other boxes but cannot resize the other boxes //when resizing a box and pushing another box into a boundary, it will now be unable to continue resizing in that direction due to the container boundary. – George Aug 31 '19 at 17:24
  • I can make the above requirements if you want, from scratch I don't want to waste my time, so would they be ok or not? – George Aug 31 '19 at 17:26
  • @George I can start another bounty for that however right now my only problem is to calgulate the top or left position with browser compability including parent margins cause that is changing all.. I just update the code. – Berker Yüceer Sep 02 '19 at 06:00
  • Right but you need to be clear in what you want. How do boxes interact with the parent container boundary? How do boxes interact with each-other? – George Sep 02 '19 at 08:08
  • I just would like to resize from any side I pull seamlessly. Whenever I pull top parts it just calgulates the mouse location and the starting location of element. Starting location of the element is wrong caused by the other elements on its way. Margins Paddings and all other Borders causes start location of div to be miscalculated. – Berker Yüceer Sep 03 '19 at 08:28
  • @George So I got a container holding these multiple divs and by including holder div all can be scaled. What I want is to be able to resize even while scaled or even while my container is at the bottom or at the side of the page, actually anywhere in the screen it should work same without causing any space between mouse and the pull dots of the div. However other divs around the page causes some miscalculation and in everybrowser its different. – Berker Yüceer Sep 03 '19 at 08:30
  • 1
    That didn't help me understand anything. I understand the current behaviour is odd / wrong, as pulling left, up etc. causes issues with margin/padding. _I can see that._ But, I also notice that when you pull south, the box below is moved out of the way. Is this desired behaviour? You could just set everything to position absolute and it would make things a whole lot easier, but then boxes won't interact with eachother. – George Sep 03 '19 at 19:39
  • By not determining the specific behaviour beforehand, you make the code a lot harder to write for yourself. Whereas if you knew what you wanted specifically, you would probably find it much easier to implement yourself. – George Sep 03 '19 at 19:41
  • @George its not desired behaviour I was just testing possibilities. Offcourse all will be absolute positioned. I want every single div to be resizable seperately. Without interacting each other. I may provide a z-index to seperate all. – Berker Yüceer Sep 04 '19 at 07:56
  • It looks like your codepen example is working now. congrats. Is there anything you would like to improve with it? I have a bunch of suggestions on how to improve the code to make it more readable and useable if you want? – George Sep 08 '19 at 13:33
  • actually it looks like working yet it does not. When you split the page into pieces with divs and when you put some margins on them again the gap between holding point and mouse location appears. In all browsers it acts differently cause in all browsers it is being calgulated differently. I just minorized the problem but certainly not solved it yet. :) – Berker Yüceer Sep 09 '19 at 05:56
  • I solved it now fully working version of it is now available in example code. – Berker Yüceer Oct 25 '19 at 10:34

2 Answers2

5

You could use getComputedStyle to get the transform value with regex and apply 1 / scale value to required coordinates. I was able to solve the issue only for the East holder (I'm too dumb for coordinate geometry :P):

let match = getComputedStyle(element)
           .transform.match(/matrix\((-?\d*\.?\d+),\s*0,\s*0,\s*(-?\d*\.?\d+),\s*0,\s*0\)/);
let scale = 1; //for .regular folks
if (match && +match[1] != 0)
   scale = 1 / +match[1]; //because we need to unapply the transformation

Sample:

function resizeable() {
  var resizers = document.querySelectorAll('.n, .s, .w, .e, .nw, .ne, .se, .sw');
  const min = 40;
  for (let i = 0; i < resizers.length; i++) {
    const currentResizer = resizers[i];
    const element = currentResizer.parentElement;
    const parent = currentResizer.parentElement.parentElement;
    let p;
    let c;
    let original_w = 0;
    let original_h = 0;
    let parent_x = 0;
    let parent_y = 0;
    let child_x = 0;
    let child_y = 0;
    let mouse_x = 0;
    let mouse_y = 0;
    let scale_x = 0;
    let scale_y = 0;
    let scroll_x = 0;
    let scroll_y = 0;
    // Mouse events
    currentResizer.addEventListener('mousedown', function(e) {
      first(e);
      document.addEventListener('mousemove', resize);
      document.addEventListener('mouseup', stopResize);
      e.preventDefault();
    });
    // Log
    function log(e){
      var str = 'original_w['+original_w+'] original_h['+original_h+'] \n'+
                'parent_x['+parent_x+'] parent_y['+parent_y+'] \n'+
                'scroll_x['+scroll_x+'] scroll_y['+scroll_y+'] \n'+
                'child_x['+child_x+'] child_y['+child_y+'] \n'+
                'scale_x['+scale_x+'] scale_y['+scale_y+'] \n'+
                'mouse_x['+mouse_x+'] mouse_y['+mouse_y+'] \n'+
                'e.pageX['+e.pageX+'] e.pageY['+e.pageY+'] \n'+
                'obj.left['+element.style.left+'] obj.top['+element.style.top+']';
      console.log(str);
      /**/
      str = '<table>'+
          '<tr>'+
            '<th colspan="2">First Locations:</td>'+
          '</tr>'+
          '<tr>'+
            '<td>original_w['+original_w+']</td>'+
            '<td>original_h['+original_h+']</td>'+
          '</tr>'+
          '<tr>'+
            '<td>parent_x['+parent_x+']</td>'+
            '<td>parent_y['+parent_y+']</td>'+
          '</tr>'+
          '<tr>'+
            '<td>scroll_x['+scroll_x+']</td>'+
            '<td>scroll_y['+scroll_y+']</td>'+
          '</tr>'+
          '<tr>'+
            '<td>child_x['+child_x+']</td>'+
            '<td>child_y['+child_y+']</td>'+
          '</tr>'+
          '<tr>'+
            '<td>scale_x['+scale_x+']</td>'+
            '<td>scale_y['+scale_y+']</td>'+
          '</tr>'+
          '<tr>'+
            '<td>mouse_x['+mouse_x+']</td>'+
            '<td>mouse_y['+mouse_y+']</td>'+
          '</tr>'+
          '<tr>'+
            '<td>e.pageX['+e.pageX+']</td>'+
            '<td>e.pageY['+e.pageY+']</td>'+
          '</tr>'+
          '<tr>'+
            '<td>obj.left['+element.style.left+']</td>'+
            '<td>obj.top['+element.style.top+']</td>'+
          '</tr>'
      '</table>';
      var m = document.getElementById("nfo"); // Debug element
      m.innerHTML = str;
    }
    // First location & width
    function first(e) {
      c = element.getBoundingClientRect();
      child_y = c.top;
      child_x = c.left;
      p = parent.getBoundingClientRect();
      parent_y = p.top;
      parent_x = p.left;
      scroll_y = window.scrollY;
      scroll_x = window.scrollX;
      original_w = parseFloat(c.width).toFixed(2);
      original_h = parseFloat(c.height).toFixed(2);
      scale_y = parseFloat(c.height / element.offsetHeight).toFixed(2);
      scale_x = parseFloat(c.width / element.offsetWidth).toFixed(2);
      mouse_y = e.pageY - scroll_y;
      mouse_x = e.pageX - scroll_x;
      log(e);
    }
    // Resize process
    function resize(e) {
      element.style.position = "absolute";
      if (currentResizer.classList.contains('se')) {
        const width = e.pageX - scroll_x - child_x ;
        const height = e.pageY - scroll_y - child_y ;
        if (width > min) {
          element.style.width = (width / scale_x) + 'px';
        }
        if (height > min) {
          element.style.height = (height / scale_y) + 'px';
        }
      }
      else if (currentResizer.classList.contains('sw')) {
        const width = original_w - (e.pageX - scroll_x - child_x);
        const height = e.pageY - scroll_y - child_y;
        if (height > min) {
          element.style.height = (height / scale_y) + 'px';
        }
        if (width > min) {
          element.style.left = e.pageX - scroll_x - parent_x + 'px';
          element.style.width = (width / scale_x) + 'px';
        }
      }
      else if (currentResizer.classList.contains('ne')) {
        const width = e.pageX - child_x - scroll_x;
        const height = original_h - (e.pageY - mouse_y - scroll_y);
        if (width > min) {
          element.style.width = (width / scale_x)  + 'px';
        }
        if (height > min) {
          element.style.height = (height / scale_y) + 'px';
          element.style.top =  e.pageY - parent_y - scroll_y + 'px';
        }
      }
      else if (currentResizer.classList.contains('nw')) {
        const width = original_w - (e.pageX - scroll_x - child_x);
        const height = original_h - (e.pageY - scroll_y - mouse_y);
        if (width > min) {
          element.style.left = e.pageX - parent_x - scroll_x + 'px';
          element.style.width = (width / scale_x) + 'px';
        }
        if (height > min) {
          element.style.height = (height / scale_y) + 'px';
          element.style.top = e.pageY - parent_y - scroll_y + 'px';
        }
      }
      else if (currentResizer.classList.contains('e')) {
        const width = e.pageX - scroll_x - child_x;
        if (width > min) {
          element.style.width = (width / scale_x) + 'px';
        }
      }
      else if (currentResizer.classList.contains('s')) {
        const height = e.pageY - scroll_y - child_y;
        if (height > min) {
          element.style.height = (height / scale_y) + 'px';
        }
      }
      else if (currentResizer.classList.contains('w')) {
        const width = original_w - (e.pageX - scroll_x - child_x);
        if (width > min) {
          element.style.width = (width / scale_x) + 'px';
          element.style.left = (e.pageX - scroll_x - parent_x) + 'px';
        }
      }
      else if (currentResizer.classList.contains('n')) {
        const height = original_h - (e.pageY - scroll_y - mouse_y);
        if (height > min) {
          element.style.height = (height / scale_y) + 'px';
          element.style.top = e.pageY - scroll_y - parent_y + 'px';
        }
      }
      log(e);
    }
    // When mouse released stop
    function stopResize(e) {
      first(e);
      document.removeEventListener('mousemove', resize);
    }
  }
}
resizeable();
body {
  width: 1200px;
}
.another_element_on_the_top {
  position: relative;
  float: left;
  margin: 10px;
  width: 100px;
  height: 100px;
}
.another_element_on_the_left {
  position: relative;
  float: left;
  clear: left;
  margin: 10px;
  width: 100px;
  height: 100px;
}
#nfo {
  position: relative;
  float: left;
}
div {
  position: absolute;
  background-color: grey;
}
.holder {
  float: left;
  position: relative;
  margin: -470px 20px 20px 20px;
  width: 550px;
  height: 600px;
}
.scaled:hover:before, .regular:hover:before {
  content: '';
  position: absolute;
  top: -3px;
  left: -3px;
  width: calc(100% - 6px);
  height: calc(100% - 6px);
  border: 6px solid #ccc;
}
.regular:nth-child(1){
  top: 5px;
  left: 5px;
  width: 120px;
  height: 120px;
  background-color: red;
}
.regular:nth-child(3){
  top: 270px;
  left: 60px;
  width: 240px;
  height: 180px;
  background-color: blue;
}
.scaled {
  top: 150px;
  left: 25px;
  width: 160px;
  height: 160px;
  transform: scale(0.6) translate(0, 0);
  transform-origin: top left 0px;
  background-color: green;
  overflow: visible;
}
.previewHeader {
  position: absolute;
  top: 10px;
  left: 10px;
  background-color: #eee;
  border: 1px solid #dedede;
}
.n, .s, .w, .e, .nw, .ne, .se, .sw {
  position: absolute;
  width: 18px;
  height: 18px;
  border: 1px solid grey;
  border-radius: 20px;
  background-color: #fff;
}
.n:hover, .s:hover, .w:hover, .e:hover,
.nw:hover, .ne:hover, .se:hover, .sw:hover {
  background-color: red;
}
.nw {
  top: -10px;
  left: -10px;
  cursor: nw-resize;
}
.ne {
  top: -10px;
  left: calc(100% - 10px);
  cursor: ne-resize;
}
.sw {
  top: calc(100% - 10px);
  left: -10px;
  cursor: sw-resize;
}
.se {
  top: calc(100% - 10px);
  left: calc(100% - 10px);
  cursor: se-resize;
}
.n {
  top: -10px;
  left: calc(50% - 10px);
  cursor: n-resize;
}
.w {
  top: calc(50% - 10px);
  left: -10px;
  cursor: w-resize;
}
.e {
  top: calc(50% - 10px);
  left:  calc(100% - 10px);
  cursor: e-resize;
}
.s {
  top: calc(100% - 10px);
  left: calc(50% - 10px);
  cursor: s-resize;
}
<div class="another_element_on_the_top">
</div>
<div class="another_element_on_the_top">
</div>
<div class="another_element_on_the_top">
</div>
<div class="another_element_on_the_top">
</div>
<div class="another_element_on_the_top">
</div>
<div class="another_element_on_the_top">
</div>
<div class="another_element_on_the_top">
</div>
<div class="another_element_on_the_top">
</div>
<div class="another_element_on_the_top">
</div>
<div class="another_element_on_the_top">
</div>

<div class="another_element_on_the_left">
</div>
<div class="another_element_on_the_left">
</div>
<div class="another_element_on_the_left">
</div>
<div class="another_element_on_the_left">
</div>
<div class="another_element_on_the_left">
</div>

<div class="holder">
  <div class="regular">
      <div class="previewHeader">Resizable</div>
      <div class="nw"></div>
      <div class="ne"></div>
      <div class="sw"></div>
      <div class="se"></div>
      <div class="n"></div>
      <div class="s"></div>
      <div class="w"></div>
      <div class="e"></div>
  </div>
  <div class="scaled">
    <div class="previewHeader">Scaled</div>
    <div class="nw"></div>
    <div class="ne"></div>
    <div class="sw"></div>
    <div class="se"></div>
    <div class="n"></div>
    <div class="s"></div>
    <div class="w"></div>
    <div class="e"></div>
  </div>
  <div class="regular">
    <div class="previewHeader">Resizable</div>
    <div class="nw"></div>
    <div class="ne"></div>
    <div class="sw"></div>
    <div class="se"></div>
    <div class="n"></div>
    <div class="s"></div>
    <div class="w"></div>
    <div class="e"></div>
  </div>
</div>
<div id="nfo"> X & Y</div>

or by using this method in another question.

   var element = document.querySelector('...');
   var scaleX = element.getBoundingClientRect().width / element.offsetWidth;

"This works because getBoundingClientRect returns the actual dimension while offsetWidth/Height is the unscaled size."

Edit: window.scrollX/Y added. Now it is usable in scrolled pages.

For future reference in any part of the page it works solid. Even while object is scaled.

Berker Yüceer
  • 7,026
  • 18
  • 68
  • 102
shrys
  • 5,860
  • 2
  • 21
  • 36
3

Have you gave a thought about using jquery resizable o.O? That will save you a lot of time and trouble :)

Here you can check, it's easy and simple : https://jsfiddle.net/maehy5tj/1/

This is all you will need to do :)

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>jQuery UI Resizable - Default functionality</title>
  <link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
  <link rel="stylesheet" href="/resources/demos/style.css">
  <style>
  #resizable { width: 150px; height: 150px; padding: 0.5em; }
  #resizable h3 { text-align: center; margin: 0; }
  </style>
  <script src="https://code.jquery.com/jquery-1.12.4.js"></script>
  <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
  <script>
  $( function() {
    $( "#resizable" ).resizable();
  } );
  </script>
</head>
<body>

<div id="resizable" class="ui-widget-content">
  <h3 class="ui-widget-header">Resizable</h3>
</div>


</body>
</html>
Prajyot Tote
  • 670
  • 5
  • 12
  • sadly the goal is doing it myself with possible different codings not by libraries and jquery resizable cannot resize element from top - left – Berker Yüceer Sep 02 '19 at 05:56
  • 1
    Ok !! I got your point :) It does help sharpen the brains ;) Though just to let you know that JQueryUI resizable can resize from all sides :) Here's an small fiddle : https://jsfiddle.net/maehy5tj/1/ – Prajyot Tote Sep 03 '19 at 12:17
  • I had no idea of this feature se is in bad location but fixable yet I do need to learn how to calgulate it. However ty for this info it is usefull.. +1 :)) – Berker Yüceer Sep 04 '19 at 08:09