summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/jquery-ui.js410
-rw-r--r--modules/organize/css/organize.css12
-rw-r--r--modules/organize/js/organize.js8
3 files changed, 297 insertions, 133 deletions
diff --git a/lib/jquery-ui.js b/lib/jquery-ui.js
index 4939d009..85e457a0 100644
--- a/lib/jquery-ui.js
+++ b/lib/jquery-ui.js
@@ -159,87 +159,98 @@ 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);
}
-
+
if(self._trigger('beforeselect', event) === false)
return true;
self._select(event, item);
self.element[0].focus();
event.preventDefault();
-
+
})
.bind('mouseup.selectable', function(event) {
if(self._listenForMouseUp) {
-
+
self._listenForMouseUp = 0;
var item = self._targetIsItem(event.target);
if (!item) return;
-
+
if(self._trigger('beforeselect', event) === false)
return true;
-
+
self._select(event, item);
self.element[0].focus();
event.preventDefault();
}
})
.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();
}
@@ -253,14 +264,14 @@ jQuery.effects||(function(d){d.effects={version:"1.7.2",save:function(g,h){for(v
.addClass("ui-selectable-lasso");
},
-
+
selectClosest: function(direction, event) {
-
+
var current = [/(down|right)/.test(direction) ? 10000 : -10000, null],
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'),
@@ -270,71 +281,84 @@ jQuery.effects||(function(d){d.effects={version:"1.7.2",save:function(g,h){for(v
};
switch(direction) {
-
+
case 'up':
if((selfOffset.top > offset.top && offset.top >= current[0]) && (offset.top != current[0] || distance.x < overlap)) {
current = [offset.top, $this];
overlap = distance.x;
}
break;
-
+
case 'down':
if((selfOffset.top < offset.top && offset.top <= current[0]) && (offset.top != current[0] || distance.x < overlap)) {
current = [offset.top, $this];
overlap = distance.x;
}
break;
-
+
case 'left':
if((selfOffset.left > offset.left && offset.left >= current[0]) && (offset.left != current[0] || distance.y < overlap)) {
current = [offset.left, $this];
overlap = distance.y;
}
break;
-
+
case 'right':
if((selfOffset.left < offset.left && offset.left <= current[0]) && (offset.left != current[0] || distance.y < overlap)) {
current = [offset.left, $this];
overlap = distance.y;
}
break;
-
+
}
});
-
- 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();
},
-
+
_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];
-
+
if (o.disabled)
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);
this.helper.css({
@@ -347,36 +371,36 @@ 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) {
-
+
var self = this, o = this.options;
-
+
if (o.disabled)
return;
-
+
//Do the lasso magic
var x1 = this.opos[0], y1 = this.opos[1], x2 = event.pageX, y2 = event.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});
-
+
//Loop through all items and check overlaps
this.items.each(function() {
-
+
var item = $.data(this, "selectable-item");
-
+
//prevent helper from being selected if appendTo: selectable
if (!item || item.element == self.element[0])
return;
-
+
var hit = false;
if (o.lasso && o.lasso.tolerance == 'touch') {
hit = ( !(item.left > x2 || item.right < x1 || item.top > y2 || item.bottom < y1) );
@@ -387,43 +411,119 @@ jQuery.effects||(function(d){d.effects={version:"1.7.2",save:function(g,h){for(v
hit ?
item.startSelected ? self._removeFromSelection($(this), event) : self._addToSelection($(this), event)
: !item.startSelected ? self._removeFromSelection($(this), event) : self._addToSelection($(this), event);
-
+
});
-
+
return false;
-
+
},
-
+
_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;
- },
-
+ },
+
_targetIsItem: function(item) {
var found = $(item).parents().andSelf().filter(':data(selectable-item)');
return found.length && found;
- },
+ },
_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].data('selectable-item').selected = false;
+ var data = this._selection[i].data('selectable-item');
+ if(triggerEvent && data && data.selected) triggerItems.push(this._selection[i]);
+ this._selection[i].removeClass('ui-selected ui-state-active');
+ if (data)
+ data.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,13 +533,13 @@ 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) {
this._trigger('select', triggerEvent, $.extend({ lasso: true }, this._uiHash(item)));
}
-
+
return item;
},
@@ -448,10 +548,14 @@ 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].data('selectable-item').selected = false;
+ this._selection[i].removeClass('ui-selected ui-state-active');
+ var data = this._selection[i].data('selectable-item');
+ if (data) {
+ data.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 +566,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,16 +583,17 @@ 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;
}
}
-
+
return $($.map(newlySelected, function(i) { return i[0]; }));
},
@@ -497,7 +602,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 +624,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);
@@ -527,84 +632,148 @@ jQuery.effects||(function(d){d.effects={version:"1.7.2",save:function(g,h){for(v
this.latestWithoutModifier = this.currentFocus;
}
-
- 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);
},
_selectAdjacent: function(event, index) {
var item = this.items.eq(this.items.index(this.currentFocus[0]) + index);
-
+
//Bail if there's no previous/next item
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() {
- var o = this.options;
+ refresh: function(fromInside) {
+
+ 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,17 +790,9 @@ 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,
lasso: {
cancel: ":input,option",
@@ -639,10 +800,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'
+ }
}
});
diff --git a/modules/organize/css/organize.css b/modules/organize/css/organize.css
index 15b5538d..ed786dac 100644
--- a/modules/organize/css/organize.css
+++ b/modules/organize/css/organize.css
@@ -102,9 +102,15 @@
width: 9em;
}
-.gOrganizeMicroThumbGridCell.ui-state-selected {
- margin: 2px;
- border: 2px solid #13A;
+.gOrganizeMicroThumbGridCell.ui-selected {
+ margin: 2px !important;
+ border: 2px solid #13A !important;
+}
+
+.gOrganizeMicroThumbGridCell.ui-state-focus,
+.gOrganizeMicroThumbGridCell.ui-state-active {
+ background: none;
+ border: 0px;
}
.ui-selectable-lasso {
diff --git a/modules/organize/js/organize.js b/modules/organize/js/organize.js
index c30f89e0..7d204708 100644
--- a/modules/organize/js/organize.js
+++ b/modules/organize/js/organize.js
@@ -1,12 +1,12 @@
(function($) {
$.organize = {
micro_thumb_draggable: {
- handle: ".ui-state-selected",
+ handle: ".ui-selected",
distance: 10,
cursorAt: { left: -10, top: -10},
appendTo: "#gOrganizeMicroThumbPanel",
helper: function(event, ui) {
- var selected = $(".ui-draggable.ui-state-selected img");
+ var selected = $(".ui-draggable.ui-selected img");
if (selected.length) {
var set = $('<div class="gDragHelper"></div>')
.css({
@@ -37,7 +37,7 @@
},
start: function(event, ui) {
- $("#gOrganizeMicroThumbPanel .ui-state-selected").hide();
+ $("#gOrganizeMicroThumbPanel .ui-selected").hide();
},
drag: function(event, ui) {
@@ -80,7 +80,7 @@
greedy: true,
drop: function(event, ui) {
if ($(event.target).hasClass("gViewOnly")) {
- $(".ui-state-selected").show();
+ $(".ui-selected").show();
$(".gOrganizeMicroThumbGridCell").css("borderStyle", "none");
} else {
$.organize.do_drop({