1

Using vanilla JavaScript only, no jQuery or other library.

Wrote a gadget to set width and height of some element, by emulating the behavior of the textarea element.

resize gadget screen shot

You click the grey square in the bottom right corner, cursor turns into "south east" cursor, while holding down the left mouse button, you can resize, and when release the mouse, resizing is done; just as with textarea. Here is example code; the size-adjustable content here is a div with overflow:scroll; but the goal is that it works with anything (I'm planning to use it with iframe.)

<!DOCTYPE html><html lang="en"><head>

<meta charset="utf-8">
<title>resize test</title>

<style>
    table.resizerTable {
        border-spacing  : 0;
        border-collapse : separate;
    }
    table.resizerTable td { padding: 0; }
    table.resizerTable div.resizer {
        width  : 20px;
        height : 20px;
        cursor : se-resize;
        background-color: #bbb;
    }
    table.resizerTable div.resizer:active {
        background-color: red;
    }
    div#resizee {
        overflow: scroll
    }
</style>

<script type="text/javascript">
var resizee = {
    getWidth: function(){
        return parseFloat(document.getElementById("resizee").style.width);
    },
    getHeight: function(){
        return parseFloat(document.getElementById("resizee").style.height);
    },
    setWidth: function(w){
        document.getElementById("resizee").style.width = w + 'px';
    },
    setHeight: function(h){
        document.getElementById("resizee").style.height = h + 'px';
    },
};
var resizer = {
    start : null,
    mousedown: function(elt, evt){
        var mainButtonDown = !!(evt.buttons % 2);
        if (!mainButtonDown) return;
        this.start = {
            x      : evt.clientX,
            y      : evt.clientY,
            width  : resizee.getWidth(),
            height : resizee.getHeight()
        };
    }
};
function mousemove(evt){
    var mainButtonDown = !!(evt.buttons % 2);
    if (mainButtonDown){
        var start = resizer.start;
        if (start){
            var x      = evt.clientX,
                y      = evt.clientY,
                dx     = x - start.x,
                dy     = y - start.y,
                width  = start.width  + dx,
                height = start.height + dy;
            resizee.setWidth(width);
            resizee.setHeight(height);
        } else {
        }
    } else {
        resizer.start = null;
    }
    //var compSty = getComputedStyle(evt.target);
}
function mouseup(){
    resizer.start = null;
}
function bodyOnload(){
    document.addEventListener('mousemove', mousemove);
    document.addEventListener('mouseup', mouseup);
    resizee.setWidth(300);
    resizee.setHeight(150);
}
</script>

</head><body onload="bodyOnload();">

<table class="resizerTable">
    <tr>
        <td>
            <div id="resizee">
                <fieldset>
                    <legend>legend title</legend>
                    <fieldset>
                        <legend>inner legend title</legend>
                        lorem ipsum dolor sit amet consectetur adipiscing elit
                    </fieldset>
                    <ul><li>foo</li><li>bar</li><li>blah blah</li><li>kvatsh</li><li>one</li><li>zwei</li><li>cinque</li></ul>
                </fieldset>
            </div>
        </td>
        <td></td>
    </tr>
    <tr>
        <td></td>
        <td>
            <div onmousedown="resizer.mousedown(this, event)" id="resizer" class="resizer"></div>
        </td>
    </tr>
</table>

<div></div>

</body></html>

It works fine in Firefox and IE, but it only works intermittently in Chrome. (Haven't tested in Safari).

Here is what happens in Chrome: Mouse-down on the handle and yank it violently. Do that 5 times or so. At some point, it will cease to work, and cursor will turn into something like this

nodrop

if you then click the handle again without moving, it will go back to working, but cease working again if you yank too violently. I couldn't get this behavior on FF or IE, no matter how much I tried.

What is this? Is there a bug in my code? If it is something with the Chrome browser what is it, and can it be worked around?

UPDATE for those copying and pasting the code: you need to control for negative width/height.

1 Answer 1

1

While you're attempting to resize, you may be selecting the .resizer, you could set user-select: none style to .resizer to avoid it from being selected:

table.resizerTable {
    border-spacing  : 0;
    border-collapse : separate;
    user-select: none;
}

<!DOCTYPE html><html lang="en"><head>

<meta charset="utf-8">
<title>resize test</title>

<style>
    table.resizerTable {
        border-spacing  : 0;
        border-collapse : separate;
        user-select: none;
    }
    table.resizerTable td { padding: 0; }
    table.resizerTable div.resizer {
        width  : 20px;
        height : 20px;
        cursor : se-resize;
        background-color: #bbb;
    }
    table.resizerTable div.resizer:active {
        background-color: red;
    }
    div#resizee {
        overflow: scroll;
    }
</style>

<script type="text/javascript">
var resizee = {
    getWidth: function(){
        return parseFloat(document.getElementById("resizee").style.width);
    },
    getHeight: function(){
        return parseFloat(document.getElementById("resizee").style.height);
    },
    setWidth: function(w){
        document.getElementById("resizee").style.width = w + 'px';
    },
    setHeight: function(h){
        document.getElementById("resizee").style.height = h + 'px';
    },
};
var resizer = {
    start : null,
    mousedown: function(elt, evt){
        var mainButtonDown = !!(evt.buttons % 2);
        if (!mainButtonDown) return;
        this.start = {
            x      : evt.clientX,
            y      : evt.clientY,
            width  : resizee.getWidth(),
            height : resizee.getHeight()
        };
    }
};
function mousemove(evt){
    var mainButtonDown = !!(evt.buttons % 2);
    if (mainButtonDown){
        var start = resizer.start;
        if (start){
            var x      = evt.clientX,
                y      = evt.clientY,
                dx     = x - start.x,
                dy     = y - start.y,
                width  = start.width  + dx,
                height = start.height + dy;
            resizee.setWidth(width);
            resizee.setHeight(height);
        } else {
        }
    } else {
        resizer.start = null;
    }
    //var compSty = getComputedStyle(evt.target);
}
function mouseup(){
    resizer.start = null;
}
function bodyOnload(){
    document.addEventListener('mousemove', mousemove);
    document.addEventListener('mouseup', mouseup);
    resizee.setWidth(300);
    resizee.setHeight(150);
}
</script>

</head><body onload="bodyOnload();">

<table class="resizerTable">
    <tr>
        <td>
            <div id="resizee">
                <fieldset>
                    <legend>legend title</legend>
                    <fieldset>
                        <legend>inner legend title</legend>
                        lorem ipsum dolor sit amet consectetur adipiscing elit
                    </fieldset>
                    <ul><li>foo</li><li>bar</li><li>blah blah</li><li>kvatsh</li><li>one</li><li>zwei</li><li>cinque</li></ul>
                </fieldset>
            </div>
        </td>
        <td></td>
    </tr>
    <tr>
        <td></td>
        <td>
            <div onmousedown="resizer.mousedown(this, event)" id="resizer" class="resizer"></div>
        </td>
    </tr>
</table>

<div></div>

</body></html>

2
  • 1
    fascinating. This appears to solve the problem. Despite me not seeing any selected text when it ceased to work. Well, what the heck. If it works, it works. Commented Oct 30, 2019 at 7:40
  • I did come across this once in chrome, I'm shocked to see it works FF and IE work properly and not in chrome lol. kudos
    – shrys
    Commented Oct 30, 2019 at 7:42

Not the answer you're looking for? Browse other questions tagged or ask your own question.