Newforms Autocomplete Widget with Scriptaculous

 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
from django.template import RequestContext
from django.shortcuts import render_to_response
from django.http import HttpResponse

from django import newforms as forms
from django.newforms.widgets import TextInput,flatatt
from django.newforms.util import smart_unicode

from django.utils.html import escape

class AutoCompleteField(TextInput):
	def __init__(self, url='', options='{paramName: "text"}', attrs=None):
		self.url = url
		self.options = options
                if attrs is None:
                    attrs = {}
                self.attrs = attrs

	def render(self, name, value=None, attrs=None):
		final_attrs = self.build_attrs(attrs, name=name)
		if value:
			value = smart_unicode(value)
			final_attrs['value'] = escape(value)
		if not self.attrs.has_key('id'):
                    final_attrs['id'] = 'id_%s' % name
		return (u'<input type="text" name="%(name)s" id="%(id)s"/> <div class="autocomplete" id="box_%(name)s"></div>'
                        '<script type="text/javascript">'
                        'new Ajax.Autocompleter(\'%(id)s\', \'box_%(name)s\', \'%(url)s\', %(options)s);'
                        '</script>') % {'attrs'	: flatatt(final_attrs),
                                        'name'	: name,
                                        'id'	: final_attrs['id'],
                                        'url'	: self.url,
                                        'options' : self.options}


#
#  Usage example
#

class TestForm(forms.Form):
    person = forms.CharField(required=False,
                             widget=AutoCompleteField(url='/autocomplete/'))

def test_view(request):
    return render_to_response('test_template.html', {'form': TestForm()},
                              context_instance=RequestContext(request))

def autocomplete(request):
    """ Return a simple response with a <ul>
    """
    if request.method == 'POST':
        text = request['text']
    # Search things on the database with 'text'
    # Or simply perform any computing with this
    # to generate a <ul>
    # But this is not important here.
    return HttpResponse(
        '''
        <ul>
           <li>ACME Inc <span class="informal"> 5012 East 5th Street</span></li>
           <li>Scriptaculous <span class="informal"> 1066 West Redlands Parkway</span></li>
           <li>Test00001</li>
           <li>Test00001</li>
           <li>Another Silly test</li>
           <li>%s</li>

        </ul>'''%text) # put the text in the end of the example list to see if this works

More like this

  1. jQuery Autocomplete by zeeg 6 years, 10 months ago
  2. jquery autocomplete widget by skam 6 years, 11 months ago
  3. NonceField for disabling autocompletion by johnnoone 5 years, 1 month ago
  4. autocompleter with database query by bbolli 6 years, 9 months ago
  5. Django JQuery Autocomplete for Model Selection by elpenia 5 years, 6 months ago

Comments

cahenan (on June 5, 2007):

very useful, tks! ;)

#

bbolli (on July 5, 2007):

To make this snippet work in my app, I had to replace the %(id)s in the big return statement with %(attrs)s. attrs wasn't used anywhere else, so I think this makes sense.

#

charliesl (on September 28, 2007):

I've modified a little the script, so the value if instancited isnt lost in the path:

return (u'[HTML_REMOVED] [HTML_REMOVED][HTML_REMOVED]' '[HTML_REMOVED]' 'new Ajax.Autocompleter(\'%(id)s\', \'box_%(name)s\', \'%(url)s\', %(options)s);' '[HTML_REMOVED]') % {'attrs': flatatt(final_attrs), 'name': name, 'id': final_attrs['id'], 'url': self.url, 'value': value, 'options' : self.options}

Basically, I've added value="%(value)s" in the html input and the corresponding param 'value': value, in the dictionary.

Great snippet, BTW

-charlie-

#

ogw (on January 10, 2009):

I added the following method to AutoCompleteField, so that when this field is required and left empty, it does not validate:

def value_from_datadict(self, data, files, name):
    val = data.get(name, None)
    if val=="-1":
        val = None
    return val

#

(Forgotten your password?)