r769 - in branches/1.7: . tests tests/visual/autocomplete

r769 - in branches/1.7: . tests tests/visual/autocomplete


Author: pazu2k@gmail.com
Date: Sat Oct 4 21:37:16 2008
New Revision: 769
Modified:
branches/1.7/tests/autocomplete.html
branches/1.7/tests/visual/autocomplete/index.html
branches/1.7/ui.autocomplete.js
Log:
Autocomplete: refactored code (unstable). Note: this is only a start - more
refactoring planned.
Modified: branches/1.7/tests/autocomplete.html
==============================================================================
--- branches/1.7/tests/autocomplete.html    (original)
+++ branches/1.7/tests/autocomplete.html    Sat Oct 4 21:37:16 2008
@@ -4,9 +4,9 @@
    <link rel="stylesheet" href="qunit/testsuite.css" type="text/css"
media="screen">
-    <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="../ui/ui.autocomplete.js"></script>
+    <script type="text/javascript"
src="../../../trunk/jquery-1.2.6.js"></script>
+    <script type="text/javascript"
src="../../../trunk/ui/ui.core.js"></script>
+    <script type="text/javascript" src="../ui.autocomplete.js"></script>
    
    <script type="text/javascript" src="qunit/testrunner.js"></script>
    <script type="text/javascript" src="simulate/jquery.simulate.js"></script>
Modified: branches/1.7/tests/visual/autocomplete/index.html
==============================================================================
--- branches/1.7/tests/visual/autocomplete/index.html    (original)
+++ branches/1.7/tests/visual/autocomplete/index.html    Sat Oct 4 21:37:16
2008
@@ -4,13 +4,13 @@
<title>jQuery Autocomplete Plugin</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="../../../ui/ui.autocomplete.js"></script>
+<script type="text/javascript"
src="../../../../../trunk/jquery-1.2.6.js"></script>
+<script type="text/javascript"
src="../../../../../trunk/ui/ui.core.js"></script>
+<script type="text/javascript" src="../../../ui.autocomplete.js"></script>
-<script type='text/javascript' src='localdata.js'></script>
+<script type="text/javascript" src="localdata.js"></script>
<link rel="stylesheet" type="text/css" href="main.css" />
-<link rel="stylesheet" href="../../../themes/default/ui.all.css"
type="text/css" media="screen" title="no title" charset="utf-8">
+<link rel="stylesheet"
href="../../../../../trunk/themes/default/ui.all.css" type="text/css"
media="screen" title="no title" charset="utf-8">
    
<script type="text/javascript">
$().ready(function() {
Modified: branches/1.7/ui.autocomplete.js
==============================================================================
--- branches/1.7/ui.autocomplete.js    (original)
+++ branches/1.7/ui.autocomplete.js    Sat Oct 4 21:37:16 2008
@@ -17,410 +17,420 @@
    _init: function() {
        
        $.extend(this.options, {
-            delay: this.options.url ? $.Autocompleter.defaults.delay : 10,
+            delay: this.options.url ? this.options.delay : 10,
            max: !this.options.scroll ? 10 : 150,
            highlight: this.options.highlight || function(value) { return value; },
// if highlight is set to false, replace it with a do-nothing function
            formatMatch: this.options.formatMatch || this.options.formatItem // if
the formatMatch option is not specified, then use formatItem for backwards
compatibility
        });
-        
-        new $.Autocompleter(this.element[0], this.options);
-        
-    },
-    
-    result: function(handler) {
-        return this.element.bind("result", handler);
-    },
-    search: function(handler) {
-        return this.element.trigger("search", [handler]);
-    },
-    flushCache: function() {
-        return this.element.trigger("flushCache");
-    },
-    setData: function(key, value){
-        return this.element.trigger("setOptions", [{ key: value }]);
-    },
-    destroy: function() {
-        return this.element.trigger("unautocomplete");
-    }
-    
-});
-$.Autocompleter = function(input, options) {
-    
-    var KEY = {
-        UP: 38,
-        DOWN: 40,
-        DEL: 46,
-        TAB: 9,
-        RETURN: 13,
-        ESC: 27,
-        COMMA: 188,
-        PAGEUP: 33,
-        PAGEDOWN: 34,
-        BACKSPACE: 8
-    };
-    
-    // Create $ object for input element
-    var $input =
$(input).attr("autocomplete", "off").addClass(options.inputClass);
-    if(options.result) $input.bind('result.autocomplete', options.result);
-    
-    var timeout;
-    var previousValue = "";
-    var cache = $.Autocompleter.Cache(options);
-    var hasFocus = 0;
-    var lastKeyPressCode;
-    var config = {
-        mouseDownOnSelect: false
-    };
-    var select = $.Autocompleter.Select(options, input, selectCurrent,
config);
-    
-    var blockSubmit;
-    
-    // prevent form submit in opera when selecting with return key
-    $.browser.opera && $(input.form).bind("submit.autocomplete", function() {
-        if (blockSubmit) {
-            blockSubmit = false;
-            return false;
+        var input = this.element[0],
+            options = this.options,
+            // Create $ object for input element
+            $input =
$(input).attr("autocomplete", "off").addClass(options.inputClass),
+            KEY = $.keyCode,
+            previousValue = "",
+            cache = $.ui.autocomplete.cache(options),
+            hasFocus = 0,
+            config = {
+                mouseDownOnSelect: false
+            },
+            timeout,
+            blockSubmit,
+            lastKeyPressCode,
+            select = $.ui.autocomplete.select(options, input, selectCurrent,
config);
+        
+        if(options.result) {
+            $input.bind('result.autocomplete', options.result);
        }
-    });
-    
-    // only opera doesn't trigger keydown multiple times while pressed,
others don't work with keypress at all
-    $input.bind(($.browser.opera ? "keypress" : "keydown") + ".autocomplete",
function(event) {
-        // track last key pressed
-        lastKeyPressCode = event.keyCode;
-        switch(event.keyCode) {
-            
-            case KEY.UP:
-                event.preventDefault();
-                if ( select.visible() ) {
-                    select.prev();
-                } else {
-                    onChange(0, true);
+
+        // prevent form submit in opera when selecting with return key
+        $.browser.opera && $(input.form).bind("submit.autocomplete", function() {
+            if (blockSubmit) {
+                blockSubmit = false;
+                return false;
+            }
+        });
+        
+        // only opera doesn't trigger keydown multiple times while pressed,
others don't work with keypress at all
+        $input.bind(($.browser.opera ? "keypress" : "keydown")
+ ".autocomplete", function(e) {
+            // track last key pressed
+            lastKeyPressCode = e.keyCode;
+            switch(e.keyCode) {
+                
+                case KEY.UP:
+                    e.preventDefault();
+                    if ( select.visible() ) {
+                        select.prev();
+                    } else {
+                        onChange(0, true);
+                    }
+                    break;
+                
+                case KEY.DOWN:
+                    e.preventDefault();
+                    if ( select.visible() ) {
+                        select.next();
+                    } else {
+                        onChange(0, true);
+                    }
+                    break;
+                
+                case KEY.PAGE_UP:
+                    e.preventDefault();
+                    if ( select.visible() ) {
+                        select.pageUp();
+                    } else {
+                        onChange(0, true);
+                    }
+                    break;
+                
+                case KEY.PAGE_DOWN:
+                    e.preventDefault();
+                    if ( select.visible() ) {
+                        select.pageDown();
+                    } else {
+                        onChange(0, true);
+                    }
+                    break;
+                
+                // matches also semicolon
+                case options.multiple && $.trim(options.multipleSeparator) == "," &&
KEY.COMMA:
+                case KEY.TAB:
+                case KEY.ENTER:
+                    if( selectCurrent() ) {
+                        // stop default to prevent a form submit, Opera needs special
handling
+                        e.preventDefault();
+                        blockSubmit = true;
+                        return false;
+                    }
+                    break;
+                
+                case KEY.ESCAPE:
+                    select.hide();
+                    break;
+                
+                default:
+                    clearTimeout(timeout);
+                    timeout = setTimeout(onChange, options.delay);
+                    break;
+            }
+        }).focus(function(){
+            // track whether the field has focus, we shouldn't process any
+            // results if the field no longer has focus
+            hasFocus++;
+        }).blur(function() {
+            hasFocus = 0;
+            if (!config.mouseDownOnSelect) {
+                hideResults();
+            }
+        }).click(function() {
+            // show select when clicking in a focused field
+            if ( hasFocus++ > 1 && !select.visible() ) {
+                onChange(0, true);
+            }
+        }).bind("search", function() {
+            // TODO why not just specifying both arguments?
+            var fn = (arguments.length > 1) ? arguments[1] : null;
+            function findValueCallback(q, data) {
+                var result;
+                if( data && data.length ) {
+                    for (var i=0; i < data.length; i++) {
+                        if( data[i].result.toLowerCase() == q.toLowerCase() ) {
+                            result = data[i];
+                            break;
+                        }
+                    }
                }
-                break;
-            
-            case KEY.DOWN:
-                event.preventDefault();
-                if ( select.visible() ) {
-                    select.next();
-                } else {
-                    onChange(0, true);
+                if( typeof fn == "function" ) fn(result);
+                else $input.trigger("result", result && [result.data, result.value]);
+            }
+            $.each(trimWords($input.val()), function(i, value) {
+                request(value, findValueCallback, findValueCallback);
+            });
+        }).bind("flushCache", function() {
+            cache.flush();
+        }).bind("setOptions", function() {
+            $.extend(options, arguments[1]);
+            // if we've updated the data, repopulate
+            if ( "data" in arguments[1] )
+                cache.populate();
+        }).bind("unautocomplete", function() {
+            select.unbind();
+            $input.unbind();
+            $(input.form).unbind(".autocomplete");
+        });
+        
+        
+        // Private methods
+        function selectCurrent() {
+            var selected = select.selected();
+            if( !selected )
+                return false;
+            
+            var v = selected.result;
+            previousValue = v;
+            
+            if ( options.multiple ) {
+                var words = trimWords($input.val());
+                if ( words.length > 1 ) {
+                    v = words.slice(0, words.length - 1).join( options.multipleSeparator
) + options.multipleSeparator + v;
                }
-                break;
+                v += options.multipleSeparator;
+            }
            
-            case KEY.PAGEUP:
-                event.preventDefault();
-                if ( select.visible() ) {
-                    select.pageUp();
-                } else {
-                    onChange(0, true);
-                }
-                break;
+            $input.val(v);
+            hideResultsNow();
+            $input.trigger("result", [selected.data, selected.value]);
+            return true;
+        };
+        
+        function onChange(crap, skipPrevCheck) {
+            if( lastKeyPressCode == $.keyCode.DELETE ) {
+                select.hide();
+                return;
+            }
            
-            case KEY.PAGEDOWN:
-                event.preventDefault();
-                if ( select.visible() ) {
-                    select.pageDown();
-                } else {
-                    onChange(0, true);
-                }
-                break;
+            var currentValue = $input.val();
            
-            // matches also semicolon
-            case options.multiple && $.trim(options.multipleSeparator) == "," &&
KEY.COMMA:
-            case KEY.TAB:
-            case KEY.RETURN:
-                if( selectCurrent() ) {
-                    // stop default to prevent a form submit, Opera needs special handling
-                    event.preventDefault();
-                    blockSubmit = true;
-                    return false;
-                }
-                break;
+            if ( !skipPrevCheck && currentValue == previousValue )
+                return;
            
-            case KEY.ESC:
-                select.hide();
-                break;
+            previousValue = currentValue;
            
-            default:
-                clearTimeout(timeout);
-                timeout = setTimeout(onChange, options.delay);
-                break;
-        }
-    }).focus(function(){
-        // track whether the field has focus, we shouldn't process any
-        // results if the field no longer has focus
-        hasFocus++;
-    }).blur(function() {
-        hasFocus = 0;
-        if (!config.mouseDownOnSelect) {
-            hideResults();
-        }
-    }).click(function() {
-        // show select when clicking in a focused field
-        if ( hasFocus++ > 1 && !select.visible() ) {
-            onChange(0, true);
-        }
-    }).bind("search", function() {
-        // TODO why not just specifying both arguments?
-        var fn = (arguments.length > 1) ? arguments[1] : null;
-        function findValueCallback(q, data) {
-            var result;
-            if( data && data.length ) {
-                for (var i=0; i < data.length; i++) {
-                    if( data[i].result.toLowerCase() == q.toLowerCase() ) {
-                        result = data[i];
-                        break;
-                    }
-                }
+            currentValue = lastWord(currentValue);
+            if ( currentValue.length >= options.minChars) {
+                $input.addClass(options.loadingClass);
+                if (!options.matchCase)
+                    currentValue = currentValue.toLowerCase();
+                request(currentValue, receiveData, hideResultsNow);
+            } else {
+                stopLoading();
+                select.hide();
            }
-            if( typeof fn == "function" ) fn(result);
-            else $input.trigger("result", result && [result.data, result.value]);
-        }
-        $.each(trimWords($input.val()), function(i, value) {
-            request(value, findValueCallback, findValueCallback);
-