Commit 547b8638 authored by Maël Kervella's avatar Maël Kervella

Commentaires et doc + retire des espaces en trop en fin de ligne

parent 12fce48e
...@@ -50,34 +50,97 @@ def bootstrap_form_typeahead(django_form, typeahead_fields, *args, **kwargs): ...@@ -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): ...@@ -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 ): ...@@ -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, ...@@ -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 ) : ...@@ -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 ) : ...@@ -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 ) : ...@@ -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 ) : ...@@ -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 ): ...@@ -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(""); ' \
......
...@@ -170,7 +170,7 @@ def new_machine(request, userid): ...@@ -170,7 +170,7 @@ def new_machine(request, userid):
messages.error(request, "Vous avez atteint le maximum d'interfaces autorisées que vous pouvez créer vous même (%s) " % max_lambdauser_interfaces) messages.error(request, "Vous avez atteint le maximum d'interfaces autorisées que vous pouvez créer vous même (%s) " % max_lambdauser_interfaces)
return redirect("/users/profil/" + str(request.user.id)) return redirect("/users/profil/" + str(request.user.id))
machine = NewMachineForm(request.POST or None) machine = NewMachineForm(request.POST or None)
interface = AddInterfaceForm(request.POST or None, infra=request.user.has_perms(('infra',))) interface = AddInterfaceForm(request.POST or None, infra=request.user.has_perms(('infra',)))
nb_machine = Interface.objects.filter(machine__user=userid).count() nb_machine = Interface.objects.filter(machine__user=userid).count()
domain = DomainForm(request.POST or None, user=user, nb_machine=nb_machine) domain = DomainForm(request.POST or None, user=user, nb_machine=nb_machine)
if machine.is_valid() and interface.is_valid(): if machine.is_valid() and interface.is_valid():
...@@ -950,7 +950,7 @@ def history(request, object, id): ...@@ -950,7 +950,7 @@ def history(request, object, id):
object_instance = Text.objects.get(pk=id) object_instance = Text.objects.get(pk=id)
except Text.DoesNotExist: except Text.DoesNotExist:
messages.error(request, "Text inexistant") messages.error(request, "Text inexistant")
return redirect("/machines/") return redirect("/machines/")
elif object == 'ns' and request.user.has_perms(('cableur',)): elif object == 'ns' and request.user.has_perms(('cableur',)):
try: try:
object_instance = Ns.objects.get(pk=id) object_instance = Ns.objects.get(pk=id)
...@@ -997,7 +997,7 @@ def history(request, object, id): ...@@ -997,7 +997,7 @@ def history(request, object, id):
@login_required @login_required
@permission_required('cableur') @permission_required('cableur')
def index_portlist(request): def index_portlist(request):
port_list = OuverturePortList.objects.all().order_by('name') port_list = OuverturePortList.objects.all().order_by('name')
return render(request, "machines/index_portlist.html", {'port_list':port_list}) return render(request, "machines/index_portlist.html", {'port_list':port_list})
@login_required @login_required
...@@ -1010,7 +1010,7 @@ def edit_portlist(request, pk): ...@@ -1010,7 +1010,7 @@ def edit_portlist(request, pk):
return redirect("/machines/index_portlist/") return redirect("/machines/index_portlist/")
port_list = EditOuverturePortListForm(request.POST or None, instance=port_list_instance) port_list = EditOuverturePortListForm(request.POST or None, instance=port_list_instance)
port_formset = modelformset_factory( port_formset = modelformset_factory(
OuverturePort, OuverturePort,
fields=('begin','end','protocole','io'), fields=('begin','end','protocole','io'),
extra=0, extra=0,
can_delete=True, can_delete=True,
...@@ -1049,7 +1049,7 @@ def del_portlist(request, pk): ...@@ -1049,7 +1049,7 @@ def del_portlist(request, pk):
def add_portlist(request): def add_portlist(request):
port_list = EditOuverturePortListForm(request.POST or None) port_list = EditOuverturePortListForm(request.POST or None)
port_formset = modelformset_factory( port_formset = modelformset_factory(
OuverturePort, OuverturePort,
fields=('begin','end','protocole','io'), fields=('begin','end','protocole','io'),
extra=0, extra=0,
can_delete=True, can_delete=True,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment