Ajax.Updater vs Script

0 views
Skip to first unread message

Jean-Philippe Encausse

unread,
Jan 27, 2008, 3:02:22 PM1/27/08
to rubyonrail...@googlegroups.com
Hi,

I would like to download the Script of MyBlogLog in AJAX and then put
it in the page.
Does anybody already did that ?


The problems seems to be generic:

1. I call a script Event.observe(window, 'load', ...
2.1 I generate <script></script> under a given Id
2.1.1 with InnerHTML it do not work
2.1.2 with dom elments it works but override the full page
2.2 Using Ajax.Updater it seems connection fails

- What is the best practice tounderstand why the connection is refused ?
- What is the best pratice to include a <script> tag in a given place
of the DOM ? should be usefull for all the gadgets doing stuff like
MyBLogLog, Viadeo, ...


Best Regards,
Jp


--
Jean-Philippe Encausse - Veille / R&D Jalios SA
Jp [at] encausse.net - http://www.encausse.com - http://www.jalias.com
GTalk: jp.encausse [at] gmail.com - SMS: sms [at] jp.encausse.net
Mob: +33 6 82 12 56 99 - Job: +33 1 39 23 92 83 - Tel: +33 1 39 18 90 15
Do it Once, Use it Twice ~ Do it Twice, Make It Once

Nathan Nobbe

unread,
Jan 27, 2008, 3:20:29 PM1/27/08
to rubyonrail...@googlegroups.com
On Jan 27, 2008 3:02 PM, Jean-Philippe Encausse <J...@encausse.net> wrote:
1. I call a script Event.observe(window, 'load', ...
2.1 I generate <script></script> under a given Id
im not entirely sure what you mean here, can you be more specific?
for example, are you dynamically creating a <script> tag and inserting
it into the dom to create functionality once the page has been loaded on
the client system?

2.1.1 with InnerHTML it do not work
2.1.2 with dom elments it works but override the full page
hmm; is the container element properly closed in the dom?

2.2 Using Ajax.Updater it seems connection fails
verify the url is valid.
check the response code from the server.
look into firebug.

- What is the best practice tounderstand why the connection is refused ?
you need to verify the url you are requesting is legitimate.
you can paste the url in the browser and see if you get a response.
you may not even be contacting the webserver, depending on the url.
if you are contacting the webserver, you should look at the response code.
this will give you insight as to why the server could not respond w/ a valid resource.
have you worked with firebug for firefox, it allows you to monitor ajax calls.
 
- What is the best pratice to include a <script> tag in a given place
of the DOM ?
If you mean dynamically, during an Ajax request, then Ajax.Updater will run anything
enclosed in <script> tags (in the response) through a call to eval(), provided
you set the Ajax option, evalScripts to true when you instantiate Ajax.Updater.

-nathan

Jean-Philippe Encausse

unread,
Jan 27, 2008, 5:04:22 PM1/27/08
to rubyonrail...@googlegroups.com
Thanks for your answer

> dynamically creating a <script> tag and inserting
> it into the dom to create functionality once the page has been loaded on
> the client system?

Yes exactly, I'm try to include the script of MyBlogLog that should be:
<script src="http://pub.mybloglog.com/comm2.php?mblID=2006121510341039"
type="text/javascript"></script>
The url is longer normally and it works.


When requesting from browser:
http://pub.mybloglog.com/comm2.php?mblID=2006121510341039
This will return a script that generate <table>

So I try:

Event.observe(window, 'load', function() {
// Using 'static' object
JCMS.plugin.mybloglog.MyBlogLog.insertScript();
});

Then I'm using a <a href="mybloglog url"></a> to retrieve the location
and url to call

JCMS.plugin.mybloglog.MyBlogLog = {

insertScript : function () {
var elm = $('MyBlogLog');

var url = elm.href;
var address = url.substring(0,url.indexOf('?'));
var params = $H(url.toQueryParams());

/* Option 1
var script = document.createElement('SCRIPT');
script.type='text/javascript';
script.src = address+"?"+params.toQueryString();
elm.parentNode.appendChild(script);
*/

/* Option 2
// elm.parentNode.innerHTML = "<script type='text/javascript'
src='"+address+"?"+params.toQueryString()+"'></script>"
*/

/* Option 3
new Ajax.Updater(elm.parentNode, address, {
parameters: {
mblID: '2006121510341039',
}
*/
});
}
};


- I don't know what is the best way to do it ?
- I do not want to directly write the <script> tag in the page because
it may slow down the page loading.
- How can I have the response code from the Ajax request ?
- Should I set a userAgent ?

Thanks

--

Nathan Nobbe

unread,
Jan 27, 2008, 8:09:09 PM1/27/08
to rubyonrail...@googlegroups.com

im not sure why you want to retrieve the remote script once the page has loaded.
why dont you just include

<script src="http://pub.mybloglog.com/comm2.php?mblID=2006121510341039"
type="text/javascript"></script>
in the server side code that produces the page?

-nathan
 

Justin Perkins

unread,
Jan 27, 2008, 10:02:19 PM1/27/08
to rubyonrail...@googlegroups.com
On Jan 27, 2008 7:09 PM, Nathan Nobbe <quicks...@gmail.com> wrote:
> im not sure why you want to retrieve the remote script once the page has
> loaded.

It's actually a very nice way to include external scripts, since the
loading of a script (with src) has an effect on page load times, which
impacts tasks that run on page load and also visible to the user by
way of the browser's progress indicator.

You can create script nodes on the fly, with normal DOM-node creating
code and it works well in Firefox and IE6/7. I have not tested other
browsers.

This is the basic idea: http://pastie.textmate.org/144194

Note that the first thing that code does is look for a script include
already on the page that has included the same script, and if it is
found, then it is removed. This may be overkill, but is done to
prevent caching problems. If the same function that includes the
script is called multiple times, and you're expecting the script to be
refreshed, then you may want to append some type of no-cache parameter
(a time stamp) onto the URL, such as:

// do this just before the call to setAttribute('src', src)
src = ( src.match( /\?/ ) ? src + '&' : src + '?' ) + ( nocache ?
'nocache=' + new Date().getTime() + '&' : '' );

This little snippet has worked out very well for me, especially when
requesting external scripts that may take a while to load.

Have a great night.

-justin

Nathan Nobbe

unread,
Jan 27, 2008, 10:14:58 PM1/27/08
to rubyonrail...@googlegroups.com

if you want a good model for dynamically loading scripts via ajax with the
protoype framework, take a look at scriptacuolus.js, they have the exact
mechanism you are looking for in place already.
also, per the construction of dom nodes dynamically, take a look at builder.js
also bundled in the scriptaculous library.

-nathan

Jean-Philippe Encausse

unread,
Jan 28, 2008, 4:29:11 AM1/28/08
to rubyonrail...@googlegroups.com
@Nathan Nobbe:

I do not want to simply write <script> tag because like Justin Perkins
explain during the loading of the page when the browser see a <script>
tag it execute it. So if the server hang, the page slow down...

Scriptaculous use a handy way to write <script> tag. But it did it
- In the <head> or where it is declared
- Immediatly not onload

@Justin Perkins:

Thanks i'm going to try that. It is close to what I already tried. If
I remember the script loads but replace the full page. It's a little
bit weird.


I will try to send my question to MyBLogLog team. May be they already
know this issue.
Thanks

--

Nathan Nobbe

unread,
Jan 28, 2008, 9:56:57 AM1/28/08
to rubyonrail...@googlegroups.com
On Jan 27, 2008 10:02 PM, Justin Perkins <justin...@gmail.com> wrote:
It's actually a very nice way to include external scripts, since the
loading of a script (with src) has an effect on page load times, which
impacts tasks that run on page load and also visible to the user by
way of the browser's progress indicator.

You can create script nodes on the fly, with normal DOM-node creating
code and it works well in Firefox and IE6/7. I have not tested other
browsers.

This is the basic idea: http://pastie.textmate.org/144194
 
great example, thanks.
also, like i mentioned, scriptaculous does essentially the same thing in
scriptaculous.js, the main difference in the scriptaculous code is that it
has some runtime checks for prototype and it only tries to load scriptaculous
modules.

  require: function(libraryName) {
    // inserting via DOM fails in Safari 2.0, so brute force approach
    document.write('<script type="text/javascript" src="'+libraryName+'"><\/script>');
  }

/// later in the code..
    $A(document.getElementsByTagName("script")).findAll( function(s) {
      return (s.src && s.src.match(/scriptaculous\.js(\?.*)?$/))
    }).each( function(s) {
      var path = s.src.replace(/scriptaculous\.js(\?.*)?$/,'');
      var includes = s.src.match(/\?.*load=([a-z,]*)/);
      (includes ? includes[1] : 'builder,effects,dragdrop,controls,slider,sound').split(',').each(
       function(include) { Scriptaculous.require(path+include+'.js') });
    });

Note that the first thing that code does is look for a script include
already on the page that has included the same script, and if it is
found, then it is removed. This may be overkill, but is done to
prevent caching problems. If the same function that includes the
script is called multiple times, and you're expecting the script to be
refreshed, then you may want to append some type of no-cache parameter
(a time stamp) onto the URL, such as:

// do this just before the call to setAttribute('src', src)
src = ( src.match( /\?/ ) ? src + '&' : src + '?' ) + ( nocache ?
'nocache=' + new Date().getTime() + '&' : '' );

This little snippet has worked out very well for me, especially when
requesting external scripts that may take a while to load.

im certainly interested in loading scripts dynamically.  it seems to me that
scripts that would be handy after a page has loaded would be best loaded in
this manor, however, scripts that need to run when the page first loads should
be included in <script> tags by the html rendered on the server.  unless im still
missing something..
for example, im working on an application where i have a script that produces
specialized buttons.  each button has several css classes that can be associated
with it depending upon the mouse position in relation to it (mouesover, mouesout,
mousedown), and it also allows client code to attach a click handler to each button.
this class is stored in its own file on the server and i load it in a <script> tag on
pages that need it.  are you saying i would be better off to load this script dynamically?

-nathan

Justin Perkins

unread,
Jan 28, 2008, 10:46:16 AM1/28/08
to rubyonrail...@googlegroups.com
On Jan 28, 2008 3:29 AM, Jean-Philippe Encausse <J...@encausse.net> wrote:
> Thanks i'm going to try that. It is close to what I already tried. If
> I remember the script loads but replace the full page. It's a little
> bit weird.

The script you are including is probably doing document.write, which
is fine if the script is running in an IFRAME (I'm guessing you're
doing advertisements?). Try using DOM-manipulation techniques instead.

-justin

Nathan Nobbe

unread,
Jan 28, 2008, 10:50:35 AM1/28/08
to rubyonrail...@googlegroups.com
On Jan 28, 2008 10:46 AM, Justin Perkins <justin...@gmail.com> wrote:
The script you are including is probably doing document.write, which
is fine if the script is running in an IFRAME (I'm guessing you're
doing advertisements?). Try using DOM-manipulation techniques instead.

the script is just a simple thing to allow 'buttons' to be animated.  they are typcially
styled span tags.  i make them appear as buttons, using css and javascript.
there is no dynamic writing of dom elements.  the dom elements are sent from
the server and im using onDOMReady() to apply the prototype based class to them.

var CssButtons = Class.create({
        initialize : function(buttonDomIds, buttonHoverClassnames, buttonPressedClassnames, clickEventHandlers, buttonNormalStyles, buttonHoverStyles, buttonPressedStyles) {
                this.buttonDomIds = $H(buttonDomIds);
                this.buttonHoverClasses = buttonHoverClassnames;
                this.buttonHoverStyles = buttonHoverStyles;
                this.buttonNormalStyles = buttonNormalStyles;
                this.buttonPressedStyles = buttonPressedStyles;
                this.buttonPressedClasses = buttonPressedClassnames;
                this.clickEventHandlers = $(clickEventHandlers);
                this._registerListeners();
// register event handlers for the buttons
        }
        ,
        _registerListeners : function() {
                this.buttonDomIds.each(function(pair) {
                        element = pair.value;
                        if($(element) == null) {                // dont attempt to register listeners for an element that doesnt exist
                                return;
                        }
                        var hoverClass = this.hoverClass;
                        var pressedClass = this.pressedClass;
                        this.buttonDomIds[pair.key] = $(element);               // extend these dom ids, prototype sytle
                        Event.observe(element, 'mouseover', function() {
                                $(this.buttonDomIds[pair.key]).select('span').each(function(elt) {
                                        elt.setStyle(this.buttonHoverStyles[pair.key]);
                                }.bind(this));
                                $(this.buttonDomIds[pair.key]).removeClassName(this.buttonHoverClasses[pair.key]);
                                $(this.buttonDomIds[pair.key]).addClassName(this.buttonHoverClasses[pair.key]);
                        }.bindAsEventListener(this));
                        Event.observe(element, 'mouseout', function() {
                                $(this.buttonDomIds[pair.key]).select('span').each(function(elt) {
                                        elt.setStyle(this.buttonNormalStyles[pair.key]);
                                }.bind(this));
                                $(this.buttonDomIds[pair.key]).removeClassName(this.buttonHoverClasses[pair.key]);
                                $(this.buttonDomIds[pair.key]).removeClassName(this.buttonPressedClasses[pair.key]);
                        }.bindAsEventListener(this));
                        Event.observe(element, 'mousedown',  function() {
                                $(this.buttonDomIds[pair.key]).select('span').each(function(elt) {
                                        elt.setStyle(this.buttonPressedStyles[pair.key]);
                                }.bind(this));
                                $(this.buttonDomIds[pair.key]).removeClassName(this.buttonHoverClasses[pair.key]);
                                $(this.buttonDomIds[pair.key]).addClassName(this.buttonPressedClasses[pair.key]);
                        }.bindAsEventListener(this));
                        /// add an event handler for the click event of the button, if one has been supplied
                        if(this.clickEventHandlers[pair.key] !== undefined &&
                                this.clickEventHandlers[pair.key] !== null) {
                                Event.observe(element, 'click', this.clickEventHandlers[pair.key]);
                        }
                }.bind(this));
        }
});

-nathan

Justin Perkins

unread,
Jan 28, 2008, 11:22:37 AM1/28/08
to rubyonrail...@googlegroups.com
On Jan 28, 2008 9:50 AM, Nathan Nobbe <quicks...@gmail.com> wrote:
> the script is just a simple thing to allow 'buttons' to be animated.

Why do you include something like that through a remote script
include? Why can't you include that code in your local application's
javascript file? Is it for maintenance reasons?

-justin

Nathan Nobbe

unread,
Jan 28, 2008, 11:27:55 AM1/28/08
to rubyonrail...@googlegroups.com
On Jan 28, 2008 11:22 AM, Justin Perkins <justin...@gmail.com> wrote:
Why do you include something like that through a remote script
include?
 
i keep the various scripts separated so that they may be reused easily.
 
Why can't you include that code in your local application's
javascript file?

you mean in a <script> tag w/o a src attribute, i could, i suppose, it wouldnt
be very difficult.  is it really that great of a benefit?
 
Is it for maintenance reasons?

no, for keeping the sources well organized.

thanks for you advice,

-nathan
Reply all
Reply to author
Forward
0 new messages