I'm trying to build an FAQ page and wish to have the user click a question and only then an answer will side down under the question.
I have code that will work this when I put it all on one page. However I wish to use a div to load various files (the FAQ div is only one of a few files I wish to add into the div). So when I use the div and an 'window onload event' the div loads but all questions and answers are fully opened and exposed.
The script to dropdown answers, placed in the HEAD section of the MainPage.html also a call to jQuery.
<script type="text/javascript">
$(document).ready(function() {
$('#faqs h1').each(function() {
var tis = $(this), state = false, answer = tis.next('div').hide().css('height','auto').slideUp();
tis.click(function() {
state = !state;
answer.slideToggle(state);
tis.toggleClass('active',state);
});
});
});
</script>
The FAQ.html
<div id="faqs">
<h1>+ Question</h1>
<div>
<p><br>Answer Here</p>
</div><br>
<h1>+ Question</h1>
<div>
<p><br>Answer Here</p>
</div><br>
</div>
The script to load the div, placed in the HEAD section of the MainPage.html
<script>
window.onload = function(){
$('#target').load('FAQ.html');
}
</script>
The div, placed in the BODY section of the MainPage
<div id="target"></div>
I have tried placing the javascript in various place on the page but still the same result. Repeat: If I place the code of FAQ.html directly in the BODY section of the MainPage it all works properly.
I have researched this also under 'conflicting jQuery' but with no success. Suggestions appreciated please.
It looks a lot like $(document).ready is run before $('#target').load finishes.
To avoid that, take the entire function you pass to $(document).ready and pass it as a last argument to $('#target').load instead, so that it gets called when loading of FAQ.html has completed:
window.onload = function(){
$('#target').load('FAQ.html', function() {
$('#faqs h1').each(function() {
var tis = $(this), state = false, answer = tis.next('div').hide().css('height','auto').slideUp();
tis.click(function() {
state = !state;
answer.slideToggle(state);
tis.toggleClass('active',state);
});
});
});
}
I assume it's because of the
$(document).ready()
callback. You're specifying a function to happen when the DOM is loaded, but by the time you've loaded in the faq.hmtl file, that's already happened. See what happens if you remove the first and last lines inside your script tags.
Also, unrelated, you're using <h1> tags incorrectly. You should only have one <h1> tag per page, as a rule. The <dl> tag is probably the most semantically meaningful in this situation.
Related
I'm loading my html files into a #content div in order to avoid the complete page to reload when clicking on a link. I'm doing this by calling the following in my index.html:
[...]
<div id="content">
<script type="text/javascript">$("#content").load("home.html");</script>
</div>
The problem is that no javascript in my global.js will be executed if it's related to one of the html files that will be loaded into my #content div.
In order to handle that fact I simply put the js of the related html file right into that specific one by posting it with the <script> command, e.g. like this:
<script type="text/javascript">
$(document).ready(function () {
$(".faq").click(function () {
$(this).find(".faq_answer").toggle();
});
});
</script>
I'm totally unhappy with it and so my question is: is there a way I could put my js back in my global.js file?
If I understand correclty your question, you need to use even delegation to assign event handlers to elements that doesn't exist yet
$(document).on("click",".faq", function (){ ... })
Where document can be replaced by any container of .faq that exists at bind time.
For more details check "Direct and delegated" section here
Try to load the page through your global.js inside of keeping it in your html page.
Keep the script that will load the content first.
This should work
Good afternoon, I am at a total loss on why this is happening. I have searched online and tried to understand what I'm doing wrong for 5+ hours and could find no solution. Here is the situation.
I have 3 pages (index.html, index.js, and stuff.html)
index.html is the main page and uses jQuery to load an HTML page into a div.
<html>
<head>
<script type="text/javascript" src="index.js"></script>
</head>
<body>
<div id="stuffHolder"></div>
<script type="text.javascript">
$(document).ready(function(){
$('#stuffHolder').load('stuff.html');
});
</script>
</body>
</html>
The stuff.html page loads just fine for me.
Inside the stuff.html I have 2 div's
1. One of the DIV's uses sprites as anchor tags to call a function named actOnStuff(options).
<div id="myStuff"><a class="myStuffSprite" href="Javascript:actOnStuff('newStuff')"><span>New Stuff</span></a></div>
<div id="yourStuff"><a class="yourStuffSprite" href="Javascript:actOnStuff('oldStuff')"><span>Old Stuff</span></a></div>
The other DIV is empty but will have innerHTML written to it later.
Inside index.js, which sits on the index.html page, I have a function
function actOnStuff(youSelected){
strHTML = "";
switch(youSelected){
case "newStuff":
strHTML += "<div id='newDIV'><span>You selected New</span></div>";
break;
case "oldStuff":
strHTML += "<div id='oldDIV'><span>You selected Old</span></div>";
break;
}
$('#placement').html(strHTML);
alert($('#placement').html());
}
My problem is that when I alert the innerHTML of the placement DIV it shows that the necessary DIV from the function as added in the alert. HOWEVER, nothing shows up in the placement DIV at all.
Any help you can provide would be wonderful as I am at a total loss as to what the problem is. Thanks in advance.
I'm not sure I can help solve the actual problem, but there's many issues and bad practices in your code that I'd like to point out for the greater good of the community.
Here's my take on your code:
HTML in body
<div id="stuff-holder"></div>
HTML in stuff.html
<div id="my-stuff">
<a class="my-stuff-sprite" href="#"><span>New Stuff</span></a>
</div>
<div id="your-stuff">
<a class="your-stuff-sprite" href="#"><span>Old Stuff</span></a>
</div>
Bad practice: CSS and HTML is most of the time not case-sensitive, so when naming IDs with camelcase such as fooBar, could create confusion with foobar or Foobar. Instead, use lowercase only and dash as separator (like in CSS).
JavaScript in index.js
I moved your ready function into index.js. I don't see a reason why you would want that in your HTML document when you already have a separate JavaScript file.
// Shorthand for ready
$(function(){
// Cache the selector
var $placement = $("#placement");
// Put function in the local scope so we don't clutter the global scope
function actOnStuff(youSelected) {
// Not declaring variables with var, makes it global (bad idea!)
var html = "";
switch (youSelected) {
case "my-stuff":
html += '<div id="new-div"><span>You selected New</span></div>';
break;
case "your-stuff":
html += '<div id="old-div"><span>You selected Old</span></div>';
break;
}
// Put new html in placement element
$placement.html(html);
// Use console.log to debug your code instead of alert
console.log($placement.html());
}
// Load stuff into stuff holder and bind event handler to load event
$("#stuff-holder")
.load("stuff.html")
.on("load", function() {
// After it has loaded, bind click events
$("#my-stuff .my-stuff-sprite, #your-stuff .your-stuff-sprite").click(function(e) {
// Prevent default click behavior
e.preventDefault();
// Get id of parent
var id = $(this).parent()[0].id;
// Execute function
actOnStuff(id);
});
});
});
Bad practice: Executing JavaScript within the href is a big no-no in todays environments. Even using onclick attributes et al is since long outdated.
Tip: Passing a function directly into jQuery is a shorthand for $(document).ready
Tip: Use console.log() instead of alert() to output everything from objects to strings to your log (might give you errors in older IE)
I still don't know where your placement element is located. Perhaps that's your culprit? If you have any questions about the above or anything else, don't hesitate to ask.
Also, check out jQuery Fundamentals which is a great resource for everyone using jQuery, from beginners to pros.
Edit: Check this jsFiddle for a demonstration of the above.
before
<script type="text/javascript" src="index.js"></script>
you should load jquery library first
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="index.js"></script>
Make sure you only have ONE element with id="placement", IE will fail if you have more than one.
Also what is the output of alert(strHTML); putted just before $('#placement').html(strHTML); does it output the string right?
I am appending an HTML document into my current page using Ajax, and removing those added divs when the close button is pressed. The problem is that when I close, the divs are removed from the document but the CSS <link rel="stylesheet" href="style.css"> are not removed, and the number keep increasing as I load and unload Ajax content. How to completely remove the loaded document with the header content (css, js) of that page?
edit: i dont know why people dont want to answer but they just come to negative voting.
this is the code that i have used to add(append the html document)
$(function(){
$("a[rel='tab']").click(function(e){
pageurl = $(this).attr('href');
$.get(pageurl, function(html) {
$(html).hide().appendTo('body').fadeIn(500);
}, 'html');
//to change the browser URL to the given link location
if(pageurl!=window.location){
window.history.pushState({path:pageurl},'',pageurl);
}
//stop refreshing to the page given in
return false;
});
});
and this code to remove the divs
function close(){
$("#mainContent").fadeOut(500, function() { $(this).remove(); });
window.history.back();
} ;
I can't see the document that you are attempting to add/remove, but I'm guessing it looks something like this:
<link rel="stylesheet" href="style.css">
<div id="main-content">
<p>Blah blah blah</p>
</div>
So when you add that content, the whole thing is inserted. When you remove it, you are only removing the div#main-content. To remove everything, two ideas come to mind:
Preferably, wrap the document in another <div> and remove that instead
Alternatively, you could select <link> elements that are siblings of the 'div#main-content`, but that has the potential to be more unpredictable.
If the document you are adding doesn't look like that, then please explain in the OP what it does look like and where the <link> elements are coming from.
If you are doing something like a HTML preview in another page, look into creating an iframe instead. Use AJAX to create a temporary URL as the source. The advantage is that you avoid conflicts that occur when you effectively merge two DOMs.
So as many others I have a problem dealing with scripts from external pages I load with ajax.
Im trying to set up a page with an "admin panel" on top of it. I want to be able to navigate to several admin pages within the panel. The different admin pages have both internal <script>and external js-files that they include. The scripts are loaded as they should but they seem to stack up or are not being managed in a good way.
I made a small test on one of the admin pages:
$('.left-col').click(function () {
alert();
});
Here, whenever I return to this page it will bind another click to it so I then get two alerts each time I click the div. I can solve this easily by running $('.left-col').unbind(); in my ajax.success.
However for some admin pages there are tons of .click/.change/.live etc and I'm not even sure what they are (i.e. from external plugins). So can I somehow unbind/remove all of the scripts loaded from each of my ajax-loaded page without having to specify each elements? I know I can use selectors with unbind but it doesnt seem very effective to loop over each div/img/input etc and unbind, and I'm not even sure if it will work.
This is how I load the admin pages:
<script type="text/javascript">
$(document).ready(function() {
function reloadAdminPanel(url) {
if(typeof(url) === "undefined") {
var url = '/admin/panel/dashboard/';
}
$.ajax({
'success': function (data, textStatus) {
var jData = $(data);
// override links in admin to run reloadAdminPanel()
jData.find('a').each(function() {
var newUrl = $(this).attr('href');
$(this).click(function(e) {
reloadAdminPanel(newUrl);
return false;
});
});
$('div.panel__inner').remove();
$('body').prepend(jData);
delete jData;
},
'url': url
});
}
reloadAdminPanel();
});
</script>
Any help is appreciated, cheers!
The structure of the page:
<html>
<body>
<div class="panel__inner"> <!-- admin panel --> </div>
<!-- rest of project site -->
</body>
</html>
Maybe itd help if you show us the structure of the elements, but from the definition of "Remove" in Jquery, it should remove the element, its children, all events and any data associated to it.
Is div.panel__inner located inside your body tag? I see that you are doing a remove on the div, but prepending the data to $('body'). Can you remove the body contents itself?
I have a page that has multiple links with various attributes (these attributes will be pulled in from a database):
index.php
<html>
<head>
<script type='text/javascript' src='header.js'></script>
</head>
<body>
My_Link_1
My_Link_2
<div id='my_container'> </div>
</body>
</html>
My header.js file has:
$(document).ready(function(){
$('.link_click').click(function(){
$("#my_container").load("classes/class.project.php", {proj: $(this).attr('id')} );
return false;
});
});
class.project.php is pretty simple:
<?php
echo "<div id='project_container'>project = ".$_POST['proj']." : end project</div>";
?>
This loads and passes the ID variable (which actually comes from a database) to class.project.php. It works fine for the first link click (either link will work). Once one link is clicked no other links with this div class will work. It feels like javascript loads the class.porject.php and it will not refresh it into that #my_container div.
I tried running this as suggested by peterpeiguo on the JQuery Fourm, with the alert box for testing wrapped inside .each:
Copy code
$(document).ready(function() {
$('.link_click').each(function() {
$(this).click(function() {
alert($(this).html());
});
});
});
This seems to work fine for the alert box. But when applying it to .load() it does not reload the page with the new passed variable. As a matter of fact, it doesn't even reload the current page. The link performs no function at that point.
The example site can be viewed here: http://nobletech.net/gl/
I looked at the link you posted, and the problem is that when you're doing load you're replacing the elements on the page with new ones, thus the event handlers don't work anymore.
What you really want to do is target the load. Something like:
$("#project_container").load("classes/class.project.php #project_container", {proj: $(this).attr('projid')} );
This only loads stuff into the proper container, leaving the links and other stuff intact.
Ideally, the php script should only return the stuff you need, not the whole page's markup.
BTW- Caching shouldn't be an issue in this case, since .load uses POST if parameters are passed. You only have to worry about ajax caching with GETs
Sounds like the request is getting cached to me.
Try this:
$.ajaxSetup ({
// Disable caching of AJAX responses */
cache: false
});
Sorry but this might be completely wrong but after examining your XHR response I saw that you are sending back html that replaces your existing elements.
So a quick fix would be to also send the following in your XHR response (your php script should output this also):
<script>
$('.link_click').each(function() {
$(this).click(function() {
alert($(this).html());
});
</script>