зеркало из https://github.com/mozilla/gecko-dev.git
+ In the quest to abolish reloadBounds(), I've rewritten draggable, droppable and resizable to operate on an item's bounds rather than directly on the div. I've also removed those routines from iQ, and integrated them into Item. Additional related cleanup and documentation.
+ Removed a little bit of aza debug code + Added size and position routines to Rect
This commit is contained in:
Родитель
c27f50120e
Коммит
992d4aee21
|
@ -52,30 +52,41 @@ var drag = {
|
|||
//
|
||||
// ----------
|
||||
// Constructor: Drag
|
||||
// Called to create a Drag in response to a jQuery-UI draggable "start" event.
|
||||
var Drag = function(element, event) {
|
||||
this.el = element;
|
||||
this.$el = iQ(this.el);
|
||||
this.item = Items.item(this.el);
|
||||
this.parent = this.item.parent;
|
||||
this.startPosition = new Point(event.clientX, event.clientY);
|
||||
this.startTime = Utils.getMilliseconds();
|
||||
|
||||
this.item.isDragging = true;
|
||||
this.item.setZ(999999);
|
||||
|
||||
this.safeWindowBounds = Items.getSafeWindowBounds();
|
||||
Trenches.activateOthersTrenches(this.el);
|
||||
|
||||
// When a tab drag starts, make it the focused tab.
|
||||
if(this.item.isAGroup) {
|
||||
var tab = Page.getActiveTab();
|
||||
if(!tab || tab.parent != this.item) {
|
||||
if(this.item._children.length)
|
||||
Page.setActiveTab(this.item._children[0]);
|
||||
// Called to create a Drag in response to an <Item> draggable "start" event.
|
||||
// Note that it is also used partially during <Item>'s resizable method as well.
|
||||
//
|
||||
// Parameters:
|
||||
// item - The <Item> being dragged
|
||||
// event - The DOM event that kicks off the drag
|
||||
var Drag = function(item, event) {
|
||||
try {
|
||||
Utils.assert('item', item && item.isAnItem);
|
||||
|
||||
this.item = item;
|
||||
this.el = item.container;
|
||||
this.$el = iQ(this.el);
|
||||
this.parent = this.item.parent;
|
||||
this.startPosition = new Point(event.clientX, event.clientY);
|
||||
this.startTime = Utils.getMilliseconds();
|
||||
|
||||
this.item.isDragging = true;
|
||||
this.item.setZ(999999);
|
||||
|
||||
this.safeWindowBounds = Items.getSafeWindowBounds();
|
||||
Trenches.activateOthersTrenches(this.el);
|
||||
|
||||
// When a tab drag starts, make it the focused tab.
|
||||
if(this.item.isAGroup) {
|
||||
var tab = Page.getActiveTab();
|
||||
if(!tab || tab.parent != this.item) {
|
||||
if(this.item._children.length)
|
||||
Page.setActiveTab(this.item._children[0]);
|
||||
}
|
||||
} else {
|
||||
Page.setActiveTab(this.item);
|
||||
}
|
||||
} else {
|
||||
Page.setActiveTab(this.item);
|
||||
} catch(e) {
|
||||
Utils.log(e);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -106,8 +117,6 @@ Drag.prototype = {
|
|||
|
||||
if (update)
|
||||
this.item.setBounds(bounds,true);
|
||||
|
||||
return ui;
|
||||
},
|
||||
|
||||
// --------
|
||||
|
@ -172,16 +181,9 @@ Drag.prototype = {
|
|||
|
||||
// ----------
|
||||
// Function: drag
|
||||
// Called in response to a jQuery-UI draggable "drag" event.
|
||||
// Called in response to an <Item> draggable "drag" event.
|
||||
drag: function(event, ui) {
|
||||
// if(this.item.isAGroup) {
|
||||
var bb = this.item.getBounds();
|
||||
bb.left = ui.position.left;
|
||||
bb.top = ui.position.top;
|
||||
this.item.setBounds(bb, true);
|
||||
ui = this.snap(event,ui,true);
|
||||
// } else
|
||||
// this.item.reloadBounds();
|
||||
this.snap(event,ui,true);
|
||||
|
||||
if(this.parent && this.parent.expanded) {
|
||||
var now = Utils.getMilliseconds();
|
||||
|
@ -195,19 +197,10 @@ Drag.prototype = {
|
|||
|
||||
// ----------
|
||||
// Function: stop
|
||||
// Called in response to a jQuery-UI draggable "stop" event.
|
||||
// Called in response to an <Item> draggable "stop" event.
|
||||
stop: function() {
|
||||
this.item.isDragging = false;
|
||||
|
||||
// I'm commenting this out for a while as I believe it feels uncomfortable
|
||||
// that groups go away when there is still a tab in them. I do this at
|
||||
// the cost of symmetry. -- Aza
|
||||
/*
|
||||
if(this.parent && !this.parent.locked.close && this.parent != this.item.parent
|
||||
&& this.parent._children.length == 1 && !this.parent.getTitle()) {
|
||||
this.parent.remove(this.parent._children[0]);
|
||||
}*/
|
||||
|
||||
if(this.parent && !this.parent.locked.close && this.parent != this.item.parent
|
||||
&& this.parent._children.length == 0 && !this.parent.getTitle()) {
|
||||
this.parent.close();
|
||||
|
@ -220,11 +213,9 @@ Drag.prototype = {
|
|||
this.item.setZ(drag.zIndex);
|
||||
drag.zIndex++;
|
||||
|
||||
this.item.reloadBounds();
|
||||
this.item.pushAway();
|
||||
}
|
||||
|
||||
Trenches.disactivate();
|
||||
|
||||
}
|
||||
};
|
||||
|
|
|
@ -203,10 +203,7 @@ window.Group = function(listOfEls, options) {
|
|||
"padding-left": "1px"
|
||||
}, {
|
||||
duration: 200,
|
||||
easing: 'tabcandyBounce',
|
||||
complete: function(){
|
||||
window.aza = self.$title;
|
||||
}
|
||||
easing: 'tabcandyBounce'
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -694,7 +691,7 @@ window.Group.prototype = iQ.extend(new Item(), new Subscribable(), {
|
|||
if( this.isNewTabsGroup() ) $el.addClass("inNewTabGroup")
|
||||
|
||||
if(!wasAlreadyInThisGroup) {
|
||||
iQ($el.get(0)).droppable("disable");
|
||||
item.droppable(false);
|
||||
item.groupData = {};
|
||||
|
||||
item.addOnClose(this, function() {
|
||||
|
@ -758,7 +755,7 @@ window.Group.prototype = iQ.extend(new Item(), new Subscribable(), {
|
|||
item.setRotation(0);
|
||||
item.setSize(item.defaultSize.x, item.defaultSize.y);
|
||||
|
||||
iQ($el.get(0)).droppable("enable");
|
||||
item.droppable(true);
|
||||
item.removeOnClose(this);
|
||||
|
||||
if(typeof(item.setResizable) == 'function')
|
||||
|
@ -1172,16 +1169,16 @@ window.Group.prototype = iQ.extend(new Item(), new Subscribable(), {
|
|||
var self = this;
|
||||
|
||||
this.dropOptions.over = function(){
|
||||
if( !self.isNewTabsGroup() )
|
||||
iQ(this).addClass("acceptsDrop");
|
||||
if( !this.isNewTabsGroup() )
|
||||
iQ(this.container).addClass("acceptsDrop");
|
||||
};
|
||||
this.dropOptions.drop = function(event){
|
||||
iQ(this).removeClass("acceptsDrop");
|
||||
self.add( drag.info.$el, {left:event.pageX, top:event.pageY} );
|
||||
iQ(this.container).removeClass("acceptsDrop");
|
||||
this.add( drag.info.$el, {left:event.pageX, top:event.pageY} );
|
||||
};
|
||||
|
||||
if(!this.locked.bounds)
|
||||
iQ(container).draggable(this.dragOptions);
|
||||
this.draggable();
|
||||
|
||||
iQ(container)
|
||||
.mousedown(function(e){
|
||||
|
@ -1224,7 +1221,7 @@ window.Group.prototype = iQ.extend(new Item(), new Subscribable(), {
|
|||
self._mouseDown = null;
|
||||
});
|
||||
|
||||
iQ(container).droppable(this.dropOptions);
|
||||
this.droppable(true);
|
||||
|
||||
this.$expander.click(function(){
|
||||
self.expand();
|
||||
|
@ -1241,10 +1238,10 @@ window.Group.prototype = iQ.extend(new Item(), new Subscribable(), {
|
|||
|
||||
if(value) {
|
||||
this.$resizer.fadeIn();
|
||||
iQ(this.container).resizable(this.resizeOptions);
|
||||
this.resizable(true);
|
||||
} else {
|
||||
this.$resizer.fadeOut();
|
||||
iQ(this.container).resizable('destroy');
|
||||
this.resizable(false);
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -98,15 +98,35 @@ window.Item = function() {
|
|||
this.userSize = null;
|
||||
|
||||
// Variable: dragOptions
|
||||
// Used to pass into iQ.fn.draggable
|
||||
// Used by <draggable>
|
||||
//
|
||||
// Possible properties:
|
||||
// cancelClass - A space-delimited list of classes that should cancel a drag
|
||||
// start - A function to be called when a drag starts
|
||||
// drag - A function to be called each time the mouse moves during drag
|
||||
// stop - A function to be called when the drag is done
|
||||
this.dragOptions = null;
|
||||
|
||||
// Variable: dropOptions
|
||||
// Used to pass into iQ.fn.droppable
|
||||
// Used by <draggable> if the item is set to droppable.
|
||||
//
|
||||
// Possible properties:
|
||||
// accept - A function to determine if a particular item should be accepted for dropping
|
||||
// over - A function to be called when an item is over this item
|
||||
// out - A function to be called when an item leaves this item
|
||||
// drop - A function to be called when an item is dropped in this item
|
||||
this.dropOptions = null;
|
||||
|
||||
// Variable: resizeOptions
|
||||
// Used to pass into iQ.fn.resizable
|
||||
// Used by <resizable>
|
||||
//
|
||||
// Possible properties:
|
||||
// minWidth - Minimum width allowable during resize
|
||||
// minHeight - Minimum height allowable during resize
|
||||
// aspectRatio - true if we should respect aspect ratio; default false
|
||||
// start - A function to be called when resizing starts
|
||||
// resize - A function to be called each time the mouse moves during resize
|
||||
// stop - A function to be called when the resize is done
|
||||
this.resizeOptions = null;
|
||||
|
||||
// Variable: isDragging
|
||||
|
@ -174,23 +194,16 @@ window.Item.prototype = {
|
|||
group.remove(drag.info.$el, {dontClose: true});
|
||||
}
|
||||
|
||||
iQ(this).removeClass("acceptsDrop");
|
||||
iQ(this.container).removeClass("acceptsDrop");
|
||||
},
|
||||
drop: function(event){
|
||||
iQ(this).removeClass("acceptsDrop");
|
||||
iQ(this.container).removeClass("acceptsDrop");
|
||||
},
|
||||
// Function: dropAcceptFunction
|
||||
// Given a DOM element, returns true if it should accept tabs being dropped on it.
|
||||
// Private to this file.
|
||||
accept: function dropAcceptFunction(el) {
|
||||
var $el = iQ(el);
|
||||
if($el.hasClass('tab')) {
|
||||
var item = Items.item($el);
|
||||
if(item && (!item.parent || !item.parent.expanded)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
accept: function dropAcceptFunction(item) {
|
||||
return (item && item.isATabItem && (!item.parent || !item.parent.expanded));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -205,11 +218,9 @@ window.Item.prototype = {
|
|||
resizeInfo = new Drag(this, e);
|
||||
},
|
||||
resize: function(e,ui){
|
||||
self.reloadBounds();
|
||||
resizeInfo.snap(e,ui, false, self.keepProportional);
|
||||
},
|
||||
stop: function(){
|
||||
self.reloadBounds();
|
||||
self.setUserSize();
|
||||
self.pushAway();
|
||||
resizeInfo.stop();
|
||||
|
@ -528,6 +539,254 @@ window.Item.prototype = {
|
|||
Trenches.unregister(this.guideTrenches[edge]); // unregister can take an array
|
||||
}
|
||||
this.guideTrenches = null;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: draggable
|
||||
// Enables dragging on this item. Note: not to be called multiple times on the same item!
|
||||
draggable: function() {
|
||||
try {
|
||||
Utils.assert('dragOptions', this.dragOptions);
|
||||
|
||||
var cancelClasses = [];
|
||||
if(typeof(this.dragOptions.cancelClass) == 'string')
|
||||
cancelClasses = this.dragOptions.cancelClass.split(' ');
|
||||
|
||||
var self = this;
|
||||
var $container = iQ(this.container);
|
||||
var startMouse;
|
||||
var startPos;
|
||||
var startSent;
|
||||
var startEvent;
|
||||
var droppables;
|
||||
var dropTarget;
|
||||
|
||||
// ___ mousemove
|
||||
var handleMouseMove = function(e) {
|
||||
// positioning
|
||||
var mouse = new Point(e.pageX, e.pageY);
|
||||
var box = self.getBounds();
|
||||
box.left = startPos.x + (mouse.x - startMouse.x);
|
||||
box.top = startPos.y + (mouse.y - startMouse.y);
|
||||
|
||||
self.setBounds(box, true);
|
||||
|
||||
// drag events
|
||||
if(!startSent) {
|
||||
if(iQ.isFunction(self.dragOptions.start)) {
|
||||
self.dragOptions.start.apply(self,
|
||||
[startEvent, {position: {left: startPos.x, top: startPos.y}}]);
|
||||
}
|
||||
|
||||
startSent = true;
|
||||
}
|
||||
|
||||
if(iQ.isFunction(self.dragOptions.drag))
|
||||
self.dragOptions.drag.apply(self, [e, {position: box.position()}]);
|
||||
|
||||
// drop events
|
||||
var newDropTarget = null;
|
||||
iQ.each(droppables, function(index, droppable) {
|
||||
if(box.intersects(droppable.bounds)) {
|
||||
var possibleDropTarget = droppable.item;
|
||||
var accept = true;
|
||||
if(possibleDropTarget != dropTarget) {
|
||||
var dropOptions = possibleDropTarget.dropOptions;
|
||||
if(dropOptions && iQ.isFunction(dropOptions.accept))
|
||||
accept = dropOptions.accept.apply(possibleDropTarget, [self]);
|
||||
}
|
||||
|
||||
if(accept) {
|
||||
newDropTarget = possibleDropTarget;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if(newDropTarget != dropTarget) {
|
||||
var dropOptions;
|
||||
if(dropTarget) {
|
||||
dropOptions = dropTarget.dropOptions;
|
||||
if(dropOptions && iQ.isFunction(dropOptions.out))
|
||||
dropOptions.out.apply(dropTarget, [e]);
|
||||
}
|
||||
|
||||
dropTarget = newDropTarget;
|
||||
|
||||
if(dropTarget) {
|
||||
dropOptions = dropTarget.dropOptions;
|
||||
if(dropOptions && iQ.isFunction(dropOptions.over))
|
||||
dropOptions.over.apply(dropTarget, [e]);
|
||||
}
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
};
|
||||
|
||||
// ___ mouseup
|
||||
var handleMouseUp = function(e) {
|
||||
iQ(window)
|
||||
.unbind('mousemove', handleMouseMove)
|
||||
.unbind('mouseup', handleMouseUp);
|
||||
|
||||
if(dropTarget) {
|
||||
var dropOptions = dropTarget.dropOptions;
|
||||
if(dropOptions && iQ.isFunction(dropOptions.drop))
|
||||
dropOptions.drop.apply(dropTarget, [e]);
|
||||
}
|
||||
|
||||
if(startSent && iQ.isFunction(self.dragOptions.stop))
|
||||
self.dragOptions.stop.apply(self, [e]);
|
||||
|
||||
e.preventDefault();
|
||||
};
|
||||
|
||||
// ___ mousedown
|
||||
$container.mousedown(function(e) {
|
||||
if(Utils.isRightClick(e))
|
||||
return;
|
||||
|
||||
var cancel = false;
|
||||
var $target = iQ(e.target);
|
||||
iQ.each(cancelClasses, function(index, class) {
|
||||
if($target.hasClass(class)) {
|
||||
cancel = true;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
if(cancel) {
|
||||
e.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
startMouse = new Point(e.pageX, e.pageY);
|
||||
startPos = self.getBounds().position();
|
||||
startEvent = e;
|
||||
startSent = false;
|
||||
dropTarget = null;
|
||||
|
||||
droppables = [];
|
||||
iQ('.iq-droppable').each(function() {
|
||||
if(this != self.container) {
|
||||
var item = Items.item(this);
|
||||
droppables.push({
|
||||
item: item,
|
||||
bounds: item.getBounds()
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
iQ(window)
|
||||
.mousemove(handleMouseMove)
|
||||
.mouseup(handleMouseUp);
|
||||
|
||||
e.preventDefault();
|
||||
});
|
||||
} catch(e) {
|
||||
Utils.log(e);
|
||||
}
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: droppable
|
||||
// Enables or disables dropping on this item.
|
||||
droppable: function(value) {
|
||||
try {
|
||||
var $container = iQ(this.container);
|
||||
if(value)
|
||||
$container.addClass('iq-droppable');
|
||||
else {
|
||||
Utils.assert('dropOptions', this.dropOptions);
|
||||
|
||||
$container.removeClass('iq-droppable');
|
||||
}
|
||||
} catch(e) {
|
||||
Utils.log(e);
|
||||
}
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: resizable
|
||||
// Enables or disables resizing of this item.
|
||||
resizable: function(value) {
|
||||
try {
|
||||
var $container = iQ(this.container);
|
||||
iQ('.iq-resizable-handle', $container).remove();
|
||||
|
||||
if(!value) {
|
||||
$container.removeClass('iq-resizable');
|
||||
} else {
|
||||
Utils.assert('resizeOptions', this.resizeOptions);
|
||||
|
||||
$container.addClass('iq-resizable');
|
||||
|
||||
var self = this;
|
||||
var startMouse;
|
||||
var startSize;
|
||||
|
||||
// ___ mousemove
|
||||
var handleMouseMove = function(e) {
|
||||
var mouse = new Point(e.pageX, e.pageY);
|
||||
var box = self.getBounds();
|
||||
box.width = Math.max(self.resizeOptions.minWidth || 0, startSize.x + (mouse.x - startMouse.x));
|
||||
box.height = Math.max(self.resizeOptions.minHeight || 0, startSize.y + (mouse.y - startMouse.y));
|
||||
|
||||
if(self.resizeOptions.aspectRatio) {
|
||||
if(startAspect < 1)
|
||||
box.height = box.width * startAspect;
|
||||
else
|
||||
box.width = box.height / startAspect;
|
||||
}
|
||||
|
||||
self.setBounds(box, true);
|
||||
|
||||
if(iQ.isFunction(self.resizeOptions.resize))
|
||||
self.resizeOptions.resize.apply(self, [e]);
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
};
|
||||
|
||||
// ___ mouseup
|
||||
var handleMouseUp = function(e) {
|
||||
iQ(window)
|
||||
.unbind('mousemove', handleMouseMove)
|
||||
.unbind('mouseup', handleMouseUp);
|
||||
|
||||
if(iQ.isFunction(self.resizeOptions.stop))
|
||||
self.resizeOptions.stop.apply(self, [e]);
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
};
|
||||
|
||||
// ___ handle + mousedown
|
||||
iQ('<div>')
|
||||
.addClass('iq-resizable-handle iq-resizable-se')
|
||||
.appendTo($container)
|
||||
.mousedown(function(e) {
|
||||
if(Utils.isRightClick(e))
|
||||
return;
|
||||
|
||||
startMouse = new Point(e.pageX, e.pageY);
|
||||
startSize = self.getBounds().size();
|
||||
startAspect = startSize.y / startSize.x;
|
||||
|
||||
if(iQ.isFunction(self.resizeOptions.start))
|
||||
self.resizeOptions.start.apply(self, [e]);
|
||||
|
||||
iQ(window)
|
||||
.mousemove(handleMouseMove)
|
||||
.mouseup(handleMouseUp);
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
});
|
||||
}
|
||||
} catch(e) {
|
||||
Utils.log(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -69,23 +69,24 @@ window.TabItem = function(container, tab) {
|
|||
// override dropOptions with custom tabitem methods
|
||||
// This is mostly to support the phantom groups.
|
||||
this.dropOptions.drop = function(e){
|
||||
$target = iQ(this);
|
||||
iQ(this).removeClass("acceptsDrop");
|
||||
$target = iQ(this.container);
|
||||
$target.removeClass("acceptsDrop");
|
||||
var phantom = $target.data("phantomGroup")
|
||||
|
||||
var group = drag.info.item.parent;
|
||||
if( group == null ){
|
||||
phantom.removeClass("phantom");
|
||||
phantom.removeClass("group-content");
|
||||
var group = new Group([$target, drag.info.$el], {container:phantom});
|
||||
group = new Group([$target, drag.info.$el], {container:phantom});
|
||||
} else
|
||||
group.add( drag.info.$el );
|
||||
};
|
||||
|
||||
this.dropOptions.over = function(e){
|
||||
var $target = iQ(this);
|
||||
var $target = iQ(this.container);
|
||||
|
||||
function elToRect($el){
|
||||
return new Rect( $el.position().left, $el.position().top, $el.width(), $el.height() );
|
||||
return new Rect( $el.position().left, $el.position().top, $el.width(), $el.height() );
|
||||
}
|
||||
|
||||
var height = elToRect($target).height * 1.5 + 20;
|
||||
|
@ -112,16 +113,18 @@ window.TabItem = function(container, tab) {
|
|||
|
||||
$target.data("phantomGroup", phantom);
|
||||
};
|
||||
this.dropOptions.out = function(e){
|
||||
var phantom = iQ(this).data("phantomGroup");
|
||||
|
||||
this.dropOptions.out = function(e){
|
||||
var phantom = iQ(this.container).data("phantomGroup");
|
||||
if(phantom) {
|
||||
phantom.fadeOut(function(){
|
||||
iQ(this).remove();
|
||||
});
|
||||
}
|
||||
}
|
||||
$div.draggable(this.dragOptions);
|
||||
$div.droppable(this.dropOptions);
|
||||
};
|
||||
|
||||
this.draggable();
|
||||
this.droppable(true);
|
||||
|
||||
// ___ more div setup
|
||||
$div.mousedown(function(e) {
|
||||
|
@ -373,10 +376,10 @@ window.TabItem.prototype = iQ.extend(new Item(), {
|
|||
|
||||
if(value) {
|
||||
$resizer.fadeIn();
|
||||
iQ(this.container).resizable(this.resizeOptions);
|
||||
this.resizable(true);
|
||||
} else {
|
||||
$resizer.fadeOut();
|
||||
iQ(this.container).resizable('destroy');
|
||||
this.resizable(false);
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -792,258 +792,6 @@ iQ.fn = iQ.prototype = {
|
|||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: draggable
|
||||
draggable: function(options) {
|
||||
try {
|
||||
if(!options)
|
||||
options = {};
|
||||
|
||||
var cancelClasses = [];
|
||||
if(typeof(options.cancelClass) == 'string')
|
||||
cancelClasses = options.cancelClass.split(' ');
|
||||
|
||||
var startMouse;
|
||||
var startPos;
|
||||
var elem;
|
||||
var $elem;
|
||||
var startSent;
|
||||
var startEvent;
|
||||
var droppables;
|
||||
var dropTarget;
|
||||
|
||||
// ___ mousemove
|
||||
var handleMouseMove = function(e) {
|
||||
// positioning
|
||||
var mouse = new Point(e.pageX, e.pageY);
|
||||
var newPos = {
|
||||
left: startPos.x + (mouse.x - startMouse.x),
|
||||
top: startPos.y + (mouse.y - startMouse.y)
|
||||
};
|
||||
|
||||
$elem.css(newPos);
|
||||
|
||||
// drag events
|
||||
if(!startSent) {
|
||||
if(iQ.isFunction(options.start))
|
||||
options.start.apply(elem, [startEvent, {position: {left: startPos.x, top: startPos.y}}]);
|
||||
|
||||
startSent = true;
|
||||
}
|
||||
|
||||
if(iQ.isFunction(options.drag))
|
||||
options.drag.apply(elem, [e, {position: newPos}]);
|
||||
|
||||
// drop events
|
||||
var bounds = $elem.bounds();
|
||||
var newDropTarget = null;
|
||||
iQ.each(droppables, function(index, droppable) {
|
||||
if(bounds.intersects(droppable.bounds)) {
|
||||
var possibleDropTarget = droppable.element;
|
||||
var accept = true;
|
||||
if(possibleDropTarget != dropTarget) {
|
||||
var dropOptions = iQ(possibleDropTarget).data('iq-droppable');
|
||||
if(dropOptions && iQ.isFunction(dropOptions.accept))
|
||||
accept = dropOptions.accept.apply(possibleDropTarget, [elem]);
|
||||
}
|
||||
|
||||
if(accept) {
|
||||
newDropTarget = possibleDropTarget;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if(newDropTarget != dropTarget) {
|
||||
var dropOptions;
|
||||
if(dropTarget) {
|
||||
dropOptions = iQ(dropTarget).data('iq-droppable');
|
||||
if(dropOptions && iQ.isFunction(dropOptions.out))
|
||||
dropOptions.out.apply(dropTarget, [e]);
|
||||
}
|
||||
|
||||
dropTarget = newDropTarget;
|
||||
|
||||
if(dropTarget) {
|
||||
dropOptions = iQ(dropTarget).data('iq-droppable');
|
||||
if(dropOptions && iQ.isFunction(dropOptions.over))
|
||||
dropOptions.over.apply(dropTarget, [e]);
|
||||
}
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
};
|
||||
|
||||
// ___ mouseup
|
||||
var handleMouseUp = function(e) {
|
||||
iQ(window)
|
||||
.unbind('mousemove', handleMouseMove)
|
||||
.unbind('mouseup', handleMouseUp);
|
||||
|
||||
if(dropTarget) {
|
||||
var dropOptions = iQ(dropTarget).data('iq-droppable');
|
||||
if(dropOptions && iQ.isFunction(dropOptions.drop))
|
||||
dropOptions.drop.apply(dropTarget, [e]);
|
||||
}
|
||||
|
||||
if(startSent && iQ.isFunction(options.stop))
|
||||
options.stop.apply(elem, [e]);
|
||||
|
||||
e.preventDefault();
|
||||
};
|
||||
|
||||
// ___ mousedown
|
||||
this.mousedown(function(e) {
|
||||
if(Utils.isRightClick(e))
|
||||
return;
|
||||
|
||||
var cancel = false;
|
||||
var $target = iQ(e.target);
|
||||
iQ.each(cancelClasses, function(index, class) {
|
||||
if($target.hasClass(class)) {
|
||||
cancel = true;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
if(cancel) {
|
||||
e.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
elem = this;
|
||||
$elem = iQ(this);
|
||||
var pos = $elem.position();
|
||||
startMouse = new Point(e.pageX, e.pageY);
|
||||
startPos = new Point(pos.left, pos.top);
|
||||
startEvent = e;
|
||||
startSent = false;
|
||||
dropTarget = null;
|
||||
|
||||
droppables = [];
|
||||
iQ('.iq-droppable').each(function() {
|
||||
if(this != elem) {
|
||||
droppables.push({
|
||||
element: this,
|
||||
bounds: iQ(this).bounds()
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
iQ(window)
|
||||
.mousemove(handleMouseMove)
|
||||
.mouseup(handleMouseUp);
|
||||
|
||||
e.preventDefault();
|
||||
});
|
||||
} catch(e) {
|
||||
Utils.log(e);
|
||||
}
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: droppable
|
||||
droppable: function(options) {
|
||||
try {
|
||||
if(options == 'enable')
|
||||
this.addClass('iq-droppable');
|
||||
else if(options == 'disable')
|
||||
this.removeClass('iq-droppable');
|
||||
else {
|
||||
this.addClass('iq-droppable');
|
||||
this.data('iq-droppable', options || {});
|
||||
}
|
||||
} catch(e) {
|
||||
Utils.log(e);
|
||||
}
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: resizable
|
||||
resizable: function(options) {
|
||||
try {
|
||||
iQ('.iq-resizable-handle', this).remove();
|
||||
|
||||
if(options == 'destroy') {
|
||||
this.removeClass('iq-resizable');
|
||||
} else {
|
||||
if(!options)
|
||||
options = {};
|
||||
|
||||
this.addClass('iq-resizable');
|
||||
|
||||
var startMouse;
|
||||
var startSize;
|
||||
var elem;
|
||||
var $elem;
|
||||
|
||||
// ___ mousemove
|
||||
var handleMouseMove = function(e) {
|
||||
var mouse = new Point(e.pageX, e.pageY);
|
||||
var newSize = {
|
||||
width: Math.max(options.minWidth || 0, startSize.x + (mouse.x - startMouse.x)),
|
||||
height: Math.max(options.minHeight || 0, startSize.y + (mouse.y - startMouse.y))
|
||||
};
|
||||
|
||||
if(options.aspectRatio) {
|
||||
if(startAspect < 1)
|
||||
newSize.height = newSize.width * startAspect;
|
||||
else
|
||||
newSize.width = newSize.height / startAspect;
|
||||
}
|
||||
|
||||
$elem.css(newSize);
|
||||
|
||||
if(iQ.isFunction(options.resize))
|
||||
options.resize.apply(elem, [e]);
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
};
|
||||
|
||||
// ___ mouseup
|
||||
var handleMouseUp = function(e) {
|
||||
iQ(window)
|
||||
.unbind('mousemove', handleMouseMove)
|
||||
.unbind('mouseup', handleMouseUp);
|
||||
|
||||
if(iQ.isFunction(options.stop))
|
||||
options.stop.apply(elem, [e]);
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
};
|
||||
|
||||
// ___ handle + mousedown
|
||||
iQ('<div>')
|
||||
.addClass('iq-resizable-handle iq-resizable-se')
|
||||
.appendTo(this)
|
||||
.mousedown(function(e) {
|
||||
if(Utils.isRightClick(e))
|
||||
return;
|
||||
|
||||
elem = this.parentNode;
|
||||
$elem = iQ(elem);
|
||||
startMouse = new Point(e.pageX, e.pageY);
|
||||
startSize = new Point($elem.width(), $elem.height());
|
||||
startAspect = startSize.y / startSize.x;
|
||||
|
||||
if(iQ.isFunction(options.start))
|
||||
options.start.apply(elem, [e]);
|
||||
|
||||
iQ(window)
|
||||
.mousemove(handleMouseMove)
|
||||
.mouseup(handleMouseUp);
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
});
|
||||
}
|
||||
} catch(e) {
|
||||
Utils.log(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -193,6 +193,16 @@ window.Rect.prototype = {
|
|||
return new Point(this.left + (this.width / 2), this.top + (this.height / 2));
|
||||
},
|
||||
|
||||
// ----------
|
||||
size: function() {
|
||||
return new Point(this.width, this.height);
|
||||
},
|
||||
|
||||
// ----------
|
||||
position: function() {
|
||||
return new Point(this.left, this.top);
|
||||
},
|
||||
|
||||
// ----------
|
||||
inset: function(a, b) {
|
||||
if(typeof(a.x) != 'undefined' && typeof(a.y) != 'undefined') {
|
||||
|
|
Загрузка…
Ссылка в новой задаче