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();""".format(target=target, > > new_exp_num=form.vars.exp_num) > elif form.errors: > response.flash = '' > else: > response.flash = '' > return dict(form=form) > > *# Then you set the widget to your field * > > widget=AutocompleteWidgetSelectOrAddOption( > request=request, > > field=db.table.representing_field, > id_field=db.table.id_field, > limitby=(0, 10), # your > pref > min_length=6, # your pref > form_title=T('Add new > element'), > controller="ref", > function="add_function", > # Name of your add_function() > button_text=T('Add new'), > placeholder=T('Start > typing...')) > > Give feedback here... > > You may consider to try it first in a dummy app so you can share it here > in case you have some difficulties to set it up... It will be easier to > help you that way, once you will have understand all the sensitive part you > will be able to set it up in you prod app rapidly... > > Richard > > On Tue, Apr 28, 2015 at 7:04 PM, LoveWeb2py <atayl...@gmail.com > <javascript:>> wrote: > > I'd love to see it, Richard! I'm banging my head against the wall with > this other method. > > On Tuesday, April 28, 2015 at 6:58:25 PM UTC-4, Richard wrote: > > My own mix of SELECT_OR_ADD_OPTION() widget and web2py > SQLFORM.widget.autocomplete... > > As wrote above I can share the code here... > > Richard > > On Tue, Apr 28, 2015 at 5:06 PM, LoveWeb2py <atayl...@gmail.com> wrote: > > What do you use as a replacement? > > On Tuesday, April 28, 2015 at 4:59:32 PM UTC-4, Richard wrote: > > in view in script tag is a good place for start... just make sure you have > the rigth id for you modal main div... In my case modal_id was coming from > an .fromat(modal_id='id')... > > But I don't recall the exact way this tutorial was doing and I was just > exposing to 2 generals reasons why form into modal won't submit > correctly... In my case my widget was appending my modal with a LOAD > component inside a form of the so the load form has to be put outside the > main form... > > I try the ressource you are using and give up because it was not full fill > all my requirement... > > Richard > > On Tue, Apr 28, 2015 at 4:54 PM, LoveWeb2py <atayl...@gmail.com> wrote: > > This is what I'm using in my layout: > > > $(function() { > $("td.w2p_fc").each(function (){ > var comment = $(this).html(); > if (comment){ > $(this).html('<div><i class="icon info icon-info-sign"></i></div>'); > $(this).children('div').attr('title',comment); > $(this).children('div').tooltip({ placement : 'right', > html : true, > trigger : 'click' }); > } > }); > }); > > This makes the comment field available as an "Information Icon" > > When I use the modal class referenced in the link it works great, the problem > is nothing stores because the form can't process properly. I'm struggling to > solve that last piece of the puzzle. > > When I > > > > On Tuesday, April 28, 2015 at 4:50:34 PM UTC-4, LoveWeb2py wrote: > > Thank you, Richard. Where do I put $("#{modal_id}").appendTo(" > body"); > > Could I just put that in the HTML file? Something like... > > <script> > $("#{modal_id}").appendTo(" > body"); > </script> > > I tried hardcoding the div_id of my modal into your code, but it didn't > work. The database doesn't update properly with the correct foreign key. I > also have some date value fields and the calendar.js doesn't pop down so > I'm thinking this has something to do with > http://linuxapuntes.blogspot.com.ar/2013/03/plugin-modal-bootstrap-web2py.html > > Do you have an example of where you'd put the appendTo ? > > > > > On Tuesday, April 28, 2015 at 1:04:57 PM UTC-4, Richard wrote: > > There is different issue when embed for into a bootstrap 2.3.2 (at > least)... One that I found were that <form> tag get ripped off... The other > depend of the way the modal form compoenent is included into the main > form... Depending how the widget is write the extra are embed beside the > original input field which don't work in case of a <form> tag since html > <form> can't be nested... Modal don't offer any convenient support à this > level and you have to manage this by yourself... But it is easy, you just > need to use jquery .appendTo() : > > Like that : $("#{modal_id}").appendTo("body"); > > And extract your component modal form which is nested into the main page > form and append it to the body instead... > > This is basically what jQuery Dialog is doing out of the box which > boostrap modal don't that make the usage of modal with component in web2py > so difficult... > > :) > > Richard > > > On Tue, Apr 28, 2015 at 12:40 PM, LoveWeb2py <atayl...@gmail.com> wrote: > > Richard, > > This is working great. > http://linuxapuntes.blogspot.com.ar/2013/03/plugin-modal-bootstrap-web2py.html > > I currently use it like this: > > def my_controller(): > from modalplugins Import Modal > field = db.mytable.field > modal = Modal(field, ' Add', 'Add area','Area') > db.mytable.field.comment = modal.create() > grid=SQLFORM.smartgrid(db.my_other_table) > formModal = modal.formModal() > return(grid=grid, formModal=formModal) > > The problem I am having now is that I can't process the modal. Do you have > any thoughts on how to do this? > > On Friday, April 17, 2015 at 9:50:15 AM UTC-4, Richard wrote: > > 'reference tablename' = 1 to many > 'list:reference tablename' = "many to many" it denormalised that why I put > it between double quotes > > Richard > > On Thu, Apr 16, 2015 at 5:13 PM, LoveWeb2py <atayl...@gmail.com> wrote: > > Richard, > > I did want to have a foreign key for info_about_field1. I guess I could do > a reference field1 ? > > > > On Thursday, April 16, 2015 at 3:02:51 PM UTC-4, Richard wrote: > > There is no relation between both tables... You can embed 2 forms as > component (LOAD()) > > if you were having list:reference type field it is differents and you have > to question yourself if you are not better to have something like > SELECT_OR_ADD_OPTION() or even better AutocompleteSelectOrAddOption() > widget... I recently update my old AutocompleteSelectOrAddOption() widget > (not finish yet) in order to move from jquery ui dialog to bootstrap > modal... I will publish a web2py slice when done. > > Just ask if it interest you I can publish preview here... > > Richard > > On Thu, Apr 16, 2015 at 2:08 PM, LoveWeb2py <atayl...@gmail.com> wrote: > > Hello, > > I'd like to have two SQLFORMs right next to each other. > > The second SQLFORM is just going to be linked to the field in table 1, but > will be used so the student can make additional comments about a field. > Model will look like this: > > db.define_table('main_table', > Field('field1','string'), > Field('field2','string'), > migrate=False) > > db.define_table('second_table', > Field('info_about_field1','list:string'), > Field('info_about_field2','list:string') > migrate=False) > > My question is... is it possible to have the second_table as a link > underneath the main_table field. I want to have a modal pop up so they can > enter additional information about the field > > > -- > 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 web2py+un...@googlegroups.com. > 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 web2py+un...@googlegroups.com. > 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 web2py+un...@googlegroups.com. > 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 web2py+un...@googlegroups.com. > 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 web2py+un...@googlegroups.com. > For more options, visit https:/ <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 web2py+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.