mirror of
https://github.com/wassname/fullcalendar.git
synced 2026-08-14 12:20:24 +08:00
large code refactor. new HTML/CSS skeleton, no more JQUI dependency, among other things
This commit is contained in:
@@ -0,0 +1,184 @@
|
||||
|
||||
/* Creates a clone of an element and lets it track the mouse as it moves
|
||||
----------------------------------------------------------------------------------------------------------------------*/
|
||||
|
||||
function MouseFollower(sourceEl, options) {
|
||||
this.options = options = options || {};
|
||||
this.sourceEl = sourceEl;
|
||||
this.parentEl = options.parentEl ? $(options.parentEl) : sourceEl.parent(); // default to sourceEl's parent
|
||||
}
|
||||
|
||||
|
||||
MouseFollower.prototype = {
|
||||
|
||||
options: null,
|
||||
|
||||
sourceEl: null, // the element that will be cloned and made to look like it is dragging
|
||||
el: null, // the clone of `sourceEl` that will track the mouse
|
||||
parentEl: null, // the element that `el` (the clone) will be attached to
|
||||
|
||||
// the initial position of el, relative to the offset parent. made to match the initial offset of sourceEl
|
||||
top0: null,
|
||||
left0: null,
|
||||
|
||||
// the initial position of the mouse
|
||||
mouseY0: null,
|
||||
mouseX0: null,
|
||||
|
||||
// the number of pixels the mouse has moved from its initial position
|
||||
topDelta: null,
|
||||
leftDelta: null,
|
||||
|
||||
mousemoveProxy: null, // document mousemove handler, bound to the MouseFollower's `this`
|
||||
|
||||
isFollowing: false,
|
||||
isHidden: false,
|
||||
isAnimating: false, // doing the revert animation?
|
||||
|
||||
|
||||
// Causes the element to start following the mouse
|
||||
start: function(ev) {
|
||||
if (!this.isFollowing) {
|
||||
this.isFollowing = true;
|
||||
|
||||
this.mouseY0 = ev.pageY;
|
||||
this.mouseX0 = ev.pageX;
|
||||
this.topDelta = 0;
|
||||
this.leftDelta = 0;
|
||||
|
||||
if (!this.isHidden) {
|
||||
this.updatePosition();
|
||||
}
|
||||
|
||||
$(document).on('mousemove', this.mousemoveProxy = $.proxy(this, 'mousemove'));
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// Causes the element to stop following the mouse. If shouldRevert is true, will animate back to original position.
|
||||
// `callback` gets invoked when the animation is complete. If no animation, it is invoked immediately.
|
||||
stop: function(shouldRevert, callback) {
|
||||
var _this = this;
|
||||
var revertDuration = this.options.revertDuration;
|
||||
|
||||
function complete() {
|
||||
this.isAnimating = false;
|
||||
_this.destroyEl();
|
||||
|
||||
this.top0 = this.left0 = null; // reset state for future updatePosition calls
|
||||
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
|
||||
if (this.isFollowing && !this.isAnimating) { // disallow more than one stop animation at a time
|
||||
this.isFollowing = false;
|
||||
|
||||
$(document).off('mousemove', this.mousemoveProxy);
|
||||
|
||||
if (shouldRevert && revertDuration && !this.isHidden) { // do a revert animation?
|
||||
this.isAnimating = true;
|
||||
this.el.animate({
|
||||
top: this.top0,
|
||||
left: this.left0
|
||||
}, {
|
||||
duration: revertDuration,
|
||||
complete: complete
|
||||
});
|
||||
}
|
||||
else {
|
||||
complete();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// Gets the tracking element. Create it if necessary
|
||||
getEl: function() {
|
||||
var el = this.el;
|
||||
|
||||
if (!el) {
|
||||
el = this.el = this.sourceEl.clone()
|
||||
.css({
|
||||
position: 'absolute',
|
||||
visibility: '', // in case original element was hidden (commonly through hideEvents())
|
||||
display: this.isHidden ? 'none' : '', // for when initially hidden
|
||||
margin: 0,
|
||||
right: 'auto', // erase and set width instead
|
||||
bottom: 'auto', // erase and set height instead
|
||||
width: this.sourceEl.width(), // explicit height in case there was a 'right' value
|
||||
height: this.sourceEl.height(), // explicit width in case there was a 'bottom' value
|
||||
opacity: this.options.opacity || '',
|
||||
zIndex: this.options.zIndex
|
||||
})
|
||||
.appendTo(this.parentEl);
|
||||
}
|
||||
|
||||
return el;
|
||||
},
|
||||
|
||||
|
||||
// Removes the tracking element if it has already been created
|
||||
destroyEl: function() {
|
||||
if (this.el) {
|
||||
this.el.remove();
|
||||
this.el = null;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// Update the CSS position of the tracking element
|
||||
updatePosition: function() {
|
||||
var sourceOffset;
|
||||
var origin;
|
||||
|
||||
this.getEl(); // ensure this.el
|
||||
|
||||
// make sure origin info was computed
|
||||
if (this.top0 === null) {
|
||||
sourceOffset = this.sourceEl.offset();
|
||||
origin = this.el.offsetParent().offset();
|
||||
this.top0 = sourceOffset.top - origin.top;
|
||||
this.left0 = sourceOffset.left - origin.left;
|
||||
}
|
||||
|
||||
this.el.css({
|
||||
top: this.top0 + this.topDelta,
|
||||
left: this.left0 + this.leftDelta
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
// Gets called when the user moves the mouse
|
||||
mousemove: function(ev) {
|
||||
this.topDelta = ev.pageY - this.mouseY0;
|
||||
this.leftDelta = ev.pageX - this.mouseX0;
|
||||
|
||||
if (!this.isHidden) {
|
||||
this.updatePosition();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// Temporarily makes the tracking element invisible. Can be called before following starts
|
||||
hide: function() {
|
||||
if (!this.isHidden) {
|
||||
this.isHidden = true;
|
||||
if (this.el) {
|
||||
this.el.hide();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// Show the tracking element after it has been temporarily hidden
|
||||
show: function() {
|
||||
if (this.isHidden) {
|
||||
this.isHidden = false;
|
||||
this.updatePosition();
|
||||
this.getEl().show();
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
Reference in New Issue
Block a user