Languages
[Edit]
EN

JavaScript - resizable div element (on drag and drop actions)

8 points
Created by:
Brandy-Mccabe
754

In this short article, we would like to show how to create div element that may be resizable on drag and drop actions on its borders. Presended solution works on desktop and mobile devices where mouse or touch gestures are used.

Resizable div element on drag and drop actions made in JavaScript.
Resizable div element on drag and drop actions made in JavaScript.

Practical example

// ONLINE-RUNNER:browser;

<!doctype html>
<html>
<head>
  <style>

    * {
        /* this style disables elements selection when user is dragging     */
        -webkit-touch-callout: none;  /* iOS Safari                         */
          -webkit-user-select: none;  /* Safari                             */
           -khtml-user-select: none;  /* Konqueror HTML                     */
             -moz-user-select: none;  /* Firefox in the past (old versions) */
              -ms-user-select: none;  /* Internet Explorer (>=10) / Edge    */
                  user-select: none;  /* Currently supported:               */
                                      /* Chrome, Opera and Firefox          */
    }

    div.resizable {
        position: absolute;
        left: 20px; right: 20px;
      	border: 5px solid gray;
    	touch-action: none;  /* <--------- REQUIRED (blocks other gestures on touch screens) */
    }

    div.body {
      	padding: 3px;
      	position: absolute;
      	left: 0; top: 0; right: 0; bottom: 0;
      	background: cyan;
        overflow: hidden;
    }

    div.handle {
        position: absolute;
      	background: transparent;
    }

    div.handle:hover {
      	background: rgba(255, 255, 255, 0.4);
    }

    div.handle.horizontal {
      	top: 0;
      	right: -5px;
      	bottom: 0;
      	width: 5px;
      	cursor: ew-resize;
    }

    div.handle.vertical {
      	left: 0;
      	right: 0;
      	bottom: -5px;
      	height: 5px;
      	cursor: ns-resize;
    }

    div.handle.both {
      	right: -5px;
      	bottom: -5px;
      	width: 5px;
      	height: 5px;
      	cursor: nwse-resize;
    }

  </style>
  <script>

    // Source: https://dirask.com/snippets/JavaScript-custom-pointerdown-pointermove-and-pointerup-events-DW3qzD
    //
    const addPointerdownListener = (element, callback) => {
        const handleMouse = (event) => {
            callback(event.clientX, event.clientY, 1.0);
        };
        const handleTouch = (event) => {
            const touch = event.touches[0];
            if (touch.identifier === 0) {
                callback(touch.clientX, touch.clientY, 0.7);
            }
        };
        element.addEventListener('mousedown', handleMouse);
        element.addEventListener('touchstart', handleTouch);
        return () => {
            element.removeEventListener('mousedown', handleMouse);
            element.removeEventListener('touchstart', handleTouch);
        };
    };
  
    // Source: https://dirask.com/snippets/JavaScript-custom-pointerdown-pointermove-and-pointerup-events-DW3qzD
    //
    const addPointermoveListener = (element, callback) => {
        const handleMouse = (event) => {
            callback(event.clientX, event.clientY, 0.7);
        };
        const handleTouch = (event) => {
            const touch = event.touches[0];
            if (touch.identifier === 0) {
                callback(touch.clientX, touch.clientY, 1.0);
            }
        };
        element.addEventListener('mousemove', handleMouse);
        element.addEventListener('touchmove', handleTouch);
        return () => {
            element.removeEventListener('mousemove', handleMouse);
            element.removeEventListener('touchmove', handleTouch);
        };
    };
  
    // Source: https://dirask.com/snippets/JavaScript-custom-pointerdown-pointermove-and-pointerup-events-DW3qzD
    //
    const addPointerupListener = (element, callback) => {
        const handleMouse = () => {
            callback();
        };
        const handleTouch = () => {
            const touch = event.touches[0];
            if (touch === undefined || touch.identifier !== 0) {
                callback();
            }
        };
        element.addEventListener('mouseup', handleMouse);
        element.addEventListener('touchend', handleTouch);
        return () => {
            element.removeEventListener('mouseup', handleMouse);
            element.removeEventListener('touchend', handleTouch);
        };
    };

    const prepareGestures = (element, callbacks) => {
        let destroyed = false;
        const start = callbacks.start;
        const end = callbacks.end;
        const doing = callbacks.doing;
        const handlePointerdown = (clientX, clientY, speed) => {
            const x = clientX;
            const y = clientY;
            const handlePointermove = (clientX, clientY, speed) => {
                if (doing) {
                    doing(clientX - x, clientY - y, speed);
                }
            };
            const handlePointerup = () => {
                removePointermoveListener();
                removePointerupListener();
                if (end) {
                    end();
                }
            };
            const removePointermoveListener = addPointermoveListener(document, handlePointermove);
            const removePointerupListener = addPointerupListener(document, handlePointerup);
            if (start) {
                start();
            }
        };
        const removePointerdownListener = addPointerdownListener(element, handlePointerdown);
        return {
            destroy: () => {
                if (destroyed) {
                    return;
                }
                removePointerdownListener();
                destroyed = true;
            }
        };
    };

    const prepareResizing = (element, handles) => {
        let destroyed = false;
        let width = null;
        let height = null;
        const style = element.style;
        const horizontal = handles.horizontal;
        const vertical = handles.vertical;
        const both = handles.both;
        const removers = new Array();
        if (horizontal) {
            const callbacks = {
                start: function() {
                    width = element.clientWidth;
                },
                doing: function(dx, dy) {
                    style.width = Math.max(0, width + dx) + 'px';
                }
            };
            removers.push(prepareGestures(horizontal, callbacks));
        }
        if (vertical) {
            const callbacks = {
                start: function() {
                    height = element.clientHeight;
                },
                doing: function(dx, dy) {
                    style.height = Math.max(0, height + dy) + 'px';
                }
            };
            removers.push(prepareGestures(vertical, callbacks));
        }
        if (both) {
            const callbacks = {
                start: function() {
                    width = element.clientWidth;
                    height = element.clientHeight;
                },
                doing: function(dx, dy) {
                    style.width = Math.max(0, width + dx) + 'px';
                    style.height = Math.max(0, height + dy) + 'px';
                }
            };
            removers.push(prepareGestures(both, callbacks));
        }
        return () => {
            if (destroyed) {
                return;
            }
            for (const entry of removers) {
                entry.destroy(null);
            }
            destroyed = true;
        };
    };

  </script>
</head>
<body style="height: 300px;">
  <div id="element" class="resizable" style="width: 200px; height: 200px;">
    <div class="body">
      Something inside...
    </div>
    <div id="horizontal" class="handle horizontal"></div>
    <div id="vertical" class="handle vertical"></div>
    <div id="both" class="handle both"></div>
  </div>
  <script>

    const element = document.querySelector('#element');

    const handles = {
        horizontal: document.querySelector('#horizontal'),
        vertical: document.querySelector('#vertical'),
        both: document.querySelector('#both')
    };

    prepareResizing(element, handles);

  </script>
</body>
</html>

 

Donate to Dirask
Our content is created by volunteers - like Wikipedia. If you think, the things we do are good, donate us. Thanks!
Join to our subscribers to be up to date with content, news and offers.
Native Advertising
🚀
Get your tech brand or product in front of software developers.
For more information Contact us
Dirask - we help you to
solve coding problems.
Ask question.

❤️💻 🙂

Join