add static files to header from a module

71 views
Skip to first unread message

pa...@cancamusa.net

unread,
Aug 13, 2014, 7:14:46 AM8/13/14
to web...@googlegroups.com

Dear all:
In the process of moving functionality from models to modules, I'm trying to add some filesto the header. When the file was in models, I did:

        response.files.append(URL('static', 'jqplot/jquery.jqplot.min.js'))
        response.files.append(URL('static', 'jqplot/jquery.jqplot.min.css'))

now that it's in modules, I tried:

        current.response.files.append(URL('static', 'jqplot/jquery.jqplot.min.js'))
        current.response.files.append(URL('static', 'jqplot/jquery.jqplot.min.css'))

but it doesn't work...
I've found a workaround, the last line in JQPlot.xml was:

        return current.response.render('jqplot.html', d)

so I can add "script" html tags to the template jqplot.html:

<script src="/karakolas/static/jqplot/jquery.jqplot.min.js"></script>
<script src="/karakolas/static/jqplot/jquery.jqplot.min.css"></script>

but I'm sure it can be done better...
Thanks

Cliff Kachinske

unread,
Aug 13, 2014, 7:21:09 AM8/13/14
to web...@googlegroups.com
Put the appending code in the controller.

Pablo Angulo

unread,
Aug 13, 2014, 7:36:15 AM8/13/14
to web...@googlegroups.com
If I understand, you mean that whenever I call JQPlot

    jqplot = JQPlot(*args, col_represent=str)

I have to append the following lines:


        response.files.append(URL('static', 'jqplot/jquery.jqplot.min.js'))
        response.files.append(URL('static', 'jqplot/jquery.jqplot.min.css'))
        response.files.append(URL('static', 'jqplot/plugins/jqplot.barRenderer.min.js'))
        response.files.append(URL('static', 'jqplot/plugins/jqplot.categoryAxisRenderer.min.js'))
        response.files.append(URL('static', 'jqplot/plugins/jqplot.pointLabels.min.js'))

or at least a call like

        jqplot = JQPlot(*args, col_represent=str)
        add_jqplot_static_files()

to avoid repetition.

yeah, that would sure work, but still: any other ideas?

I'm specifically interested in knowing why

        current.response.files.append(URL('static', 'jqplot/jquery.jqplot.min.js'))
        current.response.files.append(URL('static', 'jqplot/jquery.jqplot.min.css'))
        current.response.files.append(URL('static', 'jqplot/plugins/jqplot.barRenderer.min.js'))
        current.response.files.append(URL('static', 'jqplot/plugins/jqplot.categoryAxisRenderer.min.js'))
        current.response.files.append(URL('static', 'jqplot/plugins/jqplot.pointLabels.min.js'))

in the module does not work. I get the feeling that I will stump into that wall more times if I just hack my way around the problem now.

El 13/08/14 a las #4, Cliff Kachinske escribió:
--
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 a topic in the Google Groups "web2py-users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/web2py/1h3Ni_iywzY/unsubscribe.
To unsubscribe from this group and all its topics, send an email to web2py+un...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Leonel Câmara

unread,
Aug 13, 2014, 8:13:15 AM8/13/14
to
Simply adding to current.response.files may not work if the request is ajax (say your module has a component that is loaded by whoever is using it).

In my modules I like to use a function the plugins in s-cubism.com use to set files:

def _set_files(files):
    if current.request.ajax:
        current.response.js = (current.response.js or '') + """;(function ($) {
var srcs = $('script').map(function(){return $(this).attr('src');}),
    hrefs = $('link').map(function(){return $(this).attr('href');});
$.each(%s, function() {
    if ((this.slice(-3) == '.js') && ($.inArray(this.toString(), srcs) == -1)) {
        var el = document.createElement('script'); el.type = 'text/javascript'; el.src = this;
        document.body.appendChild(el);
    } else if ((this.slice(-4) == '.css') && ($.inArray(this.toString(), hrefs) == -1)) {
        $('<link rel="stylesheet" type="text/css" href="' + this + '" />').prependTo('head');
        if (/* for IE */ document.createStyleSheet){document.createStyleSheet(this);}
}});})(jQuery);""" % ('[%s]' % ','.join(["'%s'" % f.lower().split('?')[0] for f in files]))
    else:
        current.response.files[:0] = [f for f in files if f not in current.response.files]


Anthony

unread,
Aug 13, 2014, 8:18:17 AM8/13/14
to web...@googlegroups.com
Can you show your module code? Are you doing the appending at the top level in the module, or within a function/method?


On Wednesday, August 13, 2014 7:14:46 AM UTC-4, pa...@cancamusa.net wrote:

Pablo Angulo

unread,
Aug 13, 2014, 11:12:49 AM8/13/14
to web...@googlegroups.com
El 13/08/14 a las #4, Anthony escribió:
> Can you show your module code? Are you doing the appending at the top
> level in the module, or within a function/method?

The latter:

> # -*- coding: utf-8 -*-
> # (C) Copyright (C) 2012-14 Pablo Angulo
> # This file is part of karakolas <karakolas.org>.
>
> # karakolas is free software: you can redistribute it and/or modify
> # it under the terms of the GNU Affero General Public License as
> # published by the Free Software Foundation, either version 3 of the
> # License, or (at your option) any later version.
>
> # karakolas is distributed in the hope that it will be useful,
> # but WITHOUT ANY WARRANTY; without even the implied warranty of
> # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> # GNU General Public License for more details.
>
> # You should have received a copy of the GNU Affero General Public
> # License along with karakolas. If not, see
> # <http://www.gnu.org/licenses/>.
>
> from gluon.html import URL, FORM
> from gluon import current
> from collections import defaultdict
>
> class JQPlot(FORM):
>
> def __init__(self, query,
> row_field, col_field, data_field,
> row_ids=None, col_ids=None,
> row_represent=None, col_represent=None,
> data_represent=None,
> _id='',
> **attributes):
> '''Muestra una gráfica ligeramente interactiva para visualizar
> una relacion que representa una funcion (ref1,ref2) -> valor
> '''
> FORM.__init__(self, **attributes)
> current.response.files.append(URL('static',
> 'jqplot/jquery.jqplot.min.js'))
> current.response.files.append(URL('static',
> 'jqplot/jquery.jqplot.min.css'))
> current.response.files.append(URL('static',
> 'jqplot/plugins/jqplot.barRenderer.min.js'))
> current.response.files.append(URL('static',
> 'jqplot/plugins/jqplot.categoryAxisRenderer.min.js'))
> current.response.files.append(URL('static',
> 'jqplot/plugins/jqplot.pointLabels.min.js'))
>
> self.query = query
> self.row_field = row_field
> self.col_field = col_field
> self.data_field = data_field
>
> self.row_represent = row_represent or row_field.represent or
> (lambda x:x)
> self.col_represent = col_represent or col_field.represent or
> (lambda x:x)
> try:
> self.data_represent = data_represent or
> data_field.represent or (lambda x:x)
> except AttributeError:
> #A f.sum() or f.count() doesn't have a represent attribute
> self.data_represent = (lambda x:x)
>
> self.row_ids = row_ids or [r[row_field] for r in
> current.db(query).select(row_field, groupby=row_field)]
> self.row_names = [self.row_represent(rid) for rid in self.row_ids]
> self.col_ids = col_ids or [r[col_field] for r in
> current.db(query).select(col_field, groupby=col_field)]
> self.col_names = [self.col_represent(cid) for cid in self.col_ids]
>
> def xml(self):
>
> d = defaultdict(float)
> recs = current.db(self.query).select(
> self.row_field, self.col_field, self.data_field,
> groupby=self.row_field|self.col_field
> )
>
> for row in recs:
> d[row[self.row_field],
> row[self.col_field]]=row[self.data_field]
>
> data = [[float(d[r,c]) for c in self.col_ids] for r in
> self.row_ids]
> series_labels = ','.join("{label:'%s'}"%self.row_represent(r)
> for r in self.row_ids)
> ticks = self.col_names
>
> d = dict(data=data,ticks=ticks, series_labels=series_labels)

Pablo Angulo

unread,
Aug 13, 2014, 11:15:57 AM8/13/14
to web...@googlegroups.com
El 13/08/14 a las #4, Leonel Câmara escribió:
> Simply adding to current.response.files may not works if the request
> is ajax (say your module is loaded).

But it's not loaded via ajax, I call it like this:

> @requires_get_arguments(('grupo', db.grupo),
> ('productor', db.productor),
> _consistency= (
> ((db.grupo.id==db.grupoXred.grupo) &
>
> (db.productor.grupo==db.grupoXred.red)),
>
> (db.productor.grupo==db.grupo.id) )
> )
> @auth.requires_membership('admins_%s'%request.vars.grupo)
> def grafica_grupo_productor():
> '''Muestra tabla y grafica de productos x fecha_pedido para un
> productor fijo,
> con la cantidad total que se pide de cada producto en cada fecha
> '''
>
> iproductor = int(request.vars.productor)
> productor = db.productor[iproductor]
> igrupo = int(request.vars.grupo)
> grupo = db.grupo(igrupo)
>
> response.title = T('Estadísticas del grupo %s con
> %s')%(grupo.nombre, productor.nombre)
>
> def row_represent(pid):
> return db.producto[pid].nombre
> args = ((db.item.productoXpedido==db.productoXpedido.id) &
> (db.productoXpedido.pedido==db.pedido.id) &
> (db.pedido.productor==iproductor) &
> (db.item.grupo==igrupo),
> db.productoXpedido.producto,
> db.pedido.fecha_reparto,
> db.item.cantidad.sum())
> sheet = ROSheet(*args,
> row_represent=row_represent,
> col_totals=True)
> jqplot = JQPlot(*args,
> row_represent=row_represent,
> col_represent=str)
> return dict(sheet=sheet, jqplot=jqplot,
> nombre_productor=productor.nombre,
> grupo=grupo)

and the view is:

> {{extend 'layout.html'}}
> ... etc ...
> {{=jqplot}}
> {{=sheet}}
> ... etc ...


Pablo Angulo

unread,
Aug 13, 2014, 11:18:58 AM8/13/14
to web...@googlegroups.com
I also tried to place the
> current.response.files.append(URL('static',
> 'jqplot/jquery.jqplot.min.js'))
> current.response.files.append(URL('static',
> 'jqplot/jquery.jqplot.min.css'))
> current.response.files.append(URL('static',
> 'jqplot/plugins/jqplot.barRenderer.min.js'))
> current.response.files.append(URL('static',
> 'jqplot/plugins/jqplot.categoryAxisRenderer.min.js'))
> current.response.files.append(URL('static',
> 'jqplot/plugins/jqplot.pointLabels.min.js'))
in the xml method, but it didn't make to the response either.

El 13/08/14 a las #4, Pablo Angulo escribió:

Pablo Angulo

unread,
Aug 16, 2014, 10:47:02 AM8/16/14
to web...@googlegroups.com
I think I got it:

- As Leonel said, "Simply adding to current.response.files may not works
if the request is ajax". I have to add: if a component is loaded with
the LOAD function, adding to current.response.files will not work even
if ajax=False and ajax_trap=False.

- The statements:

current.response.files.append(URL('static',
'jqplot/jquery.jqplot.min.js'))
current.response.files.append(URL('static',
'jqplot/jquery.jqplot.min.css'))
current.response.files.append(URL('static',
'jqplot/plugins/jqplot.barRenderer.min.js'))
current.response.files.append(URL('static',
'jqplot/plugins/jqplot.categoryAxisRenderer.min.js'))
current.response.files.append(URL('static',
'jqplot/plugins/jqplot.pointLabels.min.js'))

must be placed in the __init__ method, or any other method that is
called from the controller, not from the view (like the xml method).

The combination of both issues confused me, so thanks for your help!
Reply all
Reply to author
Forward
0 new messages