PDA

View Full Version : Running Scripts within AJAX pulled content



joemccarroll
05-24-2011, 03:26 PM
I've been having some trouble adding an accordion (http://www.dynamicdrive.com/dynamicindex17/ddaccordion.htm) to a page which is pulled in via AJAX (http://www.dynamicdrive.com/dynamicindex17/ajaxtabscontent/index.htm)

. I have referred to jscheuer1's great guide on the topic - http://www.dynamicdrive.com/forums/showthread.php?t=13003

So the scripts I need to run the Accordion are -

1 - Jquery library -
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>

-------------

2 - Accordion script -

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

-------------

3 - And lastly the handler -

<script type="text/javascript">

ddaccordion.init({
headerclass: "question", //Shared CSS class name of headers group
contentclass: "answer", //Shared CSS class name of contents group
revealtype: "click", //Reveal content when user clicks or onmouseover the header? Valid value: "click", "clickgo", or "mouseover"
mouseoverdelay: 200, //if revealtype="mouseover", set delay in milliseconds before header expands onMouseover
collapseprev: false, //Collapse previous content (so only one open at any time)? true/false
defaultexpanded: [], //index of content(s) open by default [index1, index2, etc]. [] denotes no content.
onemustopen: false, //Specify whether at least one header should be open always (so never all headers closed)
animatedefault: false, //Should contents open by default be animated into view?
persiststate: false, //persist state of opened contents within browser session?
toggleclass: ["openanswer", "closedanswer"], //Two CSS classes to be applied to the header when it's collapsed and expanded, respectively ["class1", "class2"]
togglehtml: ["prefix", "<img src='/content/en/questions/images/down.png' style='width:19px; height:15px; float:left; padding:7px 5px 0px 0px;' /> ", "<img src='/content/en/questions/images/up.png' style='width:19px; height:15px; float:left; padding:7px 5px 0px 0px' /> "], //Additional HTML added to the header when it's collapsed and expanded, respectively ["position", "html1", "html2"] (see docs)
animatespeed: "slow", //speed of animation: integer in milliseconds (ie: 200), or keywords "fast", "normal", or "slow"
oninit:function(expandedindices){ //custom code to run when headers have initalized
//do nothing
},
onopenclose:function(header, index, state, isuseractivated){ //custom code to run whenever a header is opened or closed
//do nothing
}
})

</script>


---------------------------

I've followed the instructions on the above tutorial, added the span with unique ID, the mousedown and mouseup trigger, and tried to fire the scripts from within the AJAX tabs -

<script type="text/javascript">
function pollC(id, load){
if (!load&&document.getElementById(id)){
document.getElementById(id).id='';
return;
}
else if (load&&document.getElementById(id)){
if (id=='unique_1') //optional
ddaccordion(); //required
return;
}
else if (load&&!document.getElementById(id))
setTimeout("pollC('"+id+"', 'load')", 60);
}
</script>


However when I test the page, it works fine on initial page load, but when I use one of the AJAX tabs I they dont work and error states 'Function Expected on line 78' which is where I have added 'ddaccordion' above.

Could someone spare me a minute to see where I am going wrong, much appreciated.

Joe

jscheuer1
05-24-2011, 03:34 PM
If you're using one of jQuery's AJAX routines, most if not all of them allow for a callback function. Rather than try to apply that old thread which essentially tries to create a poll for AJAX routines which lack an explicit callback, use the native jQuery methods.

To be of more help, I would really need to see the page:

Please post a link to a page on your site that contains the problematic code so we can check it out.

joemccarroll
05-24-2011, 04:10 PM
Hi John,

Can you have a look within the attached?

The page is on a test site on a secure server, only accessible internally here.

I can get it out live on a test URL if you need.

Joe

jscheuer1
05-24-2011, 05:45 PM
OK, Ajax Tabs has a callback too. First two questions:


Do all of the AJAX imported tabs have accordions on them, if not do any of them?


And you're using a default tab. Is the markup for that already on the page and has it an accordion?


Looks like #2 is a yes, is it? What about #1?

joemccarroll
05-24-2011, 11:52 PM
Hi John,

yes I have a default tab so that answers number 2.

And yes all the tabs have accordions on them, there are 12 in total.

Its for an FAQs section so you might get a better picture.

We have questions (headers) in each AJAX content with answers which should be collapsable. I have used a default tab which houses the first set of FAQs.

Joe

jscheuer1
05-25-2011, 03:30 AM
OK. It would be hard for me to simulate and/or anticipate all that will entail. But I'll try. I immediately have another question:

Are all of the accordions the same as far as the init goes? I mean, do they all have the same settings including the header and content classes?

I'll assume that they do for now, and give you something to try. First get rid of:


<script type="text/javascript">
function pollC(id, load){
if (!load&&document.getElementById(id)){
document.getElementById(id).id='';
return;
}
else if (load&&document.getElementById(id)){
if (id=='unique_1') //optional
ddaccordion(); //required
return;
}
else if (load&&!document.getElementById(id))
setTimeout("pollC('"+id+"', 'load')", 60);
}
</script>

And get rid of all of these:


onmousedown="pollC('unique_1')" onmouseup="pollC('unique_1', 'load')"

Change this:


<script type="text/javascript">

ddaccordion.init({
headerclass: "question", //Shared CSS class name of headers group
contentclass: "answer", //Shared CSS class name of contents group
revealtype: "click", //Reveal content when user clicks or onmouseover the header? Valid value: "click", "clickgo", or "mouseover"
mouseoverdelay: 200, //if revealtype="mouseover", set delay in milliseconds before header expands onMouseover
collapseprev: false, //Collapse previous content (so only one open at any time)? true/false
defaultexpanded: [], //index of content(s) open by default [index1, index2, etc]. [] denotes no content.
onemustopen: false, //Specify whether at least one header should be open always (so never all headers closed)
animatedefault: false, //Should contents open by default be animated into view?
persiststate: false, //persist state of opened contents within browser session?
toggleclass: ["openanswer", "closedanswer"], //Two CSS classes to be applied to the header when it's collapsed and expanded, respectively ["class1", "class2"]
togglehtml: ["prefix", "<img src='/content/en/questions/images/down.png' style='width:19px; height:15px; float:left; padding:7px 5px 0px 0px;' /> ", "<img src='/content/en/questions/images/up.png' style='width:19px; height:15px; float:left; padding:7px 5px 0px 0px' /> "], //Additional HTML added to the header when it's collapsed and expanded, respectively ["position", "html1", "html2"] (see docs)
animatespeed: "slow", //speed of animation: integer in milliseconds (ie: 200), or keywords "fast", "normal", or "slow"
oninit:function(expandedindices){ //custom code to run when headers have initalized
//do nothing
},
onopenclose:function(header, index, state, isuseractivated){ //custom code to run whenever a header is opened or closed
//do nothing
}
})

</script>

to:


<script type="text/javascript">
ddaccordion.startit = function(){
ddaccordion.init({
headerclass: "question", //Shared CSS class name of headers group
contentclass: "answer", //Shared CSS class name of contents group
revealtype: "click", //Reveal content when user clicks or onmouseover the header? Valid value: "click", "clickgo", or "mouseover"
mouseoverdelay: 200, //if revealtype="mouseover", set delay in milliseconds before header expands onMouseover
collapseprev: false, //Collapse previous content (so only one open at any time)? true/false
defaultexpanded: [], //index of content(s) open by default [index1, index2, etc]. [] denotes no content.
onemustopen: false, //Specify whether at least one header should be open always (so never all headers closed)
animatedefault: false, //Should contents open by default be animated into view?
persiststate: false, //persist state of opened contents within browser session?
toggleclass: ["openanswer", "closedanswer"], //Two CSS classes to be applied to the header when it's collapsed and expanded, respectively ["class1", "class2"]
togglehtml: ["prefix", "<img src='/content/en/questions/images/down.png' style='width:19px; height:15px; float:left; padding:7px 5px 0px 0px;' /> ", "<img src='/content/en/questions/images/up.png' style='width:19px; height:15px; float:left; padding:7px 5px 0px 0px' /> "], //Additional HTML added to the header when it's collapsed and expanded, respectively ["position", "html1", "html2"] (see docs)
animatespeed: "slow", //speed of animation: integer in milliseconds (ie: 200), or keywords "fast", "normal", or "slow"
oninit:function(expandedindices){ //custom code to run when headers have initalized
//do nothing
},
onopenclose:function(header, index, state, isuseractivated){ //custom code to run whenever a header is opened or closed
//do nothing
}
});
};
ddaccordion.startit();
</script>

Change this:


<script type="text/javascript">

var countries=new ddajaxtabs("Questions", "countrydivcontainer")
countries.setpersist(true)
countries.setselectedClassTarget("link") //"link" or "linkparent"
countries.init()
</script>

to:


<script type="text/javascript">
jQuery(function($){
$('#Questions a').mousedown(function(){
$('#countrydivcontainer').empty();
}).mouseup(function(){
if(this.getAttribute('rel') === '#default'){
setTimeout(function(){ddaccordion.startit();}, 100);
}
});
});

var countries=new ddajaxtabs("Questions", "countrydivcontainer")
countries.setpersist(true)
countries.setselectedClassTarget("link") //"link" or "linkparent"
countries.init()

countries.onajaxpageload = function(pageurl){
ddaccordion.startit();
}
</script>

Make sure the browser's cache is cleared and then see what happens.

Note: There could be problems. If so, pay strict attention to what happens/doesn't happen and when so you can report it to me.

joemccarroll
05-25-2011, 07:56 AM
Hi John,

thanks for your help.

1 - Yes in answer to your first question yes they all have the same settings.

2 - I've followed your steps cleared cache and reloaded the page.

In IE the pages now just hang indefinitely, so they don't load at all.

On Mozilla the page loads but with peculiar output. There are two icons on each expandable header, and when I click it either does nothing or expands and collapses rapidly.

I can't report much more than that as the page won't load in IE for me.

Any suggestions?

Joe

jscheuer1
05-25-2011, 03:29 PM
I can get it out live on a test URL if you need.

I think it's time for that. Your results are encouraging. We just need to find a way to prevent some kind of looping that's seemingly occurring. I had tried the jQuery .empty() in an effort to remove all the content and all of its events. But it seems that even though the accordion is jQuery based, that's not enough. That might not be the issue though.

I just saw something in ddaccordion.js that has to be changed for this to work. Near the end find the init function. near the beginning of it we see:


init:function(config){
document.write('<style type="text/css">\n')
document.write('.'+config.contentclass+'{display: none}\n') //generate CSS to hide contents
document.write('a.hiddenajaxlink{display: none}\n') //CSS class to hide ajax link
document.write('<\/style>')
jQuery(document).ready(function($){
ddaccordion.urlparamselec . . .

That's fine the first time. But every time after that, it will cause problems. But not, at least I don't think the kind you're reporting.

Change it to:


init:function(config){
if(!ddaccordion[config.contentclass + 'style']){
jQuery('head').eq(0).append('<style type="text/css">.'+config.contentclass+'{display: none}a.hiddenajaxlink{display: none}</style>');
ddaccordion[config.contentclass + 'style'] = true;
}
jQuery(document).ready(function($){
ddaccordion.urlparamselec . . .

If that doesn't fix it, it's time for that live demo.

joemccarroll
05-26-2011, 07:59 AM
We are so close!

Let me explain the final issue - I will then build to a site so you can see should you not think of the reason behind this last problem.

I am dynamically selecting tabs from a FAQs homepage with the twelve categories using the - <a href="target.htm?tabinterfaceid=index">Target Page</a> method.

This works fine but only for the first content, the content which resides in the default tab.

When I try to load any of the others dynamically, initially two icons are added to the accordion active header, both down and up icons, and when used causes some erratic behaviour.

Just let me know if you can figure without me going to test, I will do otherwise tonight.

Thanks very much.

Joe

jscheuer1
05-26-2011, 08:08 AM
Yes I need a live demo.

joemccarroll
06-03-2011, 09:32 AM
Hi John, OK I've got this on a live test site for you now so it will be easier for you to see the issue.

I have a landing page www[dot]jet2[dot]com/t3stingquestions.aspx

This is merely a menu to link into an FAQ topic, dynamically selecting a tab using a remote link, eg <a href="target.htm?tabinterfaceid=index">Target Page</a>

As you see when you select any of the icons the page loads OK, but we have two of the icons which are added from the 'togglehtml' (up and down arrows) on each header, and when we try to open a header it behaves erratically.

BUT - when we select another page from within the http://www[dot]jet2[dot]com/t3stingAnswers.aspx page on the menu down the left it works as it should.

Its as if loading if from a remote page is causing the trouble, everything else works fine when we use the page after landing on it from the homepage.

Let me know if you need anymore information

Thanks again for your time

jscheuer1
06-03-2011, 06:08 PM
Seems to only be a problem when the page loads and only if it's with a param greater than 0 and then not always, but almost always.

If you have a different take on the problem let me know.

To solve what I see as the problem, on t3stingAnswers.aspx replace:


<script type="text/javascript">
ddaccordion.startit = function(){
ddaccordion.init({
headerclass: "question", //Shared CSS class name of headers group
contentclass: "answer", //Shared CSS class name of contents group
revealtype: "click", //Reveal content when user clicks or onmouseover the header? Valid value: "click", "clickgo", or "mouseover"
mouseoverdelay: 200, //if revealtype="mouseover", set delay in milliseconds before header expands onMouseover
collapseprev: false, //Collapse previous content (so only one open at any time)? true/false
defaultexpanded: [], //index of content(s) open by default [index1, index2, etc]. [] denotes no content.
onemustopen: false, //Specify whether at least one header should be open always (so never all headers closed)
animatedefault: false, //Should contents open by default be animated into view?
persiststate: false, //persist state of opened contents within browser session?
toggleclass: ["openanswer", "closedanswer"], //Two CSS classes to be applied to the header when it's collapsed and expanded, respectively ["class1", "class2"]
togglehtml: ["prefix", "<img src='/content/en/questions/images/down.png' style='width:19px; height:15px; float:left; padding:7px 5px 0px 0px;' /> ", "<img src='/content/en/questions/images/up.png' style='width:19px; height:15px; float:left; padding:7px 5px 0px 0px' /> "], //Additional HTML added to the header when it's collapsed and expanded, respectively ["position", "html1", "html2"] (see docs)
animatespeed: "slow", //speed of animation: integer in milliseconds (ie: 200), or keywords "fast", "normal", or "slow"
oninit:function(expandedindices){ //custom code to run when headers have initalized
//do nothing
},
onopenclose:function(header, index, state, isuseractivated){ //custom code to run whenever a header is opened or closed
//do nothing
}
});
};
ddaccordion.startit();
</script>

with:


<script type="text/javascript">
ddaccordion.startit = function(){
ddaccordion.init({
headerclass: "question", //Shared CSS class name of headers group
contentclass: "answer", //Shared CSS class name of contents group
revealtype: "click", //Reveal content when user clicks or onmouseover the header? Valid value: "click", "clickgo", or "mouseover"
mouseoverdelay: 200, //if revealtype="mouseover", set delay in milliseconds before header expands onMouseover
collapseprev: false, //Collapse previous content (so only one open at any time)? true/false
defaultexpanded: [], //index of content(s) open by default [index1, index2, etc]. [] denotes no content.
onemustopen: false, //Specify whether at least one header should be open always (so never all headers closed)
animatedefault: false, //Should contents open by default be animated into view?
persiststate: false, //persist state of opened contents within browser session?
toggleclass: ["openanswer", "closedanswer"], //Two CSS classes to be applied to the header when it's collapsed and expanded, respectively ["class1", "class2"]
togglehtml: ["prefix", "<img src='/content/en/questions/images/down.png' style='width:19px; height:15px; float:left; padding:7px 5px 0px 0px;' /> ", "<img src='/content/en/questions/images/up.png' style='width:19px; height:15px; float:left; padding:7px 5px 0px 0px' /> "], //Additional HTML added to the header when it's collapsed and expanded, respectively ["position", "html1", "html2"] (see docs)
animatespeed: "slow", //speed of animation: integer in milliseconds (ie: 200), or keywords "fast", "normal", or "slow"
oninit:function(expandedindices){ //custom code to run when headers have initalized
//do nothing
},
onopenclose:function(header, index, state, isuseractivated){ //custom code to run whenever a header is opened or closed
//do nothing
}
});
};
(function(){
function getQval(n){
if(typeof n !== 'string'){
return null;
}
var r = new RegExp('[?&;]' + n + '=([^&;#]*)'), m = location.search;
return (m = r.exec(m))? unescape(m[1]) : null;
}
var index = getQval('Questions');
if(!index || index == 0){
ddaccordion.startit();
}
})();
</script>

What I think is happening is that when a page is fetched via AJAX onload the accordion is usually but not always initializing twice. Doing it like this will ensure that the accordion only initializes on AJAX load (not AJAX load and DOM load), except when the param is 0 or if there is no param. With 0 or no param it must initialize on load of the DOM, and will. It has to because there will be no AJAX call and therefore no AJAX load.

If there are any problems, leave this new code in place and tell me about it so I can check it out.

joemccarroll
06-06-2011, 08:38 AM
That has worked!

Thanks very much for your time John. Excellent work.

Joe