The commented lines in the class was there because I recently refactor it to make it use boostrap modal instead of jquery ui dialog as you may understand carefully reading the code!!
:-P Richard On Mon, May 11, 2015 at 2:40 PM, LoveWeb2py <[email protected]> wrote: > Are the commented lines necessary or was that for self reference? > > # js += '$("#%s_option_add_trigger"). > click(function() {' \ > # ' $("#%s_dialog-form").dialog("open");' \ > # ' return false;' \ > # ' }); ' % (my_select_id, my_select_id) > > > > On Thursday, May 7, 2015 at 9:33:28 AM UTC-4, Richard wrote: >> >> you need bootstrap 2.3.2 (not tested with BS3, but I am pretty sure it is >> not working, too differents)... >> >> Did you try it with a recent web2py setup? I would suggest you try with >> web2py 2.9.5 which is what I use actually and it works... >> >> Richard >> >> On Thu, May 7, 2015 at 9:20 AM, LoveWeb2py <[email protected]> wrote: >> >>> Another observation: >>> >>> All of this code: >>> >>> >>> >>>> js += '$(function() {' \ >>>> ' $("#%s_option_add_trigger").button({' \ >>>> ' text: true,' \ >>>> ' icons: {' \ >>>> ' primary: "ui-icon-circle-plus"' \ >>>> ' }' \ >>>> ' });' \ >>>> '});' % (my_select_id) >>>> js += '$(function() { ' \ >>>> ' $( "#%s_option_add_trigger" ).css("margin-left", >>>> "+=5"); ' \ >>>> '});' % (my_select_id) >>>> js += >>>> '$("#{modal_id}").appendTo("body");'.format(modal_id=my_select_id >>>> + "_modal-form") >>>> >>>>> >>>>> Get's commented out when it's rendered so it ends up looking like this >>> <!-- $(document).read(function() .... .appendTo("body");}); //--> >>> >>> Any idea why that could be happening and would that impact the button >>> showing the modal >>> >>> On Thursday, May 7, 2015 at 8:45:49 AM UTC-4, LoveWeb2py wrote: >>> >>>> Hi Richard! >>>> >>>> I think I'm getting close. No more errors, and I applied the widget to >>>> the field successfully. I see the + sign next to my field, but nothing >>>> happens when I click it so I'm going over the javascript with a fine tooth >>>> comb. Is there any additional .js or .css files I need to include? >>>> >>>> This is really looking promising! >>>> >>>> On Wednesday, May 6, 2015 at 12:42:34 PM UTC-4, Richard wrote: >>>> >>>> Let say the FK field is field2 : >>>> >>>> Field('field2','reference main_table', # Better syntax thand >>>> "db.main_table" >>>> widget=AutocompleteWidgetSelectOrAddOption( >>>> request=request, >>>> >>>> field=db.main_table.field1, # which is you reprensting field >>>> id_field= >>>> db.main_table.id, >>>> limitby=(0, 10), # how >>>> much records you want in the dropbox >>>> min_length=6, # when >>>> you want the autocomplete pop in or how many caracters user have to entered >>>> before the autocomplete kickin >>>> form_title=T('Add new >>>> title'), >>>> controller="controler >>>> name that contains the below function", >>>> function="your add >>>> function name", >>>> button_text=T('Add >>>> new'), >>>> placeholder=T('Start >>>> typing...')) >>>> >>>> Richard >>>> >>>> On Wed, May 6, 2015 at 12:34 PM, LoveWeb2py <[email protected]> wrote: >>>> >>>> Thank you, Richard. I think i'm getting closer. Could you show me an >>>> example of how you apply this to a specific field in SQLFORM? >>>> >>>> Going back to my original model: >>>> >>>> db.define_table('main_table', >>>> Field('field1','string'), >>>> Field('field2','string'), >>>> migrate=False) >>>> >>>> db.define_table('second_table', >>>> Field('field1','db.main_table'), >>>> Field('field2','db.main_table') >>>> migrate=False) >>>> >>>> How could I integrate your widget with field 2 for a SQLFORM? >>>> >>>> >>>> >>>> >>>> >>>> >>>> On Wednesday, May 6, 2015 at 9:40:02 AM UTC-4, Richard wrote: >>>> >>>> The id field and what field you want to show as a representation of the >>>> id field of the referenced table... >>>> >>>> Start by putting the widget class in model file even if it not a good >>>> thing to see if you can make it works... >>>> >>>> In the module I have these imports : >>>> >>>> from gluon.html import * >>>> from gluon.sqlhtml import * >>>> from gluon import current >>>> from gluon.compileapp import LOAD >>>> >>>> >>>> Which may not be related to the widget class... >>>> >>>> Richard >>>> >>>> >>>> On Tue, May 5, 2015 at 4:28 PM, LoveWeb2py <[email protected]> wrote: >>>> >>>> Hi Richard, >>>> >>>> I'm trying to get this setup, but am receiving an error self.url = >>>> URL(args=request.args)\nNameError: global name \'URL\' is not defined\n'. >>>> I'm wondering if this is because the gluon hasn't been imported yet. >>>> >>>> Also, could you ellaborate more on this? >>>> >>>> >>>> field=db.table.representing_field, >>>> >>>> id_field=db.table.id_field, >>>> >>>> id_field should be the foreignkey table if I am not mistaking? >>>> db.table.representing field, and db.table2.id_field (with foreign key) does >>>> that sound right? >>>> >>>> >>>> On Wednesday, April 29, 2015 at 10:04:35 AM UTC-4, Richard wrote: >>>> >>>> *# In a modules :* >>>> >>>> class AutocompleteWidgetSelectOrAddOption(object): >>>> _class = 'string' >>>> >>>> def __init__(self, >>>> request, >>>> field, >>>> id_field=None, >>>> db=None, >>>> orderby=None, >>>> limitby=(0, 10), >>>> keyword='_autocomplete_%(fieldname)s', >>>> min_length=2, >>>> # >>>> ------------------------------------------------------------- >>>> # From : SelectOrAddOption >>>> controller=None, function=None, form_title=None, >>>> button_text = None, dialog_width=1000, >>>> # >>>> ------------------------------------------------------------- >>>> placeholder=None >>>> ): >>>> self.request = request >>>> self.keyword = keyword % dict(fieldname=field.name) >>>> self.db = db or field._db >>>> self.orderby = orderby >>>> self.limitby = limitby >>>> self.min_length = min_length >>>> self.fields = [field] >>>> self.placeholder = placeholder >>>> if id_field: >>>> self.is_reference = True >>>> self.fields.append(id_field) >>>> else: >>>> self.is_reference = False >>>> if hasattr(request, 'application'): >>>> self.url = URL(args=request.args) >>>> self.callback() >>>> else: >>>> self.url = request >>>> # >>>> ---------------------------------------------------------------------- >>>> # From : SelectOrAddOption >>>> if form_title is None: >>>> self.form_title = current.T('Add New') >>>> else: >>>> self.form_title = current.T(form_title) >>>> if button_text is None: >>>> self.button_text = current.T('Add') >>>> else: >>>> self.button_text = current.T(button_text) >>>> self.dialog_width = dialog_width >>>> >>>> self.controller = controller >>>> self.function = function >>>> # >>>> ---------------------------------------------------------------------- >>>> >>>> def callback(self): >>>> if self.keyword in self.request.vars: >>>> field = self.fields[0] >>>> rows = >>>> self.db(field.like(self.request.vars[self.keyword]+'%') >>>> ).select(orderby=self.orderby, >>>> limitby=self.limitby, *self.fields) >>>> if rows: >>>> if self.is_reference: >>>> id_field = self.fields[1] >>>> raise HTTP(200, SELECT(_id=self.keyword, >>>> _class='autocomplete', >>>> _size=len(rows), >>>> _multiple=(len(rows) == 1), >>>> *[OPTION(s[field.name], >>>> _value=s[id_field.name], >>>> _selected=(k == 0)) >>>> for k, s in >>>> enumerate(rows)]).xml()) >>>> else: >>>> raise HTTP(200, SELECT(_id=self.keyword, >>>> _class='autocomplete', >>>> _size=len(rows), >>>> _multiple=(len(rows) == 1), >>>> *[OPTION(s[field.name], >>>> _selected=(k == 0)) >>>> for k, s in >>>> enumerate(rows)]).xml()) >>>> else: >>>> >>>> raise HTTP(200, '') >>>> >>>> def __call__(self, field, value, **attributes): >>>> # >>>> ---------------------------------------------------------------------- >>>> # From : SelectOrAddOption >>>> my_select_id = '%s_%s' % (field._tablename, field.name) >>>> # 'test_ph_eregistry_id' #select_widget.attributes.get('_id', >>>> None) >>>> >>>> add_args = [my_select_id] >>>> # create a div that will load the specified controller via ajax >>>> # form_loader_div = DIV(LOAD(c=self.controller, >>>> f=self.function, args=add_args, ajax=True), >>>> # _id=my_select_id + "_dialog-form", >>>> _title=self.form_title) >>>> form_loader_div = DIV(DIV(BUTTON('x', _type='button', >>>> _class='close', >>>> **{'_data-dismiss': 'modal', >>>> '_aria-hidden': 'true'}), >>>> H3(self.form_title, >>>> _id='myModalLabel'), _class='modal-header'), >>>> DIV(LOAD(c=self.controller, >>>> f=self.function, args=add_args, ajax=True, ajax_trap=True), >>>> _class='modal-body'), >>>> _id=my_select_id + "_modal-form", >>>> _class='modal hide fade', >>>> **{'_tabindex': '-1', '_role': 'dialog', >>>> '_aria-labelledby': 'myModalLabel', >>>> '_aria-hidden': 'true'}) >>>> # generate the "add" button that will appear next the options >>>> widget and open our modal >>>> activator_button = A(I(_class='icon-plus-sign icon-2x'), >>>> _id=my_select_id+"_option_add_trigger", >>>> _class='add-and-select-button') >>>> # create javascript for creating and opening the dialog >>>> # js = '$("#%s_dialog-form").dialog({' \ >>>> # ' autoOpen: false,' \ >>>> # ' show: "fade",' \ >>>> # ' hide: "fade",' \ >>>> # ' width: %s' \ >>>> # ' });' % (my_select_id, self.dialog_width) >>>> js = '$("#%s_modal-form").modal({ backdrop: true, keyboard: >>>> true, show: false });' % (my_select_id) >>>> # js += '$("#%s_option_add_trigger").click(function() {' \ >>>> # ' $("#%s_dialog-form").dialog("open");' \ >>>> # ' return false;' \ >>>> # ' }); ' % (my_select_id, my_select_id) >>>> js += '$("#%s_option_add_trigger").click(function() ' \ >>>> '{ $("#%s_modal-form").modal("show"); return false; }); ' >>>> % (my_select_id, my_select_id) >>>> # decorate our activator button for good measure >>>> js += '$(function() {' \ >>>> ' $("#%s_option_add_trigger").button({' \ >>>> ' text: true,' \ >>>> ' icons: {' \ >>>> ' primary: "ui-icon-circle-plus"' \ >>>> ' }' \ >>>> ' });' \ >>>> '});' % (my_select_id) >>>> js += '$(function() { ' \ >>>> ' $( "#%s_option_add_trigger" ).css("margin-left", >>>> "+=5"); ' \ >>>> '});' % (my_select_id) >>>> js += >>>> '$("#{modal_id}").appendTo("body");'.format(modal_id=my_select_id + >>>> "_modal-form") >>>> # jQuery .appendTo() move modal div in body to avoid nested >>>> form which are not allow in HTML >>>> js = """$(document).ready(function() { >>>> %s >>>> });""" % js >>>> jq_script = SCRIPT(js, _type="text/javascript") >>>> >>>> wrapper = DIV(_id=my_select_id+"_adder_wrapper") >>>> # >>>> ---------------------------------------------------------------------- >>>> default = dict( >>>> _type='text', >>>> value=(not value is None and str(value)) or '', >>>> ) >>>> attr = StringWidget._attributes(field, default, >>>> _placeholder=self.placeholder, **attributes) >>>> div_id = self.keyword+'_div' >>>> attr['_autocomplete'] = 'off' >>>> if self.is_reference: >>>> key2 = self.keyword+'_aux' >>>> key3 = self.keyword+'_auto' >>>> # >>>> ----------------------------------------------------------------------------- >>>> # find the longest record and set input size attribute >>>> accordingly >>>> length = self.fields[0].len() >>>> longest_record_length = len(self.db().select(self.fields[0], >>>> >>>> orderby=~length, >>>> limitby=(0, >>>> 1)).first()[self.fields[0].name]) >>>> attr['_size'] = int(longest_record_length * 1.20) # 20% >>>> wider field width >>>> # >>>> ----------------------------------------------------------------------------- >>>> attr['_class'] = 'string' >>>> name = attr['_name'] >>>> if 'requires' in attr: >>>> del attr['requires'] >>>> attr['_name'] = key2 >>>> value = attr['value'] >>>> record = self.db(self.fields[1] == >>>> value).select(self.fields[0]).first() >>>> attr['value'] = record and record[self.fields[0].name] >>>> attr['_onblur'] = "$('#%(div_id)s').delay(1000).fadeOut();" >>>> % \ >>>> dict(div_id=div_id, u='F'+self.keyword) >>>> # delay(500) is pretty important for "$('#%s').keyup(); >>>> $('#%s').blur();" >>>> # from the add_eregistry function >>>> attr['_onkeyup'] = \ >>>> "$('#%(key3)s').val('');" \ >>>> "var e = event.which?event.which:event.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=' + >>>> encodeURI($('#%(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);" \ >>>> " $('#%(key)s').click( %(u)s);" \ >>>> " };" \ >>>> " });" \ >>>> "else $('#%(div_id)s').fadeOut();" % dict(url=self.url, >>>> min_length=self.min_length, >>>> >>>> key=self.keyword, id=attr['_id'], key2=key2, key3=key3, >>>> name=name, >>>> div_id=div_id, u='F'+self.keyword) >>>> if self.min_length == 0: >>>> attr['_onfocus'] = attr['_onkeyup'] >>>> wrapper.components.extend([TAG[''](INPUT(**attr), >>>> INPUT(_type='hidden', >>>> _id=key3, >>>> _value=value, >>>> _name=name, >>>> requires=field.requires), >>>> DIV(_id=div_id, >>>> _style='position:absolute;')), >>>> form_loader_div, >>>> activator_button, >>>> jq_script]) >>>> return wrapper >>>> else: >>>> attr['_name'] = field.name >>>> attr['_onblur'] = "$('#%(div_id)s').delay(1000).fadeOut();" >>>> % \ >>>> dict(div_id=div_id, u='F'+self.keyword) >>>> # delay(500) is pretty important for "$('#%s').keyup(); >>>> $('#%s').blur();" >>>> # from the add_eregistry function >>>> attr['_onkeyup'] = \ >>>> "var e = event.which?event.which:event.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=' + encodeURI($('#%(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);" \ >>>> " $('#%(key)s').click( %(u)s);" \ >>>> "});" \ >>>> "else $('#%(div_id)s').fadeOut();" % dict(url=self.url, >>>> min_length=self.min_length, >>>> >>>> key=self.keyword, id=attr['_id'], div_id=div_id, >>>> >>>> u='F'+self.keyword) >>>> if self.min_length == 0: >>>> attr['_onfocus'] = attr['_onkeyup'] >>>> wrapper.components.extend([TAG[''](INPUT(**attr), >>>> DIV(_id=div_id, >>>> >>>> _style='position:absolute;')), >>>> form_loader_div, >>>> activator_button, >>>> jq_script]) >>>> return wrapper >>>> >>>> # In a model (a model file which is already call before you set your >>>> widget...) >>>> from a_widget import AutocompleteWidgetSelectOrAddOption >>>> >>>> *# In your controller * >>>> >>>> def add_function(): >>>> """ >>>> Modal form for adding element >>>> """ >>>> >>>> buttons = [TAG.button((I('', _class='icon-ok icon-large >>>> icon-white'), CAT(' '), STRONG(T('Add'))), >>>> _type='submit', >>>> _class='btn btn-small btn-primary', >>>> _id='add_button_id', >>>> _name='add_button', >>>> )] >>>> form = SQLFORM(db.table, buttons=buttons, formstyle=formstyle, >>>> separator=separator) >>>> response.js = '$(document).ready(function(){ >>>> $(".input_wrapper").has(".error").addClass("inputError"); ' \ >>>> '$(".w2p_fw").has(".error").addClass("control-group >>>> error"); ' \ >>>> '$(".w2p_fw").each(function(){ >>>> $(this).find(".error_wrapper").appendTo(this); }); });' >>>> response.js += '$(document).ready(function(){ >>>> $("textarea").elastic(); });' >>>> response.js += '$(document).ready(function () { >>>> $("[rel=tooltip]").tooltip(); });' >>>> if form.process(formname='add_form').accepted: >>>> response.flash = T("Added") >>>> target = request.args(0) >>>> # close modal >>>> response.js = >>>> '$("#{target}_modal-form").modal("hide");'.format(target=target) >>>> # update the select options >>>> response.js += """$("#{target}").append( >>>> "<option value='{new_id}'> >>>> {new_id} >>>> </option>");""".format(target=target, new_id= >>>> form.vars.id) >>>> # select newly added option >>>> response.js += """$("#{target}").val("{new_exp_num}"); >>>> $('#{target}').keyup(); $('#{target}').blur(); >>>> >>>> ... >>> >>> -- >>> Resources: >>> - http://web2py.com >>> - http://web2py.com/book (Documentation) >>> - http://github.com/web2py/web2py (Source code) >>> - https://code.google.com/p/web2py/issues/list (Report Issues) >>> --- >>> You received this message because you are subscribed to the Google >>> Groups "web2py-users" group. >>> To unsubscribe from this group and stop receiving emails from it, send >>> an email to [email protected]. >>> For more options, visit https://groups.google.com/d/optout. >>> >> >> -- > Resources: > - http://web2py.com > - http://web2py.com/book (Documentation) > - http://github.com/web2py/web2py (Source code) > - https://code.google.com/p/web2py/issues/list (Report Issues) > --- > You received this message because you are subscribed to the Google Groups > "web2py-users" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to [email protected]. > For more options, visit https://groups.google.com/d/optout. > -- Resources: - http://web2py.com - http://web2py.com/book (Documentation) - http://github.com/web2py/web2py (Source code) - https://code.google.com/p/web2py/issues/list (Report Issues) --- You received this message because you are subscribed to the Google Groups "web2py-users" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.

