check all images loaded after .ajax request? - javascript

I need to know when all images are loaded from appended html source to perform another function. How can I check that?
$(document).ready(function () {
$('a.load-more').click(function (e) {
e.preventDefault();
$.ajax({
type: "GET",
url: $(this).attr('href'),
data: {
page: last_id
},
dataType: "script",
success: function () {
$('.load-more').show();
}
});
});
});
I'm appending html source like this:
$('.container').append('<%= escape_javascript(render(:partial => #items)) %>');
It gives html source successfully, but I can't find out when all images from that source is loaded
.container updates every time link is clicked Load more
and the .container source looks like this:
<ul class="container">
<%= render #items %>
</ul>

On all browsers supporting event capturing phase, you can capture onload event for all new added images:
document.addEventListener(
'load',
function(event){
var elm = event.target;
if( elm.nodeName.toLowerCase() === 'img' && $(elm).closest('.container').length && !$(elm).hasClass('loaded')){ // or any other filtering condition
console.log('image loaded');
$(elm).addClass('loaded');
if($('.container img.loaded').length === $('.container img').length) {
// do some stuff
console.log("All images loaded!")
}
}
},
true // Capture event
);
To support e.g IE8 which doesn't handle capturing phase, you should set onload event to specific images once they are added in the DOM, setting it in script onload event.

Related

jQuery interact with appended data

Can anyone point out what I'm doing wrong here? I'm trying to interact with data (appended using ajax)
The alerts fire if the element is already in DOM, but not when It's appended.
Am I using the ".on" wrong?
$(function() {
$('.card').on('click','.add-exercise', function() {
alert('clicked');
});
// Detect 'enter' key up
$('#search').on('keyup', function(e){
if(e.keyCode == 13)
{
console.log('hit enter key');
$(this).trigger("enterKey");
}
});
$('#search').on("enterKey",function(e){
$.ajax({
url: '{{ url("exercises/load") }}',
method: "POST",
data: {
_token: "{{csrf_token()}}",
search: $('#search').val(),
},
dataType: "text",
success: function(data) {
console.log(data);
$('.exercise-result').remove();
$('.card-deck').append(data);
}
});
});
});
I guess you have other .card elements in data.
You have to assign the event click again for them. The event is currently only assigned to your first .card elements. This is why it doesn't fire on your new .card elements.
I believe you need to add the event again each time the append is done. Try this and let me know if it works:
function addEvent() {
$('.card').on('click','.add-exercise', function() {
alert('clicked');
});
}
$(function() {
addEvent();
// Detect 'enter' key up
$('#search').on('keyup', function(e){
if(e.keyCode == 13)
{
console.log('hit enter key');
$(this).trigger("enterKey");
}
});
$('#search').on("enterKey",function(e){
$.ajax({
url: '{{ url("exercises/load") }}',
method: "POST",
data: {
_token: "{{csrf_token()}}",
search: $('#search').val(),
},
dataType: "text",
success: function(data) {
console.log(data);
$('.exercise-result').remove();
$('.card-deck').append(data);
addEvent();
}
});
});
});
I think the .card element is also loading dynamically, in order to make event delegation works properly you need to bind it to an element which is present at the time of page load.
So either you can attach it to the document object.
$(document).on('click','.card .add-exercise', function(){
// rest of your code
});
or better approach would be, attach to an element which is present at the time of page load(I guess .card-deck is present at the time of page load since you are appending data to that or attach to body tag).
$('.card-deck').on('click','.card .add-exercise', function(){
// rest of your code
});

javascript/jquery doesn't work in ajax

I have php page "Home.php", that present user posts(using ajax).
This is how I get the posts:
<script type="text/javascript">
function loadmore()
{
var val = document.getElementById("result_no").value;
var userval = document.getElementById("user_id").value;
$.ajax({
type: 'post',
url: 'fetch.php',
data: {
getresult:val,
getuserid:userval
},
success: function (response) {
var content = document.getElementById("result_para");
content.innerHTML = content.innerHTML+response;
// We increase the value by 2 because we limit the results by 2
document.getElementById("result_no").value = Number(val)+10;
}
});
}
</script>
<div id="content">
<div id="result_para">
</div>
</div>
In every post, there is a like button(which also uses ajax). This is how I save the likes:
<script type="text/javascript">
function likethis(likepostid)
{
$.ajax({
type: 'post',
url: 'fetchlikes.php',
data: {
getpostid:likepostid
},
success: function (response) {
}
});
}
</script>
Before I used ajax to present posts, all worked well. But now when I press the like button, it DOES save the like, BUT the javascript/jquery doesn't work. I tried to make alert when I pressed the LIKE button, but it didn't work.
This is the index.js code(the javascript). It add +1 likes, when the user press the button:
$('.btn-counter_likecount').on('click', function(event, count) {
event.preventDefault();
//alert("hello");
var $this = $(this),
count = $this.attr('data-count'),
active = $this.hasClass('active'),
multiple = $this.hasClass('multiple-count_likecount');
$.fn.noop = $.noop;
$this.attr('data-count', ! active || multiple ? ++count : --count )[multiple ? 'noop' : 'toggleClass']('active');
});
EDIT fetchlikes.php:
<?php
mysql_connect('localhost','root','');
mysql_select_db('blabla');
$postid=$_POST['getpostid'];
mysql_query("UPDATE user_post SET likes_count=likes_count+1 WHERE post_id='$postid'");
?>
Because your posts are being loaded dynamically, the javascript where you bind the event is running before the posts are actually loaded, thus the buttons don't exist when you try to bind the event. You can use delegated events in jQuery to handle this.
Your previous code
$('.btn-counter_likecount').on('click', function(event, count) {
....
});
New Code
$('#result-para').on('click','.btn-counter_likecount',function(event, count) {
....
}
This way the event will actually be bound to a parent element that already exists when jQuery's ready() function runs. This way, the event handler checks for matching elements when the event is fired rather than when the event is bound.
For further reading, look into jQuery's delegated events

How to stop a div loading an HTML page

The remove() on id main is called from clicking another external button. The problem is if the user clicks btn1 and quickly presses that external button, the remove is getting called before the event handler for btn1. As a result of which the popup is loaded after the div has been removed. Is there a way by which the load request can be stopped when event handler for remove is clicked? I tried with jqXHR.abort() when remove method is called,but that doesn't work because the remove is called before the ajax is even sent.
There are many buttons like btn1 which will send ajax requests to load HTML and Few HTMlL files for e.g a.html will load some script files like a.js, which will be executed. And if the script refers to some variable which was deleted in remove(), there will be a TypeError.
<div id="base">
<div id="main">
<!-- some more HTML elements -->
<button id="btn1"></button>
</div>
<div id ="popup">
</div>
</div>
<script>
var xhr;
$("#btn1").on("click", function(){
xhr = $.ajax(
url: "a.html",
success: function(){
//do something
}),
type: "GET"
});
$("#main").on("remove", function(){
// delete all resources,etc.
xhr.abort();
});
</script>
Try using a global variable
var removed = 0;
$('externabutton').click(function(){
$("#main").remove();
removed = 1;
});
$("#btn1").on("click", function(){
xhr = $.ajax(
url: "a.html",
success: function(data){
if (removed == 0 ) {
//append the data
} else {removed ==0;}
}),
type: "GET"
});
As the xhr is async, so we cannot guarantee the xhr is finished before #main.remove method. Maybe you could use a flag to control this.
var isRemoved = false, xhr;
$("#btn1").on("click", function(){
if(isRemoved) return;
xhr = $.ajax({
url: "a.html",
success: function(){
//do something
if(isRemoved) return;
},
type: "GET"
});
});
$("#main").on("remove", function(){
isRemoved = true;
xhr && xhr.abort();
});

Javascript ajax calls don't work inside of dynamically loaded HTML

I'm trying to write a generic javascript script to facilitate clicking through <a href> links while only replacing the inner HTML instead of reloading the whole page. The strange thing is, it works, except on any link inside of freshly loaded HTML.
<script src="{{ asset('bundles/app/js/jquery-2.2.0.min.js') }}"></script>
<script src="{{ asset('bundles/app/js/jquery.menu-aim.js') }}"></script>
<script src="{{ asset('bundles/app/js/main.js') }}"></script>
<script type="text/javascript">
$(document).ready(function() {
$("a").on("click", function(){
event.preventDefault();
$.ajax({
'url': $(this).attr('href'),
type: "post",
success: function(response, status) {
document.getElementById("content").innerHTML = response;
},
error: function() {
console.log('failure');
}
});
});
});
</script>
When I place the exact same URL from the loaded HTML directly in the sidebar menu containing the initial links, it loads fine. According to the documentation, the .on function should attach itself to any elements added later. I've also tried .delegate and the deprecated .live as suggested by older answers but then even the menu sidebar stopped working.
What am I missing here?
Here I assume your link container is "content" by ID, if not fix that with the correct container ID OR even wrap them IN one:
$(document).ready(function() {
$('#content').on('click', 'a', function() {
event.preventDefault();
$.ajax({
'url': $(this).attr('href'),
type: "post"
}).done(function(response, status) {
document.getElementById("content").innerHTML = response;
}).fail(function() {
console.log('failure');
});
});
});
Example markup:
<div id="content">
clickme
</div>
This is NOT as desirable, (placing it on the document) place the handler on the container
if you can
$(document).ready(function() {
$(document).on('click', 'a', function() {
event.preventDefault();
$.ajax({
'url': $(this).attr('href'),
type: "post"
}).done(function(response, status) {
document.getElementById("content").innerHTML = response;
}).fail(function() {
console.log('failure');
});
});
});
As to WHY this is not desirable (the document); you want to place your event handler hooks as close to the element as possible; when you attach to the document as here, if forces the code to go through the entire document for the event handler to find the a links and look for clicks on those.
Note the the documentation says
"A selector string to filter the descendants of the selected elements that trigger the event. If the selector is null or omitted, the event is always triggered when it reaches the selected element."
Thus for the a selector in your case. SO it places the event handler on EVERYTHING in the document, THEN filters on the a selector for yours. SO if you place it on a smaller container, it has to filter less on every event (click) that is executed.
You have to apply the behaviour to the loaded HTML as well, like in this example (not tested):
$(document).ready(function() {
function addBehaviour() {
// .off first so existing behaviour will be removed and not applied multiple times
$("a").off("click").on("click", function(){
event.preventDefault();
$.ajax({
'url': $(this).attr('href'),
type: "post",
success: function(response, status) {
document.getElementById("content").innerHTML = response;
addBehaviour(); // add the behaviour
},
error: function() {
console.log('failure');
}
});
});
}
addBehaviour();
});

JS script doesn't work when i click back on site

i create a nav on my site. Navigation works good but when i back on the main site all script from js file doesn't work. Script for my nav:
var default_content="";
$(document).ready(function(){
//Ajax navigate
checkURL();
$('footer a').click(function(){
checkURL(this.hash);
});
default_content = $('#login_box').html();
setInterval("checkURL()",250);
.........
Methods:
var lasturl="";
function checkURL(hash)
{
if(!hash) hash=window.location.hash;
if(hash != lasturl)
{
lasturl=hash;
if(hash=="")
$('#login_box').html(default_content);
else
loadPage(hash);
}
}
function loadPage(url)
{
url=url.replace('#page','');
$.ajax({
type: "POST",
url: "include/help4meApi.php",
data: 'page='+url+'&tag=navigation',
dataType: "html",
success: function(msg){
if(parseInt(msg)!=0)
{
$('#login_box').html(msg);
}
}
});
}
Problem is when i back to the main site scripts doesn't work.
the issue comes from here $('#login_box').html(default_content);. When u calle the .html() the event binded within the element will be cleaned.
When you backspace, back to the main page, the event handler is already not there, so you have to register it again
//For show and hide register values
$("#registerInputsBtn").click(function(){
$(".register_information").hide(1000);
$(".register_values").show(1000);
$("#firstname").focus();
});
register again on the piece of code that you assign the content to #login_box. For example the quick fix:
if(hash==""){
$('#login_box').html(default_content);
$("#registerInputsBtn").click(function(){
$(".register_information").hide(1000);
$(".register_values").show(1000);
$("#firstname").focus();
});
}
but here the codes are not DRY :( rearrange the flow on how the page load and the register the event in the correct flow is recommended.

Categories

Resources