Calculating absolute position in % I'm making a website for a friend (just for fun) where we have to move a lot of svg images in absolute positions. To make it easier I wrote some code to calculate the % position of each element so we can do it faster.

I'm wondering what you think about it and what can I do to improve it. And also any improvements to my style of coding are welcome.

&lt;html&gt;

&lt;head&gt;
    &lt;!-- Just some style to differentiate the object --&gt;
    &lt;style&gt;
        .draggable{
            width: 10px;
            height: 10px;
            background: red;
        }
    &lt;/style&gt;
&lt;/head&gt;

&lt;body&gt;
    &lt;!-- The item that we will be moving around --&gt;
    &lt;div class="draggable"&gt;&lt;/div&gt;
    &lt;script&gt;

    class Mover{
        constructor(htmlObject,parent, position){
            // Store the object to move
            this.htmlObject = htmlObject;
            // The parent of the object
            this.parent = parent;
            // The type of position : 'relative'/'absolute'
            this.position = position;
            // Modify the elements and start the listeners
            this.init();
        }

        init(){
            // Make the item draggable
            this.htmlObject.draggable = 'true';
            // Set its position type to the user input
            this.htmlObject.style.position = this.position;
            // Modify its zIndex to make sure that you can always see where it is.
            this.htmlObject.style.zIndex = '9999';
            // Add some border just make it easier to find the item.
            this.htmlObject.style.border = '1px solid black';
            // Add the listeners for the drop and drag events to the parent
            this.parent.ondrop = (event)=&gt;{ this.drop(event) };
            this.parent.ondragover = (event)=&gt;{ this.allowDrop(event) };
        }

        drop(e){
            e.preventDefault();
            let pos = this.calculatePos(e.x, e.y);
            // Set the object position equal to the event x and y pos in %
            this.htmlObject.style.top = pos.h+'%';
            this.htmlObject.style.left = pos.w+'%';
        }

        allowDrop(e){
            // Allow to drop.
            e.preventDefault();
        }

        calculatePos(w,h){
            // Get the parent Width and Height
            let mx = this.parent.offsetWidth;
            let mh = this.parent.offsetHeight;
            // -- Just testing stuff --
            // let mx = innerWidth;
            // let mh = innerHeight;
            // ------------------------
            // Calculate the % based on the parent size.
            return {w : (w/mx) * 100, h : (h/mh) * 100}
        }

    }

    // Initialize the movable item.
    const draggableElement = new Mover(document.querySelector('.dragable'),document.querySelector('body'),'absolute')   
    &lt;/script&gt;
&lt;/body&gt;
About Constructor

It is considered a bad practice for a constructor to have side effects for multiple reasons. You can browse numerous resources online on this subject. Here are a few whys:


The reader/maintainer of the code does not expect a constructor to have any side effects;
Such constructor is hard or impossible to test;
It violates a whole bunch of principles, including Principle of least astonishment, SRP.


So, yeah instead of

constructor(htmlObject,parent, position){
  // ...
  this.init();
}


you should rather create an instance and invoke the init() on it; like this

const draggableElement = new Mover(
  document.querySelector('.dragable'),
  document.querySelector('body'),
  'absolute',
);
draggableElement.init();


If you are not planning to add the function that disables "moving" of an element, you may even not need a local variable holding the reference to a Mover:

new Mover(
  document.querySelector('.dragable'),
  document.querySelector('body'),
  'absolute',
)
.init();


Naming Things

Naming is important. Method init() is not informative. You may want to rename it to something like enableElementDragging(). A symmetric counter part is now too easy too name – disableElementDragging().



Nano variable names are evil. What is e? An error? An exception? An event? To figure that out I need to look at a place where the function is being invoked. That's mental burden.

Same applies to pos, w, and h... If you are in VS Code or any other smart editor, it's a matter of hitting F2 and renaming it.

Names mx and mh are particularly unfortunate since they are meant to be symmetric to/consistent with w and h. Thus, mx should be mw! Also, I could not decipher what the m prefix means in both of these variables.

Just spell things out: position, width, height, parentWidth, parentHeight, calculatePosition().