diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/jquery-ui.js | 298 |
1 files changed, 225 insertions, 73 deletions
diff --git a/lib/jquery-ui.js b/lib/jquery-ui.js index 4939d009..8777e4fe 100644 --- a/lib/jquery-ui.js +++ b/lib/jquery-ui.js @@ -159,30 +159,41 @@ jQuery.effects||(function(d){d.effects={version:"1.7.2",save:function(g,h){for(v var self = this; this.items = $(this.options.filter, this.element); - this.element.addClass("ui-selectable"); + this.element.addClass("ui-selectable ui-widget"); //Set the currentFocus to the first item - this.currentFocus = this.items.eq(0); + this.currentFocus = this.items.eq(0).attr('tabindex', 0); //Refresh item positions - this.refresh(); + this.refresh(1); //Disable text selection this.element.disableSelection(); //Prepare caret selection - if(this.options.lasso) this._mouseInit(); + if(this.options.lasso) { + + // we need to move the lasso options onto the root options for the mouse clas + if(this.options.lasso !== true) { + $.extend(this.options, this.options.lasso); + } + + this._mouseInit(); + } this.element .bind('mousedown.selectable', function(event) { + if(self.options.disabled) + return; + var item = self._targetIsItem(event.target); if (!item) return; - + // If item is part of current selection and current // selection is multiple, return and allow mouseup // to fire (Windows gets this right too, OSX doesn't) - if(self._selection.length > 1 && $(item).hasClass(self.options.selectedClass)) { + if(self._selection.length > 1 && $(item).hasClass('ui-selected')) { return (self._listenForMouseUp = 1); } @@ -210,36 +221,36 @@ jQuery.effects||(function(d){d.effects={version:"1.7.2",save:function(g,h){for(v } }) .bind('focus.selectable', function() { - self.currentFocus.addClass('ui-focused'); + if(!self.options.disabled) self.currentFocus.addClass('ui-state-focus'); }) .bind('blur.selectable', function() { - self.currentFocus.removeClass('ui-focused'); + if(!self.options.disabled) self.currentFocus.removeClass('ui-state-focus'); }) .bind('keydown.selectable', function(event) { - if(!self.options.keyboard) + if(!self.options.keyboard || self.options.disabled) return; if(self._trigger('beforeselect', event) === false) return true; if(event.keyCode == $.ui.keyCode.DOWN) { - self.options.smart ? self.selectClosest('down', event) : self.selectNext(event); + self.options.closest ? self.selectClosest('down', event) : self.next(event); event.preventDefault(); } if(event.keyCode == $.ui.keyCode.RIGHT) { - self.options.smart ? self.selectClosest('right', event) : self.selectNext(event); + self.options.closest ? self.selectClosest('right', event) : self.next(event); event.preventDefault(); } if(event.keyCode == $.ui.keyCode.UP) { - self.options.smart ? self.selectClosest('up', event) : self.selectPrevious(event); + self.options.closest ? self.selectClosest('up', event) : self.previous(event); event.preventDefault(); } if(event.keyCode == $.ui.keyCode.LEFT) { - self.options.smart ? self.selectClosest('left', event) : self.selectPrevious(event); + self.options.closest ? self.selectClosest('left', event) : self.previous(event); event.preventDefault(); } @@ -260,7 +271,7 @@ jQuery.effects||(function(d){d.effects={version:"1.7.2",save:function(g,h){for(v overlap = 10000, selfOffset = this.currentFocus.data('selectable-item'); - $(this.options.filter, this.element).not(this.currentFocus).filter(':visible').each(function() { + this.items.not(this.currentFocus).filter(':visible').each(function() { var $this = $(this), offset = $this.data('selectable-item'), @@ -303,13 +314,23 @@ jQuery.effects||(function(d){d.effects={version:"1.7.2",save:function(g,h){for(v }); - return current[1] ? this._select(event, current[1]) : false; + // if nothing close is found, bail + if(!current[1]) + return false; + + //We need to find the index of the current, and the index of the new one to call selectAdjacent + // - calling _select doesn't work, since it's only for mouse interaction (no ctrl focus move!) + var currentIndex = this.items.index(this.currentFocus[0]); + var newIndex = this.items.index(current[1]); + + return this._selectAdjacent(event, newIndex - currentIndex); }, destroy: function() { + this.items.removeClass("ui-selectable-item ui-selected ui-state-active"); this.element - .removeClass("ui-selectable ui-selectable-disabled") + .removeClass("ui-selectable ui-selectable-disabled ui-widget") .removeData("selectable") .unbind(".selectable"); this._mouseDestroy(); @@ -318,11 +339,11 @@ jQuery.effects||(function(d){d.effects={version:"1.7.2",save:function(g,h){for(v _mouseCapture: function(event) { //If the item we start dragging on is a selectable, we bail (if keyboard is used) this.clickedOnItem = this._targetIsItem(event.target); - return !this.options.keyboard || !this.clickedOnItem; + return true; // TODO: this starts the lasso on items as well - we might want to introduce an option to disable this }, _mouseStart: function(event) { - + var self = this, o = this.options; this.opos = [event.pageX, event.pageY]; @@ -330,10 +351,13 @@ jQuery.effects||(function(d){d.effects={version:"1.7.2",save:function(g,h){for(v return; //Cache positions - this.refresh(); + this.refresh(1); //Trigger start event this._trigger("start", event, this._uiHash()); + + //Save the current selection as previous + this._previousSelection = this._selection.slice(); // append and position helper (lasso) $('body').append(this.helper); @@ -347,12 +371,12 @@ jQuery.effects||(function(d){d.effects={version:"1.7.2",save:function(g,h){for(v }); //Tell the intersection that some start selected - this.items.filter('.'+this.options.selectedClass).each(function() { - if(event.metaKey) { - if(this != self.clickedOnItem) $.data(this, "selectable-item").startSelected = true; - } else self._removeFromSelection($(this), event); - }); - + for (var i = this._selection.length - 1; i >= 0; i--){ + if(event.metaKey || event.ctrlKey) { + if(this != self.clickedOnItem) $(this._selection[i]).data("selectable-item").startSelected = true; + } else self._removeFromSelection($(this._selection[i]), event); + }; + }, _mouseDrag: function(event) { @@ -395,7 +419,41 @@ jQuery.effects||(function(d){d.effects={version:"1.7.2",save:function(g,h){for(v }, _mouseStop: function(event) { - this._trigger("stop", event, this._uiHash()); + + var newlySelected = [], + newlyDeselected = []; + + // Find out the delta of the newly selected items + for (var i=0; i < this._selection.length; i++) { + var wasAlreadyPartOfPreviousSelection = false; + for (var j=0; j < this._previousSelection.length; j++) { + if(this._selection[i][0] == this._previousSelection[j][0]) + wasAlreadyPartOfPreviousSelection = true; + }; + if(!wasAlreadyPartOfPreviousSelection) newlySelected.push(this._selection[i]); + }; + + // Find out the delta of the newly unselected items + for (var i = this._previousSelection.length - 1; i >= 0; i--){ + if(!this._previousSelection[i].data('selectable-item').selected) newlyDeselected.push(this._previousSelection[i]); + }; + + + // Transform both deltas into jQuery objects + newlySelected = $($.map(newlySelected, function(i) { return i[0]; })); + newlyDeselected = $($.map(newlyDeselected, function(i) { return i[0]; })); + + var uiHash = $.extend(this._uiHash(), { + added: newlySelected || [], + removed: newlyDeselected || [] + }); + this._trigger("stop", event, uiHash); + + // Trigger change event if anything has changed + if((newlySelected && newlySelected.length) || (newlyDeselected && newlyDeselected.length)) { + this._trigger('change', event, uiHash); + } + this.helper.remove(); return false; }, @@ -407,23 +465,63 @@ jQuery.effects||(function(d){d.effects={version:"1.7.2",save:function(g,h){for(v _selection: [], + _endSelection: function(event, newlySelected) { + + //Only trigger the 'deselect' event if items have been removed from the selection + var newlyDeselected = this._triggerDeselection(event); + + //Only trigger 'select' event if items have been added to the selection + if(newlySelected && newlySelected.length) + this._trigger('select', event, this._uiHash(newlySelected, 'added')); + + // Trigger change event if anything has changed + if((newlySelected && newlySelected.length) || (newlyDeselected && newlyDeselected.length)) { + var uiHash = $.extend(this._uiHash(), { + added: newlySelected || [], + removed: newlyDeselected || [] + }); + this._trigger('change', event, uiHash); + } + + }, + + _triggerDeselection: function(event) { + + var triggerItems = []; + + for (var i = this._previousSelection.length - 1; i >= 0; i--){ + var data = this._previousSelection[i].data('selectable-item'); + if(!data || !data.selected) triggerItems.push(this._previousSelection[i]); + }; + + this._previousSelection = []; + triggerItems = $($.map(triggerItems, function(i) { return i[0]; })); + if(triggerItems.length) this._trigger('deselect', event, this._uiHash(triggerItems, 'removed')); + + return triggerItems; + + }, + _clearSelection: function(triggerEvent) { var triggerItems = []; for (var i = this._selection.length - 1; i >= 0; i--){ if(triggerEvent && this._selection[i].data('selectable-item').selected) triggerItems.push(this._selection[i]); - this._selection[i].removeClass(this.options.selectedClass); + this._selection[i].removeClass('ui-selected ui-state-active'); this._selection[i].data('selectable-item').selected = false; }; + this._previousSelection = this._selection.slice(); this._selection = []; - if(triggerEvent) this._trigger('unselect', triggerEvent, this._uiHash($($.map(triggerItems, function(i) { return i[0]; })), 'removed')); + if(triggerEvent && triggerItems.length) this._trigger('deselect', triggerEvent, this._uiHash($($.map(triggerItems, function(i) { return i[0]; })), 'removed')); }, _toggleSelection: function(item, event) { - item.data('selectable-item').selected ? this._removeFromSelection(item, event) : this._addToSelection(item); + var selected = item.data('selectable-item').selected; + selected ? this._removeFromSelection(item, event) : this._addToSelection(item); + return !selected; }, _addToSelection: function(item, triggerEvent) { @@ -433,7 +531,7 @@ jQuery.effects||(function(d){d.effects={version:"1.7.2",save:function(g,h){for(v this._selection.push(item); this.latestSelection = item; - item.addClass(this.options.selectedClass); + item.addClass('ui-selected ui-state-active'); item.data('selectable-item').selected = true; if(triggerEvent) { @@ -448,10 +546,10 @@ jQuery.effects||(function(d){d.effects={version:"1.7.2",save:function(g,h){for(v for (var i=0; i < this._selection.length; i++) { if (this._selection[i][0] == item[0]) { - this._selection[i].removeClass(this.options.selectedClass); + this._selection[i].removeClass('ui-selected ui-state-active'); this._selection[i].data('selectable-item').selected = false; this._selection.splice(i,1); - if(triggerEvent) this._trigger('unselect', triggerEvent, this._uiHash($(item), 'removed')); + if(triggerEvent) this._trigger('deselect', triggerEvent, this._uiHash($(item), 'removed')); break; } }; @@ -462,10 +560,10 @@ jQuery.effects||(function(d){d.effects={version:"1.7.2",save:function(g,h){for(v var newlySelected = []; - if (event.shiftKey && this.options.multiple) { + if (event && event.shiftKey) { //Clear the previous selection to make room for a shift selection - this._clearSelection(event); + this._clearSelection(); var index = this.items.index(this.latestWithoutModifier[0]) > this.items.index(this.currentFocus[0]) ? -1 : 1; var i = this.latestWithoutModifier.data('selectable-item').selected ? this.items.eq(this.items.index(this.latestWithoutModifier[0])+index) : this.latestWithoutModifier; @@ -479,10 +577,11 @@ jQuery.effects||(function(d){d.effects={version:"1.7.2",save:function(g,h){for(v } else { - if (event.metaKey) { - this._toggleSelection(this.currentFocus, event); + if (event && (event.metaKey || event.ctrlKey)) { + var withMetaIsNewlySelected = this._toggleSelection(this.currentFocus, event); + if(withMetaIsNewlySelected) newlySelected.push(this.currentFocus); } else { - this._clearSelection(event); + this._clearSelection(); newlySelected.push(this._addToSelection(this.currentFocus)); this.latestWithoutModifier = this.currentFocus; } @@ -497,7 +596,7 @@ jQuery.effects||(function(d){d.effects={version:"1.7.2",save:function(g,h){for(v var newlySelected = []; - if (event.shiftKey && this.options.multiple) { + if (event && event.shiftKey) { if (this.currentFocus.data('selectable-item').selected) { this._removeFromSelection(this.previousFocus, event); @@ -519,7 +618,7 @@ jQuery.effects||(function(d){d.effects={version:"1.7.2",save:function(g,h){for(v } else { //If the CTRL or Apple/Win key is pressed, only set focus - if (event.metaKey) + if (event && (event.metaKey || event.ctrlKey)) return; this._clearSelection(event); @@ -528,24 +627,24 @@ jQuery.effects||(function(d){d.effects={version:"1.7.2",save:function(g,h){for(v } - return $($.map(newlySelected, function(i) { return i[0]; })); + return $($.map(newlySelected, function(i) { if(i) return i[0]; })); }, _select: function(event, item) { //Set the current selection to the previous/next item - this.previousFocus = this.currentFocus; - this.currentFocus = $(item); + this.previousFocus = this.currentFocus.attr('tabindex', -1); + this.currentFocus = $(item).attr('tabindex', 0); - this.previousFocus.removeClass('ui-focused'); - this.currentFocus.addClass('ui-focused'); + this.previousFocus.removeClass('ui-state-focus'); + this.currentFocus.addClass('ui-state-focus'); //Set and update the selection var newlySelected = this._updateSelectionMouse(event); - //Trigger select event - if(newlySelected && newlySelected.length) this._trigger('select', event, this._uiHash(newlySelected, 'added')); + // Ending the selection does a diff and then triggers appropriate events + this._endSelection(event, newlySelected); }, @@ -557,54 +656,118 @@ jQuery.effects||(function(d){d.effects={version:"1.7.2",save:function(g,h){for(v if (!item.length) return; //Set the current selection to the previous/next item - this.previousFocus = this.currentFocus; - this.currentFocus = item; + this.previousFocus = this.currentFocus.attr('tabindex', -1); + this.currentFocus = item.attr('tabindex', 0); - this.previousFocus.removeClass('ui-focused'); - this.currentFocus.addClass('ui-focused'); + this.previousFocus.removeClass('ui-state-focus'); + this.currentFocus.addClass('ui-state-focus'); //Set and update the selection + this._previousSelection = this._selection.slice(); var newlySelected = this._updateSelection(event, index); - //Trigger select event - if(newlySelected && newlySelected.length) this._trigger('select', event, this._uiHash(newlySelected, 'added')); + // Ending the selection does a diff and then triggers appropriate events + this._endSelection(event, newlySelected); }, - selectPrevious: function(event) { + previous: function(event) { this._selectAdjacent(event, -1); }, - selectNext: function(event) { + next: function(event) { this._selectAdjacent(event, 1); }, - refresh: function() { + refresh: function(fromInside) { - var o = this.options; + var o = this.options, self = this; this.items = $(o.filter, this.element); + this.items.addClass('ui-selectable-item'); this.items.each(function() { + var $this = $(this); var pos = $this.offset(); + + if(self.currentFocus && self.currentFocus[0] != this) + $this.attr('tabindex', -1); + $.data(this, "selectable-item", { left: pos.left, top: pos.top, right: pos.left + $this.width(), bottom: pos.top + $this.height(), startSelected: false, - selected: $this.hasClass(o.selectedClass) + selected: $this.hasClass('ui-selected') }); }); + + + if(!fromInside) { + this._previousSelection = this._selection.slice(); + this._selection = []; + for (var i=0; i < this._previousSelection.length; i++) { + if(this._previousSelection[i][0].parentNode) this._selection.push(this._previousSelection[i]); + }; + + this._endSelection(); + } + }, select: function(item) { - //TODO + + if(!isNaN(parseInt(item))) + item = this.items.get(item); + + item = $(item, this.element); + if(!item.length) return; + + // clear the current selection + this._clearSelection(); + + // select all found + var newlySelected = [], self = this; + item.each(function(i) { + if(i == 0) { //Setting the focus on the first item in the list + self.previousFocus = self.currentFocus.attr('tabindex', -1); + self.currentFocus = $(this).attr('tabindex', 0); + self.previousFocus.removeClass('ui-state-focus'); + self.currentFocus.addClass('ui-state-focus'); + } + newlySelected.push(self._addToSelection($(this))); + }); + + // Ending the selection does a diff and then triggers appropriate events + this._endSelection(event, $($.map(newlySelected, function(i) { return i[0]; }))); + }, deselect: function(item) { - if(!item) this._clearSelection(true); - //TODO: Deselect single elements + + // if no item was specified, deselect all + if(!item) + this._clearSelection(true); + + if(!isNaN(parseInt(item))) + item = this.items.get(item); + + item = $(item, this.element); + if(!item.length) return; + + //store the current selection + this._previousSelection = this._selection.slice(); + + // deselect all found + var self = this; + item.each(function() { + self._removeFromSelection($(this)); + }); + + // Ending the selection does a diff and then triggers appropriate events + this._endSelection(event); + }, _uiHash: function(items, specialKey) { @@ -621,15 +784,7 @@ jQuery.effects||(function(d){d.effects={version:"1.7.2",save:function(g,h){for(v $.extend($.ui.selectable, { defaults: { - - //TODO: Figure out how to move these defaults out - cancel: ":input,option", - delay: 0, - distance: 1, - appendTo: 'body', - - multiple: true, - smart: true, + closest: true, filter: '> *', keyboard: true, @@ -639,10 +794,7 @@ jQuery.effects||(function(d){d.effects={version:"1.7.2",save:function(g,h){for(v distance: 1, tolerance: 'touch', appendTo: 'body' - }, - - //Should we really delete that? - selectedClass: 'ui-state-selected' + } } }); |