Forum Moderators: open

Message Too Old, No Replies

GetElementByID for ID imported via AJAX

Accessing IDs included via AJAX

         

JAB Creations

5:09 am on Sep 26, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I have a menu which I wish to highlight, however it is loaded as an AJAX includes, not with the rest of the page when initially requested.

Here are a couple scripts I'd like to know how to adjust for use with AJAX. I'd like to see the script adaptation to AJAX on at least two scripts so I can pick up the pattern. Thanks!

- John

JavaScript #1

// setStyleById: given an element id, style property and
// value, apply the style.
// args:
// i - element id
// p - property
// v - value
//
function setstylebyid(i, p, v)
{
var n = document.getElementById(i);
n.style[p] = v;
}

XHTML Event

<element onevent="setstylebyid('menuaudio', 'backgroundColor', '#666');" />

JavaScript Two

document.getElementById('prompts').focus();

XtendScott

2:02 pm on Sep 26, 2007 (gmt 0)

10+ Year Member



Any HTML included via AJAX should be available to the browser as soon as it is loaded.

<script> on the other hand should be loaded within the page or linked at the time of the initial page load. When you inject AJAX the script does ot get parsed by the browser, thus is not available.

JAB Creations

3:04 am on Sep 27, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Testing this further I've found that if a script tries to access the ID (and say change it's backgroundColor) it is possible by default from within the AJAX included file itself, but I still can't do so from the initially loaded page.

- John

XtendScott

3:59 am on Sep 27, 2007 (gmt 0)

10+ Year Member



I have never had any problem accessing ID's from AJAX'd in HTML.

Your "function setstylebyid(i, p, v)" should be on the initial page when loaded(not in the Ajax'd HTML).

Is it possible the even calling the function is being triggered prior to the return of the HTML after the xmlhttp.readyState == 4? I have gotten errors when I have not waited properly for the data to return and the code isn't there yet.

I just got it to work with a onClick event after a window.onload event ajax'd in "<div id="menuaudio" style="width:300px; height:100px; border:1px solid red;"> THIS IS MY DIV </div>" from a static menuaudio.htm file.

In the example below I am using XHConn.js for the AJAX call. I modified the "xmlhttp.open(sMethod, sURL+"?"+sVars+"&XHCrnd="+rndNum, true);" to include a random number to prevent browser caching. Let me know if you want it.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>
<head>
<title>Untitled</title>
</head>

<body>
<script language="JavaScript" src="XHConn.js"></script>
<script type="text/javascript">
window.onload = getHTML;

// setStyleById: given an element id, style property and
// value, apply the style.
// args:
// i - element id
// p - property
// v - value
//
function setstylebyid(i, p, v)
{
var n = document.getElementById(i);
n.style[p] = v;
return false;
}

function getHTML()
{
var myConn = new XHConn();
if (!myConn) alert("XMLHTTP not available. Try a newer/better browser.");
var fnWhenDone = function (oXML)
{
document.getElementById('putItHere').innerHTML=oXML.responseText;
};
myConn.connect("menuaudio.htm", "GET", "", fnWhenDone);

}
</script>

<a style="text-decoration:underline; cursor:pointer;" onclick="return setstylebyid('menuaudio', 'backgroundColor', '#666');" >TEST CLICK</a>

<div id="putItHere"></div>

</body>
</html>

daveVk

4:22 am on Sep 27, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Check where AJAX is loaded the html into, if it a frame, iframe or separate window, document.getElementById is probably refering to wrong
document.

JAB Creations

4:35 am on Sep 27, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Here are a couple of odd things...

1.) The error console initially tells me that the ID does not exist.

2.) When trying to trigger the background color to change from another element (either in the initially loaded page or from the AJAX includes) it works if I've already loaded the AJAX includes....

3.) HOWEVER while it does see the ID and change it's background color it immediately resets back to the original background color if I call the function from the initial page load but it works just fine if the script to change the background color is from an element loaded from the AJAX includes.

So from that I know that the issue is that my single function which includes multiple sub-functions that it's simply not initially seeing the ID.

As far as all the other bizarre behavior I'm going to try to get a working test.

- John

JAB Creations

4:40 am on Sep 27, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Scott,

It was set to 4, when I changed it (know nothing about it so assumed lower values are legit) to 3 and then triggered the script to change the ID's background color it worked and didn't flash back off! The problem still remains however to have the initial script which loads the AJAX includes to somehow "wait" a moment in a JavaScript sense before it jumps after that ID to change it's color.

- John

PS

Here is my AJAX includes script which has been great at reducing my site's initial page sizes. ;)

//
// AJAX Includes
//
var bustcachevar=1 //bust potential caching of external pages after initial request? (1=yes, 0=no)
var loadedobjects=""
var rootdomain="http://"+window.location.hostname
var bustcacheparameter=""

function ajaxpage(url, containerid){
var page_request = false
if (window.XMLHttpRequest) // if Mozilla, Safari etc
page_request = new XMLHttpRequest()
else if (window.ActiveXObject){ // if IE
try {
page_request = new ActiveXObject("Msxml2.XMLHTTP")
}
catch (e){
try{
page_request = new ActiveXObject("Microsoft.XMLHTTP")
}
catch (e){}
}
}
else
return false
page_request.onreadystatechange=function(){
loadpage(page_request, containerid)
}
if (bustcachevar) //if bust caching of external page
bustcacheparameter=(url.indexOf("?")!=-1)? "&"+new Date().getTime() : "?"+new Date().getTime()
page_request.open('GET', url+bustcacheparameter, true)
page_request.send(null)
}

function loadpage(page_request, containerid){
if (page_request.readyState == 3 && (page_request.status==200 ¦¦ window.location.href.indexOf("http")==-1))
document.getElementById(containerid).innerHTML=page_request.responseText
}

function loadobjs(){
if (!document.getElementById)
return
for (i=0; i<arguments.length; i++){
var file=arguments[i]
var fileref=""
if (loadedobjects.indexOf(file)==-1){ //Check to see if this object has not already been added to page before proceeding
if (file.indexOf(".js")!=-1){ //If object is a js file
fileref=document.createElement('script')
fileref.setAttribute("type","text/javascript");
fileref.setAttribute("src", file);
}
else if (file.indexOf(".css")!=-1){ //If object is a css file
fileref=document.createElement("link")
fileref.setAttribute("rel", "stylesheet");
fileref.setAttribute("type", "text/css");
fileref.setAttribute("href", file);
}
}
if (fileref!=""){
document.getElementsByTagName("head").item(0).appendChild(fileref)
loadedobjects+=file+" " //Remember this object as being already added to page
}
}
}

JAB Creations

4:51 am on Sep 27, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



The problem seems to be that manipulating an ID included via AJAX must not be executed during same event whatsoever otherwise it will always fail to see the ID initially. The problem in that regard is that I would have to write a junk approach such as when the user onmouseout from the anchor that spawned the event as a separate event to then execute the background color change, but that seams weak sauce and I'm sure someone who has bumped in to this problem at one point or another?

- John

JAB Creations

7:03 am on Sep 27, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I looked up JavaScript event order and I'm now reading about capturing and bubbling.

I'm not very clear on the concept because the article I was reading applied to two elements (like a span inside of a header).

However it's my understanding that this could be used to pause one of the sub-functions and have it "listen" for the ID, the AJAX script does it's thing, and once the ID exists, the sub-function (that is of course physically placed after the AJAX function anyway) will then resume and execute?

- John

XtendScott

2:30 pm on Sep 27, 2007 (gmt 0)

10+ Year Member



It was set to 4

4 should be the correct option.

readyState
The readystatechange event fires when the readyState of the request changes. This property can have four values, which theoretically work in the way shown below. In practice, though, the browsers don't quite follow this de facto standard.

0 Uninitialized - open() has not been called yet.
1 Loading - send() has not been called yet.
2 Loaded - send() has been called, headers and status are available.
3 Interactive - Downloading, responseText holds the partial data.
4 Completed - Finished with all operations.

readyState 4 is equivalent to the load event and is a standard part of any xmlhttp script. I have never understood what the other three readyStates are good for; why would you need to know that responseText holds the partial data, for instance? One more mystery to solve.

from:quirksmode.org

It sounds like the function is trying to change the element before it is there.

Try calling the function to change it here:

function loadpage(page_request, containerid){
if (page_request.readyState == 4 && (page_request.status==200 ¦¦ window.location.href.indexOf("http")==-1))
document.getElementById(containerid).innerHTML=page_request.responseText;

setstylebyid('menuaudio', 'backgroundColor', '#666');
}

That would make sure it is waiting for the HTML to return.

JAB Creations

8:57 pm on Sep 27, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Thanks for the suggestion Scott but it still acts like before. With the state set to 4 even when I click on the link with the group of events it only "flashes" the background color on the element on the second click but still does not see the ID available on the initial click. Other elements on the page are still able to set the backgroundColor without it flashing back off if the ID has been added to the page via AJAX already.

From my perspective doesn't your suggested code simply execute only if the readyState is 4? Since the entire event and all the included functions executes before state 4 is reached is there a way to make a timed loop to pause and retry executing the script? I am suggesting a timed loop since I'm not sure if an uncontrolled loop would be too intense for some computers/browsers and end up making the computer/browser unresponsive?

- John

XtendScott

5:32 am on Sep 28, 2007 (gmt 0)

10+ Year Member



With the state set to 4 even when I click on the link with the group of events it only "flashes" the background color on the element on the second click but still does not see the ID available on the initial click.

John,

That sounds like on the 1st click the ID is not back yet from the AJAX call when requested but then the ID gets inserted. The second click changes the background color of the ID that came from the first click, but then the 2nd AJAX call from the 2nd click replaces that ID with a new one.

Are you making multiple requests to load data into multiple setions at the same time? If so can you successfully perform a single call. Maybe I am misunderstanding what you are trying to do exactly, but the data isn't completely back until readystate == 4. You can process elements that aren't dependent upon the returned HTML.

scott