AJAX loads content twice - javascript

I am trying to build a sidebar navigation, which uses AJAX to load content inside a div.
So far it is working great, it is just that i noticed, that everytime i click onto the buttons to navigate to a different site on my page, the site content seems to be loaded on top of the current content.
I have got this hypothesis, because on every site load my site sends one request to a server, to get data from there.
Now if i already visited the site on my page, that sends this request, navigate to a different site on my page and navigate back to the first site, this site sends two requests to the server.
If i am repeating those steps, it just adds up and the request gets sent 3,4,5..times
This is the Code of my navigation bar:
<div id="sidedrawer" class="mui--no-user-select">
<div class="mui-divider"></div>
<ul>
<li onClick="remote();" href="./#remote">
<strong>Remote</strong>
</li>
<li onClick="groups();" href="./#groups">
<strong>Groups</strong>
</li>
<li onClick="devices();" href="./#devices">
<strong>Devices</strong>
</li>
<li onClick="users();" href="./#users">
<strong>Users</strong>
</li>
<li onClick="programs();" href="./#programs">
<strong>Programs</strong>
</li>
<li onClick="settings();" href="./#settings">
<strong>Settings</strong>
</li>
</ul>
</div>
The functions remote()/groups()/devices() look about the same:
function remote() {
showSubPage("Remote", "./remote.php");
}
showSubpage() looks like this:
function showSubPage(title, page){
changeTabName(title);
$.ajax({
url: page,
type: "GET",
cache: false,
success:function(data){
var $main = $('#main');
$main.html('');
$main.html(data);
}
});
}
Main is just a normal div:
<div id="main"></div>
Does anyone have an idea why my page does not get called just once everytime i click the links?
Edit:
When i am looking into the source code of my page, the content is only listed once.
Edit2: I figured that the problem does not come from the ajax itself.
This is the PHP-code that i am using to generate my page.
function addGroup($groupId, $groupname, $devicearr)
{
echo('<div class="group">
<h3>'.$groupname);
echo('<div class="verticalcenter"><div class="toggle-button toggle-button-selected " id="groupButton'.$groupId.'"><button></button></div></div>');
echo(' </h3>
<div>
<table class="devicetable">
');
foreach ($devicearr as &$device) {
echo('<tr>
<td>'.$device['name'].'</td>');
if($device['status'] == 1){
echo('<td class="togglecolumn"><div class="verticalcenter" ><div class="toggle-button toggle-button-selected group'.$groupId.' device'.$device['id'].'" id="group'.$groupId.'device'.$device['id'].'" ><button></button></div></div></td></tr>');
} else {
echo('<td class="togglecolumn"><div class="verticalcenter"><div class="toggle-button group'.$groupId.' device'.$device['id'].'" id="group'.$groupId.'device'.$device['id'].'"><button></button></div></div></td></tr>');
}
echo ('<script>
$(document).on("click","#group'.$groupId.'device'.$device['id'].'", function() {
if($("#group'.$groupId.'device'.$device['id'].'").hasClass("toggle-button-selected")){
$(".device'.$device['id'].'").removeClass("toggle-button-selected");
var frame = document.createElement("iframe");
frame.src = "http://localhost/callMethod";
frame.style.left = "-9999px";
frame.style.display = "none";
frame.onload = function() {
this.parentNode.removeChild(this);
};
document.body.appendChild(frame);
}
else{
$(".device'.$device['id'].'").addClass("toggle-button-selected");
var frame = document.createElement("iframe");
frame.src = "http://localhost/callMethod";
frame.style.left = "-9999px";
frame.style.display = "none";
frame.onload = function() {
this.parentNode.removeChild(this);
};
document.body.appendChild(frame);
}
});
</script>');
}
echo('
</table>
</div>
</div>');
}
My code creates a button for each "device" that is in the "devicearr". But when my page got called twice and i click the button once, it registers two click events.

Instead of:
$(document).on("click","#group'.$groupId.'device'.$device['id'].'", function() {
});
I used:
$("#group'.$groupId.'device'.$device['id'].'").click( function() {
});
so that the Click-Event does not stay alive after reloading the ajax content.
Additionally (not necessarily needed), i also unbind the click-event, before i register the click-event with:
$("#group'.$groupId.'device'.$device['id'].'").off("click");
Thanks to Barmar for the hint.

Related

jQuery / javascript How to load Script when a css class presents in the page

I have a page shows a list of rows and with a pagination, when you click on next page the next page loads in same page contains another list of rows. so basically next page loads a bunch of other rows without my exact page been reloaded
So the problem im haven is i use this script below while it works fine but when the next page loads in same window this script does not work for them.
I hope i make sense here :) what is a good solution for this?
$('.ltwitch').each(function () {
var tnick = $(this).data('tnick');
var span = $(this).next();
$.getJSON("https://api.twitch.tv/kraken/streams/" + tnick + ".json?callback=?", function (data) {
if (data.stream === null) {
span.html(
'<strong class="ipsOnlineStatus ipsOnlineStatus_offline"><i class="fa fa-circle"></i></strong><h4 class="ipsDataItem_title ipsType_break"> ' + tnick + ' </h4><div class="ipsDataItem_meta">Offline</div>');
} else {
var views = data.stream.viewers;
var game = data.stream.game;
span.html(
'<strong class="ipsOnlineStatus ipsOnlineStatus_online"><i class="fa fa-circle"></i></strong><h4 class="ipsDataItem_title ipsType_break"> ' + tnick + ' </h4><div class="ipsDataItem_meta"> ' + views + ' viewers </div><div class="ipsDataItem_meta">Playing: '+ game +' </div>');
}
$(function() {
var online = $('.ipsOnlineStatus_online').closest('.cCmsRecord_row');
var first = $('.cCmsRecord_row')[0];
online.each(function() {
$(first).before(this);
});
});
short of HTML
<ol class="List">
<li class="row">
<div class="main">
<a href="#" class="ease">
<div class="ltwitch" data-tnick="esl_lol"></div>
</a>
</div>
</li>
<li class="row">
<div class="main">
<a href="#" class="ease">
<div class="ltwitch" data-tnick="esl_lol"></div>
</a>
</div>
</li>
....
....
....
</ol>
<div data-role="tablePagination">
<ul class="ipsPagination">
<li class="ipsPagination_prev ipsPagination_inactive">Prev</li>
<li class="ipsPagination_next">Next</li>
</ul>
</div>
It sounds like you want to wrap your work in a named function so you can call it on subsequent paging. Your code right now is most likely in a document ready which is only called on initial page load. Turning all of that work into a function now allows it to be called many times.
function myFunction () {
...
};
myFunction();
Then where your pagination code is set up ( I figure an anchor click binding ) just call myFunction() again.
$('.ipsPagination_next').click(function(){
...
myFunction();
});
I would note that if these two areas are in different document ready functions or different files, ideas like scope and encapsulation might become problematic. We'd have to see more code to confirm if it would be an issue. If you are having problems you could put the function myFunction() onto the root which would be outside of any document ready, load, or whatever you might be using. Then it would be on the root or window level.
window.myFunction = function () {
...each(... your current work
};
This could be used if you aren't sure about encapsulation or how scope works.
Your $('.ltwitch') selector only captures the classes present in the first page. When a subsequent page is loaded, $('.ltwitch') is not executed again on the new classes.
I suggest that you somehow differentiate between classes corresponding to already loaded pages, and classes corresponding to new pages. You could do this by adding a class, e.g. .already-loaded to the classes as you load them.
$.getJSON("https://api.twitch.tv/kraken/streams/" + tnick + ".json?callback=?", function (data) {
$(this).addClass('already-loaded'); // Mark as loaded.
...
This way, replace your first line with this:
$('.ltwitch').not('.already-loaded').each(function () {
...
Not tested, but could work.

Open Expanding List from Href

I'm trying to modify this pen I found on CodePen. I'd like to be able to open a specific list on the page from another page. Clicking the link should open the corresponding section on the next page on page load.
I'm a bit of a newbie when it comes to jQuery, so I appreciate any help I can get. I've tried searching around and have an idea of what I need to target, but I haven't been able to make it happen. Here is my code:
HTML:
<!--Link on Previous Page-->
Click Here
<!--Target List-->
<div class="integration-list">
<ul>
<li class="integration">
<a class="expand" id="list">
<div class="expand_intro"><h3 class="teal_bold">Click Here</h3></div>
<div class="right-arrow">▼</div>
</a>
<div class="detail">
<div><p>Lorem Ipsum Dolor...</p></div>
</div>
</li>
</ul>
</div>
JS:
$(function() {
$(".expand").on( "click", function() {
$(this).next().slideToggle(100);
$expand = $(this).find(">:nth-child(2)");
if($expand.text() == "▼") {
$expand.text("▲");
} else {
$expand.text("▼");
}
var hash = window.location.hash;
var thash = hash.substring(hash.lastIndexOf('#'), hash.length);
$('.expand').find('a[href*='+ thash + ']').trigger('click');
});
});
Few things that I did to get it to work:
The trigger event is probably firing before the handler is actually attached. You can use setTimeout as a way around this.
Also, even with setTimeout around $('.expand').find('a[href*='+ thash + ']').trigger('click'); it didn't work for me. I changed that to simply $(thash).click();.
The complete code of the "expand.js" file:
$(function() {
var hash = window.location.hash;
var thash = hash.substring(hash.lastIndexOf('#'), hash.length);
setTimeout(function() {
$(thash).click();
}, 10);
$(".expand").on( "click", function() {
$(this).next().slideToggle(100);
$expand = $(this).find(">:nth-child(2)");
if($expand.text() == "â–¼") { //If you copy/paste, make sure to fix these arrows
$expand.text("â–²");
} else {
$expand.text("â–¼");
}
});
});
Apparently the arrows don't display properly here, so watch that if you copy/paste this.

iframe video array

I am trying to make it so when I click the 'next' button it will increment the variable videoCounter and then reload the iframe so it plays the next video in the array.
Currently it just seems to reload the whole page and do nothing?
<script>
var videoCounter = 0;
var videoArray = new Array();
videoArray[0] = "//www.youtube.com/embed/nEBHkEeH42Y";
videoArray[1] = "//www.youtube.com/embed/1GlticqrECU",
videoArray[2] = "//www.youtube.com/embed/BMOUsI8JIaI";
function Increment() {
videoCounter++;
ReloadIFrame();
}
function ReloadIFrame() {
SetCurrentVideo();
document.getElementById('iframe').contentDocument.location.reload(true);
}
function SetCurrentVideo() {
document.getElementById("iframe").src = videoArray[videoCounter];
}
</script>
<iframe id="iframe" width="520" height="280" src="SetCurrentVideo();"
frameborder="0" allowfullscreen></iframe>
<ul class="pager">
<li class="previous disabled" id="videoOlder">← Older
</li>
<li id="videoTitle">Title here</li>
<li class="next" id="videoNewer" onclick="Increment();"> Newer →
</li>
</ul>
Currently, the page reloads because clicking on the a tag causes the browser to send the user to the destination of the link - because you haven't put a URL in the href of this link, the destination is the current page.
Each time the page loads, the value of videoCounter is reinitialised to 0; it appears to reload and do nothing because it's always loading the first video again.
To prevent the default behaviour of an anchor (a tag) you need to return false; from the handler:
function Increment() {
videoCounter++;
ReloadIFrame();
return false;
}
Update; you also have a syntax error on the second line (a comma instead of a semi-colon), which may be preventing the rest of your code from being defined.
Here's a full working example for you:
http://jsfiddle.net/UqXVf/1/

jQuery loads external HTML file but does not stay still after page refresh

I am trying to do something different without knowing if it is a good idea or not
I have a navigation menu as the following:
...
<li>Home</li>
<li>FAQ</li>
<li>Contact</li>
...
I do not want to use a server-side scripting because it takes more time to make db connection and define some configuration, and not want to multiply the pages for each one. So I made a master page index.php
in body section
there are two elements:
an h3 element to display the page title and a div to display the content which is called from another html source.
...
<div class="container">
<h3 id="pageTitle"></h3>
<div id="pageContent"></div>
</div>
...
I am using jQuery's click event to load the page into the div
$(function() {
$("a[href^='#m']").click(
function() {
$("#pageTitle").text($(this).text());
$("#pageContent").load($(this).attr("href").substring(1) + ".html"); //removing # char.
});
});
It works fine. But when I press F5 it returns the initial state as normal. How can I load the current page by referencing the address bar (I can see eg. sitename/#mfaq) when page is refreshed.
I think, first I need to detect if page is refreshing and load the corresponding html file in according to the #m**** on the addressbar.
$(function() {
$("a[href^='#m']").click( function(evt) {
// ------ This should work
// renamed parameter elem to evt like corrected in comment
evt.preventDefault();
$("#pageTitle").text($(this).text());
$("#pageContent").load($(this).attr("href").substring(1) + ".html");
});
});
Add to your DOM ready function:
if (window.location.hash != "") {
$("#pageTitle").text($("a[href='"+window.location.hash+"']").text());
$("#pageContent").load(window.location.hash.slice(1) + ".html");
}
I have made this. It works well. But I am not sure about performance issues:
$(function() {
var address = $(location).attr('href');
var hash = address.lastIndexOf("#");
var page = address.substring(hash+1);
if (hash < 1)
{
$("#pageContent").load("mhome.html");
$("#pageTitle").html("Default Page Title");
}
else
{
$("#pageContent").load(page + ".html");
$("#pageTitle").html($("a[href='" + address.substring(hash) + "']").text());
}
$("a[href^='#m']").click(
function() {
$("#pageTitle").text($(this).text());
$("#pageContent").load($(this).attr("href").substring(1) + ".html");
});
});

Swipe JS not working with populated content

I'm using Swipe JS 2.
If I make the HTML structure myself, it works perfectly, but if I populate the HTML with content coming from the jQuery, it stops on the second slide.
My HTML structure:
<div id="map" class="swipe">
<div class="swipe-wrap">
<div class="city" id="current">
<div class="location">Current Location</div>
</div>
</div>
</div>
<nav>
<ul id="position">
<li class="on">Current location</li>
</ul>
</nav>
This is my structure on the jQuery.
$.getJSON("http://localhost/locations.php", function(localdata) {
$.each(localdata.locations, function(i, geolocal){
var vcountry = geolocal['country'];
var vregion = geolocal['region'];
var vcity = geolocal['city'];
country = vcountry.replace(' ','_');
region = vregion.replace(' ','_');
city = vcity.replace(' ','_');
// THE PROBLEM IS HERE. IF I USE AJAX OR GETJSON HERE INSIDE THE OTHER GETJSON, THE SWIPE IS BROKEN.
$.ajax({
type: "GET",
url: "http://localhost/remotexml.php?url=http://www.yr.no/place/"+ country +"/"+ region +"/"+ city +"/forecast.xml",
success: function(xml) {
var localName = $(xml).find('location name').text();
$('#map div.swipe-wrap .city:last-child').after('\n<div class="city">\n<div class="location">'+localName+'</div>\n</div>\n</div>');
$('#position').append('\n<li>'+localName+'</li>');
}
});
});
})
.success(function() { })
.error(function() { })
.complete(function() {
var slider =
Swipe(document.getElementById('map'), {
auto: 5000,
continuous: true,
callback: function(pos) {
var i = bullets.length;
while (i--) {
bullets[i].className = ' ';
}
bullets[pos].className = 'on';
}
});
var bullets = document.getElementById('position').getElementsByTagName('li');
});
What happens is: when I see the HTML created by the jQuery, is perfect. jQuery is creating the divs inside the slider and the lis inside the list. Perfect. When I run the website, load and starts perfectly, but then, when changes slide, stops on the second slide, and the second slide is blank. Nothing there. Even thought there is content on the HTML.
The most weird part? If I start the Developer Tools (Command + Alt + I on Chrome), right after the website loads, it WORKS PERFECTLY. What kind of bizar behavior is this? :D
Anybody can help me to make this Swipe JS to run?
If you're populating the slider with content via an AJAX request, then you will most likely have to wait until that AJAX request is finished before you build the slider - i.e. in the success callback of your AJAX function.

Categories