r1610 - in branches/dev/selectable: tests/visual ui

r1610 - in branches/dev/selectable: tests/visual ui


Author: paul.bakaus
Date: Thu Jan 15 09:17:02 2009
New Revision: 1610
Modified:
branches/dev/selectable/tests/visual/selectable_keyboard.html
branches/dev/selectable/ui/ui.selectable.js
Log:
dev-selectable: new version of selectable with lasso, candidate for
inclusion in 1.6
Modified: branches/dev/selectable/tests/visual/selectable_keyboard.html
==============================================================================
--- branches/dev/selectable/tests/visual/selectable_keyboard.html    (original)
+++ branches/dev/selectable/tests/visual/selectable_keyboard.html    Thu Jan
15 09:17:02 2009
@@ -3,8 +3,9 @@
    <head>
        <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
        <title>keyboard_selection</title>
-        <script type="text/javascript" src="../../jquery-1.2.6.js"></script>
-        <script type="text/javascript" src="../../ui/ui.core.js"></script>
+        <script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.0/jquery.js"></script>
+        <script src="../../../../../trunk/ui/ui.core.js" type="text/javascript"
charset="utf-8"></script>
+        
        <script type="text/javascript" src="../../ui/ui.selectable.js"></script>
        <style type="text/css" media="screen">
@@ -26,8 +27,14 @@
                $("ul").selectable({
+                    lasso: true,
+
                    select: function(event, ui) {
-                        //console.log(ui.selection);
+                        console.log('select: ', ui.item);
+                    },
+                    
+                    unselect: function(event, ui) {
+                        console.log('unselect', ui.item);
                    }
                });
Modified: branches/dev/selectable/ui/ui.selectable.js
==============================================================================
--- branches/dev/selectable/ui/ui.selectable.js    (original)
+++ branches/dev/selectable/ui/ui.selectable.js    Thu Jan 15 09:17:02 2009
@@ -1,10 +1,10 @@
/*
* jQuery UI Selectable @VERSION
*
- * Copyright (c) 2008 Paul Bakaus
+ * Copyright (c) 2009 AUTHORS.txt (http://ui.jquery.com/about)
* Dual licensed under the MIT (MIT-LICENSE.txt)
* and GPL (GPL-LICENSE.txt) licenses.
- *
+ *
* http://docs.jquery.com/UI/Selectables
*
* Depends:
@@ -12,102 +12,214 @@
*/
(function($) {
-    $.widget('ui.selectable', {
+    $.widget('ui.selectable', $.extend({}, $.ui.mouse, {
        _init: function() {
            var self = this;
+            this.element.addClass("ui-selectable");
            //Set the currentFocus to the first item
            this.currentFocus = $($(this.options.filter, this.element)[0]);
+            
+            //Refresh item positions
+            this.refresh();
            //Disable text selection
            this.element.disableSelection();
+            //Prepare caret selection
+            if(this.options.lasso) this._mouseInit();
+
            this.element
                .bind('mousedown', function(event) {
-                    var item;
-                    $(event.target).parents().andSelf().each(function() {
-                        if ($(self.options.filter, self.element).index(this) != -1) item =
this;
-                    });
-
-                    if (!item)
-                        return;
+                    var item = self._targetIsItem(event.target);
+                    if (!item) return;
                    self._select(event, item);
                    self.element[0].focus();
                    event.preventDefault();
+                    
                })
                .bind('focus.selectable', function() {
-                    self.currentFocus.addClass(self.options.focusClass);
+                    self.currentFocus.addClass('ui-focused');
                })
                .bind('blur.selectable', function() {
-                    self.currentFocus.removeClass(self.options.focusClass);
+                    self.currentFocus.removeClass('ui-focused');
                })
                .bind('keydown.selectable', function(event) {
-                    if (event.keyCode == $.keyCode.DOWN || event.keyCode ==
$.keyCode.RIGHT) {
+                    if(!self.options.keyboard)
+                        return;
+
+                    if (event.keyCode == $.ui.keyCode.DOWN || event.keyCode ==
$.ui.keyCode.RIGHT) {
                        self.selectNext(event);
                        event.preventDefault();
                    }
-                    if (event.keyCode == $.keyCode.UP || event.keyCode == $.keyCode.LEFT)
{
+                    if (event.keyCode == $.ui.keyCode.UP || event.keyCode ==
$.ui.keyCode.LEFT) {
                        self.selectPrevious(event);
                        event.preventDefault();
                    }
-                    if ((event.ctrlKey || event.metaKey) && event.keyCode ==
$.keyCode.SPACE) {
-                        self._toggleSelection(self.currentFocus);
+                    if ((event.ctrlKey || event.metaKey) && event.keyCode ==
$.ui.keyCode.SPACE) {
+                        self._toggleSelection(self.currentFocus, event);
                    }
                });
+            this.helper = $(document.createElement('div'))
+                .css({border:'1px dotted black'})
+                .addClass("ui-selectable-helper");
+
        },
+        destroy: function() {
+            this.element
+                .removeClass("ui-selectable ui-selectable-disabled")
+                .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;
+        },
+        
+        _mouseStart: function(event) {
+            
+            var self = this, o = this.options;
+            this.opos = [event.pageX, event.pageY];
+    
+            if (o.disabled)
+                return;
+    
+            //Cache positions
+            this.refresh();
+    
+            //Trigger start event
+            this._trigger("start", event, this._uiHash());
+    
+            // append and position helper (lasso)
+            $('body').append(this.helper);
+            this.helper.css({
+                zIndex: 100,
+                position: "absolute",
+                left: event.clientX,
+                top: event.clientY,
+                width: 0,
+                height: 0
+            });
+
+            //Tell the intersection that some start selected
+            $(this.options.filter,
this.element).filter('.ui-selected').each(function() {
+                if(event.metaKey) {
+                    if(this != self.clickedOnItem)
$.data(this, "selectable-item").startSelected = true;
+                } else self._removeFromSelection($(this), 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.options.filter, this.element).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.tolerance == 'touch') {
+                    hit = ( !(item.left > x2 || item.right < x1 || item.top > y2 ||
item.bottom < y1) );
+                } else if (o.tolerance == 'fit') {
+                    hit = (item.left > x1 && item.right < x2 && item.top > y1 &&
item.bottom < y2);
+                }
+
+                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());
+            this.helper.remove();
+            return false;
+        },    
+        
+        _targetIsItem: function(item) {
+            var test = false, self = this;
+            $(item).parents().andSelf().each(function() {
+                if ($(self.options.filter, self.element).index(this) != -1) test =
this;
+            });
+            return test;
+        },        
+
        _selection: [],
-        _clearSelection: function() {
+        _clearSelection: function(triggerEvent) {
            for (var i = this._selection.length - 1; i >= 0; i--){
-                this._selection[i]
-                    .removeClass(this.options.selectClass)
-                    .data('ui-selected', false);
+                if(triggerEvent &&
this._selection[i].data('selectable-item').selected)
this._trigger('unselect', triggerEvent, this._uiHash(this._selection[i]));
+                this._selection[i].removeClass('ui-selected');
+                this._selection[i].data('selectable-item').selected = false;
            };
            this._selection = [];
        },
-        _toggleSelection: function(item) {
-            if (item.data('ui-selected')) {
-                this._removeFromSelection(item);
-            } else {
-                this._addToSelection(item);
-            }
+        _toggleSelection: function(item, event) {
+                item.data('selectable-item').selected ?
this._removeFromSelection(item, event) : this._addToSelection(item);
        },
-        _addToSelection: function(item) {
+        _addToSelection: function(item, triggerEvent) {
-            if (item.data('ui-selected'))
-                return;
+            if (item.data('selectable-item').selected)
+                return null;
            this._selection.push(item);
            this.latestSelection = item;
-            item
-                .addClass(this.options.selectClass)
-                .data('ui-selected', true);
+            item.addClass('ui-selected');
+            item.data('selectable-item').selected = true;
+            
+            if(triggerEvent) {
+                this._trigger('select', triggerEvent, $.extend({ lasso: true },
this._uiHash(item)));
+            }
+            
+            return item;
        },
-        _removeFromSelection: function(item) {
+        _removeFromSelection: function(item, triggerEvent) {
            for (var i=0; i < this._selection.length; i++) {
                if (this._selection[i][0] == item[0]) {
-                    this._selection[i]
-                        .removeClass(this.options.selectClass)
-                        .data('ui-selected', false);
+                    this._selection[i].removeClass('ui-selected');
+                    this._selection[i].data('selectable-item').selected = false;
                    this._selection.splice(i,1);
+                    if(triggerEvent) this._trigger('unselect', triggerEvent,
this._uiHash($(item)));
                    break;
                }
            };
@@ -116,15 +228,17 @@
        _updateSelectionMouse: function(event) {
+            var newlySelected = [];
+
            if (event.shiftKey && this.options.multiple) {
                //Clear the previous selection to make room for a shift selection
-                this._clearSelection();
+                this._clearSelection(event);
                var dir = $(this.options.filter,
this.element).index(this.latestWithoutModifier[0]) > $(this.options.filter,
this.element).index(this.currentFocus[0]) ? 'prev' : 'next';
-                var i = this.latestWithoutModifier.data('ui-selected') ?
this.latestWithoutModifier[dir]() : this.latestWithoutModifier;
+                var i = this.latestWithoutModifier.data('selectable-item').selected ?
this.latestWithoutModifier[dir]() : this.latestWithoutModifier;
                while(i.length && i[0] != this.currentFocus[0]) {
-                    this._addToSelection(i);
+                    newlySelected.push(this._addToSelection(i));
                    i = i[dir]();
                }
@@ -133,31 +247,35 @@
            } else {
-                if (event.ctrlKey || event.metaKey) {
-                    this._toggleSelection(this.currentFocus);
+                if (event.metaKey) {
+                    this._toggleSelection(this.currentFocus, event);
                } else {
-                    this._clearSelection();
-                    this._addToSelection(this.currentFocus);
+                    this._clearSelection(event);
+                    newlySelected.push(this._addToSelection(this.currentFocus));
                    this.latestWithoutModifier = this.currentFocus;
                }
            }
+            
+            return $($.map(newlySelected, function(i) { return i[0]; }));
        },
        _updateSelection: function(event, dir) {
+            var newlySelected = [];
+
            if (event.shiftKey && this.options.multiple) {
-                if (this.currentFocus.data('ui-selected')) {
-                    this._removeFromSelection(this.previousFocus);
+                if (this.currentFocus.data('selectable-item').selected) {
+                    this._removeFromSelection(this.previousFocus, event);
                } else {
                    var dir2 = $(this.options.filter,
this.element).index(this.latestSelection[0]) > $(this.options.filter,
this.element).index(this.currentFocus[0]) ? 'next' : 'prev';
-                    if (!this.previousFocus.data('ui-selected')) {
+                    if (!this.previousFocus.data('selectable-item').selected) {
                        var i = dir == dir2 ? this.previousFocus[dir2]() :
this.previousFocus;
-                        while(i.length && !i.data('ui-selected')) {
-                            this._addToSelection(i);
+                        while(i.length && !i.data('selectable-item').selected) {
+                            newlySelected.push(this._addToSelection(i));
                            i = i[dir2]();
                        }
                    }
@@ -169,14 +287,16 @@
            } else {
                //If the CTRL or Apple/Win key is pressed, only set focus
-                if (event.ctrlKey || event.metaKey)
+                if (event.metaKey)
                    return;
-                this._clearSelection();
-                this._addToSelection(this.currentFocus);
+                this._clearSelection(event);
+                newlySelected.push(this._addToSelection(this.currentFocus));
                this.latestWithoutModifier = this.currentFocus;
            }
+            
+            return $($.map(newlySelected, function(i) { return i[0]; }));
        },
@@ -186,14 +306,14 @@
            this.previousFocus = this.currentFocus;
            this.currentFocus = $(item);
-            this.previousFocus.removeClass(