/* * jQuery UI Selectable * * Copyright (c) 2008 Richard D. Worth (rdworth.org) * Dual licensed under the MIT (MIT-LICENSE.txt) * and GPL (GPL-LICENSE.txt) licenses. * * http://docs.jquery.com/UI/Selectables * * Depends: * ui.core.js */ (function($) { $.widget("ui.selectable", $.extend({}, $.ui.mouse, { init: function() { var self = this; this.element.addClass("ui-selectable"); this.dragged = false; // cache selectee children based on filter var selectees; this.refresh = function() { selectees = $(self.options.filter, self.element[0]); selectees.each(function() { var $this = $(this); var pos = $this.offset(); $.data(this, "selectable-item", { element: this, $element: $this, left: pos.left, top: pos.top, right: pos.left + $this.width(), bottom: pos.top + $this.height(), startselected: false, selected: $this.hasClass('ui-selected'), selecting: $this.hasClass('ui-selecting'), unselecting: $this.hasClass('ui-unselecting') }); }); }; this.refresh(); this.selectees = selectees.addClass("ui-selectee"); this.mouseInit(); this.helper = $(document.createElement('div')).css({border:'1px dotted black'}); }, toggle: function() { if(this.options.disabled){ this.enable(); } else { this.disable(); } }, destroy: function() { this.element .removeClass("ui-selectable ui-selectable-disabled") .removeData("selectable") .unbind(".selectable"); this.mouseDestroy(); }, mouseStart: function(e) { var self = this; this.opos = [e.pageX, e.pageY]; if (this.options.disabled) return; var options = this.options; this.selectees = $(options.filter, this.element[0]); // selectable START callback this.element.triggerHandler("selectablestart", [e, { "selectable": this.element[0], "options": options }], options.start); $('body').append(this.helper); // position helper (lasso) this.helper.css({ "z-index": 100, "position": "absolute", "left": e.clientX, "top": e.clientY, "width": 0, "height": 0 }); if (options.autoRefresh) { this.refresh(); } this.selectees.filter('.ui-selected').each(function() { var selectee = $.data(this, "selectable-item"); selectee.startselected = true; if (!e.ctrlKey) { selectee.$element.removeClass('ui-selected'); selectee.selected = false; selectee.$element.addClass('ui-unselecting'); selectee.unselecting = true; // selectable UNSELECTING callback self.element.triggerHandler("selectableunselecting", [e, { selectable: self.element[0], unselecting: selectee.element, options: options }], options.unselecting); } }); var isSelectee = false; $(e.target).parents().andSelf().each(function() { if($.data(this, "selectable-item")) isSelectee = true; }); return this.options.keyboard ? !isSelectee : true; }, mouseDrag: function(e) { var self = this; this.dragged = true; if (this.options.disabled) return; var options = this.options; var x1 = this.opos[0], y1 = this.opos[1], x2 = e.pageX, y2 = e.pageY; if (x1 > x2) { var tmp = x2; x2 = x1; x1 = tmp; } if (y1 > y2) { var tmp = y2; y2 = y1; y1 = tmp; } this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1}); this.selectees.each(function() { var selectee = $.data(this, "selectable-item"); //prevent helper from being selected if appendTo: selectable if (!selectee || selectee.element == self.element[0]) return; var hit = false; if (options.tolerance == 'touch') { hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) ); } else if (options.tolerance == 'fit') { hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2); } if (hit) { // SELECT if (selectee.selected) { selectee.$element.removeClass('ui-selected'); selectee.selected = false; } if (selectee.unselecting) { selectee.$element.removeClass('ui-unselecting'); selectee.unselecting = false; } if (!selectee.selecting) { selectee.$element.addClass('ui-selecting'); selectee.selecting = true; // selectable SELECTING callback self.element.triggerHandler("selectableselecting", [e, { selectable: self.element[0], selecting: selectee.element, options: options }], options.selecting); } } else { // UNSELECT if (selectee.selecting) { if (e.ctrlKey && selectee.startselected) { selectee.$element.removeClass('ui-selecting'); selectee.selecting = false; selectee.$element.addClass('ui-selected'); selectee.selected = true; } else { selectee.$element.removeClass('ui-selecting'); selectee.selecting = false; if (selectee.startselected) { selectee.$element.addClass('ui-unselecting'); selectee.unselecting = true; } // selectable UNSELECTING callback self.element.triggerHandler("selectableunselecting", [e, { selectable: self.element[0], unselecting: selectee.element, options: options }], options.unselecting); } } if (selectee.selected) { if (!e.ctrlKey && !selectee.startselected) { selectee.$element.removeClass('ui-selected'); selectee.selected = false; selectee.$element.addClass('ui-unselecting'); selectee.unselecting = true; // selectable UNSELECTING callback self.element.triggerHandler("selectableunselecting", [e, { selectable: self.element[0], unselecting: selectee.element, options: options }], options.unselecting); } } } }); return false; }, mouseStop: function(e) { var self = this; this.dragged = false; var options = this.options; $('.ui-unselecting', this.element[0]).each(function() { var selectee = $.data(this, "selectable-item"); selectee.$element.removeClass('ui-unselecting'); selectee.unselecting = false; selectee.startselected = false; self.element.triggerHandler("selectableunselected", [e, { selectable: self.element[0], unselected: selectee.element, options: options }], options.unselected); }); $('.ui-selecting', this.element[0]).each(function() { var selectee = $.data(this, "selectable-item"); selectee.$element.removeClass('ui-selecting').addClass('ui-selected'); selectee.selecting = false; selectee.selected = true; selectee.startselected = true; self.element.triggerHandler("selectableselected", [e, { selectable: self.element[0], selected: selectee.element, options: options }], options.selected); }); this.element.triggerHandler("selectablestop", [e, { selectable: self.element[0], options: this.options }], this.options.stop); this.helper.remove(); return false; } })); $.extend($.ui.selectable, { defaults: { distance: 1, delay: 0, cancel: ":input", appendTo: 'body', autoRefresh: true, filter: '*', tolerance: 'touch' } }); })(jQuery);