| 1 |
(function($) {
|
| 2 |
|
| 3 |
//If the UI scope is not availalable, add it
|
| 4 |
$.ui = $.ui || {};
|
| 5 |
|
| 6 |
//Add methods that are vital for all mouse interaction stuff (plugin registering)
|
| 7 |
$.extend($.ui, {
|
| 8 |
plugin: {
|
| 9 |
add: function(w, c, o, p) {
|
| 10 |
var a = $.ui[w].prototype; if(!a.plugins[c]) a.plugins[c] = [];
|
| 11 |
a.plugins[c].push([o,p]);
|
| 12 |
},
|
| 13 |
call: function(instance, name, arguments) {
|
| 14 |
var c = instance.plugins[name]; if(!c) return;
|
| 15 |
var o = instance.interaction ? instance.interaction.options : instance.options;
|
| 16 |
var e = instance.interaction ? instance.interaction.element : instance.element;
|
| 17 |
|
| 18 |
for (var i = 0; i < c.length; i++) {
|
| 19 |
if (o[c[i][0]]) c[i][1].apply(e, arguments);
|
| 20 |
}
|
| 21 |
}
|
| 22 |
}
|
| 23 |
});
|
| 24 |
|
| 25 |
$.fn.mouseInteractionDestroy = function() {
|
| 26 |
this.each(function() {
|
| 27 |
if($.data(this, "ui-mouse")) $.data(this, "ui-mouse").destroy();
|
| 28 |
});
|
| 29 |
}
|
| 30 |
|
| 31 |
$.ui.mouseInteraction = function(el,o) {
|
| 32 |
|
| 33 |
if(!o) var o = {};
|
| 34 |
this.element = el;
|
| 35 |
$.data(this.element, "ui-mouse", this);
|
| 36 |
|
| 37 |
this.options = {};
|
| 38 |
$.extend(this.options, o);
|
| 39 |
$.extend(this.options, {
|
| 40 |
handle : o.handle ? ($(o.handle, el)[0] ? $(o.handle, el) : $(el)) : $(el),
|
| 41 |
helper: o.helper || 'original',
|
| 42 |
preventionDistance: o.preventionDistance || 0,
|
| 43 |
dragPrevention: o.dragPrevention ? o.dragPrevention.toLowerCase().split(',') : ['input','textarea','button','select','option'],
|
| 44 |
cursorAt: { top: ((o.cursorAt && o.cursorAt.top) ? o.cursorAt.top : 0), left: ((o.cursorAt && o.cursorAt.left) ? o.cursorAt.left : 0), bottom: ((o.cursorAt && o.cursorAt.bottom) ? o.cursorAt.bottom : 0), right: ((o.cursorAt && o.cursorAt.right) ? o.cursorAt.right : 0) },
|
| 45 |
cursorAtIgnore: (!o.cursorAt) ? true : false, //Internal property
|
| 46 |
appendTo: o.appendTo || 'parent'
|
| 47 |
})
|
| 48 |
o = this.options; //Just Lazyness
|
| 49 |
|
| 50 |
if(!this.options.nonDestructive && (o.helper == 'clone' || o.helper == 'original')) {
|
| 51 |
|
| 52 |
// Let's save the margins for better reference
|
| 53 |
o.margins = {
|
| 54 |
top: parseInt($(el).css('marginTop')) || 0,
|
| 55 |
left: parseInt($(el).css('marginLeft')) || 0,
|
| 56 |
bottom: parseInt($(el).css('marginBottom')) || 0,
|
| 57 |
right: parseInt($(el).css('marginRight')) || 0
|
| 58 |
};
|
| 59 |
|
| 60 |
// We have to add margins to our cursorAt
|
| 61 |
if(o.cursorAt.top != 0) o.cursorAt.top = o.margins.top;
|
| 62 |
if(o.cursorAt.left != 0) o.cursorAt.left += o.margins.left;
|
| 63 |
if(o.cursorAt.bottom != 0) o.cursorAt.bottom += o.margins.bottom;
|
| 64 |
if(o.cursorAt.right != 0) o.cursorAt.right += o.margins.right;
|
| 65 |
|
| 66 |
|
| 67 |
if(o.helper == 'original')
|
| 68 |
o.wasPositioned = $(el).css('position');
|
| 69 |
|
| 70 |
} else {
|
| 71 |
o.margins = { top: 0, left: 0, right: 0, bottom: 0 };
|
| 72 |
}
|
| 73 |
|
| 74 |
var self = this;
|
| 75 |
this.mousedownfunc = function(e) { // Bind the mousedown event
|
| 76 |
return self.click.apply(self, [e]);
|
| 77 |
}
|
| 78 |
o.handle.bind('mousedown', this.mousedownfunc);
|
| 79 |
|
| 80 |
//Prevent selection of text when starting the drag in IE
|
| 81 |
if($.browser.msie) $(this.element).attr('unselectable', 'on');
|
| 82 |
|
| 83 |
}
|
| 84 |
|
| 85 |
$.extend($.ui.mouseInteraction.prototype, {
|
| 86 |
plugins: {},
|
| 87 |
currentTarget: null,
|
| 88 |
lastTarget: null,
|
| 89 |
timer: null,
|
| 90 |
slowMode: false,
|
| 91 |
init: false,
|
| 92 |
destroy: function() {
|
| 93 |
this.options.handle.unbind('mousedown', this.mousedownfunc);
|
| 94 |
},
|
| 95 |
trigger: function(e) {
|
| 96 |
return this.click.apply(this, arguments);
|
| 97 |
},
|
| 98 |
click: function(e) {
|
| 99 |
|
| 100 |
var o = this.options;
|
| 101 |
|
| 102 |
window.focus();
|
| 103 |
if(e.which != 1) return true; //only left click starts dragging
|
| 104 |
|
| 105 |
// Prevent execution on defined elements
|
| 106 |
var targetName = (e.target) ? e.target.nodeName.toLowerCase() : e.srcElement.nodeName.toLowerCase();
|
| 107 |
for(var i=0;i<o.dragPrevention.length;i++) {
|
| 108 |
if(targetName == o.dragPrevention[i]) return true;
|
| 109 |
}
|
| 110 |
|
| 111 |
//Prevent execution on condition
|
| 112 |
if(o.startCondition && !o.startCondition.apply(this, [e])) return true;
|
| 113 |
|
| 114 |
var self = this;
|
| 115 |
this.mouseup = function(e) { return self.stop.apply(self, [e]); }
|
| 116 |
this.mousemove = function(e) { return self.drag.apply(self, [e]); }
|
| 117 |
|
| 118 |
var initFunc = function() { //This function get's called at bottom or after timeout
|
| 119 |
$(document).bind('mouseup', self.mouseup);
|
| 120 |
$(document).bind('mousemove', self.mousemove);
|
| 121 |
self.opos = [e.pageX,e.pageY]; // Get the original mouse position
|
| 122 |
}
|
| 123 |
|
| 124 |
if(o.preventionTimeout) { //use prevention timeout
|
| 125 |
if(this.timer) clearInterval(this.timer);
|
| 126 |
this.timer = setTimeout(function() { initFunc(); }, o.preventionTimeout);
|
| 127 |
return false;
|
| 128 |
}
|
| 129 |
|
| 130 |
initFunc();
|
| 131 |
return false;
|
| 132 |
|
| 133 |
},
|
| 134 |
start: function(e) {
|
| 135 |
|
| 136 |
var o = this.options; var a = this.element;
|
| 137 |
o.co = $(a).offset(); //get the current offset
|
| 138 |
|
| 139 |
this.helper = typeof o.helper == 'function' ? $(o.helper.apply(a, [e,this]))[0] : (o.helper == 'clone' ? $(a).clone()[0] : a);
|
| 140 |
|
| 141 |
if(o.appendTo == 'parent') { // Let's see if we have a positioned parent
|
| 142 |
var cp = a.parentNode;
|
| 143 |
while (cp) {
|
| 144 |
if(cp.style && ($(cp).css('position') == 'relative' || $(cp).css('position') == 'absolute')) {
|
| 145 |
o.pp = cp;
|
| 146 |
o.po = $(cp).offset();
|
| 147 |
o.ppOverflow = !!($(o.pp).css('overflow') == 'auto' || $(o.pp).css('overflow') == 'scroll'); //TODO!
|
| 148 |
break;
|
| 149 |
}
|
| 150 |
cp = cp.parentNode ? cp.parentNode : null;
|
| 151 |
};
|
| 152 |
|
| 153 |
if(!o.pp) o.po = { top: 0, left: 0 };
|
| 154 |
}
|
| 155 |
|
| 156 |
this.pos = [this.opos[0],this.opos[1]]; //Use the relative position
|
| 157 |
this.rpos = [this.pos[0],this.pos[1]]; //Save the absolute position
|
| 158 |
|
| 159 |
if(o.cursorAtIgnore) { // If we want to pick the element where we clicked, we borrow cursorAt and add margins
|
| 160 |
o.cursorAt.left = this.pos[0] - o.co.left + o.margins.left;
|
| 161 |
o.cursorAt.top = this.pos[1] - o.co.top + o.margins.top;
|
| 162 |
}
|
| 163 |
|
| 164 |
|
| 165 |
|
| 166 |
if(o.pp) { // If we have a positioned parent, we pick the draggable relative to it
|
| 167 |
this.pos[0] -= o.po.left;
|
| 168 |
this.pos[1] -= o.po.top;
|
| 169 |
}
|
| 170 |
|
| 171 |
this.slowMode = (o.cursorAt && (o.cursorAt.top-o.margins.top > 0 || o.cursorAt.bottom-o.margins.bottom > 0) && (o.cursorAt.left-o.margins.left > 0 || o.cursorAt.right-o.margins.right > 0)) ? true : false; //If cursorAt is within the helper, set slowMode to true
|
| 172 |
|
| 173 |
if(!o.nonDestructive) $(this.helper).css('position', 'absolute');
|
| 174 |
if(o.helper != 'original') $(this.helper).appendTo((o.appendTo == 'parent' ? a.parentNode : o.appendTo)).show();
|
| 175 |
|
| 176 |
// Remap right/bottom properties for cursorAt to left/top
|
| 177 |
if(o.cursorAt.right && !o.cursorAt.left) o.cursorAt.left = this.helper.offsetWidth+o.margins.right+o.margins.left - o.cursorAt.right;
|
| 178 |
if(o.cursorAt.bottom && !o.cursorAt.top) o.cursorAt.top = this.helper.offsetHeight+o.margins.top+o.margins.bottom - o.cursorAt.bottom;
|
| 179 |
|
| 180 |
this.init = true;
|
| 181 |
|
| 182 |
if(o._start) o._start.apply(a, [this.helper, this.pos, o.cursorAt, this, e]); // Trigger the start callback
|
| 183 |
this.helperSize = { width: $(this.helper).outerWidth(), height: $(this.helper).outerHeight() }; //Set helper size property
|
| 184 |
return false;
|
| 185 |
|
| 186 |
},
|
| 187 |
stop: function(e) {
|
| 188 |
|
| 189 |
var o = this.options; var a = this.element; var self = this;
|
| 190 |
|
| 191 |
$(document).unbind('mouseup', self.mouseup);
|
| 192 |
$(document).unbind('mousemove', self.mousemove);
|
| 193 |
|
| 194 |
if(this.init == false) return this.opos = this.pos = null;
|
| 195 |
if(o._beforeStop) o._beforeStop.apply(a, [this.helper, this.pos, o.cursorAt, this, e]);
|
| 196 |
|
| 197 |
if(this.helper != a && !o.beQuietAtEnd) { // Remove helper, if it's not the original node
|
| 198 |
$(this.helper).remove(); this.helper = null;
|
| 199 |
}
|
| 200 |
|
| 201 |
if(!o.beQuietAtEnd) {
|
| 202 |
//if(o.wasPositioned) $(a).css('position', o.wasPositioned);
|
| 203 |
if(o._stop) o._stop.apply(a, [this.helper, this.pos, o.cursorAt, this, e]);
|
| 204 |
}
|
| 205 |
|
| 206 |
this.init = false;
|
| 207 |
this.opos = this.pos = null;
|
| 208 |
return false;
|
| 209 |
|
| 210 |
},
|
| 211 |
drag: function(e) {
|
| 212 |
|
| 213 |
if (!this.opos || ($.browser.msie && !e.button)) return this.stop.apply(this, [e]); // check for IE mouseup when moving into the document again
|
| 214 |
var o = this.options;
|
| 215 |
|
| 216 |
this.pos = [e.pageX,e.pageY]; //relative mouse position
|
| 217 |
if(this.rpos && this.rpos[0] == this.pos[0] && this.rpos[1] == this.pos[1]) return false;
|
| 218 |
this.rpos = [this.pos[0],this.pos[1]]; //absolute mouse position
|
| 219 |
|
| 220 |
if(o.pp) { //If we have a positioned parent, use a relative position
|
| 221 |
this.pos[0] -= o.po.left;
|
| 222 |
this.pos[1] -= o.po.top;
|
| 223 |
}
|
| 224 |
|
| 225 |
if( (Math.abs(this.rpos[0]-this.opos[0]) > o.preventionDistance || Math.abs(this.rpos[1]-this.opos[1]) > o.preventionDistance) && this.init == false) //If position is more than x pixels from original position, start dragging
|
| 226 |
this.start.apply(this,[e]);
|
| 227 |
else {
|
| 228 |
if(this.init == false) return false;
|
| 229 |
}
|
| 230 |
|
| 231 |
if(o._drag) o._drag.apply(this.element, [this.helper, this.pos, o.cursorAt, this, e]);
|
| 232 |
return false;
|
| 233 |
|
| 234 |
}
|
| 235 |
});
|
| 236 |
|
| 237 |
})(jQuery);
|