Integration with forms
======================
The purpose of this documentation is to describe every element in a
chronological manner. Because you want to know everything about this app and
hack like crazy.
It is complementary with the quick documentation.
Django startup
~~~~~~~~~~~~~~
Registry
--------
Autodiscovery is part of the `autocomplete_light.registry` module:
.. automodule:: autocomplete_light.registry
Autodiscovery is the first thing that happens as it is called early in urls.py:
.. autofunction:: autocomplete_light.registry.autodiscover
autocomplete_light.registry.autodiscover fills
`autocomplete_light.registry.registry`, which is an instance of
ChannelRegistry:
.. autoclass:: autocomplete_light.registry.ChannelRegistry
:members:
Channels
--------
As you can see, registration creates a channel if it is only passed a model.
You'll want to make your own channel class, this is what a channel looks like:
.. automodule:: autocomplete_light.channel.base
:members:
Forms
-----
To save you some boilerplate, a couple of helpers are provided:
.. automodule:: autocomplete_light.forms
:members:
Page rendering
--------------
It is important to load jQuery first, and then autocomplete_light and
application specific javascript, it can look like this::
{% load autocomplete_light_tags %}
{% autocomplete_light_static %}
.. autofunction:: autocomplete_light.templatetags.autocomplete_light_tags.autocomplete_light_static
That said, if you only want to make a global navigation autocomplete, you only need::
Widget in action
~~~~~~~~~~~~~~~~
Widget definition
-----------------
The first thing that happens is the definition of an AutocompleteWidget in a
form:
.. autoclass:: autocomplete_light.widgets.AutocompleteWidget
:members:
Widget rendering
----------------
This is what the default widget template looks like:
.. literalinclude:: ../../autocomplete_light/templates/autocomplete_light/widget.html
:language: html
Javascript initialization
-------------------------
deck.js initializes all widgets that have bootstrap='normal' (the default), as you can see::
$('.autocomplete_light_widget[data-bootstrap=normal]').each(function() {
$(this).yourlabs_deck();
});
If you want to initialize the deck yourself, set the widget or channel
bootstrap to something else, say 'yourinit'. Then, add to
`yourapp/static/yourapp/autocomplete_light.js` something like::
$('.autocomplete_light_widget[data-bootstrap=yourinit]').each(function() {
$(this).yourlabs_deck({
getValue: function(result) {
// your own logic to get the value from an html result
return ...;
}
});
});
`yourapp/static/yourapp/autocomplete_light.js` will be automatically collected by
by autodiscover, and the script tag generated by
`{% autocomplete_light_static %}`.
In `django-cities-light source
`_, you can see a `more interresting example
`_
where two autocompletes depend on each other.
You should take a look at the code of `autocomplete.js
`_
and `deck.js
`_,
as it lets you override everything.
One interresting note is that the plugins (yourlabs_autocomplete and
yourlabs_deck) hold a registry. Which means that:
- calling someElement.yourlabs_deck() will instanciate a deck with the passed
overrides
- calling someElement.yourlabs_deck() again will return the deck instance for
someElement
Javascript cron
---------------
deck.js includes a javascript function that is executed every two seconds. It
checks each widget's hidden select for a value that is not in the deck, and
adds it to the deck if any.
This is useful for example, when an item was added to the hidden select via the
'+' button in django admin. But if you create items yourself in javascript and
add them to the select it would work too.
Javascript events
-----------------
When the autocomplete input is focused, autocomplete.js checks if there are
enought caracters in the input to display an autocomplete box. If minCharacters
is 0, then it would open even if the input is empty, like a normal select box.
If the autocomplete box is empty, it will fetch the channel view. The channel
view will delegate the rendering of the autocomplete box to the actual channel.
So that you can override anything you want directly in the channel.
.. autoclass:: autocomplete_light.views.ChannelView
:members:
.. automethod:: autocomplete_light.channel.base.ChannelBase.render_autocomplete
:noindex:
.. automethod:: autocomplete_light.channel.base.ChannelBase.result_as_html
:noindex:
Then, autocomplete.js recognizes options with a selector. By default, it is
'.result'. This means that any element with the '.result' class in the
autocomplete box is considered as an option.
When an option is selected, deck.js calls it's method getValue() and adds this
value to the hidden select. Also, it will copy the result html to the deck.
When an option is removed from the deck, deck.js also removes it from the
hidden select.