Page 3 of 3 FirstFirst 123
Results 21 to 30 of 30

Thread: Firing scripts on Ajax imported pages

  1. #21
    Join Date
    Sep 2007
    Location
    The Netherlands
    Posts
    1,879
    Thanks
    49
    Thanked 266 Times in 258 Posts
    Blog Entries
    56

    Default

    Hi John,
    I've given 'it' much thought, and come up with the following.
    My main concern was to use Ajax as a means to include external content (on the client) and to be able to execute the EXTERNAL CODE pertaining to the external content.
    I thought that document.write was a good way to achieve this. I now realize that we can do without document.write providing we do synchronous requests (with all the disadvantages).
    There's a serious problem indeed in fetching external code if we stick to asynchronous requests at all time, see this.
    ===
    Arie.

  2. #22
    Join Date
    Mar 2005
    Location
    SE PA USA
    Posts
    30,495
    Thanks
    82
    Thanked 3,449 Times in 3,410 Posts
    Blog Entries
    12

    Default

    That's all well and good, and I suppose sync requests have their place. However, consider this (evolving) script:

    Code:
    /* AJAX import Script (c)2010 John Davenport Scheuer
       as first seen in http://www.dynamicdrive.com/forums/
       username: jscheuer1 - This Notice Must Remain for Legal Use
       */
    function loadXmlHttp(url, id, bust){
    	var f = this;
    	f.success = f.failure = function(){return;};
    	f.el = typeof id === 'string'? document.getElementById(id) : id;
    	bust = !bust? null : new Date().getTime();
    	f.url = bust && loadXmlHttp.re[1].test(url)? url + '&bust=' + bust : bust? url + '?bust=' + bust : url;
    	if (loadXmlHttp.xmlHttp){
    		f.xmlHttp = loadXmlHttp.xmlHttp();
    		f.xmlHttp.open("GET", f.url, true);
    		f.xmlHttp.onreadystatechange = function(){f.stateChanged();};
    		f.xmlHttp.send(null);
    	}
    	else alert('Your browser does not support AJAX!'); // substitute your desired request object unsupported code here
    }
    
    loadXmlHttp.xmlHttp = null; loadXmlHttp.re = [/^http/.test(window.location.href), /\?/];
    /*@cc_on @*/ // used here and below, limits try/catch to those IE browsers that both benefit from and support it
    /*@if(@_jscript_version >= 5) // prevents errors in old browsers that barf on try/catch & problems in IE if Active X disabled
    	try {loadXmlHttp.ie = window.ActiveXObject}catch(e){};
    @end @*/
    if (window.XMLHttpRequest && (!loadXmlHttp.ie || loadXmlHttp.re[0])){
    	loadXmlHttp.xmlHttp = function(){return new XMLHttpRequest();}; // Firefox, Opera 8.0+, Safari, others, IE 7+ when live - this is the standard method
    } else if(/(object)|(function)/.test(typeof createRequest)) {
    	loadXmlHttp.xmlHttp = createRequest; // ICEBrowser, perhaps others
    } else {
    	loadXmlHttp.xmlHttp = null;
    	loadXmlHttp.ie = null;
    	// Internet Explorer 5 to 6, includes IE 7+ when local //
    	/*@if(@_jscript_version >= 5)
    		try {
    			loadXmlHttp.ie = new ActiveXObject("Msxml2.XMLHTTP");
    			loadXmlHttp.xmlHttp = function(){return new ActiveXObject("Msxml2.XMLHTTP");};
    		} catch(e){
    			try {
    				loadXmlHttp.ie = new ActiveXObject("Microsoft.XMLHTTP");
    				loadXmlHttp.xmlHttp = function(){return new ActiveXObject("Microsoft.XMLHTTP");};
    			} catch(e){loadXmlHttp.xmlHttp = null;}
    		}
    	@end @*/
    }
    
    loadXmlHttp.prototype.stateChanged = function(){
    	if(this.xmlHttp.readyState === 4){
    		if(this.xmlHttp.status == 200 || !loadXmlHttp.re[0]){
    			if(this.el){
    				this.el.innerHTML = this.xmlHttp.responseText;
    			}
    			this.success();
    		} else {
    			this.failure();
    		}
    	}
    };
    In its simplest form it may be used to place ordinary content into an element by its id:

    Code:
    new loadXmlHttp('external.htm', 'target_id');
    More complex uses -

    Do so while ensuring that the imported file is not retrieved from cache:

    Code:
    new loadXmlHttp('external.htm', 'target_id', true);
    Execute some code after successful import:

    Code:
    var myRequest = new loadXmlHttp('external.htm', 'target_id');
    myRequest.success = function(){myLightbox.updateLinks();};
    There are many possibilities. The failure function can be used to execute code appropriate to a failure to import the intended content or (as below) simply to try again later. The target element may be changed and/or set to null originally:

    Code:
    (function(){
    	var statsrequest = new loadXmlHttp('shoutcaststats.php', null, true), repeat = arguments.callee;
    	statsrequest.success = statsrequest.failure = function(){setTimeout(repeat, 30000);};
    	statsrequest.el = document.getElementById('div2');
    })();
    Other arbitrary properties may be assigned and then used in the success and/or failure functions. No target element need be used, the success function can be employed to do whatever with the responseText or other properties of the response (XML, Headers).

    This code isn't anything all that new. It's pretty much what the major libraries do, but without the need of such a library.

    On the immediate list for additional options to add:

    • The ability to specify GET or POST.
    • If POST, the ability to send $_POST data.
    • Make repetitive requests easier to initialize, with an option to use interval or timeout for them.
    • Optional use of an initialization object, rather than individual argument items.


    But I'm getting a bit off topic. Getting back to your issue, importing code, like a script - I still maintain that the code should be on the 'top' page. The only options I know of to that are a sync request or appending a script tag after setting its src attribute. Either way, you are left waiting in real time for the server to fetch it and the browser to parse it before you can use it. With anything complex, you are just as well served by including it on the 'top' page to begin with. You still need to wait on the server and the browser, but it's the most direct route.
    - John
    ________________________

    Show Additional Thanks: International Rescue Committee - Donate or: The Ocean Conservancy - Donate or: PayPal - Donate

  3. #23
    Join Date
    Sep 2007
    Location
    The Netherlands
    Posts
    1,879
    Thanks
    49
    Thanked 266 Times in 258 Posts
    Blog Entries
    56

    Default

    Quote Originally Posted by jscheuer1 View Post
    I still maintain that the code should be on the 'top' page.
    That's exactly what I do in my last proposal: code out of the external page and into the top page. After that, a synchronous request, because an asynchronous request may fail in terms of code execution. I noticed that it also fails if we use your script as applied to the flex menu: the flex code does not run.
    ===
    Arie.

  4. #24
    Join Date
    Mar 2005
    Location
    SE PA USA
    Posts
    30,495
    Thanks
    82
    Thanked 3,449 Times in 3,410 Posts
    Blog Entries
    12

    Default

    Works good here:

    http://home.comcast.net/~jscheuer1/side/flex_ajax/

    IE was a little balky, but it came around. The added code in the conditional script area appears to only be required locally anyway. See (which of course still works in all others):

    http://home.comcast.net/~jscheuer1/s...x/ie_index.htm

    For the same page without it.


    BTW, since Flex Menu already uses jQuery, jQuery could probably be used for the AJAX import.
    Last edited by jscheuer1; 08-09-2010 at 03:55 PM. Reason: more info on IE
    - John
    ________________________

    Show Additional Thanks: International Rescue Committee - Donate or: The Ocean Conservancy - Donate or: PayPal - Donate

  5. #25
    Join Date
    Sep 2007
    Location
    The Netherlands
    Posts
    1,879
    Thanks
    49
    Thanked 266 Times in 258 Posts
    Blog Entries
    56

    Default

    Quote Originally Posted by jscheuer1 View Post
    Works good here.
    Yes, you're right. I only checked it on the hard drive, where it didn't work.
    ===
    Arie.

  6. #26
    Join Date
    Mar 2005
    Location
    SE PA USA
    Posts
    30,495
    Thanks
    82
    Thanked 3,449 Times in 3,410 Posts
    Blog Entries
    12

    Default

    In fairness to you I had to remove, comment out this from the flexdropdown.js script:

    Code:
    //By default, add flex menu to anchor links with attribute "data-flexmenu"
    jQuery(document).ready(function($){
    	var $anchors=$('*[data-flexmenu]')
    	$anchors.each(function(){
    		$(this).addflexmenu(this.getAttribute('data-flexmenu'))
    	})
    })
    There probably is code somewhere that prevents repeat initialization. At least several DD scripts have that. One should be able to get around that by using a different selector for imported content. But, without at least a minor rewrite to the flexdropdown.js script, that would make removing and adding back the menu content problematic, but probably so regardless of the import method.

    Also, I was right about using jQuery for the import:

    http://home.comcast.net/~jscheuer1/s...x/jq_index.htm

    works like a charm, no need for my AJAX script.
    - John
    ________________________

    Show Additional Thanks: International Rescue Committee - Donate or: The Ocean Conservancy - Donate or: PayPal - Donate

  7. #27
    Join Date
    Sep 2007
    Location
    The Netherlands
    Posts
    1,879
    Thanks
    49
    Thanked 266 Times in 258 Posts
    Blog Entries
    56

  8. #28
    Join Date
    Mar 2005
    Location
    SE PA USA
    Posts
    30,495
    Thanks
    82
    Thanked 3,449 Times in 3,410 Posts
    Blog Entries
    12

    Default

    Using all jQuery methods, we can easily remove and restore the menu, probably even import various menus as well as have a hard coded Flex Menu(s) on the page at the same time without modifying flexdropdown.js:

    http://home.comcast.net/~jscheuer1/s...x_ajax/all_jq/

    Using just:

    Code:
    jQuery(function($){
    	$.ajax({ url: "../external.htm", success: function(response){
    	        $('#flexTarget').html(response);
    	        $('*[data-flexmenu]').each(function(){
    			$(this).addflexmenu(this.getAttribute('data-flexmenu'));
    			});
    		}});
    });
    works cross browser for simply inserting the menu.

    The 'problem' with flexdropdown.js was just as I imagined. It keeps track of initialized menus and won't reinitialize one it thinks it already has. The only way it keeps track is by the id's of the flyouts, so even if they are removed, it will still think they are there. Further though, it assigns data and events to elements and moves them around in the DOM. This is no problem for the first insertion. But if we wish to reinsert, or insert a different menu in the same spot, we have to clean up the mess from the previous one, including the record of the id, all of the markup and assigned data and events. That's what this latest version (the link, not the code block above) does.
    Last edited by jscheuer1; 08-10-2010 at 01:35 PM. Reason: Found a better way
    - John
    ________________________

    Show Additional Thanks: International Rescue Committee - Donate or: The Ocean Conservancy - Donate or: PayPal - Donate

  9. The Following User Says Thank You to jscheuer1 For This Useful Post:

    molendijk (08-10-2010)

  10. #29
    Join Date
    Sep 2007
    Location
    The Netherlands
    Posts
    1,879
    Thanks
    49
    Thanked 266 Times in 258 Posts
    Blog Entries
    56

    Default

    Ahah! That explains a lot of things that were puzzling me. Thanks.
    ===
    Arie.

  11. #30
    Join Date
    Sep 2007
    Location
    The Netherlands
    Posts
    1,879
    Thanks
    49
    Thanked 266 Times in 258 Posts
    Blog Entries
    56

    Default

    Hi John,
    I found that there are still too many cases in which (i) doing a request after the page has finished loading and / or (ii) refusing synchronous requests may cause problems as far as execution of external code is concerned.
    So I created this workaround. (I know you won't agree).
    ===
    Arie.
    Last edited by molendijk; 09-09-2010 at 11:48 AM. Reason: URL modified

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •