Merge pull request #1469 from niphlod/fix/1069
fixes #1069, untangles the js, modernizes the approach
This commit is contained in:
+115
-20
@@ -657,7 +657,8 @@ class AutocompleteWidget(object):
|
|||||||
def __init__(self, request, field, id_field=None, db=None,
|
def __init__(self, request, field, id_field=None, db=None,
|
||||||
orderby=None, limitby=(0, 10), distinct=False,
|
orderby=None, limitby=(0, 10), distinct=False,
|
||||||
keyword='_autocomplete_%(tablename)s_%(fieldname)s',
|
keyword='_autocomplete_%(tablename)s_%(fieldname)s',
|
||||||
min_length=2, help_fields=None, help_string=None, at_beginning = True):
|
min_length=2, help_fields=None, help_string=None,
|
||||||
|
at_beginning=True, default_var='ac'):
|
||||||
|
|
||||||
self.help_fields = help_fields or []
|
self.help_fields = help_fields or []
|
||||||
self.help_string = help_string
|
self.help_string = help_string
|
||||||
@@ -680,7 +681,9 @@ class AutocompleteWidget(object):
|
|||||||
else:
|
else:
|
||||||
self.is_reference = False
|
self.is_reference = False
|
||||||
if hasattr(request, 'application'):
|
if hasattr(request, 'application'):
|
||||||
self.url = URL(args=request.args)
|
urlvars = request.vars
|
||||||
|
urlvars[default_var] = 1
|
||||||
|
self.url = URL(args=request.args, vars=urlvars)
|
||||||
self.callback()
|
self.callback()
|
||||||
else:
|
else:
|
||||||
self.url = request
|
self.url = request
|
||||||
@@ -688,35 +691,55 @@ class AutocompleteWidget(object):
|
|||||||
def callback(self):
|
def callback(self):
|
||||||
if self.keyword in self.request.vars:
|
if self.keyword in self.request.vars:
|
||||||
field = self.fields[0]
|
field = self.fields[0]
|
||||||
|
kword = self.request.vars[self.keyword]
|
||||||
if isinstance(field, Field.Virtual):
|
if isinstance(field, Field.Virtual):
|
||||||
records = []
|
records = []
|
||||||
table_rows = self.db(self.db[field.tablename]).select(orderby=self.orderby)
|
table_rows = self.db(self.db[field.tablename]).select(orderby=self.orderby)
|
||||||
count = 0
|
count = 0
|
||||||
for row in table_rows:
|
for row in table_rows:
|
||||||
if self.at_beginning:
|
if self.at_beginning:
|
||||||
if row[field.name].lower().startswith(self.request.vars[self.keyword]):
|
if row[field.name].lower().startswith(kword):
|
||||||
count += 1
|
count += 1
|
||||||
records.append(row)
|
records.append(row)
|
||||||
else:
|
else:
|
||||||
if self.request.vars[self.keyword] in row[field.name].lower():
|
if kword in row[field.name].lower():
|
||||||
count += 1
|
count += 1
|
||||||
records.append(row)
|
records.append(row)
|
||||||
if count == 10:
|
if count == 10:
|
||||||
break
|
break
|
||||||
rows = Rows(self.db, records, table_rows.colnames, compact=table_rows.compact)
|
rows = Rows(self.db, records, table_rows.colnames,
|
||||||
|
compact=table_rows.compact)
|
||||||
elif settings and settings.global_settings.web2py_runtime_gae:
|
elif settings and settings.global_settings.web2py_runtime_gae:
|
||||||
rows = self.db(field.__ge__(self.request.vars[self.keyword]) & field.__lt__(self.request.vars[self.keyword] + u'\ufffd')).select(orderby=self.orderby, limitby=self.limitby, *(self.fields+self.help_fields))
|
rows = self.db(field.__ge__(kword) &
|
||||||
|
field.__lt__(kword + u'\ufffd')
|
||||||
|
).select(orderby=self.orderby,
|
||||||
|
limitby=self.limitby,
|
||||||
|
*(self.fields + self.help_fields))
|
||||||
elif self.at_beginning:
|
elif self.at_beginning:
|
||||||
rows = self.db(field.like(self.request.vars[self.keyword] + '%', case_sensitive=False)).select(orderby=self.orderby, limitby=self.limitby, distinct=self.distinct, *(self.fields+self.help_fields))
|
rows = self.db(field.like(kword + '%', case_sensitive=False)
|
||||||
|
).select(orderby=self.orderby,
|
||||||
|
limitby=self.limitby,
|
||||||
|
distinct=self.distinct,
|
||||||
|
*(self.fields + self.help_fields))
|
||||||
else:
|
else:
|
||||||
rows = self.db(field.contains(self.request.vars[self.keyword], case_sensitive=False)).select(orderby=self.orderby, limitby=self.limitby, distinct=self.distinct, *(self.fields+self.help_fields))
|
rows = self.db(field.contains(kword, case_sensitive=False)
|
||||||
|
).select(orderby=self.orderby,
|
||||||
|
limitby=self.limitby,
|
||||||
|
distinct=self.distinct,
|
||||||
|
*(self.fields + self.help_fields))
|
||||||
if rows:
|
if rows:
|
||||||
if self.is_reference:
|
if self.is_reference:
|
||||||
id_field = self.fields[1]
|
id_field = self.fields[1]
|
||||||
if self.help_fields:
|
if self.help_fields:
|
||||||
options = [OPTION(
|
options = [
|
||||||
self.help_string % dict([(h.name, s[h.name]) for h in self.fields[:1] + self.help_fields]),
|
OPTION(
|
||||||
_value=s[id_field.name], _selected=(k == 0)) for k, s in enumerate(rows)]
|
self.help_string % dict(
|
||||||
|
[(h.name, s[h.name]) for h
|
||||||
|
in self.fields[:1] + self.help_fields]),
|
||||||
|
_value=s[id_field.name],
|
||||||
|
_selected=(k == 0))
|
||||||
|
for k, s in enumerate(rows)
|
||||||
|
]
|
||||||
else:
|
else:
|
||||||
options = [OPTION(
|
options = [OPTION(
|
||||||
s[field.name], _value=s[id_field.name],
|
s[field.name], _value=s[id_field.name],
|
||||||
@@ -763,28 +786,100 @@ class AutocompleteWidget(object):
|
|||||||
record = self.db(
|
record = self.db(
|
||||||
self.fields[1] == value).select(self.fields[0]).first()
|
self.fields[1] == value).select(self.fields[0]).first()
|
||||||
attr['value'] = record and record[self.fields[0].name]
|
attr['value'] = record and record[self.fields[0].name]
|
||||||
attr['_onblur'] = "jQuery('#%(div_id)s').delay(1000).fadeOut('slow');" % \
|
attr['_onblur'] = "jQuery('#%(div_id)s').delay(500).fadeOut('slow');" % \
|
||||||
dict(div_id=div_id, u='F' + self.keyword)
|
dict(div_id=div_id, u='F' + self.keyword)
|
||||||
attr['_onkeyup'] = "jQuery('#%(key3)s').val('');var e=event.which?event.which:event.keyCode; function %(u)s(){jQuery('#%(id)s').val(jQuery('#%(key)s :selected').text());jQuery('#%(key3)s').val(jQuery('#%(key)s').val())}; if(e==39) %(u)s(); else if(e==40) {if(jQuery('#%(key)s option:selected').next().length)jQuery('#%(key)s option:selected').attr('selected',null).next().attr('selected','selected'); %(u)s();} else if(e==38) {if(jQuery('#%(key)s option:selected').prev().length)jQuery('#%(key)s option:selected').attr('selected',null).prev().attr('selected','selected'); %(u)s();} else if(jQuery('#%(id)s').val().length>=%(min_length)s) jQuery.get('%(url)s?%(key)s='+encodeURIComponent(jQuery('#%(id)s').val()),function(data){if(data=='')jQuery('#%(key3)s').val('');else{jQuery('#%(id)s').next('.error').hide();jQuery('#%(div_id)s').html(data).show().focus();jQuery('#%(div_id)s select').css('width',jQuery('#%(id)s').css('width'));jQuery('#%(key3)s').val(jQuery('#%(key)s').val());jQuery('#%(key)s').change(%(u)s);jQuery('#%(key)s').click(%(u)s);};}); else jQuery('#%(div_id)s').fadeOut('slow');" % \
|
js = """
|
||||||
|
(function($) {
|
||||||
|
function doit(e_) {
|
||||||
|
$('#%(key3)s').val('');
|
||||||
|
var e=e_.which?e_.which:e_.keyCode;
|
||||||
|
function %(u)s(){
|
||||||
|
$('#%(id)s').val($('#%(key)s :selected').text());
|
||||||
|
$('#%(key3)s').val($('#%(key)s').val())
|
||||||
|
};
|
||||||
|
if(e==39) %(u)s();
|
||||||
|
else if(e==40) {
|
||||||
|
if($('#%(key)s option:selected').next().length)
|
||||||
|
$('#%(key)s option:selected').attr('selected',null).next().attr('selected','selected');
|
||||||
|
%(u)s();
|
||||||
|
}
|
||||||
|
else if(e==38) {
|
||||||
|
if($('#%(key)s option:selected').prev().length)
|
||||||
|
$('#%(key)s option:selected').attr('selected',null).prev().attr('selected','selected');
|
||||||
|
%(u)s();
|
||||||
|
}
|
||||||
|
else if($('#%(id)s').val().length>=%(min_length)s)
|
||||||
|
$.get('%(url)s&%(key)s='+encodeURIComponent($('#%(id)s').val()),
|
||||||
|
function(data){
|
||||||
|
if(data=='')$('#%(key3)s').val('');
|
||||||
|
else{
|
||||||
|
$('#%(id)s').next('.error').hide();
|
||||||
|
$('#%(div_id)s').html(data).show().focus();
|
||||||
|
$('#%(div_id)s select').css('width',$('#%(id)s').css('width'));
|
||||||
|
$('#%(key3)s').val($('#%(key)s').val());
|
||||||
|
$('#%(key)s').change(%(u)s).click(%(u)s);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
else $('#%(div_id)s').fadeOut('slow');
|
||||||
|
}
|
||||||
|
var tmr = null;
|
||||||
|
$("#%(id)s").on('keyup focus',function(e) {
|
||||||
|
if (tmr) clearTimeout(tmr);
|
||||||
|
if($('#%(id)s').val().length>=%(min_length)s) {
|
||||||
|
tmr = setTimeout(function() { tmr = null; doit(e); }, 300);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})(jQuery)""".replace('\n', '').replace(' ' * 4, '') % \
|
||||||
dict(url=self.url, min_length=self.min_length,
|
dict(url=self.url, min_length=self.min_length,
|
||||||
key=self.keyword, id=attr['_id'], key2=key2, key3=key3,
|
key=self.keyword, id=attr['_id'], key2=key2, key3=key3,
|
||||||
name=name, div_id=div_id, u='F' + self.keyword)
|
name=name, div_id=div_id, u='F' + self.keyword)
|
||||||
if self.min_length == 0:
|
|
||||||
attr['_onfocus'] = attr['_onkeyup']
|
|
||||||
return CAT(INPUT(**attr),
|
return CAT(INPUT(**attr),
|
||||||
INPUT(_type='hidden', _id=key3, _value=value,
|
INPUT(_type='hidden', _id=key3, _value=value,
|
||||||
_name=name, requires=field.requires),
|
_name=name, requires=field.requires),
|
||||||
|
SCRIPT(js),
|
||||||
DIV(_id=div_id, _style='position:absolute;'))
|
DIV(_id=div_id, _style='position:absolute;'))
|
||||||
else:
|
else:
|
||||||
attr['_name'] = field.name
|
attr['_name'] = field.name
|
||||||
attr['_onblur'] = "jQuery('#%(div_id)s').delay(1000).fadeOut('slow');" % \
|
attr['_onblur'] = "jQuery('#%(div_id)s').delay(500).fadeOut('slow');" % \
|
||||||
dict(div_id=div_id, u='F' + self.keyword)
|
dict(div_id=div_id, u='F' + self.keyword)
|
||||||
attr['_onkeyup'] = "var e=event.which?event.which:event.keyCode; function %(u)s(){jQuery('#%(id)s').val(jQuery('#%(key)s').val())}; if(e==39) %(u)s(); else if(e==40) {if(jQuery('#%(key)s option:selected').next().length)jQuery('#%(key)s option:selected').attr('selected',null).next().attr('selected','selected'); %(u)s();} else if(e==38) {if(jQuery('#%(key)s option:selected').prev().length)jQuery('#%(key)s option:selected').attr('selected',null).prev().attr('selected','selected'); %(u)s();} else if(jQuery('#%(id)s').val().length>=%(min_length)s) jQuery.get('%(url)s?%(key)s='+encodeURIComponent(jQuery('#%(id)s').val()),function(data){jQuery('#%(id)s').next('.error').hide();jQuery('#%(div_id)s').html(data).show().focus();jQuery('#%(div_id)s select').css('width',jQuery('#%(id)s').css('width'));jQuery('#%(key)s').change(%(u)s);jQuery('#%(key)s').click(%(u)s);}); else jQuery('#%(div_id)s').fadeOut('slow');" % \
|
js = """
|
||||||
|
(function($) {
|
||||||
|
function doit(e_) {
|
||||||
|
var e=e_.which?e_.which:e_.keyCode;
|
||||||
|
function %(u)s(){
|
||||||
|
$('#%(id)s').val($('#%(key)s').val())
|
||||||
|
};
|
||||||
|
if(e==39) %(u)s();
|
||||||
|
else if(e==40) {
|
||||||
|
if($('#%(key)s option:selected').next().length)
|
||||||
|
$('#%(key)s option:selected').attr('selected',null).next().attr('selected','selected');
|
||||||
|
%(u)s();
|
||||||
|
} else if(e==38) {
|
||||||
|
if($('#%(key)s option:selected').prev().length)
|
||||||
|
$('#%(key)s option:selected').attr('selected',null).prev().attr('selected','selected');
|
||||||
|
%(u)s();
|
||||||
|
} else if($('#%(id)s').val().length>=%(min_length)s)
|
||||||
|
$.get('%(url)s&%(key)s='+encodeURIComponent($('#%(id)s').val()),
|
||||||
|
function(data){
|
||||||
|
$('#%(id)s').next('.error').hide();
|
||||||
|
$('#%(div_id)s').html(data).show().focus();
|
||||||
|
$('#%(div_id)s select').css('width',$('#%(id)s').css('width'));
|
||||||
|
$('#%(key)s').change(%(u)s).click(%(u)s);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
else $('#%(div_id)s').fadeOut('slow');
|
||||||
|
}
|
||||||
|
var tmr = null;
|
||||||
|
$("#%(id)s").on('keyup focus',function(e) {
|
||||||
|
if (tmr) clearTimeout(tmr);
|
||||||
|
if($('#%(id)s').val().length>=%(min_length)s) {
|
||||||
|
tmr = setTimeout(function() { tmr = null; doit(e); }, 300);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})(jQuery)""".replace('\n', '').replace(' ' * 4, '') % \
|
||||||
dict(url=self.url, min_length=self.min_length,
|
dict(url=self.url, min_length=self.min_length,
|
||||||
key=self.keyword, id=attr['_id'], div_id=div_id, u='F' + self.keyword)
|
key=self.keyword, id=attr['_id'], div_id=div_id, u='F' + self.keyword)
|
||||||
if self.min_length == 0:
|
return CAT(INPUT(**attr), SCRIPT(js),
|
||||||
attr['_onfocus'] = attr['_onkeyup']
|
|
||||||
return CAT(INPUT(**attr),
|
|
||||||
DIV(_id=div_id, _style='position:absolute;'))
|
DIV(_id=div_id, _style='position:absolute;'))
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user