This is a JavaScript library that lets you easily implement user-friendly and customisable dragging and resizing of your page elements.
Добавил: Amro   Дата: 05.11.2014 12:22

This is a JavaScript library that lets you easily implement user-friendly and customisable dragging and resizing of your page elements. You might want to use it as part of a web application -- it contains all you need for a lightweight "windowing" system. Features include:

  • Can both drag and resize page elements.
  • Works with absolute and relatively positioned elements in your page.
  • Customisable appearance as it makes extensive use of CSS classes for layout of its resisze handles.
  • Unobtrusive, Object-Orientated JavaScript means it's easy to add to your pages.
  • Bounding boxes and minimum sizes can be set and automatically enforced.
  • Cross-browser compatible so it works for everyone.
  • Small code size so your visitors don't have to wait!

Javascript

if (typeof addEvent != 'function') {
    var addEvent = function(o, t, f, l) {
        var d = 'addEventListener',
            n = 'on' + t,
            rO = o,
            rT = t,
            rF = f,
            rL = l;
        if (o[d] && !l) return o[d](t, f, false);
        if (!o._evts) o._evts = {};
        if (!o._evts[t]) {
            o._evts[t] = o[n] ? {
                b: o[n]
            } : {};
            o[n] = new Function('e', 'var r=true,o=this,a=o._evts["' + t + '"],i;for(i in a){o._f=a[i];r=o._f(e||window.event)!=false&&r;o._f=null}return r');
            if (t != 'unload') addEvent(window, 'unload', function() {
                removeEvent(rO, rT, rF, rL)
            })
        }
        if (!f._i) f._i = addEvent._i++;
        o._evts[t][f._i] = f
    };
    addEvent._i = 1;
    var removeEvent = function(o, t, f, l) {
        var d = 'removeEventListener';
        if (o[d] && !l) return o[d](t, f, false);
        if (o._evts && o._evts[t] && f._i) delete o._evts[t][f._i]
    }
}

function cancelEvent(e, c) {
    e.returnValue = false;
    if (e.preventDefault) e.preventDefault();
    if (c) {
        e.cancelBubble = true;
        if (e.stopPropagation) e.stopPropagation()
    }
};

function DragResize(myName, config) {
    var props = {
        myName: myName,
        enabled: true,
        handles: ['tl', 'tm', 'tr', 'ml', 'mr', 'bl', 'bm', 'br'],
        isElement: null,
        isHandle: null,
        element: null,
        handle: null,
        minWidth: 10,
        minHeight: 10,
        minLeft: 0,
        maxLeft: 9999,
        minTop: 0,
        maxTop: 9999,
        zIndex: 1,
        mouseX: 0,
        mouseY: 0,
        lastMouseX: 0,
        lastMouseY: 0,
        mOffX: 0,
        mOffY: 0,
        elmX: 0,
        elmY: 0,
        elmW: 0,
        elmH: 0,
        allowBlur: true,
        ondragfocus: null,
        ondragstart: null,
        ondragmove: null,
        ondragend: null,
        ondragblur: null
    };
    for (var p in props) this[p] = (typeof config[p] == 'undefined') ? props[p] : config[p]
};
DragResize.prototype.apply = function(node) {
    var obj = this;
    addEvent(node, 'mousedown', function(e) {
        obj.mouseDown(e)
    });
    addEvent(node, 'mousemove', function(e) {
        obj.mouseMove(e)
    });
    addEvent(node, 'mouseup', function(e) {
        obj.mouseUp(e)
    })
};
DragResize.prototype.select = function(newElement) {
    with(this) {
        if (!document.getElementById || !enabled) return;
        if (newElement && (newElement != element) && enabled) {
            element = newElement;
            element.style.zIndex = ++zIndex;
            if (this.resizeHandleSet) this.resizeHandleSet(element, true);
            elmX = parseInt(element.style.left);
            elmY = parseInt(element.style.top);
            elmW = element.offsetWidth;
            elmH = element.offsetHeight;
            if (ondragfocus) this.ondragfocus()
        }
    }
};
DragResize.prototype.deselect = function(delHandles) {
    with(this) {
        if (!document.getElementById || !enabled) return;
        if (delHandles) {
            if (ondragblur) this.ondragblur();
            if (this.resizeHandleSet) this.resizeHandleSet(element, false);
            element = null
        }
        handle = null;
        mOffX = 0;
        mOffY = 0
    }
};
DragResize.prototype.mouseDown = function(e) {
    with(this) {
        if (!document.getElementById || !enabled) return true;
        var elm = e.target || e.srcElement,
            newElement = null,
            newHandle = null,
            hRE = new RegExp(myName + '-([trmbl]{2})', '');
        while (elm) {
            if (elm.className) {
                if (!newHandle && (hRE.test(elm.className) || isHandle(elm))) newHandle = elm;
                if (isElement(elm)) {
                    newElement = elm;
                    break
                }
            }
            elm = elm.parentNode
        }
        if (element && (element != newElement) && allowBlur) deselect(true);
        if (newElement && (!element || (newElement == element))) {
            if (newHandle) cancelEvent(e);
            select(newElement, newHandle);
            handle = newHandle;
            if (handle && ondragstart) this.ondragstart(hRE.test(handle.className))
        }
    }
};
DragResize.prototype.mouseMove = function(e) {
    with(this) {
        if (!document.getElementById || !enabled) return true;
        mouseX = e.pageX || e.clientX + document.documentElement.scrollLeft;
        mouseY = e.pageY || e.clientY + document.documentElement.scrollTop;
        var diffX = mouseX - lastMouseX + mOffX;
        var diffY = mouseY - lastMouseY + mOffY;
        mOffX = mOffY = 0;
        lastMouseX = mouseX;
        lastMouseY = mouseY;
        if (!handle) return true;
        var isResize = false;
        if (this.resizeHandleDrag && this.resizeHandleDrag(diffX, diffY)) {
            isResize = true
        } else {
            var dX = diffX,
                dY = diffY;
            if (elmX + dX < minLeft) mOffX = (dX - (diffX = minLeft - elmX));
            else if (elmX + elmW + dX > maxLeft) mOffX = (dX - (diffX = maxLeft - elmX - elmW));
            if (elmY + dY < minTop) mOffY = (dY - (diffY = minTop - elmY));
            else if (elmY + elmH + dY > maxTop) mOffY = (dY - (diffY = maxTop - elmY - elmH));
            elmX += diffX;
            elmY += diffY
        }
        with(element.style) {
            left = elmX + 'px';
            width = elmW + 'px';
            top = elmY + 'px';
            height = elmH + 'px'
        }
        if (window.opera && document.documentElement) {
            var oDF = document.getElementById('op-drag-fix');
            if (!oDF) {
                var oDF = document.createElement('input');
                oDF.id = 'op-drag-fix';
                oDF.style.display = 'none';
                document.body.appendChild(oDF)
            }
            oDF.focus()
        }
        if (ondragmove) this.ondragmove(isResize);
        cancelEvent(e)
    }
};
DragResize.prototype.mouseUp = function(e) {
    with(this) {
        if (!document.getElementById || !enabled) return;
        var hRE = new RegExp(myName + '-([trmbl]{2})', '');
        if (handle && ondragend) this.ondragend(hRE.test(handle.className));
        deselect(false)
    }
};
DragResize.prototype.resizeHandleSet = function(elm, show) {
    with(this) {
        if (!elm._handle_tr) {
            for (var h = 0; h < handles.length; h++) {
                var hDiv = document.createElement('div');
                hDiv.className = myName + ' ' + myName + '-' + handles[h];
                elm['_handle_' + handles[h]] = elm.appendChild(hDiv)
            }
        }
        for (var h = 0; h < handles.length; h++) {
            elm['_handle_' + handles[h]].style.visibility = show ? 'inherit' : 'hidden'
        }
    }
};
DragResize.prototype.resizeHandleDrag = function(diffX, diffY) {
    with(this) {
        var hClass = handle && handle.className && handle.className.match(new RegExp(myName + '-([tmblr]{2})')) ? RegExp.$1 : '';
        var dY = diffY,
            dX = diffX,
            processed = false;
        if (hClass.indexOf('t') >= 0) {
            rs = 1;
            if (elmH - dY < minHeight) mOffY = (dY - (diffY = elmH - minHeight));
            else if (elmY + dY < minTop) mOffY = (dY - (diffY = minTop - elmY));
            elmY += diffY;
            elmH -= diffY;
            processed = true
        }
        if (hClass.indexOf('b') >= 0) {
            rs = 1;
            if (elmH + dY < minHeight) mOffY = (dY - (diffY = minHeight - elmH));
            else if (elmY + elmH + dY > maxTop) mOffY = (dY - (diffY = maxTop - elmY - elmH));
            elmH += diffY;
            processed = true
        }
        if (hClass.indexOf('l') >= 0) {
            rs = 1;
            if (elmW - dX < minWidth) mOffX = (dX - (diffX = elmW - minWidth));
            else if (elmX + dX < minLeft) mOffX = (dX - (diffX = minLeft - elmX));
            elmX += diffX;
            elmW -= diffX;
            processed = true
        }
        if (hClass.indexOf('r') >= 0) {
            rs = 1;
            if (elmW + dX < minWidth) mOffX = (dX - (diffX = minWidth - elmW));
            else if (elmX + elmW + dX > maxLeft) mOffX = (dX - (diffX = maxLeft - elmX - elmW));
            elmW += diffX;
            processed = true
        }
        return processed
    }
};

Css

/* Required CSS classes: must be included in all pages using this script */

/* Apply the element you want to drag/resize */
.drsElement {
 position: absolute;
 border: 1px solid #333;
}

/*
 The main mouse handle that moves the whole element.
 You can apply to the same tag as drsElement if you want.
*/
.drsMoveHandle {
 height: 20px;
 background-color: #CCC;
 border-bottom: 1px solid #666;
 cursor: move;
}

/*
 The DragResize object name is automatically applied to all generated
 corner resize handles, as well as one of the individual classes below.
*/
.dragresize {
 position: absolute;
 width: 5px;
 height: 5px;
 font-size: 1px;
 background: #EEE;
 border: 1px solid #333;
}

/*
 Individual corner classes - required for resize support.
 These are based on the object name plus the handle ID.
*/
.dragresize-tl {
 top: -8px;
 left: -8px;
 cursor: nw-resize;
}
.dragresize-tm {
 top: -8px;
 left: 50%;
 margin-left: -4px;
 cursor: n-resize;
}
.dragresize-tr {
 top: -8px;
 right: -8px;
 cursor: ne-resize;
}

.dragresize-ml {
 top: 50%;
 margin-top: -4px;
 left: -8px;
 cursor: w-resize;
}
.dragresize-mr {
 top: 50%;
 margin-top: -4px;
 right: -8px;
 cursor: e-resize;
}

.dragresize-bl {
 bottom: -8px;
 left: -8px;
 cursor: sw-resize;
}
.dragresize-bm {
 bottom: -8px;
 left: 50%;
 margin-left: -4px;
 cursor: s-resize;
}
.dragresize-br {
 bottom: -8px;
 right: -8px;
 cursor: se-resize;
}

Use

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

// Using DragResize is simple!
// You first declare a new DragResize() object, passing its own name and an object
// whose keys constitute optional parameters/settings:

var dragresize = new DragResize('dragresize',
 { minWidth: 50, minHeight: 50, minLeft: 20, minTop: 20, maxLeft: 600, maxTop: 600 });

// Optional settings/properties of the DragResize object are:
//  enabled: Toggle whether the object is active.
//  handles[]: An array of drag handles to use (see the .JS file).
//  minWidth, minHeight: Minimum size to which elements are resized (in pixels).
//  minLeft, maxLeft, minTop, maxTop: Bounding box (in pixels).

// Next, you must define two functions, isElement and isHandle. These are passed
// a given DOM element, and must "return true" if the element in question is a
// draggable element or draggable handle. Here, I'm checking for the CSS classname
// of the elements, but you have have any combination of conditions you like:

dragresize.isElement = function(elm)
{
 if (elm.className && elm.className.indexOf('drsElement') > -1) return true;
};
dragresize.isHandle = function(elm)
{
 if (elm.className && elm.className.indexOf('drsMoveHandle') > -1) return true;
};

// You can define optional functions that are called as elements are dragged/resized.
// Some are passed true if the source event was a resize, or false if it's a drag.
// The focus/blur events are called as handles are added/removed from an object,
// and the others are called as users drag, move and release the object's handles.
// You might use these to examine the properties of the DragResize object to sync
// other page elements, etc.

dragresize.ondragfocus = function() { };
dragresize.ondragstart = function(isResize) { };
dragresize.ondragmove = function(isResize) { };
dragresize.ondragend = function(isResize) { };
dragresize.ondragblur = function() { };

// Finally, you must apply() your DragResize object to a DOM node; all children of this
// node will then be made draggable. Here, I'm applying to the entire document.
dragresize.apply(document);

//]]>
</script>

HTML

<!--
 Here's our draggable elements.
 All that's required is that they have a relative or absolute CSS 'position',
 and are matched by the isElement/isHandle methods of a DragResize object.
 Easy!
-->

<div class="drsElement"
 style="left: 50px; top: 150px; width: 250px; height: 120px;
 background: #CDF; text-align: center">
 <div class="drsMoveHandle">Div 0</div>
 Content
</div>

<div class="drsElement"
 style="left: 20px; top: 300px; width: 150px; height: 200px;
 background: #FDC; text-align: center">
 <div class="drsMoveHandle">Div 1</div>
 Content
</div>

<div class="drsElement drsMoveHandle"
 style="left: 150px; top: 280px; width: 50px; height: 100px;
 background: #DFC; text-align: center">
 Div 2
 Content
</div>
comments powered by HyperComments