If you benefit from web2py hope you feel encouraged to pay it forward by contributing back to society in whatever form you choose!

Steps:

1) Put the jquery.jmpopups-0.5.1 in the static folder. It can be found at http://code.google.com/p/jmpopups/

2) Put the following lines into the web2py_ajax.html, BEFORE of the <script type="text/javascript"> tag:

<script src="{{=URL(r=request,c='static',f='jquery.jmpopups-0.5.1.js')}}" type="text/javascript"></script>

3) Put the following lines into the web2py_ajax.html, INSIDE the <script type="text/javascript"> tag:

$.setupJMPopups({
    screenLockerBackground: "#003366",
    screenLockerOpacity: "0.7"
});

function openAjaxPopup(name_popup, width, url) {
    $.openPopupLayer({
        name: name_popup,
        width: width,
        url: url
    });
}

4) Put the module widgetAddLink.py in the modules folder. The contents of the file is below:

#!/usr/bin/env python 
# coding: utf8 
from gluon.html import *
from gluon.http import *
from gluon.validators import *
from gluon.sqlhtml import *
# request, response, session, cache, T, db(s) 
# must be passed and cannot be imported!

class OPTIONS_WITH_ADD_LINK:
    def __init__(self,**parameters):
         self.parameters=parameters
    def __del__(self): pass
    def __call__(self,field,value):
        """
        example::
            db.main.product.widget = OPTIONS_WITH_ADD_LINK(T=T, r=request, c="product")

        When the form is rendered it shows a dropbox and a "add" link
        """        

        # Create a SELECT object
        select = OptionsWidget.widget(field,value)

        # Get the parameters
        request = self.parameters["r"] 
        a = request.application
        c = self.parameters["c"]
        T = self.parameters["T"]
        f = self.parameters["f"] or None #new paremeter either None or the name of the field to use           

        requires = select.attributes["requires"]

        # If is not the "IS_IN_DB" validator then can be that the line below fails 
        # because the requires can't have "ks" object        
        try:
            # Get the field name from the foreign table from validator IS_IN_DB
            if f is None:
                field_name = requires.ks[0]
            else:
                field_name = f #use the one we specified (because there was no "ks" object)
        except AttributeError:
            return select
        else:
            # Get the id from the SELECT object that allows adding an option
            select_id = select.attributes.get('_id', None)

            id = "%(tablename)s_%(fieldname)s" % {"tablename":field._tablename,
                "fieldname":field.name}
            popup_id = "popup_%s" % id
            width = 700

            # Build the URL responsible for opening a popup window in the same screen
            url= URL(r=request, c=c, f="create_popup",
                vars=dict(title_name=field.name,field_name=field_name, 
                        select_id=select_id))


            # Create the script that add the "Add" link after the SELECT object
            add_link = A(T("Add"), 
                                    _id="add_%s" % id,
                                    _name="add_%s" % id,
                                    _href="#",
                                    _onclick=("openAjaxPopup('%(name)s',%(width)d,'%(url)s')"\
                                        % {"id": id, "name":popup_id, "width":width, "url":url}),
                                    _title="Add")

            return DIV(select, " ", add_link)

def create_popup(request, table):
    """
    Create a popup with a form to register a new record
    """

    select_id = request.vars.select_id
    form_name = "form_%(name)s" % {"name":select_id}
    field_name = request.vars.field_name

    url_ajax = URL(r=request,f='validate_popup', 
        vars=dict(form_name=form_name, select_id=select_id, field_name=field_name))

    # Build the script responsible for submiting the form via ajax
    script_submit = SCRIPT("""jQuery('#%(form)s').submit(function(){ 
        jQuery.ajax({
                 type: "POST",
                 url: "%(url_ajax)s",
                 data: jQuery("#%(form)s").serialize(),
                 success: function(msg){jQuery('#message').html(msg);} });
        return false;
        });""" %  {"form":form_name, "url_ajax":url_ajax}  )

    form = SQLFORM(table, _enctype=None, _id=form_name,_action=None, _method=None)
    return dict(form=form,script_submit=script_submit,message=DIV(_id="message")) 

def validate_popup(request, table):
    """
    Validate the data from popup 
    """

    select_id = request.vars.select_id or None
    field_name = request.vars.field_name or None
    field_value = request.vars["%s" % field_name]

    form = SQLFORM(table)

    if form.accepts(request.vars,formname=None):
        script = "$.closePopupLayer();"
        if select_id:
            script_add_option = """$("#%s").append("<option value='%s'>%s</option>");""" \
                % (select_id, form.vars.id, field_value)
            script_select_option = """$("#%s").val("%s");""" % (select_id, field_value)
        return SCRIPT(script,script_add_option,script_select_option)
    elif form.errors:
        return DIV(TABLE(*[TR("%s %s" % (k,v)) for k, v in form.errors.items()]))

5) Put the popup.html in the views folder. The contents of the file is below:

<style type="text/css" media="screen">
    .popup {background:#FFF; border:1px solid #333; padding:1px;}
    .popup-header {height:24px; padding:7px; background:url("bgr_popup_header.jpg") repeat-x;}
    .popup-header h2 {margin:0; padding:0; font-size:18px; float:left;}
    .popup-header .close-link {float:right; font-size:11px;}
    .popup-body {padding:10px;}
</style>
<div class="popup">
    <div class="popup-header">
        <h2>{{=T("Create a %(name)s", dict(name=request.vars.title_name)) }}</h2>
        <a href="javascript:;" onclick="$.closePopupLayer()" title="Close" class="close-link">{{=T("Close")}}</a>
        <br clear="both" />
    </div>
    <div class="popup-body">
        {{=message}}
        {{=form}}
        {{=script_submit}}
    </div>
</div>

6) Import the module in your model (maybe db.py):

exec('from applications.%s.modules.widgetAddLink import *' % request.application)

7) Add this widget to some field that uses the validator IS_IN_DB. Example:

db.main.product.requires = IS_IN_DB(db,db.product.id,db.product.name)
db.main.product.widget = OPTIONS_WITH_ADD_LINK(T=T, r=request, c="product")

Note: The OPTIONS_WITH_ADD_LINK requires three arguments:

a) T object (the object T is the language translator)

b) Request

c) and the name of the controller responsible for add a new register to the field in the left side

d) f (field) is optional.

8) Import the module in the controller specified above, in the widget configuration (e.g. product.py):

exec('import applications.%s.modules.widgetAddLink as popup' % request.application)

9) Add the following two methods into this controller:

def create_popup():
    response.view='popup.html'
    return popup.create_popup(request, db.tablename)

def validate_popup():
    return popup.validate_popup(request, db.tablename)

Note: Replace db.tablename to the desired table. Example: db.product

Ready! This should work.


Issues known:

1) The record is added at the end of the list in the combo box. The widget does not reload the combo box object to sort it properly, just adds an item via jquery.

Related slices

Comments (14)

  • Login to post



  • 0
    matclab 14 years ago
    In fact, the script is send as expected. The problem is that the validate_popup function does not get the name of the file that should have been uploaded (and my guess is that no file where uploaded by using the popup window....). I'll investigate more and keep you informed.

  • 0
    matclab 14 years ago
    Hello, This slice looks nice. I still have some difficulties to make it working. The pop-up pops-up as wanted, but the submit button is inoperant. If I add
     print res['script_submit']
    
    In create_popup() I get on stdout :
    
    
    Which looks ok, but still no submit url in the "form_card_file" form (as seen with firebug).... Do you have any clue ?

  • 0
    renatocaliari 14 years ago
    Sophie, It would needs some modification in this widget.

  • 0
    sophie 14 years ago
    This is using the SQLFORM. What can i do if i want to add this link through the controller? I am creating the table in the controller, i think i have to put the widget here, but i dont know how. My controlles is this: form=FORM(TABLE( TD("Caracteristica"), TD(SELECT(_name="caracteristica", *[OPTION(x.Caracteristica.nCaracteristica +' - '+ x.TipoCaracteristica.nTipoCaracteristica,_value=x.Caracteristica.id) for x in db((db.Caracteristica.idTipoCaracteristica==db.TipoCaracteristica.id)&\ (db.Caracteristica.id.belongs(lista))).select(orderby=db.Caracteristica.nCaracteristica)])), TD("Descripcion"),INPUT(_type='text',_name="descripcion"), INPUT(_type='submit',_value='Submit'))) if form.accepts(request.vars, session): if not form.vars.caracteristica=="": db.CaracteristicaCientifico.insert(nCaracteristicaCientifico=form.vars.descripcion, idCaracteristica=form.vars.caracteristica,idCientifico=session.idPrincipal) redirect(URL(r=request, c='cientifico', f='insert', args=["db","CaracteristicaCientifico"])) else: form.errors.caracteristica ='Seleccionar un registro'

  • 0
    renatocaliari 14 years ago
    Thanks mr.freeze!
show more comments

Hosting graciously provided by:
Python Anywhere