mirror of
https://gitlab2.federez.net/re2o/re2o
synced 2024-11-22 11:23:10 +00:00
Valable sans JS
This commit is contained in:
parent
b89fb3f580
commit
919537f278
2 changed files with 211 additions and 103 deletions
|
@ -129,11 +129,13 @@ def generate_ipv4_mbf_param( form, is_type_tt ):
|
||||||
i_engine = { 'ipv4': generate_ipv4_engine( is_type_tt ) }
|
i_engine = { 'ipv4': generate_ipv4_engine( is_type_tt ) }
|
||||||
i_match_func = { 'ipv4': generate_ipv4_match_func( is_type_tt ) }
|
i_match_func = { 'ipv4': generate_ipv4_match_func( is_type_tt ) }
|
||||||
i_update_on = { 'ipv4': [f_type_id( is_type_tt )] }
|
i_update_on = { 'ipv4': [f_type_id( is_type_tt )] }
|
||||||
|
i_gen_select = { 'ipv4': False }
|
||||||
i_mbf_param = {
|
i_mbf_param = {
|
||||||
'choices': i_choices,
|
'choices': i_choices,
|
||||||
'engine': i_engine,
|
'engine': i_engine,
|
||||||
'match_func': i_match_func,
|
'match_func': i_match_func,
|
||||||
'update_on': i_update_on
|
'update_on': i_update_on,
|
||||||
|
'gen_select': i_gen_select
|
||||||
}
|
}
|
||||||
return i_mbf_param
|
return i_mbf_param
|
||||||
|
|
||||||
|
|
|
@ -113,12 +113,29 @@ def massive_bootstrap_form(form, mbf_fields, *args, **kwargs):
|
||||||
A dict of list of ids that the values depends on. The engine
|
A dict of list of ids that the values depends on. The engine
|
||||||
and the typeahead properties are recalculated and reapplied.
|
and the typeahead properties are recalculated and reapplied.
|
||||||
Example :
|
Example :
|
||||||
'addition' : {
|
'update_on' : {
|
||||||
'field_A' : [ 'id0', 'id1', ... ] ,
|
'field_A' : [ 'id0', 'id1', ... ] ,
|
||||||
'field_B' : ... ,
|
'field_B' : ... ,
|
||||||
...
|
...
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gen_select (optional)
|
||||||
|
A dict of boolean telling if the form should either generate
|
||||||
|
the normal select (set to true) and then use it to generate
|
||||||
|
the possible choices and then remove it or either (set to
|
||||||
|
false) generate the choices variable in this tag and do not
|
||||||
|
send any select.
|
||||||
|
Sending the select before can be usefull to permit the use
|
||||||
|
without any JS enabled but it will execute more code locally
|
||||||
|
for the client so the loading might be slower.
|
||||||
|
If not specified, this variable is set to true for each field
|
||||||
|
Example :
|
||||||
|
'gen_select' : {
|
||||||
|
'field_A': True ,
|
||||||
|
'field_B': ... ,
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
See boostrap_form_ for other arguments
|
See boostrap_form_ for other arguments
|
||||||
|
|
||||||
**Usage**::
|
**Usage**::
|
||||||
|
@ -146,6 +163,11 @@ def massive_bootstrap_form(form, mbf_fields, *args, **kwargs):
|
||||||
[ '<field1>': '<update_on1>'
|
[ '<field1>': '<update_on1>'
|
||||||
[, '<field2>': '<update_on2>'
|
[, '<field2>': '<update_on2>'
|
||||||
[, ... ] ] ]
|
[, ... ] ] ]
|
||||||
|
} ],
|
||||||
|
[, 'gen_select': {
|
||||||
|
[ '<field1>': '<gen_select1>'
|
||||||
|
[, '<field2>': '<gen_select2>'
|
||||||
|
[, ... ] ] ]
|
||||||
} ]
|
} ]
|
||||||
} ]
|
} ]
|
||||||
[ <standard boostrap_form parameters> ]
|
[ <standard boostrap_form parameters> ]
|
||||||
|
@ -163,6 +185,7 @@ def massive_bootstrap_form(form, mbf_fields, *args, **kwargs):
|
||||||
engine = param.get('engine', {})
|
engine = param.get('engine', {})
|
||||||
match_func = param.get('match_func', {})
|
match_func = param.get('match_func', {})
|
||||||
update_on = param.get('update_on', {})
|
update_on = param.get('update_on', {})
|
||||||
|
gen_select = param.get('gen_select', {})
|
||||||
hidden_fields = [h.name for h in form.hidden_fields()]
|
hidden_fields = [h.name for h in form.hidden_fields()]
|
||||||
|
|
||||||
html = ''
|
html = ''
|
||||||
|
@ -184,40 +207,43 @@ def massive_bootstrap_form(form, mbf_fields, *args, **kwargs):
|
||||||
multiple = f_value.widget.allow_multiple_selected
|
multiple = f_value.widget.allow_multiple_selected
|
||||||
f_bound = f_value.get_bound_field( form, f_name )
|
f_bound = f_value.get_bound_field( form, f_name )
|
||||||
|
|
||||||
|
if gen_select.get(f_name, True) :
|
||||||
|
html += render_field(
|
||||||
|
f_bound,
|
||||||
|
*args,
|
||||||
|
**kwargs
|
||||||
|
)
|
||||||
|
|
||||||
f_value.widget = TextInput(
|
f_value.widget = TextInput(
|
||||||
attrs = {
|
attrs = {
|
||||||
'name': 'mbf_'+f_name,
|
'name': 'mbf_'+f_name,
|
||||||
'placeholder': f_value.empty_label
|
'placeholder': f_value.empty_label
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
html += render_field(
|
replace_input = render_field(
|
||||||
f_value.get_bound_field( form, f_name ),
|
f_value.get_bound_field( form, f_name ),
|
||||||
*args,
|
*args,
|
||||||
**kwargs
|
**kwargs
|
||||||
)
|
)
|
||||||
|
|
||||||
if multiple :
|
if not gen_select.get(f_name, True) :
|
||||||
content = mbf_js(
|
html += replace_input
|
||||||
f_name,
|
|
||||||
f_value,
|
content = mbf_js(
|
||||||
f_bound,
|
f_name,
|
||||||
multiple,
|
f_value,
|
||||||
choices,
|
f_bound,
|
||||||
engine,
|
multiple,
|
||||||
match_func,
|
replace_input,
|
||||||
update_on
|
choices,
|
||||||
)
|
engine,
|
||||||
else :
|
match_func,
|
||||||
content = hidden_tag( f_bound, f_name ) + mbf_js(
|
update_on,
|
||||||
f_name,
|
gen_select
|
||||||
f_value,
|
)
|
||||||
f_bound,
|
if not multiple and not gen_select.get(f_name, True) :
|
||||||
multiple,
|
content += hidden_tag( f_bound, f_name )
|
||||||
choices,
|
|
||||||
engine,
|
|
||||||
match_func,
|
|
||||||
update_on
|
|
||||||
)
|
|
||||||
html += render_tag(
|
html += render_tag(
|
||||||
'div',
|
'div',
|
||||||
content = content,
|
content = content,
|
||||||
|
@ -257,12 +283,14 @@ def hidden_tag( f_bound, f_name ):
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
def mbf_js( f_name, f_value, f_bound, multiple,
|
def mbf_js( f_name, f_value, f_bound, multiple, replace_input,
|
||||||
choices_, engine_, match_func_, update_on_ ) :
|
choices_, engine_, match_func_, update_on_, gen_select_ ) :
|
||||||
""" The whole script to use """
|
""" The whole script to use """
|
||||||
|
|
||||||
|
gen_select = gen_select_.get( f_name, True )
|
||||||
|
|
||||||
choices = ( mark_safe( choices_[f_name] ) if f_name in choices_.keys()
|
choices = ( mark_safe( choices_[f_name] ) if f_name in choices_.keys()
|
||||||
else default_choices( f_value ) )
|
else default_choices( f_value, f_bound, gen_select ) )
|
||||||
|
|
||||||
engine = ( mark_safe( engine_[f_name] ) if f_name in engine_.keys()
|
engine = ( mark_safe( engine_[f_name] ) if f_name in engine_.keys()
|
||||||
else default_engine ( f_name ) )
|
else default_engine ( f_name ) )
|
||||||
|
@ -272,82 +300,120 @@ def mbf_js( f_name, f_value, f_bound, multiple,
|
||||||
|
|
||||||
update_on = update_on_[f_name] if f_name in update_on_.keys() else []
|
update_on = update_on_[f_name] if f_name in update_on_.keys() else []
|
||||||
|
|
||||||
if multiple :
|
if gen_select :
|
||||||
js_content = (
|
if multiple :
|
||||||
'var choices_{f_name} = {choices};'
|
js_content = (
|
||||||
'var engine_{f_name};'
|
'$( "#{input_id}" ).ready( function() {{'
|
||||||
'var setup_{f_name} = function() {{'
|
'var choices_{f_name} = {choices};'
|
||||||
'engine_{f_name} = {engine};'
|
'{del_select}'
|
||||||
'$( "#{input_id}" ).tokenfield( "destroy" );'
|
'var engine_{f_name};'
|
||||||
'$( "#{input_id}" ).tokenfield({{typeahead: [ {datasets} ] }});'
|
'var setup_{f_name} = function() {{'
|
||||||
'}};'
|
'engine_{f_name} = {engine};'
|
||||||
'$( "#{input_id}" ).bind( "tokenfield:createtoken", {create} );'
|
'$( "#{input_id}" ).tokenfield( "destroy" );'
|
||||||
'$( "#{input_id}" ).bind( "tokenfield:edittoken", {edit} );'
|
'$( "#{input_id}" ).tokenfield({{typeahead: [ {datasets} ] }});'
|
||||||
'$( "#{input_id}" ).bind( "tokenfield:removetoken", {remove} );'
|
'}};'
|
||||||
'{updates}'
|
'$( "#{input_id}" ).bind( "tokenfield:createtoken", {tok_create} );'
|
||||||
'$( "#{input_id}" ).ready( function() {{'
|
'$( "#{input_id}" ).bind( "tokenfield:edittoken", {tok_edit} );'
|
||||||
'setup_{f_name}();'
|
'$( "#{input_id}" ).bind( "tokenfield:removetoken", {tok_remove} );'
|
||||||
'{init_input}'
|
'{tok_updates}'
|
||||||
'}} );'
|
'setup_{f_name}();'
|
||||||
).format(
|
'{tok_init_input}'
|
||||||
f_name = f_name,
|
'}} );'
|
||||||
choices = choices,
|
)
|
||||||
engine = engine,
|
else :
|
||||||
input_id = input_id( f_bound ),
|
js_content = (
|
||||||
datasets = default_datasets( f_name, match_func ),
|
'$( "#{input_id}" ).ready( function() {{'
|
||||||
create = tokenfield_create( f_name, f_bound ),
|
'var choices_{f_name} = {choices};'
|
||||||
edit = tokenfield_edit( f_name, f_bound ),
|
'{del_select}'
|
||||||
remove = tokenfield_remove( f_name, f_bound ),
|
'{gen_hidden}'
|
||||||
updates = ''.join( [ (
|
'var engine_{f_name};'
|
||||||
'$( "#{u_id}" ).change( function() {{'
|
'var setup_{f_name} = function() {{'
|
||||||
'setup_{f_name}();'
|
'engine_{f_name} = {engine};'
|
||||||
'{reset_input}'
|
'$( "#{input_id}" ).typeahead( "destroy" );'
|
||||||
'}} );'
|
'$( "#{input_id}" ).typeahead( {datasets} );'
|
||||||
).format(
|
'}};'
|
||||||
u_id = u_id,
|
'$( "#{input_id}" ).bind( "typeahead:select", {typ_select} );'
|
||||||
reset_input = tokenfield_reset_input( f_bound ),
|
'$( "#{input_id}" ).bind( "typeahead:change", {typ_change} );'
|
||||||
f_name = f_name
|
'{typ_updates}'
|
||||||
) for u_id in update_on ]
|
'setup_{f_name}();'
|
||||||
),
|
'{typ_init_input}'
|
||||||
init_input = tokenfield_init_input( f_name, f_bound ),
|
'}} );'
|
||||||
)
|
)
|
||||||
else :
|
else :
|
||||||
js_content = (
|
if multiple :
|
||||||
'var choices_{f_name} = {choices};'
|
js_content = (
|
||||||
'var engine_{f_name};'
|
'var choices_{f_name} = {choices};'
|
||||||
'var setup_{f_name} = function() {{'
|
'var engine_{f_name};'
|
||||||
'engine_{f_name} = {engine};'
|
'var setup_{f_name} = function() {{'
|
||||||
'$( "#{input_id}" ).typeahead( "destroy" );'
|
'engine_{f_name} = {engine};'
|
||||||
'$( "#{input_id}" ).typeahead( {datasets} );'
|
'$( "#{input_id}" ).tokenfield( "destroy" );'
|
||||||
'}};'
|
'$( "#{input_id}" ).tokenfield({{typeahead: [ {datasets} ] }});'
|
||||||
'$( "#{input_id}" ).bind( "typeahead:select", {select} );'
|
'}};'
|
||||||
'$( "#{input_id}" ).bind( "typeahead:change", {change} );'
|
'$( "#{input_id}" ).bind( "tokenfield:createtoken", {tok_create} );'
|
||||||
'{updates}'
|
'$( "#{input_id}" ).bind( "tokenfield:edittoken", {tok_edit} );'
|
||||||
'$( "#{input_id}" ).ready( function() {{'
|
'$( "#{input_id}" ).bind( "tokenfield:removetoken", {tok_remove} );'
|
||||||
'setup_{f_name}();'
|
'{tok_updates}'
|
||||||
'{init_input}'
|
'$( "#{input_id}" ).ready( function() {{'
|
||||||
'}} );'
|
'setup_{f_name}();'
|
||||||
).format(
|
'{tok_init_input}'
|
||||||
f_name = f_name,
|
'}} );'
|
||||||
choices = choices,
|
|
||||||
engine = engine,
|
|
||||||
input_id = input_id( f_bound ),
|
|
||||||
datasets = default_datasets( f_name, match_func ),
|
|
||||||
select = typeahead_select( f_bound ),
|
|
||||||
change = typeahead_change( f_bound ),
|
|
||||||
updates = ''.join( [ (
|
|
||||||
'$( "#{u_id}" ).change( function() {{'
|
|
||||||
'setup_{f_name}();'
|
|
||||||
'{reset_input}'
|
|
||||||
'}} );'
|
|
||||||
).format(
|
|
||||||
u_id = u_id,
|
|
||||||
reset_input = typeahead_reset_input( f_bound ),
|
|
||||||
f_name = f_name
|
|
||||||
) for u_id in update_on ]
|
|
||||||
),
|
|
||||||
init_input = typeahead_init_input( f_name, f_bound ),
|
|
||||||
)
|
)
|
||||||
|
else :
|
||||||
|
js_content = (
|
||||||
|
'var choices_{f_name} = {choices};'
|
||||||
|
'var engine_{f_name};'
|
||||||
|
'var setup_{f_name} = function() {{'
|
||||||
|
'engine_{f_name} = {engine};'
|
||||||
|
'$( "#{input_id}" ).typeahead( "destroy" );'
|
||||||
|
'$( "#{input_id}" ).typeahead( {datasets} );'
|
||||||
|
'}};'
|
||||||
|
'$( "#{input_id}" ).bind( "typeahead:select", {typ_select} );'
|
||||||
|
'$( "#{input_id}" ).bind( "typeahead:change", {typ_change} );'
|
||||||
|
'{typ_updates}'
|
||||||
|
'$( "#{input_id}" ).ready( function() {{'
|
||||||
|
'setup_{f_name}();'
|
||||||
|
'{typ_init_input}'
|
||||||
|
'}} );'
|
||||||
|
)
|
||||||
|
|
||||||
|
js_content = js_content.format(
|
||||||
|
f_name = f_name,
|
||||||
|
choices = choices,
|
||||||
|
del_select = del_select( f_bound, replace_input ),
|
||||||
|
gen_hidden = gen_hidden( f_bound ),
|
||||||
|
engine = engine,
|
||||||
|
input_id = input_id( f_bound ),
|
||||||
|
datasets = default_datasets( f_name, match_func ),
|
||||||
|
typ_select = typeahead_select( f_bound ),
|
||||||
|
typ_change = typeahead_change( f_bound ),
|
||||||
|
tok_create = tokenfield_create( f_name, f_bound ),
|
||||||
|
tok_edit = tokenfield_edit( f_name, f_bound ),
|
||||||
|
tok_remove = tokenfield_remove( f_name, f_bound ),
|
||||||
|
typ_updates = ''.join( [ (
|
||||||
|
'$( "#{u_id}" ).change( function() {{'
|
||||||
|
'setup_{f_name}();'
|
||||||
|
'{reset_input}'
|
||||||
|
'}} );'
|
||||||
|
).format(
|
||||||
|
u_id = u_id,
|
||||||
|
reset_input = typeahead_reset_input( f_bound ),
|
||||||
|
f_name = f_name
|
||||||
|
) for u_id in update_on ]
|
||||||
|
),
|
||||||
|
tok_updates = ''.join( [ (
|
||||||
|
'$( "#{u_id}" ).change( function() {{'
|
||||||
|
'setup_{f_name}();'
|
||||||
|
'{reset_input}'
|
||||||
|
'}} );'
|
||||||
|
).format(
|
||||||
|
u_id = u_id,
|
||||||
|
reset_input = tokenfield_reset_input( f_bound ),
|
||||||
|
f_name = f_name
|
||||||
|
) for u_id in update_on ]
|
||||||
|
),
|
||||||
|
tok_init_input = tokenfield_init_input( f_name, f_bound ),
|
||||||
|
typ_init_input = typeahead_init_input( f_name, f_bound ),
|
||||||
|
)
|
||||||
|
|
||||||
return render_tag( 'script', content=mark_safe( js_content ) )
|
return render_tag( 'script', content=mark_safe( js_content ) )
|
||||||
|
|
||||||
|
@ -403,9 +469,21 @@ def tokenfield_reset_input( f_bound ) :
|
||||||
input_id = input_id( f_bound ),
|
input_id = input_id( f_bound ),
|
||||||
)
|
)
|
||||||
|
|
||||||
def default_choices( f_value ) :
|
def default_choices( f_value, f_bound, gen_select ) :
|
||||||
""" The JS script creating the variable choices_<fieldname> """
|
""" The JS script creating the variable choices_<fieldname> """
|
||||||
return '[{objects}]'.format(
|
if gen_select :
|
||||||
|
c = ( 'function plop(o) {{'
|
||||||
|
'var c = [];'
|
||||||
|
'for( let i=0 ; i<o.length ; i++) {{'
|
||||||
|
'c.push( {{ key: o[i].value, value :o[i].text }} );'
|
||||||
|
'}}'
|
||||||
|
'return c;'
|
||||||
|
'}} ($("#{select_id}")[0].options)'
|
||||||
|
).format (
|
||||||
|
select_id = input_id( f_bound )
|
||||||
|
)
|
||||||
|
else :
|
||||||
|
c = '[{objects}]'.format(
|
||||||
objects = ','.join(
|
objects = ','.join(
|
||||||
[ '{{key:{k},value:"{v}"}}'.format(
|
[ '{{key:{k},value:"{v}"}}'.format(
|
||||||
k = choice[0] if choice[0] != '' else '""',
|
k = choice[0] if choice[0] != '' else '""',
|
||||||
|
@ -414,6 +492,34 @@ def default_choices( f_value ) :
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
return c
|
||||||
|
|
||||||
|
def del_select( f_bound, replace_input ) :
|
||||||
|
""" The JS script to delete the select if it has been generated
|
||||||
|
and replace it with an input. """
|
||||||
|
return ( 'var p = $("#{select_id}").parent()[0];'
|
||||||
|
'var new_input = `{replace_input}`;'
|
||||||
|
'p.innerHTML = new_input;'
|
||||||
|
).format(
|
||||||
|
select_id = input_id( f_bound ),
|
||||||
|
replace_input = replace_input
|
||||||
|
)
|
||||||
|
|
||||||
|
def gen_hidden( f_bound ):
|
||||||
|
""" The JS script to add a hidden tag to store the value. """
|
||||||
|
return ( 'var d = $("#{custom_div_id}")[0];'
|
||||||
|
'var i = document.createElement("input");'
|
||||||
|
'i.id = "{hidden_id}";'
|
||||||
|
'i.name = "{name}";'
|
||||||
|
'i.value = "";'
|
||||||
|
'i.type = "hidden";'
|
||||||
|
'd.appendChild(i);'
|
||||||
|
).format(
|
||||||
|
custom_div_id = custom_div_id( f_bound ),
|
||||||
|
hidden_id = hidden_id( f_bound ),
|
||||||
|
name = f_bound.html_name
|
||||||
|
)
|
||||||
|
|
||||||
def default_engine ( f_name ) :
|
def default_engine ( f_name ) :
|
||||||
""" The JS script creating the variable engine_<field_name> """
|
""" The JS script creating the variable engine_<field_name> """
|
||||||
return (
|
return (
|
||||||
|
|
Loading…
Reference in a new issue