(function($) { //Make nodes selectable by expression $.extend($.expr[':'], { selectable: "(' '+a.className+' ').indexOf(' ui-selectable ')" }); $.extend($.expr[':'], { selectee: "(' '+a.className+' ').indexOf(' ui-selectee ')" }); $.fn.selectable = function(o) { return this.each(function() { if (!$(this).is(".ui-selectable")) new $.ui.selectable(this, o); }); } $.ui.selectable = function(el, o) { var options = { filter: '*' }; var o = o || {}; $.extend(options, o); //Extend and copy options this.element = el; var self = this; //Do bindings self.dragged = false; $.extend(options, { helper: function() { return $(document.createElement('div')).css({border:'1px dotted black'}); }, _start: function(h,p,c,t,e) { self.start.apply(t, [self, e]); // Trigger the start callback }, _drag: function(h,p,c,t,e) { self.dragged = true; self.drag.apply(t, [self, e]); // Trigger the drag callback }, _stop: function(h,p,c,t,e) { self.stop.apply(t, [self, e]); // Trigger the end callback self.dragged = false; } }); //Initialize mouse interaction this.mouse = new $.ui.mouseInteraction(el, options); //Add the class for themeing $(this.element).addClass("ui-selectable"); $(this.element).children(options.filter).addClass("ui-selectee"); } $.extend($.ui.selectable.prototype, { plugins: {}, start: function(self, ev) { $(self.mouse.helper).css({'z-index': 100, position: 'absolute', left: ev.clientX, top: ev.clientY, width:0, height: 0}); if (ev.ctrlKey) { if ($(ev.target).is('.ui-selected')) { $(ev.target).removeClass('ui-selected').addClass('ui-unselecting'); $(self.element).triggerHandler("selectableunselecting", [ev, { selectable: self.element, unselecting: ev.target, options: this.options }], this.options.unselecting); } } else { self.unselecting(self, ev, this.options); self.selectingTarget(self, ev, this.options); } }, drag: function(self, ev) { var x1 = self.mouse.opos[0], y1 = self.mouse.opos[1], x2 = ev.pageX, y2 = ev.pageY; if (x1 > x2) { var tmp = x2; x2 = x1; x1 = tmp; } if (y1 > y2) { var tmp = y2; y2 = y1; y1 = tmp; } $(self.mouse.helper).css({left: x1, top: y1, width: x2-x1, height: y2-y1}); self.selectingTarget(self, ev, this.options); }, stop: function(self, ev) { var options = this.options; $('.ui-selecting', self.element).each(function() { $(this).removeClass('ui-selecting').addClass('ui-selected'); $(self.element).triggerHandler("selectableselected", [ev, { selectable: self.element, selected: this, options: options }], options.selected); }); $('.ui-unselecting', self.element).each(function() { $(this).removeClass('ui-unselecting'); $(self.element).triggerHandler("selectableunselected", [ev, { selectable: self.element, unselected: this, options: options }], options.unselected); }); }, unselecting: function(self, ev, options) { $('.ui-selected', self.element).each(function() { if (this != ev.target) { $(this).removeClass('ui-selected').addClass('ui-unselecting'); $(self.element).triggerHandler("selectableunselecting", [ev, { selectable: self.element, unselecting: this, options: options }], options.unselecting); } }); }, selectingTarget: function(self, ev, options) { var target = $(ev.target); if (target.is('.ui-selectee:not(.ui-selecting)')) { target.removeClass('ui-selected').removeClass('ui-unselecting').addClass('ui-selecting'); $(self.element).triggerHandler("selectableselecting", [ev, { selectable: self.element, selecting: ev.target, options: options }], options.selecting); } } }); })(jQuery);