Resizer //JavaScript Repository

Description

Allows resizing any object as well as applying resizing filters.
Created: 2005.11.18

Dependencies

Code (Download)

//+ Jonas Raoni Soares Silva
//@ http://jsfromhell.com/dhtml/resizer [rev. #1]

Resizer = function(o){
    var $ = (($ = this).o = o, $.f = [], $),
        getHandler = function getHandler(h, v){return function(e){$.h = h, $.v = v, $.begin(e);};}
    for(var j, e, x, y, i = 3, k = -1, d = $.d = new Array(8); i;)
        for(j = (--i, 3); j; (--j != 1 || i != 1) && (d[++k] = [i, j, "",
            e = document.body.appendChild(document.createElement("div"))]),
            addEvent(e, "mousedown", getHandler(d[k][0], d[k][1])),
            e.style.position = "absolute", e.style.display = "none"
        );
}
with({p: Resizer.prototype}){
    p.h = 0, p.v = 0, p.pd = {x: 0, y: 0}, p.po = {x: 0, y: 0, h: 0, w: 0}, p.av = false;
    p.getMouse = function(e){
        var w = window, b = document.body;
        return {x: e.clientX + (w.scrollX || b.scrollLeft || b.parentNode.scrollLeft || 0),
            y: e.clientY + (w.scrollY || b.scrollTop || b.parentNode.scrollTop || 0)};
    };
    p.getOffset = function(o, s){
        for(var r = {x: o.offsetLeft, y: o.offsetTop, h: o.offsetHeight, w: o.offsetWidth};
            (o = o.offsetParent) && (!s || !/relative/i.test(o.style.position));
            r.x += o.offsetLeft, r.y += o.offsetTop);
        return r;
    };
    p.update = function(){
        var i, x, s, $ = this, d = $.d, o = $.getOffset($.o);
        for(i = d.length; i; x = d[--i], s = x[3].style, s.left = o.x + o.w * x[0] / 2 + "px",
            s.top = o.y + o.h * x[1] / 2 + "px");
    };
    p.showAnchors = function(s){
        var i, x, $ = this, d = $.d, o = $.getOffset($.o), m = ["none", "block"];
        for($.av = !!s, i = d.length; i; x = d[--i], x[3].style.display = m[+$.av]);
        $.update();
    };
    p.setAnchorClass = function(c){
        var i, d = this.d, map = {se: 0, e: 1, ne: 2, n: 3, s: 4, nw: 5, w: 6, sw: 7};
        if(typeof c == "string")
            for(i = d.length; i; d[--i][3].className = c);
        else
            for(i in c) d[map[i.toLowerCase()]][3].className = c[i];
    };
    p.addFilter = function(f){
        this.f[this.f.length] = f;
    },
    p.begin = function(e){
        var $ = this, p = $.getMouse(e);
        $.po = $.getOffset($.o, 1);
        $.pd = {x: $.po.x - p.x, y: $.po.y - p.y};
        addEvent(document, "mousemove", $.drag, $);
        addEvent(document, "mouseup", $.end, $);
        $.callEvent("onstart", e);
    };
    p.end = function(e){
        var $ = this;
        removeEvent(document, "mousemove", $.drag, $);
        removeEvent(document, "mouseup", $.end, $);
        $.callEvent("onend", e);
    };
    p.drag = function(e){
        var f, i, $ = this, p = $.getMouse(e), o = $.getOffset($.o), z = {x: 0, y: 0, w: 0, h: 0}, s = $.o.style;
        $.h != 1 ? (z.x = $.h ? $.po.x : p.x + $.pd.x, z.w = $.po.w + (p.x - $.po.x + $.pd.x) * ($.h - 1)) : (z.x = $.po.x, z.w = $.po.w);
        $.v != 1 ? (z.y = $.v ? $.po.y : p.y + $.pd.y, z.h = $.po.h + (p.y - $.po.y + $.pd.y) * ($.v - 1)) : (z.y = $.po.y, z.h = $.po.h);
        z.h < 0 && (z.y -= z.h = -z.h, $.v ^= 2, $.po.y += $.po.h, $.pd.y -= $.po.h *= -1);
        z.w < 0 && (z.x -= z.w = -z.w, $.h ^= 2, $.po.x += $.po.w, $.pd.x -= $.po.w *= -1);
        for(f = $.f, i = f.length; i; f[--i] && f[i].call(z, e, $));
        s.top = z.y + "px", s.left = z.x + "px", s.height = z.h + "px", s.width = z.w + "px";
        $.update();
        $.callEvent("onresize", e);
    };
    p.callEvent = function(e){
        return this[e] instanceof Function ? this[e].apply(this, [].slice.call(arguments, 1)) : undefined;
    };
}

Example (Example)

<style type="text/css">
#box, #box2, #box3{
    position: absolute;
    left: 50px;
    top: 100px;
    width: 300px;
    height: 100px;
    overflow: hidden;
    background: ;
    border: #999 solid 1px;
}
#box2{
    top: 215px;
    width: 400px;
}
#container{
    position: relative;
    top: 160px;
    width: 600px;
    height: 300px;
    overflow: hidden;
    background: #ffe;
    border: 1px solid;
}
.marker{
    font-size: 1px;
    width: 10px;
    height: 10px;
    margin-left: -5px;
    margin-top: -5px;
    border: #000 solid 1px;
    cursor: move;
}
.green{
    background: #0f0;
}
</style>

<div id="container">
    <div id="box3">
        Within a container with "position:relative"
    </div>
</div>
<div id="box">
    With max size filter and markers with different classes
</div>
<div id="box2">
    With filter to keep the 1:1 proportion when resizing by the diagonals holding the shift key 
</div>

<script type="text/javascript">
//<![CDATA[

x = new Resizer(document.getElementById("box"));
x.setAnchorClass("marker");
x.setAnchorClass({n: "marker green", s: "marker green", w: "marker green", e: "marker green"});
x.showAnchors(true);

limitSize = function(e, o){
    var x = 400, y = 200, c = this;
    c.h > y && (!o.v && (c.y += c.h - y), c.h = y);
    c.w > x && (!o.h && (c.x += c.w - x), c.w = x);
}
x.addFilter(limitSize);


y = new Resizer(document.getElementById("box2"));
y.setAnchorClass("marker");
y.showAnchors(true);

shiftResize = function(e, o){
    var c = this, d = c.w - c.h;
    e.shiftKey && o.h != 1 && o.v != 1 &&
    (d > 0 ? c.h = c.w : c.w = c.h,
    !o.v ? d > 0 ? c.y -= d : !o.h && (c.x += d)
    : !o.h && d < 0 && (c.x += d));
}
y.addFilter(shiftResize);

document.getElementById("container").style.position = "relative";
z = new Resizer(document.getElementById("box3"));
z.setAnchorClass("marker");
z.showAnchors(true);

//]]>
</script>

Help

Constructor

Resizer(element: HTMLElement)
Generates an instance of Resizer.
element
element that will receive the resizing support

Properties

Resizer.h: Integer
Specifies the horizontal position of the anchor that is beeing dragged, where: 0 = left, 1 = middle, 2 = right.
Resizer.v: Integer
Specifies the vertical position of the anchor that is beeing dragged, where: 0 = top, 1 = middle, 2 = bottom.
Resizer.po: Object
Keep the coords of where the object was when the resizing started, contain 4 properties: x (left), y (top), w (width) and h (height).
Resizer.o: HTMLElement
HTML element associated to the resizer.
Resizer.f: Array
Array containing the movementation filters.
Resizer.av: Boolean
Tells if the drag anchors are visible.

Methods

Resizer.update(void): void
Forces the repositioning of the drag anchors.
Resizer.showAnchors(show: Boolean): void
Show/hide the drag anchors.
show
if true, show, otherwise hide the anchors
Resizer.setAnchorClass(info: Object): void
Sets up the CSS class for all or just some anchors.
info
accepts two types of input, if a String is passed: the class will set the class name of all the anchors with the passed string, the other alternative allow you to set just determinated anchors, just pass an object containing "magical" properties defined with CSS class names (look at the example), the properties are: se (southeast), e (east), ne (northeast), n (north), s (south), nw (northwest), w (west), sw (southwest)
Resizer.addFilter(handler: Function(event: Event, resizer: Resizer): void): void
Adds a movementation filter to the resizer.
handler
function to be added, it receives as argument the event object and the instance itself. The scope of the function (the "this" variable) has four properties: x (left), y (top), w (width) and h (height), by changing any of them, you also change the element coords

Events

Resizer.onstart: function(event: Event): void
This event is called when the resizing starts.
event
event object
Resizer.onresize: function(event: Event): void
This event is called while the element is beeing resized.
event
event object
Resizer.onstop: function(event: Event): void
This event is called when the resizing finishes.
event
event object

Rank (Votes: 31)

4.10