Re: [w2py-dev] response.files for ajax

89 views
Skip to first unread message

Massimo Di Pierro

unread,
Sep 6, 2011, 10:23:14 PM9/6/11
to web2py-d...@googlegroups.com
Is this a good idea? Should't the JS be loaded with the loading page? Usually people expect ajax requests to be quick, if they have js and css dependencies they may not be efficient. If we provide an api than we want to encourage this programming style. What do others think?


On Sep 4, 2011, at 6:41 AM, kenji4569 wrote:

> I'v developed several plugins, and I found some of them were
> unavailable when using ajax LOAD, because they requires js and css
> files stored in response.files (e.g. http://dev.s-cubism.com/plugin_uploadify_widget,
> http://dev.s-cubism.com/plugin_anytime_widget).
>
> Specifically, I'd written the follwing code in each plugin file:
>
> def _set_files(files):
> current.response.files[:0] = [f for f in files if f not in
> current.response.files]
>
> It was okey before I used the LOAD helper (ajax=True) with the
> plugin.
>
> So, after struggles, I ended up writing the following code:
>
> 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]
>
> In this nasty code, js and css files of the plugin are dynamically
> downloaded without re-download.
>
> I am expecting that, it would be possible to use the former short
> "_set_files" function in the plugin for ajax, if web2py recognized the
> response.files in ajax requests.
>
> Further, I'v had to modify a script written in each plugin, for
> example,
>
> From:
> """
> jQuery(function() {
> jQuery("#%(id)s").xxx({...});
> });
> """ % {...}
>
> To:
> """
> jQuery(function() { var t = 10; (function run() {if ((function() {
> var el = jQuery("#%(id)s");
> if (el.xxx == undefined) { return true; }
> el.xxx({...});
> })()) {setTimeout(run, t); t = 2*t;}})();});
> """ % {...}
> (this code waits until required js files are downloaded)
>
> Although it works fine, it needs a bit boilerplate.
> I think it might be good if a function for such a boilerplate is
> provided in global by web2py_ajax.js, or
> response.something.append("""...""") could be used for this.
>
> What do you think? or any alternatives are already provided?
>
> Thanks in advance,
> Kenji
>
> --
> mail from:GoogleGroups "web2py-developers" mailing list
> make speech: web2py-d...@googlegroups.com
> unsubscribe: web2py-develop...@googlegroups.com
> details : http://groups.google.com/group/web2py-developers
> the project: http://code.google.com/p/web2py/
> official : http://www.web2py.com/

Michele Comitini

unread,
Sep 7, 2011, 5:26:46 AM9/7/11
to web2py-d...@googlegroups.com
I have seen other frameworks that have a protocol to manage ajax
events, I think it is useful.
The ajax function can do that but you need to use ':eval' target and
then you are on your own.

What it is useful is having a standard way to push changes into the
loading page using the controller.
For instance

response.ajax_header_contributions=dict(css=[...], js=[...])
response.ajax_before=<js code>
repsonse.ajax_after=<js code>

and so on. The above info can be sent back as json to the caller ajax
function that decodes it and takes appropriate actions.
Compatibility can be kept by using another ':<target>' target type in
ajax function.

mic

2011/9/7 Massimo Di Pierro <massimo....@gmail.com>:

Anthony

unread,
Sep 7, 2011, 8:14:10 PM9/7/11
to web2py-d...@googlegroups.com
I can see a use case for allowing ajax components or other ajax content to dynamically load CSS and JS files, particularly when there are lots of possible ajax components, and you don't want the loading page to have to load all possible CSS and JS files until they are actually needed. It could also be useful for plugins that may end up in ajax components, as there may be no easy way for the plugin to get CSS/JS files inserted into the loading page (which I think is the case that prompted this discussion).

Maybe add a jQuery ajaxSuccess or ajaxComplete event handler in web2py_ajax.js. Whenever an ajax request completes, the handler can check for a special web2py-include-files header, and if present, the list of files could be passed to a web2py_include_files() function that would check if any of the files are already in the head and insert them if they are not. On the server side, before returning the response, the framework could check if request.ajax is True and if there are any response.files, and if so, add them to the web2py-include-files header.

Anthony

kenji4569

unread,
Sep 7, 2011, 11:06:04 PM9/7/11
to web2py-developers
This is an actual usecase of my plugin:
http://dev.s-cubism.com/plugin_anytime_widget
http://dev.s-cubism.com/plugin_anytime_widget/test/_/load

The former is a demo for normal non-ajax requests,
and the latter is a demo for ajax requests using LOAD function.

You can see that, JS and CSS files are statically loaded for non-ajax
requests, while they are dynamically loaded for ajax requests which
would be not so inefficient.
In this case, I also have the plugin informing web2py of the files
transparently for no-ajax and ajax requests: https://gist.github.com/1202320
So it would be nice that web2py could handle response.files for both
non-ajax and ajax requests.

Further, if you do not want to loose the efficiency for ajax
requests,
you only have to insert the files into the page invoking the LOAD
function, outside the plugin.
Because each JS code embeded in the plugin html is a self-aware for
its initialization (specifically, the code itself waits the
initialization until the required condition becomes true):
https://gist.github.com/1202321
Then I think, using the ajaxSuccess/ajaxComplete event handler could
make the self-aware JS code more efficient by replacing a timer model
to the event model.
It might be usefull for using such a response.ajax_before/
response.ajax_after here.
But in this case as well, I want to make the plugin code transparent
for both non-ajax and ajax requests.

Kenji

Martín Mulone

unread,
Sep 8, 2011, 6:37:30 AM9/8/11
to web2py-d...@googlegroups.com
+1. It would be great if we have a solution to this problem. Massimo you are right perhaps is not the best way to load the files in ajax but I met this problem before, when you have many plugins that change dynamically the page. 

2011/9/8 kenji4569 <hos...@s-cubism.jp>



--

Massimo Di Pierro

unread,
Sep 11, 2011, 9:18:47 PM9/11/11
to web2py-d...@googlegroups.com
Sorry I have ignored this thread because of lack of time. I will get back to this during the week...
Reply all
Reply to author
Forward
0 new messages