|
|
@ -50,34 +50,97 @@ def bootstrap_form_typeahead(django_form, typeahead_fields, *args, **kwargs): |
|
|
A list of field names (comma separated) that should be rendered |
|
|
A list of field names (comma separated) that should be rendered |
|
|
with typeahead instead of the default bootstrap renderer. |
|
|
with typeahead instead of the default bootstrap renderer. |
|
|
|
|
|
|
|
|
choices |
|
|
bft_param |
|
|
A string representing the choices in JS. The choices must be an |
|
|
A dict of parameters for the bootstrap_form_typeahead tag. The |
|
|
array of objects. Each of those objects must at least have the |
|
|
possible parameters are the following. |
|
|
fields 'key' (value to send) and 'value' (value to display). |
|
|
|
|
|
Other fields can be added as desired. |
|
|
choices |
|
|
If not specified, the key is the id of the object and the value |
|
|
A dict of strings representing the choices in JS. The keys of |
|
|
is its string representation as in a normal bootstrap form. |
|
|
the dict are the names of the concerned fields. The choices |
|
|
Example : |
|
|
must be an array of objects. Each of those objects must at |
|
|
choices='[{key:0,value:"choice0",extrafield:"data0"}, {...},...];' |
|
|
least have the fields 'key' (value to send) and 'value' (value |
|
|
|
|
|
to display). Other fields can be added as desired. |
|
|
match_func |
|
|
For a more complex structure you should also consider |
|
|
A string representing a valid JS function used in the dataset to |
|
|
reimplementing the engine and the match_func. |
|
|
overload the matching engine. This function is used the source of |
|
|
If not specified, the key is the id of the object and the value |
|
|
the dataset. This function receives 2 parameters, the query and |
|
|
is its string representation as in a normal bootstrap form. |
|
|
the synchronize function as specified in typeahead.js documentation. |
|
|
Example : |
|
|
If needed, the local variables 'choices' and 'engine' contains |
|
|
'choices' : { |
|
|
respectively the array of possible values and the engine to match |
|
|
'field_A':'[{key:0,value:"choice0",extra:"data0"},{...},...]', |
|
|
queries with possible values. |
|
|
'field_B':..., |
|
|
If not specified, the function used display up to the 10 first |
|
|
... |
|
|
elements if the query is empty and else the matching results. |
|
|
} |
|
|
Example : |
|
|
|
|
|
match_func='function(q, sync) { engine.search(q, sync); }' |
|
|
engine |
|
|
|
|
|
A dict of strings representating the engine used for matching |
|
|
|
|
|
queries and possible values with typeahead. The keys of the |
|
|
|
|
|
dict are the names of the concerned fields. The string is valid |
|
|
|
|
|
JS code. |
|
|
|
|
|
If not specified, BloodHound with relevant basic properties is |
|
|
|
|
|
used. |
|
|
|
|
|
Example : |
|
|
|
|
|
'engine' : {'field_A': 'new Bloodhound()', 'field_B': ..., ...} |
|
|
|
|
|
|
|
|
|
|
|
match_func |
|
|
|
|
|
A dict of strings representing a valid JS function used in the |
|
|
|
|
|
dataset to overload the matching engine. The keys of the dict |
|
|
|
|
|
are the names of the concerned fields. This function is used |
|
|
|
|
|
the source of the dataset. This function receives 2 parameters, |
|
|
|
|
|
the query and the synchronize function as specified in |
|
|
|
|
|
typeahead.js documentation. If needed, the local variables |
|
|
|
|
|
'choices_<fieldname>' and 'engine_<fieldname>' contains |
|
|
|
|
|
respectively the array of all possible values and the engine |
|
|
|
|
|
to match queries with possible values. |
|
|
|
|
|
If not specified, the function used display up to the 10 first |
|
|
|
|
|
elements if the query is empty and else the matching results. |
|
|
|
|
|
Example : |
|
|
|
|
|
'match_func' : { |
|
|
|
|
|
'field_A': 'function(q, sync) { engine.search(q, sync); }', |
|
|
|
|
|
'field_B': ..., |
|
|
|
|
|
... |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
update_on |
|
|
|
|
|
A dict of list of ids that the values depends on. The engine |
|
|
|
|
|
and the typeahead properties are recalculated and reapplied. |
|
|
|
|
|
Example : |
|
|
|
|
|
'addition' : { |
|
|
|
|
|
'field_A' : [ 'id0', 'id1', ... ] , |
|
|
|
|
|
'field_B' : ... , |
|
|
|
|
|
... |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
See boostrap_form_ for other arguments |
|
|
See boostrap_form_ for other arguments |
|
|
|
|
|
|
|
|
**Usage**:: |
|
|
**Usage**:: |
|
|
|
|
|
|
|
|
{% bootstrap_form_typeahead form ['field1[,field2[,...]]] %} |
|
|
{% bootstrap_form_typeahead |
|
|
|
|
|
form |
|
|
|
|
|
[ '<field1>[,<field2>[,...]]' ] |
|
|
|
|
|
[ { |
|
|
|
|
|
[ 'choices': { |
|
|
|
|
|
[ '<field1>': '<choices1>' |
|
|
|
|
|
[, '<field2>': '<choices2>' |
|
|
|
|
|
[, ... ] ] ] |
|
|
|
|
|
} ] |
|
|
|
|
|
[, 'engine': { |
|
|
|
|
|
[ '<field1>': '<engine1>' |
|
|
|
|
|
[, '<field2>': '<engine2>' |
|
|
|
|
|
[, ... ] ] ] |
|
|
|
|
|
} ] |
|
|
|
|
|
[, 'match_func': { |
|
|
|
|
|
[ '<field1>': '<match_func1>' |
|
|
|
|
|
[, '<field2>': '<match_func2>' |
|
|
|
|
|
[, ... ] ] ] |
|
|
|
|
|
} ] |
|
|
|
|
|
[, 'update_on': { |
|
|
|
|
|
[ '<field1>': '<update_on1>' |
|
|
|
|
|
[, '<field2>': '<update_on2>' |
|
|
|
|
|
[, ... ] ] ] |
|
|
|
|
|
} ] |
|
|
|
|
|
} ] |
|
|
|
|
|
[ <standard boostrap_form parameters> ] |
|
|
|
|
|
%} |
|
|
|
|
|
|
|
|
**Example**: |
|
|
**Example**: |
|
|
|
|
|
|
|
|
@ -133,12 +196,15 @@ def bootstrap_form_typeahead(django_form, typeahead_fields, *args, **kwargs): |
|
|
return mark_safe( form ) |
|
|
return mark_safe( form ) |
|
|
|
|
|
|
|
|
def input_id( f_name ) : |
|
|
def input_id( f_name ) : |
|
|
|
|
|
""" The id of the HTML input element """ |
|
|
return 'id_'+f_name |
|
|
return 'id_'+f_name |
|
|
|
|
|
|
|
|
def hidden_id( f_name ): |
|
|
def hidden_id( f_name ): |
|
|
|
|
|
""" The id of the HTML hidden input element """ |
|
|
return 'typeahead_hidden_'+f_name |
|
|
return 'typeahead_hidden_'+f_name |
|
|
|
|
|
|
|
|
def hidden_tag( f_bound, f_name ): |
|
|
def hidden_tag( f_bound, f_name ): |
|
|
|
|
|
""" The HTML hidden input element """ |
|
|
return render_tag( |
|
|
return render_tag( |
|
|
'input', |
|
|
'input', |
|
|
attrs={ |
|
|
attrs={ |
|
|
@ -151,6 +217,7 @@ def hidden_tag( f_bound, f_name ): |
|
|
|
|
|
|
|
|
def typeahead_js( f_name, f_value, |
|
|
def typeahead_js( f_name, f_value, |
|
|
t_choices, t_engine, t_match_func, t_update_on ) : |
|
|
t_choices, t_engine, t_match_func, t_update_on ) : |
|
|
|
|
|
""" The whole script to use """ |
|
|
|
|
|
|
|
|
choices = mark_safe(t_choices[f_name]) if f_name in t_choices.keys() \ |
|
|
choices = mark_safe(t_choices[f_name]) if f_name in t_choices.keys() \ |
|
|
else default_choices( f_value ) |
|
|
else default_choices( f_value ) |
|
|
@ -188,10 +255,12 @@ def typeahead_js( f_name, f_value, |
|
|
return render_tag( 'script', content=mark_safe( js_content ) ) |
|
|
return render_tag( 'script', content=mark_safe( js_content ) ) |
|
|
|
|
|
|
|
|
def reset_input( f_name, f_value ) : |
|
|
def reset_input( f_name, f_value ) : |
|
|
|
|
|
""" The JS script to reset the fields values """ |
|
|
return '$("#'+input_id(f_name)+'").typeahead("val","");\n' \ |
|
|
return '$("#'+input_id(f_name)+'").typeahead("val","");\n' \ |
|
|
'$("#'+hidden_id(f_name)+'").val("");' |
|
|
'$("#'+hidden_id(f_name)+'").val("");' |
|
|
|
|
|
|
|
|
def default_choices( f_value ) : |
|
|
def default_choices( f_value ) : |
|
|
|
|
|
""" The JS script creating the variable choices_<fieldname> """ |
|
|
return '[' + \ |
|
|
return '[' + \ |
|
|
', '.join([ \ |
|
|
', '.join([ \ |
|
|
'{key: ' + (str(choice[0]) if choice[0] != '' else '""') + \ |
|
|
'{key: ' + (str(choice[0]) if choice[0] != '' else '""') + \ |
|
|
@ -201,6 +270,7 @@ def default_choices( f_value ) : |
|
|
']' |
|
|
']' |
|
|
|
|
|
|
|
|
def default_engine ( f_name ) : |
|
|
def default_engine ( f_name ) : |
|
|
|
|
|
""" The JS script creating the variable engine_<field_name> """ |
|
|
return 'new Bloodhound({ ' \ |
|
|
return 'new Bloodhound({ ' \ |
|
|
'datumTokenizer: Bloodhound.tokenizers.obj.whitespace("value"), ' \ |
|
|
'datumTokenizer: Bloodhound.tokenizers.obj.whitespace("value"), ' \ |
|
|
'queryTokenizer: Bloodhound.tokenizers.whitespace, ' \ |
|
|
'queryTokenizer: Bloodhound.tokenizers.whitespace, ' \ |
|
|
@ -209,6 +279,7 @@ def default_engine ( f_name ) : |
|
|
'})' |
|
|
'})' |
|
|
|
|
|
|
|
|
def default_datasets( f_name, match_func ) : |
|
|
def default_datasets( f_name, match_func ) : |
|
|
|
|
|
""" The JS script creating the datasets to use with typeahead """ |
|
|
return '{ ' \ |
|
|
return '{ ' \ |
|
|
'hint: true, ' \ |
|
|
'hint: true, ' \ |
|
|
'highlight: true, ' \ |
|
|
'highlight: true, ' \ |
|
|
@ -221,6 +292,7 @@ def default_datasets( f_name, match_func ) : |
|
|
'}' |
|
|
'}' |
|
|
|
|
|
|
|
|
def default_match_func ( f_name ) : |
|
|
def default_match_func ( f_name ) : |
|
|
|
|
|
""" The JS script creating the matching function to use with typeahed """ |
|
|
return 'function(q, sync) {' \ |
|
|
return 'function(q, sync) {' \ |
|
|
'if (q === "") {' \ |
|
|
'if (q === "") {' \ |
|
|
'var nb = 10;' \ |
|
|
'var nb = 10;' \ |
|
|
@ -235,6 +307,8 @@ def default_match_func ( f_name ) : |
|
|
'}' |
|
|
'}' |
|
|
|
|
|
|
|
|
def typeahead_updater( f_name ): |
|
|
def typeahead_updater( f_name ): |
|
|
|
|
|
""" The JS script creating the function triggered when an item is |
|
|
|
|
|
selected through typeahead """ |
|
|
return 'function(evt, item) { ' \ |
|
|
return 'function(evt, item) { ' \ |
|
|
'$("#'+hidden_id(f_name)+'").val( item.key ); ' \ |
|
|
'$("#'+hidden_id(f_name)+'").val( item.key ); ' \ |
|
|
'$("#'+hidden_id(f_name)+'").change();' \ |
|
|
'$("#'+hidden_id(f_name)+'").change();' \ |
|
|
@ -242,6 +316,9 @@ def typeahead_updater( f_name ): |
|
|
'}' |
|
|
'}' |
|
|
|
|
|
|
|
|
def typeahead_change( f_name ): |
|
|
def typeahead_change( f_name ): |
|
|
|
|
|
""" The JS script creating the function triggered when an item is changed |
|
|
|
|
|
(i.e. looses focus and value has changed since the moment it gained focus |
|
|
|
|
|
""" |
|
|
return 'function(evt) { ' \ |
|
|
return 'function(evt) { ' \ |
|
|
'if ($("#'+input_id(f_name)+'").typeahead("val") === "") {' \ |
|
|
'if ($("#'+input_id(f_name)+'").typeahead("val") === "") {' \ |
|
|
'$("#'+hidden_id(f_name)+'").val(""); ' \ |
|
|
'$("#'+hidden_id(f_name)+'").val(""); ' \ |
|
|
|