How can I use Ajax reload without breaking all jquery events? - javascript

I'm trying to reproduce the loading effect we can see on the google material.io website : when selecting a menu item, the content and url change, but the sidebar doesn"t move, as if only the content was changing..
can someone can explain me how to do this ? is it like the tehcnique described on css ticks tutorial "dynamic page replacing content" or something more like ajax ?
I have this code in html :
<div id="containerWrapper">
<div class="flex-row">
<div id="menu" class="flex-col-xs-12 flex-col-md-2 generator_menu">
<nav role="navigation" id="navigation" aria-label="Menu principal">
MY MENU HERE
</nav>
</div>
<div id="contentWrapper" class="flex-col-md-10">
<div id="guts">
<div class="flex-col-xs-12 generator_main">
MY CONTENT HERE
</div>
<div class="flex-col-xs-2">A sidebar dynamic TOC</div>
</div>
</div>
</div>
</div>
<footer></footer>
And the Ajax Code:
$("#menuList a").on('click',function(e){
e.preventDefault();
pageurl = $(this).prop('href');
$.ajax({url:pageurl,success: function(data){
$('#contentWrapper').html($(data).find('#guts'));
// Rerun Prism syntax highlighting on the current page
Prism.highlightAll();
return false;
}});
if(pageurl!=window.location){
window.history.pushState({path:pageurl},'',pageurl);
}
return false;
});
$(window).bind('popstate', function() {
$.ajax({url:location.pathname,success: function(data){
$('#guts').html(data);
}});
});
My problem:
-All my jquery events are in a dedicated file, wrapped in a jQuery(document).ready(function($) {}.
-If I put my ajax code like this, everything works except the ajax call..If I wrap my ajax code in a jQuery(document).ready(function($) {}., ajax works but all my other jquery events are broken when I click on any menu item and reload the page.
So is there a simple trick to make ajax works together with others jquery functions ?

Ok, finally I followed an answer given here..
In a js file, I wrapped my ajax call in a jQuery(document).ready(function(){}/
In a separate file, I wrapped all my jquery code in a function (scroll functions, clicks on menu function, filters, show/hide functions etc.):
function initialise(){}
Then in this same second file, at the end, I throw initialize function when document is ready, and when Ajax is complete :
$(document).ready(function(){
initialise();
});
$(document).ajaxComplete(function () {
initialise();
});
Now everything looks fine..
If there is a better way, I'll be glad to learn more on this..

Related

Loading different pages while keeping the same header

I have a question, I'm working on my first portfolio with html, css and javascript.It's just a simple site with a header with the nav menu and the body with some of my info, I was wondering if there's a way besides iframe to load only the body everytime I click a link without affecting the header:
<header>
<nav>
Home, about me, etc
</nav>
</header>
<body>
this is my home page
</body>
To really get in to one page app development using a library like Angularjs really does the trick. If you just need something really simple you can use the jQuery load function. For instance:
<body>
<button id="home">Home</button>
<button id="about">About</button>
<button id="examples">Examples</button>
<div id="content">
this is my home page
</div>
</body>
<script language="Javascript">
$("#home").click(function() {
$( "#content" ).load( "home.html" ); //Load all retrieved content
});
$("#about").click(function() {
//Only load content from a specific node
$( "#content" ).load( "about.html #desc" );
});
$("#examples").click(function() {
//More specific loading of node
$( "#content" ).load( "examples.html #storeMain .container" );
});
</script>
This is the same question that started me off learning to program.
Things have gotten a lot better as far as loading dynamic content on the fly... but also - much more complicated as far as setup / build tools / JS frameworks etc.
People will say --- just use HTML or PHP / and that it doesn't matter if the whole page is reloaded and the header repaints... but those people aren't like you. What if you want to look at a picture of the band WHILE listening to a song (myspace)... - or you want your header to fade to a different background and do an animation...
Here is a PHP example that explains it all: https://css-tricks.com/dynamic-page-replacing-content
Here is a hacky JS way to do it / where all of the info is on one page... but is hidden and then shown with JS / but - the URL isn't going to change: https://codepen.io/sheriffderek/pen/zxmjgr
// build a reusable function that switches the "view"
var switchView = function(trigger) {
$('.view').addClass('hidden');
var currentSection;
currentSection = $(trigger).data('view');
$('.' + currentSection).removeClass('hidden');
console.log("you are currently on:" + currentSection);
};
// when you click the menu item... run that function to switch to the associated "view" based on it's data attribute
$('.view-controls a').on('click', function() {
switchView(this);
});
$('.header').on('click', function() {
$('.compact-menu').toggleClass('active');
});
$('.compact-menu a').on('click', function() {
$('.compact-menu').removeClass('active');
}); // I had to add this code just to post a codepen link : /
Example in action: http://bryanleebrowncomposer.com
Not ideal... but if you aren't going to have URL change anyway... this is actually better for SEO - and it's easy - and gets you the snappy style.
Here is a JavaScript framework way: https://www.codementor.io/sheriffderek/less-than-ambitious-websites-with-ember-js-5mtthoijp
I love Ember.js - but if you were going to try your hand at another framework - I'd take a look at this vue.js way: https://scotch.io/tutorials/how-to-build-a-simple-single-page-application-using-vue-2-part-1
All roads lead to pain and suffering - for the most part. Good luck! Post your outcome, will yah?
You could dynamically load your pages and inject it to your main page (single page).
As another option, which is partially not what you are looking for, you can load different pages via url and then dynamically rendering a header/footer onload (multiple page). But multiple pages will allow you to avoid having to manipulate URL states manually through something like domain.com?page=about and it's generally much more manageable in terms of regular website development.
If I make it single page, I load the body content via ajax. Like so
<div class="header">Lorem ipsum</div>
<div class="content-wrapper">
<!--Load content HTML here via ajax -->
</div>
<div class="footer">Lorem ipsum</div>
For multi-page setups, I do this
<div class="header-wrapper">
<!--Load header HTML here via ajax or render them via a javascript component -->
</div>
<div class="content-wrapper">Lorem ipsum</div>
<div class="footer-wrapper">
<!--Load footer HTML here via ajax or render them via a javascript component -->
</div>
The ajax part is as simple as this. (using jQuery ajax, axios, or http)
$.ajax({
type : 'GET',
url : 'foo.html',
dataType : 'html',
success : function(data){
wrapper.innerHTML = data;
},
Look up dynamically loading html via ajax so that you don't have to constantly repeat yourself implementing the same headers/footers across your pages. OR, like I said, you can also make/adopt a UI component to do it for you without ajax.

hide div when another div is loaded

I have this :
window.onload = function() {
$("#show").load("show.php");
}
and my html :
<div id='loader'>Loading Data</div>
<div id='show'></div>
<div id='other'>some text.........</div>
What I want is, on page loaded, html show <div id='loader'> and <div id='other'> when JS/JQuery success loaded the <div id='show'> then hide <div id='loader'>
Can you help me?
.load() provide a callback you can use this. Just updated your js with following
$("#show").load("show.php", function(){
$('#loader, #show').toggle();
});
as #techLove's comment here, I found this working on me. I modified his answer into this:
$( "#show" ).load( "show.php", function() {$("#loader").css("display","none");});
load() has a callback that runs when it is complete. Use this to show and hide the relevant divs. You should also use jQuery ready function instead of window.onload so that the page won't have to wait for all resources (images etc) before it can load in the php:
$(document).ready(function() {
$("#show").load("show.php", function() {
$('#loader').hide();
});
});
EDIT: Super User's answer provides a better solution than using .hide(), wish I'd thought of it!

Jquery Animate overlapping on Loading Image

I am working on a project in which the navigation does not really changes pages but gets data using services based on which navigation link I click and update data using jquery .html() method, I want to use a loader that shows up on clicking any link and hides the content, when ajax services is successfull i want to remove the loader and show back the content, but somehow the animations are overlapping causing animations to fail,
in example code here i am not using ajax to update my page but a simple button
and jquery to update the data
<body>
<div id="loader">
<img src="loader.gif" alt="">
</div>
<br>
<div id="content">
This is the content
</div>
<input type="button" id="update" value="Update Data">
</body>
<script>
function showContent(){
$('#loader').fadeOut(200).promise().done(function(){
$('#content').fadeIn(200).promise().done(function(){
});
});
}
function hideContent(){
$('#content').fadeOut(200).promise().done(function(){
$('#loader').fadeIn(200).promise().done(function(){
});
});
}
$("#update").click(function(){
hideContent();
$("#content").html("New Data");
setTimeout(showContent(), 10000);
});
</script>
on clicking update, this should happen
content should disappear,
loader should appear,
update content,
loader disappear,
content appear,
but i get both loader and content appeared in the end
I used setTimeout to give some delay but it doesnt works , i also used some flags earlier but that didnt work too .
JsFiddle : JsFiddleLink
Why use setTimeout()? You can return, chain the promise
function showContent(){
return $('#loader').fadeOut(200).promise().done(function(){
return $('#content').html(data).fadeIn(200).promise()
});
}
function hideContent(){
return $('#content').fadeOut(200)
.done(function() {
this.empty();
return $('#loader').fadeIn(200).promise()
});
}
$("#update").click(function() {
hideContent().then(showContent)
})

How do I use javascript from content loaded with AJAX?

I have done a lot of researching in other questions and on Google, and so far nothing has worked. I have some JavaScript/jQuery experience and consider myself fluent in PHP.
I am developing an app for work that uses jQuery to load pages from the navigation menu. Here is the setup of that element so far:
<menu>
<button value="home">HOME</button>
<button value="process_sheets">PROCESS SHEETS</button>
<button value="admin">ADMINISTRATION</button>
<button value="faq">FAQ</button>
<div id="search-container"></div>
</menu>
<script>
$("menu button").each(function() {
$(this).on("click", function() {
$.get(null, {
page: $(this).val()
}, function(data) {
$("article#content").html($.parseHTML(data));
}, 'html');
});
});
</script>
The problem is that I have a simple accordion on one page that has code that isn't working when loaded through the menu.
Here is the accordion code:
$(function($) {
$('#accordion').find('.accordion-toggle').on('click', function(){
$(this).next().slideToggle('fast');
$(".accordion-content").not($(this).next()).slideUp('fast');
});
});
<h2>Process Sheets</h2>
<div id="process-sheets-accordion">
<h4 class="accordion-toggle">GE</h4>
<div class="accordion-content">
<?php include 'static_section_form.php'; ?>
</div>
<h4 class="accordion-toggle">5"</h4>
<div class="accordion-content">
<p>Vivamus facilisisnibh scelerisque laoreet.</p>
</div>
etc...
</div>
If the code in question is actually in the text returned by the ajax call, the problem is that that doesn't get executed when you load via get and then parse it and add it to the page.
jQuery has a function specifically designed for doing exactly that, though: load:
$("menu button").each(function() {
$(this).on("click", function() {
$("article#content").load(null, {page: $(this).val()});
});
});
load will retrieve the page using ajax, extract the scripts from it, put the content into the element, and then execute the scripts.
The above would use POST because we're passing an object as the second argument, but as you're using GET, we should just add page to the URL:
$("article#content").load(location.pathname + "?page=" + encodeURIComponent($(this).val()));
...or by passing it as a string:
$("article#content").load(location.pathname, "page=" + encodeURIComponent($(this).val()));
If you don't give a data object, load defaults to GET instead of POST.
Side note: I've never seen null as the URL for $.get before. I've copied it to the load call above, but I don't think null is valid (in either place), as there's nothing in the documentation saying it can be anything but a string. Use an actual URL, such as the location.pathname I've used in the GET example above.
Here is the working snippet of code which does exactly as I intended:
$("menu button").each(function() {
$(this).on("click", function() {
$("#content").load(window.location.pathname + "?page=" + encodeURIComponent($(this).val()));
});
});

calling an external script and .load jquery conflict

I'm pretty sure this is another DOH! facepalm questions but as designer and not a programmer I need some help getting it right.
What I have is an index file calling local .html files via jQuery .load. Just like this:
(some tabs functionality not relative here - thus the link target call)
Lightbox</li>
<div id=lightbox">
<div class="load">
<script type="text/javascript">
$('.load').load('examples/lightbox.html');
</script>
</div>
</div>
I also have an external .js file that has a bunch of functions that handles some lightboxes among other things. Standard <script src="js/typography.js" type="text/javascript"></script>
Which contains:
$(document).ready(function(){
$(".open-lightbox").on("click", function(){
$('.lightbox').css('display','block');
});
$('.close-lightbox').click(function(){
$('.lightbox').css('display','none');
});
});
My problem is that if the externally called .html file has any elements dependent on the .js file ie. the lightbox popup it doesn't work.
something like :
LightBox Link
<div class="lightbox">
lightbox content
Close
</div>
If i move the html code right to the index page instead of the .load, no problem, same if I moved the JS as an inline <script>...</script> rather than calling it extrenally. Works fine in both cases.
My spidey sense tells me this has something to do with my function and .load not executing in the order I need them to, but my javascript copy/paste skills only go this far.
Can anyone tell me if I can make this combination work? I'd really appreciate it.
EDIT
Maybe I explained my self poorly so let me try and post a better example.
If my index code is as followed everything works: My lightbox pops up as intended.
<li>Link to open Tab Content</li>
<div id="thistabid">
<--Tab Content below-->
<div class="somehtmlpage-load">
LightBox Link
<div class="lightbox">
lightbox content
Close
</div>
</div>
<--End Tab Content-->
</div>
When the said tab is clicked the content inside "thistabid" show up. Whatever that content may be.
Now if i do :
<li>Link to open Tab Content</li>
<div id="thistabid">
<--Tab Content below-->
<div class="somehtmlpage-load">
<script type="text/javascript">
$('.somehtmlpage-load').load('examples/lightbox.html');
</script>
</div>
<--End Tab Content-->
</div>
The lightbox doesn't work. The content of lightbox.html is
LightBox Link
<div class="lightbox">
lightbox content
Close
</div>
Same as the html in the 1st example where everything works. The only difference it's being jQuery loaded rather than hard coded.
What I mean by "if the externally called .html file has any elements dependent on the .js file ie. the lightbox popup" is that if the html is part of the externally called file then the lightbox function isn't working. If it's hard coded it pops up like intended.
On 1st glance the .on seems like should be the solution but most likley my implementation of it is off the mark :/
The 'on' or the 'live' function needs to be applied through an element that exists on the page. Generally some parent of the actual element is used. Can you try something on the following lines with the correct references to the elements on your page:
<li>Link to open Tab Content</li>
<div id="thistabid">
<--Tab Content below-->
<div class="somehtmlpage-load">
<!--leave tab empty for now -->
</div>
<--End Tab Content-->
</div>
<script>
(function(){
$('.somehtmlpage-load').load('examples/lightbox.html');
//live or on needs to be applied to an element that exists on th page
$('#thistabid').on('click', '.open-lightbox', function(){
$('.lightbox').css('display','block');
});
$('#thistabid').on('click', '.close-lightbox', function(){
$('.lightbox').css('display','none');
});
})();
</script>
There seems to be a race condition between your load() and document ready.
To address this you'll need to:
either wait for the load() to complete before you attach the click events
or attach the click to the container of your load() step and use event delegation.
See this page and this other one for more information on how to use on() for delegation.
The code would look like this:
$(".somehtmlpage-load").on("click", ".open-lightbox", function(){
$('.lightbox').css('display','block');
});
Using a SSI solved my problem. I was trying to keep it all Local Drive friendly but it seemed to be causing more problems than anticipated.
Pick your favorite dev environment...I didn't run into any conflicts on either.
ASP - <!--#include file = "examples/lightbox.html" -->
PHP - <?php include 'examples/lightbox.html';?>
Just in case someone else runs into a similar problem.

Categories

Resources