PDA

View Full Version : Firing scripts on Ajax imported pages



molendijk
07-04-2010, 11:23 PM
1) CODE TITLE: Firing scripts on Ajax imported pages

2) AUTHOR NAME: Arie Molendijk

3) DESCRIPTION: There have been several questions lately on the DD forums on how to make 'external' scripts fire on Ajax imported pages. The general idea underlying the answers given to these questions has been that these scripts generally do not execute. The goal of this thread is to show that - on the contrary - external scripts belonging to Ajax imported files can be easily forced to execute. All we have to do is document.write the external files to a hidden div.

4) URL TO CODE:
http://www.let.rug.nl/molendyk/include_ajax_no_code_excecution_problem/main.html

jscheuer1
07-05-2010, 10:02 PM
Hi Arie,

I don't know if you intended this or not, but it doesn't look good:

Your 'imported functions' work before they are imported. So, regardless of whether or not your code performs as advertised, it looks just like it would if it had done nothing.

Also, this is not AJAX.

molendijk
07-05-2010, 11:15 PM
Your 'imported functions' work before they are imported.
Excellent observation. The imported functions work before the include(content,id) function makes the external text visible because the external files containing the functions are document.written (invisibly) to the main page while it is still loading. It's the include(content,id) function that makes the text of the external files visible (at an arbitrarily chosen part of the page). In other words, this is not an authentic dynamic Ajax-include, but one that makes it look like one.


So, regardless of whether or not your code performs as advertised, it looks just like it would if it had done nothing.
No, if the code would have done nothing, the external functions would not work in the main page.
The whole idea is to (i) invisibly import external text AND code with the help of document.write (as opposite to innerHTML or appendChild, document.write brings in external code together with text); (ii) make the external text visible with innerHTML and appendChild (using the include(content,id) function).

To resume what I did: I faked dynamically including external text PLUS code by (i) bringing in external text plus code (using document.write) while the main page is loading and (ii) making the external text visible 'afterwards'.
===
Arie.

jscheuer1
07-06-2010, 12:35 AM
After playing with the code you supplied in:

http://www.dynamicdrive.com/forums/showpost.php?p=230664&postcount=7

I presumed as much as what you are saying.

I'm not sure how this is any different in effect, though much less efficient than:


<script type="text/javascript" src="some.js"></script>

molendijk
07-06-2010, 09:16 AM
I'm not sure how this is any different in effect, though much less efficient than:

<script type="text/javascript" src="some.js"></script>
Yes, my code does about the same. But it does not have to transform the external content into js-format before inclusion.
===
Arie.

jscheuer1
07-06-2010, 09:55 AM
Yes, my code does about the same. But it does not have to transform the external content into js-format before inclusion.
===
Arie.

An external script tag doesn't transform anything either.

So for scripts then there are external script tags. For code that is not, there's ordinary AJAX. Why complicate things with document.write()?

molendijk
07-06-2010, 11:37 AM
OK John, I misunderstood you. What I mean is this:
Suppose we want to include an external file external.html having text and code. Then if we want to be able to run the code after inclusion, we can do (among other things) the following:
(i) We include external.html (with the help of Ajax or some other method, like a hidden iframe) using innerHTML (and/or appendChild). In that case, we have to use some separate device for including the code belonging to external.html (but see (iii)).
(ii) We entirely transform external.html to a text-string Str and then document.write Str to the main document (I thought you were referring to this in your previous post). In that case, we don't have to separately include the external code belonging to external.html, thanks to document.write.
(iii) We do as in (i), but at the same time we document.write external.html to a hidden div of the main page with the help of Ajax. Using Ajax dispenses us from transforming external.html to a text-string first (see (ii)). The code will run, thanks to document.write.
===
Arie.

jscheuer1
07-06-2010, 12:35 PM
When using AJAX (Asynchronous JavaScript and XML), your code must use the asynchronous method, otherwise it's not AJAX. Using the asynchronous method, document.write will probably fail or cause undesirable results.

Regardless of the nature of the request (be it synchronous or asynchronous), using the responseText doesn't dispense with converting the external file to a text string. It is a text string. In other words you have done just that, converted the external file to a text string.

Since you are apparently stuck using a non-AJAX synchronous request, your page will hang if there is a problem (server traffic too high, file not found, etc.). It's somewhat like having an alert on the page and no one ever clicks OK.

Why anyone would prefer this over an external script tag is beyond me.

molendijk
07-06-2010, 01:23 PM
When using AJAX (Asynchronous JavaScript and XML), your code must use the asynchronous method, otherwise it's not AJAX.
That's correct. So let's call it Pseudo-Ajax, or Mini-Hercules, or whatever.


Regardless of the nature of the request (be it synchronous or asynchronous), using the responseText doesn't dispense with converting the external file to a text string. It is a text string. In other words you have done just that, converted the external file to a text string.
Correct. But I don't see the problem there. That's exactly why I introduced document.write.


Why anyone would prefer this over an external script tag is beyond me.
Using my script, you don't have to figure out what exactly is the external code you have to explicitly (manually, probably) bring into the main page in order for the external code to automatically work (in the main page). As I see it, that's a clear advantage of my script if the external code is complicated.
===
Arie.

jscheuer1
07-06-2010, 01:58 PM
Using my script, you don't have to figure out what exactly is the external code you have to explicitly (manually, probably) bring into the main page in order for the external code to automatically work (in the main page). As I see it, that's a clear advantage of my script if the external code is complicated.

You always have to figure out what the script is. Otherwise you don't know what code it is you are running. If the script is dynamically generated, use the appropriate extension for the script filename. Even then you know what the script code is, just not the specifics that will be passed to it.

Just put the script in an external file and invoke it on the main page with an external script tag. There will be less chance of a server problem or document.write() messing up the rest of the page.

molendijk
07-06-2010, 06:07 PM
You always have to figure out what the script is. Otherwise you don't know what code it is you are running..
Suppose I have a standalone listmenu in a file menu.html. Also suppose I want to include the menu in a page includer.html. Then I know what script(s) I want to run in includer.html without specifically looking what is inside menu.html: I want to run the script(s) that make(s) menu.html work as a standalone menu. Using my document.write lines in the Ajax-script, then, will make the external script(s) work in includer.html.
===
Arie.

jscheuer1
07-07-2010, 12:12 AM
Suppose I have a standalone listmenu in a file menu.html. Also suppose I want to include the menu in a page includer.html. Then I know what script(s) I want to run in includer.html without specifically looking what is inside menu.html: I want to run the script(s) that make(s) menu.html work as a standalone menu. Using my document.write lines in the Ajax-script, then, will make the external script(s) work in includer.html.

So will other methods that don't involve a synchronous request and the document.write() method. In case you don't know, if a request is synchronous, as your code appears to require, it can cause the page to hang if there is any problem.

Also, using document.write() to execute script code is very much like using eval.

Either of these two methods (document.write to execute script code and synchronous requests) will often work. But, more often than most other methods, they will cause problems.

molendijk
07-08-2010, 12:09 AM
So will other methods that don't involve a synchronous request and the document.write() method. In case you don't know, if a request is synchronous, as your code appears to require, it can cause the page to hang if there is any problem.

Also, using document.write() to execute script code is very much like using eval.

Either of these two methods (document.write to execute script code and synchronous requests) will often work. But, more often than most other methods, they will cause problems.
John, see my last post here (http://www.dynamicdrive.com/forums/showthread.php?p=231012#post231012). My code seems to work even if a non-existing page is requested or if the page_to_be_included is 'heavy'. No page-hanging problems.
===
Arie.

jscheuer1
07-08-2010, 03:53 AM
Well, I didn't think of that. But with a page not found, you are getting a page. I'm talking about a situation where there is no page supplied for a 404. That's rare but can happen. There are also other cases where the request could fail. If in any of those the server doesn't send something that can be interpreted as the responseText, the page will hang. This is not so with an asynchronous request.

As for a heavy request being constituted by a large image, that's wrong. Unless it's the image itself that is requested synchronously, all you are doing is pulling in code to get the image. After that the image loads in the normal manner for all image loads on a page, which is asynchronously.

molendijk
07-08-2010, 10:27 PM
So, John, if I get you right, you would not recommend this DD-script (http://www.dynamicdrive.com/dynamicindex17/ajaxincludes.htm) nor this one (http://www.dynamicdrive.com/dynamicindex17/ajaxrotate.htm) (both of which my script is an exension)?
===
Arie.

jscheuer1
07-09-2010, 03:11 AM
Would anyone? If you haven't noticed, DD often keeps around outdated and/or unwise scripts.

This site lives on traffic. Many of these scripts, like disable right click or some of the early menus and slide shows just aren't reasonable. But they do draw people in.

I'm not entirely opposed to such an approach on DD's part. It does get folks interested.

In any case, the scripts you refer to are not AJAX and neither is your script.

I'm not opposed to synchronous requests in general. They should not be called AJAX though. They're not. At the time DD authored those scripts, I don't think DD knew the difference. Those pages haven't been updated since then. That's all.

At least DD's more recent forays into AJAX are actual AJAX.

As far as I can see though, all you are doing is pulling in external script code. That's a job for an external script tag.

If I recall correctly, you even recommend that for compatibility with IE that it is best to document.write an external script tag.

That being the case, why not just use an external script tag to begin with?

Additionally, you are often writing other content along with your script to the head. Even though this is to a display none division, it's invalid in the head and could therefore lead to problems.

And there is the matter of using document.write() to write javascript. It's fairly safe the way you are doing it. But whenever you execute code that was a string passed to eval(), innerHTML, document.write(), or to new Function(), (there could be others) you are asking for trouble.

molendijk
07-10-2010, 04:26 PM
John, thanks for all your useful observations.
While keeping my old script - since it seems to work in most cases - I'm planning to create an asynchronous Ajax request that will at least run the code that is internal in the pages_to_be_included. In this regard, the following can be observed (which is not typically Ajax, but can be applied to Ajax).
If we have a string str containing text AND code, then the following works (by which I mean that the code inside the string can be activated), but we don't want this, since it's the non-Ajax equivalent of my synchronous Ajax-script:

<script type="text/javascript">
var str =
'<script type="text\/javascript">\nfunction red()\n{\ndocument.body.style.background=\'red\'\n}\nfunction yellow()\n{\ndocument.body.style.background=\'yellow\'\n}\n<\/script>\nEXTERNAL 1<br>\n<a href="javascript: void(0)" onclick="red()">make background red<\/a><br>\n<a href="javascript: void(0)" onclick="yellow()">make background yellow<\/a><br>';

document.write('<div style="display: none">');
document.write(str);
document.write('<\/div>');
function include(content,id){
document.getElementById(id).innerHTML=content
}
</script>

<a href="javascript: void(0)" onclick="include(str,'some_div');">add string containing text and code</a>
<div id="some_div" ></div>
The following won't work, by which I mean that the code contained in str is not executed:

<script type="text/javascript">
var str =
'<script type="text\/javascript">\nfunction red()\n{\ndocument.body.style.background=\'red\'\n}\nfunction yellow()\n{\ndocument.body.style.background=\'yellow\'\n}\n<\/script>\nEXTERNAL 1<br>\n<a href="javascript: void(0)" onclick="red()">make background red<\/a><br>\n<a href="javascript: void(0)" onclick="yellow()">make background yellow<\/a><br>';

function include(content,id){
document.getElementById(id).innerHTML=content
}
</script>

<a href="javascript: void(0)" onclick="include(str,'some_div');">add string containing text and code</a>
<div id="some_div" ></div>

This does work, but only in Firefox, not in IE/Chrome/Opera:

<script type="text/javascript">
var str =
'<script type="text\/javascript">\nfunction red()\n{\ndocument.body.style.background=\'red\'\n}\nfunction yellow()\n{\ndocument.body.style.background=\'yellow\'\n}\n<\/script>\nEXTERNAL 1<br>\n<a href="javascript: void(0)" onclick="red()">make background red<\/a><br>\n<a href="javascript: void(0)" onclick="yellow()">make background yellow<\/a><br>';

function include(content,id){
var newdiv = document.createElement("div");
newdiv.innerHTML = content;
document.getElementById(id).appendChild(newdiv);
}
</script>

<a href="javascript: void(0)" onclick="include(str,'some_div');">add string containing text and code</a>
<div id="some_div" ></div>
This works everywhere except in IE and Chrome:

<script type="text/javascript">
var str =
'<script type="text\/javascript">\nfunction red()\n{\ndocument.body.style.background=\'red\'\n}\nfunction yellow()\n{\ndocument.body.style.background=\'yellow\'\n}\n<\/script>\nEXTERNAL 1<br>\n<a href="javascript: void(0)" onclick="red()">make background red<\/a><br>\n<a href="javascript: void(0)" onclick="yellow()">make background yellow<\/a><br>';

function include(content,id){
rng = document.createRange();
rng.setStartBefore(document.getElementById(id));
htmlFrag = rng.createContextualFragment(content);
document.getElementById(id).appendChild(htmlFrag);
}
</script>

<a href="javascript: void(0)" onclick="include(str,'some_div');">add string containing text and code</a>
<div id="some_div" ></div>
And this works works everywhere!:

<script type="text/javascript">
var str =
'<script type="text\/javascript">\nfunction red()\n{\ndocument.body.style.background=\'red\'\n}\nfunction yellow()\n{\ndocument.body.style.background=\'yellow\'\n}\n<\/script>\nEXTERNAL 1<br>\n<a href="javascript: void(0)" onclick="red()">make background red<\/a><br>\n<a href="javascript: void(0)" onclick="yellow()">make background yellow<\/a><br>';

function include(content,id){
document.getElementById(id).innerHTML=content

//Found at http://www.webdeveloper.com/forum/archive/index.php/t-177998.html
var search=str
document.getElementById(id).innerHTML=search;
var script;
while(script = search.match(/(<script[^>]+javascript[^>]+>\s*(<!--)?)/i))
{
search = search.substr(search.indexOf(RegExp.$1) + RegExp.$1.length);
if (!(endscript = search.match(/((-->)?\s*<\/script>)/))) break;
block = search.substr(0, search.indexOf(RegExp.$1));
search = search.substring(block.length + RegExp.$1.length);
var oScript = document.createElement('script');
oScript.text = block;
document.getElementsByTagName("head").item(0).appendChild(oScript);
}
}
</script>

<a href="javascript: void(0)" onclick="include(str,'some_div');">add string containing text and code</a>
<div id="some_div" ></div>

I'll try to transform the last script into asynchronous Ajax code. Shouldn't be too difficult. I'll let you know as soon as I'll be back from a vacation that starts to morrow.
Arie.

jscheuer1
07-10-2010, 05:55 PM
RegExp.$1

is deprecated. But one can substitute elements of an array created by match() or exec().

However, that's a fine point. This code still generates javascript from a string, which isn't a real great idea. There are other ways to get the end result you want. This one works in all modern browsers:


<script type="text/javascript" src="external.js"></script>

If you want to later fetch and/or inject HTML code that will use that script, fine.

I don't see the big deal, except that folks so often do get excited when they see that their scripts on AJAX imported pages aren't working. They just need to put the scripts on the 'top' page. But scripts which initialize onload still have problems.

There are ways of overcoming that. One is to do a poll to initialize elements that arrive later (I believe that is what jQuery's live() does). Another is rather than rely upon initializing an event to an element, initialize it to the document and analyze the target element to determine what if any action to take.

In the case of that other thread where I believe the person wants to import a script that was generated by PHP onload of the page:


<script type="text/javascript" src="somescript.php"></script>

Which can be generated in part via session variables or even get:


<script type="text/javascript" src="somescript.php?param1=22&amp;param2=<?php echo $username; ?>"></script>

molendijk
07-27-2010, 07:29 PM
I don't know much about regex. What should I do to make the following script work without the deprecated $1? (It works as it is).

<script type="text/javascript">
var str =
'<script type="text\/javascript">\nfunction red()\n{\ndocument.body.style.background=\'red\'\n}\nfunction yellow()\n{\ndocument.body.style.background=\'yellow\'\n}\n<\/script>\nEXTERNAL 1<br>\n<a href="javascript: void(0)" onclick="red()">make background red<\/a><br>\n<a href="javascript: void(0)" onclick="yellow()">make background yellow<\/a><br>';

function include(content,id){
document.getElementById(id).innerHTML=content

//Found at http://www.webdeveloper.com/forum/archive/index.php/t-177998.html
var search=str
document.getElementById(id).innerHTML=search;
var script;
while(script = search.match(/(<script[^>]+javascript[^>]+>\s*(<!--)?)/i))
{
search = search.substr(search.indexOf(RegExp.$1) + RegExp.$1.length);
if (!(endscript = search.match(/((-->)?\s*<\/script>)/))) break;
block = search.substr(0, search.indexOf(RegExp.$1));
search = search.substring(block.length + RegExp.$1.length);
var oScript = document.createElement('script');
oScript.text = block;
document.getElementsByTagName("head").item(0).appendChild(oScript);
}
}
</script>
Thanks in advance,
Arie.

jscheuer1
07-28-2010, 12:18 AM
As I said, it's a fine point. There are much better ways of including javascript on a page than document.write(), regardless of whether regular expressions are used or not. Another method for use with AJAX is the callback. You can create a callback in your AJAX routine by including it or a hook for it in the onreadystatechange function. That's how the major script libraries do it.

As to this minor business on deprecated properties for regular expressions, see:

https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Deprecated_Features#RegExp_Properties

It's the first listed.

The properties and methods that aren't deprecated are listed here:

https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/RegExp#Properties_2

To get these values from a regular expression, one can do a match, as you already have. Set a variable equal to that match. If the match finds nothing, that variable will be null. If it does find a match, it will be an array. I usually use trial and error to find what index of the array has what I want, but the documentation I linked to above does specify it for you.

Also, with the exec() method (depending upon the regular expression) often there is only one index (0) and it contains the matched string.

molendijk
08-08-2010, 11:17 PM
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 (http://www.let.rug.nl/molendyk/include_ajax_plus_code_best_way/includer.html).
===
Arie.

jscheuer1
08-09-2010, 01:11 AM
That's all well and good, and I suppose sync requests have their place. However, consider this (evolving) script:


/* 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:


new loadXmlHttp('external.htm', 'target_id');

More complex uses -

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


new loadXmlHttp('external.htm', 'target_id', true);

Execute some code after successful import:


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:


(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.

molendijk
08-09-2010, 02:44 PM
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 (http://www.dynamicdrive.com/dynamicindex1/flexdropdown.htm): the flex code does not run.
===
Arie.

jscheuer1
08-09-2010, 03:36 PM
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/side/flex_ajax/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.

molendijk
08-09-2010, 04:23 PM
Works good here.
Yes, you're right. I only checked it on the hard drive, where it didn't work.
===
Arie.

jscheuer1
08-09-2010, 05:10 PM
In fairness to you I had to remove, comment out this from the flexdropdown.js script:


//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/side/flex_ajax/jq_index.htm

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

molendijk
08-09-2010, 05:23 PM
Thanks John, very useful.
===
Arie.

jscheuer1
08-09-2010, 06:20 PM
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/side/flex_ajax/all_jq/

Using just:


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.

molendijk
08-10-2010, 07:20 PM
Ahah! That explains a lot of things that were puzzling me. Thanks.
===
Arie.

molendijk
09-06-2010, 02:06 PM
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 (http://www.let.rug.nl/molendyk/include_ajax_while_loading2/include_ajax_while_loading.html). (I know you won't agree).
===
Arie.