jquery autocomplete widget

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# widgets.py

from django import newforms as forms
from django.newforms.widgets import flatatt
from django.newforms.util import smart_unicode
from django.utils.html import escape
from django.utils.simplejson import JSONEncoder

class JQueryAutoComplete(forms.TextInput):
    def __init__(self, source, options={}, attrs={}):
        """source can be a list containing the autocomplete values or a
        string containing the url used for the XHR request.
        
        For available options see the autocomplete sample page::
        http://jquery.bassistance.de/autocomplete/"""
        
        self.options = None
        self.attrs = {'autocomplete': 'off'}
        self.source = source
        if len(options) > 0:
            self.options = JSONEncoder().encode(options)
        
        self.attrs.update(attrs)
    
    def render_js(self, field_id):
        if isinstance(self.source, list):
            source = JSONEncoder().encode(self.source)
        elif isinstance(self.source, str):
            source = "'%s'" % escape(self.source)
        else:
            raise ValueError('source type is not valid')
        
        options = ''
        if self.options:
            options += ',%s' % self.options

        return u'$(\'#%s\').autocomplete(%s%s);' % (field_id, source, options)

    def render(self, name, value=None, attrs=None):
        final_attrs = self.build_attrs(attrs, name=name)
        if value:
            final_attrs['value'] = escape(smart_unicode(value))

        if not self.attrs.has_key('id'):
            final_attrs['id'] = 'id_%s' % name    
        
        return u'''<input type="text" %(attrs)s/>
        <script type="text/javascript"><!--//
        %(js)s//--></script>
        ''' % {
            'attrs' : flatatt(final_attrs),
            'js' : self.render_js(final_attrs['id']),
        }

# views.py - sample view

from django.http import HttpResponse, HttpResponseBadRequest
from django.views.decorators.cache import cache_page
from apps.foo.models import Foo

def autocomplete(request):
    def iter_results(results):
        if results:
            for r in results:
                yield '%s|%s\n' % (r.name, r.id)
    
    if not request.GET.get('q'):
        return HttpResponse(mimetype='text/plain')
    
    q = request.GET.get('q')
    limit = request.GET.get('limit', 15)
    try:
        limit = int(limit)
    except ValueError:
        return HttpResponseBadRequest() 

    foos = Foo.objects.filter(name__startswith=q)[:limit]
    return HttpResponse(iter_results(foos), mimetype='text/plain')

autocomplete = cache_page(autocomplete, 60 * 60)

More like this

  1. Autocomplete TextInput Widget w/ Static Data (jQuery UI) by JoeLinux 1 year, 1 month ago
  2. jQuery Autocomplete by zeeg 6 years, 10 months ago
  3. Newforms Autocomplete Widget with Scriptaculous by eopadoan 6 years, 10 months ago
  4. Django JQuery Autocomplete for Model Selection by elpenia 5 years, 6 months ago
  5. DropDownMultiple widget by marinho 5 years, 11 months ago

Comments

seb (on May 16, 2007):

Hi, I tried to use your widget, very usefull by the way, but it took me some time to realise that (line 53) the 'js' key should need the url matching with your 'autocomplete' view, right? In fact, I'm wondering how it works if you send a list of elements to self.source? Thanks for your reply!

#

slypheed (on May 23, 2007):

The data returned from the view needs to have a linebreak after each entry.

So line 66 needs to be changed to:

            yield '%s|%s\n' % (r.name, r.id)

#

skam (on June 1, 2007):

thank you, now it is fixed

#

Lau (on June 6, 2007):

I had a problem with IE coughing on the [HTML_REMOVED] for registering the event handlers with jQuery. I changed line 38 to register den handlers on onLoad:

return u'$(function() {$(\'#%s\').autocomplete(%s%s);})' % (field_id, source, options)

#

oxyum (on February 6, 2008):

I think lines 10 & 11 must be in __init__ method, because in the current state "attrs" is unsable.

Now this widget work like Singleton pattern and when we set "attrs" in one field, we get it in other fields too.

#

skam (on February 11, 2008):

fixed

#

jeje (on October 24, 2008):

Has anyone a full working example to provide me (including urls.py, form definitions, etc) ? Because I can't make it work. I'm newbie to newforms so that may be the reason.

Thanks.

#

michaelh (on August 20, 2009):

Hi. I like it alot :o) I can see this snippet is from 2007. My question is: does it work with Django ver 1.1 ?

#

Romain Hardouin (on October 28, 2009):

@michaelh : not as is. e.g. django.newforms is now available as simply django.forms

I haven't try yet but have a peep at #1097

#

(Forgotten your password?)