webgui/www/extras/admin/layout.js
Doug Bell c7825d4f74 only drag handles should drag asset
this prevents problems with not being able to input or interact with
assets while the drag handles are showing
2011-04-22 18:05:56 -05:00

365 lines
10 KiB
JavaScript

/**
* WebGUI.Layout -- Handle drag/drop of assets inside of layouts
*/
bind = function ( scope, func ) {
return function() { func.apply( scope, arguments ) }
};
if ( typeof WebGUI == "undefined" ) {
WebGUI = {};
}
/**
* Initialize the layout positions and drag/drop inside the given element
* cfg is an object of configuration:
* url = the URL to save the layout to
*
*/
WebGUI.Layout = function (elem, cfg) {
this.elem = elem;
this.cfg = cfg;
// Some special vars
this.scrollJump = 50;
this.blankCount = 0;
// Init layout positions
var positions = this.getPositions();
for ( var i = 0; i < positions.length; i++ ) {
var pos = positions[i];
var children = this.getPositionElements( pos );
if ( children.length == 0 ) {
// No child nodes, create an empty target
this.addBlankTarget(pos);
}
else {
// Check the child nodes for the right IDs to initialize dragdrop
for ( var x = 0; x < children.length; x++ ) {
var elem = children[x];
if ( elem.id.match(/wg-content-asset-(.{22})/) ) {
new WebGUI.LayoutItem( elem, null, null, this );
}
}
}
}
};
/**
* Get all the position wrapper elements
*/
WebGUI.Layout.prototype.getPositions
= function () {
return YAHOO.util.Dom.getElementsByClassName( 'wg-content-position', '*', this.elem );
};
/**
* Get all the elements inside of a given position
*/
WebGUI.Layout.prototype.getPositionElements
= function ( pos ) {
var elems = [];
for ( var i = 0; i < pos.childNodes.length; i++ ) {
var child = pos.childNodes[i];
if ( child.nodeType == 1 ) { // Only elements
elems.push(child);
}
}
return elems;
};
/**
* Adjust the scrollbars to keep the content visible
*/
WebGUI.Layout.prototype.adjustScroll
= function (e) {
scrY=0;
scrX=0;
// Y scroll
if (e.clientY > document.body.clientHeight-this.scrollJump) {
if (e.clientY + document.body.scrollTop < pageHeight - (this.scrollJump + 60)) {
scrY=this.scrollJump;
window.scroll(document.body.scrollLeft,document.body.scrollTop + scrY);
y-=scrY;
}
}else if (e.clientY < this.scrollJump) {
if (document.body.scrollTop < this.scrollJump) {
scrY = document.body.scrollTop;
}else {
scrY=this.scrollJump;
}
window.scroll(document.body.scrollLeft,document.body.scrollTop - scrY);
y+=scrY;
}
// X scroll
if (e.clientX > document.body.clientWidth-this.scrollJump) {
if (e.clientX + document.body.scrollLeft < pageWidth - (this.scrollJump + 60)) {
scrX=this.scrollJump;
window.scroll(document.body.scrollLeft + scrX,document.body.scrollTop);
x-=scrX;
}
}else if (e.clientX < this.scrollJump) {
if (document.body.scrollLeft < this.scrollJump) {
scrX = document.body.scrollLeft;
}else {
scrX=this.scrollJump;
}
window.scroll(document.body.scrollLeft - scrX,document.body.scrollTop);
x+=scrX;
}
};
/**
* Add a blank drag target to an area. Used to provide a position with no children a
* a place to make babies
*/
WebGUI.Layout.prototype.addBlankTarget
= function ( el ) {
var blank = document.createElement("div");
blank.className="blank";
blank.id = "blank" + new Date().getTime() + this.blankCount++;
el.appendChild(blank);
blank.style.top = 0+"px";
blank.style.left = 0+"px";
// Add child for target
var empty = document.createElement("div");
blank.appendChild( empty );
empty.className = "empty";
return new YAHOO.util.DDTarget(blank);
};
/**
* Move the content
*/
WebGUI.Layout.prototype.move
= function (from,to,position) {
if (from!=to && from && to) {
var fromParent = from.parentNode;
fromParent.removeChild(from);
// If we've removed the last one, add a blank element
if ( this.getPositionElements(fromParent).length == 0) {
this.addBlankTarget(fromParent);
}
var toParent = to.parentNode;
var toChildren = this.getPositionElements(toParent);
if ( this.isBlank( toChildren[0] ) ) {
toParent.removeChild(toChildren[0]);
toParent.appendChild(from);
}
else if (position == "top") {
toParent.insertBefore( from, to );
}
else {
children = this.getPositionElements(toParent);
i=0;
while (children[i] != to && i < children.length) {
i++;
}
if (i == children.length - 1) {
toParent.appendChild(from);
}
else {
toParent.insertBefore(from,children[i+1]);
}
}
}
};
/**
* Check if a layout position is blank
*/
WebGUI.Layout.prototype.isBlank
= function ( obj ) {
return obj.className.indexOf( "blank" ) != -1;
};
/**
* Save the new layout to the server, using the configured URL
*/
WebGUI.Layout.prototype.save
= function () {
// Create the content map
contentMap = "";
var positions = this.getPositions();
for ( var i = 0; i < positions.length; i ++ ) {
var pos = positions[i];
// Seperator character
if ((contentMap != "") || ( i == 1 )) { // if first position is blank, still add a .
contentMap+=".";
}
var children = this.getPositionElements( pos );
for ( var j = 0; j < children.length; j++) {
if (contentMap != "" && (contentMap.lastIndexOf(".") != contentMap.length-1)) {
contentMap+=",";
}
if ( !this.isBlank( children[j] ) ) {
contentMap+=children[j].id.replace(/^wg-content-asset-/,"");
}
}
}
// Send it off!
YAHOO.util.Connect.asyncRequest( 'POST', this.cfg.url, {
success : function () {},
failure : function () {}
}, "map=" + contentMap );
};
/****************************************************************************
* WebGUI.LayoutItem -- a single item in a layout
*/
WebGUI.LayoutItem
= function(elem, sGroup, config, layout) {
this.elem = elem;
this.layout = layout;
WebGUI.LayoutItem.superclass.constructor.call(this, elem, sGroup, config);
// Add a dragger control
var dragger = document.createElement( 'div' );
dragger.className = "draggable";
var dragTrigger = document.createElement( 'div' );
dragTrigger.className = "dragTrigger dragTriggerWrap";
dragTrigger.id = elem.id + "_handle";
var icon = document.createElement( 'img' );
icon.src = getWebguiProperty( 'extrasURL' ) + 'icon/arrow_out.png';
dragTrigger.appendChild( icon );
dragger.appendChild( dragTrigger );
elem.insertBefore( dragger, elem.firstChild );
this.setHandleElId( dragTrigger.id );
};
YAHOO.extend(WebGUI.LayoutItem, YAHOO.util.DDProxy);
/**
* Function called when starting a drag
*/
WebGUI.LayoutItem.prototype.startDrag
= function(x, y) {
// make the proxy look like the source element
var dragEl = this.getDragEl();
var clickEl = this.getEl();
YAHOO.util.Dom.setStyle(clickEl, "visibility", "hidden");
dragEl.innerHTML = clickEl.innerHTML;
dragEl.className = "dragging";
YAHOO.util.Dom.setStyle(dragEl, "color", YAHOO.util.Dom.getStyle(clickEl, "color"));
YAHOO.util.Dom.setStyle(dragEl, "backgroundColor", YAHOO.util.Dom.getStyle(clickEl, "backgroundColor"));
YAHOO.util.Dom.setStyle(dragEl, "border", "2px solid gray");
};
/**
* Function called when stopping a drag outside of a dropzone
*/
WebGUI.LayoutItem.prototype.onDragOut
= function (e, id) {
var obj = YAHOO.util.Dom.get(id);
if ( this.layout.isBlank(obj) ) {
document.getElementById(id).className="blank";
}else if (obj.className == 'draggedOverTop' || obj.className == 'draggedOverBottom') {
document.getElementById(id).className="dragable";
}
};
/**
* Called when the drag is over, either success or fail
*/
WebGUI.LayoutItem.prototype.endDrag
= function (e) {
var srcEl = this.getEl();
var proxy = this.getDragEl();
// Show the proxy element and animate it to the src element's location
YAHOO.util.Dom.setStyle(proxy, "visibility", "");
var a = new YAHOO.util.Motion(
proxy, {
points: {
to: YAHOO.util.Dom.getXY(srcEl)
}
},
0.2,
YAHOO.util.Easing.easeOut
)
var proxyid = proxy.id;
var thisid = this.id;
// Hide the proxy and show the source element when finished with the animation
a.onComplete.subscribe(function() {
YAHOO.util.Dom.setStyle(proxyid, "visibility", "hidden");
YAHOO.util.Dom.setStyle(thisid, "visibility", "");
});
a.animate();
};
/**
* Called when the item is dropped on a drag target.
* Update the item and update the content positions
*/
WebGUI.LayoutItem.prototype.onDragDrop
= function (e, id) {
var position;
if (this.goingUp) {
position = "top";
}
else{
position = "bottom";
}
var target = this.getEl();
var destination = YAHOO.util.Dom.get(id);
if ( !this.layout.isBlank( destination ) ){
destination.className = "dragable";
destination = YAHOO.util.Dom.get(id);
}
this.layout.move(target, destination, position);
this.layout.save();
};
/**
* Called periodically while we are dragging an element
*/
WebGUI.LayoutItem.prototype.onDrag
= function (e) {
// Keep track of the direction of the drag for use during onDragOver
var y = YAHOO.util.Event.getPageY(e);
if (y < this.lastY) {
this.goingUp = true;
} else if (y > this.lastY) {
this.goingUp = false;
}
this.lastY = y;
this.layout.adjustScroll(e);
},
/**
* Called when a dragging item is over a drag target
*/
WebGUI.LayoutItem.prototype.onDragOver
= function (e, id) {
var srcEl = this.getEl();
if(srcEl.id == id){return;}
var obj = YAHOO.util.Dom.get(id);
// We are only concerned with list items, we ignore the dragover
// notifications for the list.
if ( this.layout.isBlank( obj ) ) {
document.getElementById(id).className="blankOver";
}else if (this.goingUp) {
document.getElementById(id).className="draggedOverTop";
}else {
document.getElementById(id).className="draggedOverBottom";
}
}