This is the code I'm using to get all loaded images:
$("img").on('load', function() {
console.log('Image Loaded');
}).each(function() {
if(this.complete){
//$(this).trigger('load');
var img = $(this).attr('src');
console.log(img);
}
});
but it's not working with those that are loaded with ajax afterwards, so I tried:
$(document).on('load', 'img', function(){
console.log('Image Loaded');
}).each(function() {
if(this.complete){
//$(this).trigger('load');
var img = $(this).attr('src');
console.log(img);
}
});
but it's not doing anything, what would be the correct way? I need to manipulate the parent divs of each image that is freshly loaded, so getting just all images period on every ajax load would be overkill and not elegant
How about this?
$(document).on('load', 'img', function(){
console.log('Image Loaded');
var parent = $(this).parent(); //or .parents('div') or .closest('div'), etc..
//do something with parent
});
I will suggest that you create a function for getting images and also call the same function after ajax execution.
Edit
Pass an id or class string present in document or returned ajax data to limit the scope of the function
function getImages(id) {
$('#' + id).find("img").on('load', function() {
console.log('Image Loaded');
}).each(function() {
if(this.complete) {
//$(this).trigger('load');
var img = $(this).attr('src');
console.log(img);
}
});
}
getImages('outsideAjax'); // call during normal execution. outsideAjax is an id within your html document but not in the returned ajax data
$.ajax({
// ajax settings
}).done(function() {
// post ajax code
// append returned data to document
getImages('insideAjax'); // recall after successful ajax execution and appending of returned data. 'insideAjax' is an id inside your return ajax data
}).fail(function(jqXHR, textStatus, errorThrown) {
// report error
});
This is how I solved it:
<img src="' + picUrl + '" onload="checkPic(\'' + picUrl + '\', this.naturalHeight, this.height);" class="pic">
Inside AJAX response.
I think it's self explanatory, works perfectly!
In the checkPic functuion I find this element by the src and get the parent elements and so on.
Related
I am trying to create a dropdown menu that I dynamically insert into using jQuery. The objects I'm inserting are notifications, so I want to be able to mark them as read when I click them.
I have an AJAX call that refreshes the notifications every second from the Django backend.
Once it's been refreshed, I insert the notifications into the menu.
I keep an array of the notifications so that I don't create duplicate elements. I insert the elements by using .append(), then I use the .on() method to add a click event to the <li> element.
Once the click event is initiated, I call a function to .remove() the element and make an AJAX call to Django to mark the notification as read.
Now my problem:
The first AJAX call to mark a notification as read always works. But any call after that does not until I refresh the page. I keep a slug value to identify the different notifications.
Every call I make before the refresh uses the first slug value. I can't figure out why the slug value is tied to the first element I mark as read.
Also, if anyone has a better idea on how to approach this, please share.
Here's my code:
var seen = [];
function removeNotification(elem, urlDelete) {
elem.remove();
console.log("element removed");
$.ajax({
url: urlDelete,
type: 'get',
success: function(data) {
console.log("marked as read");
},
failure: function(data) {
console.log('failure to mark as read');
}
});
}
function insertNotifications(data) {
for (var i = 0; i < data.unread_list.length; i++) {
var slug = data.unread_list[i].slug
var urlDelete = data.unread_list[i].url_delete;
if (seen.indexOf(slug) === -1) {
var elem = $('#live-notify-list').append("<li id='notification" +
i + "' > " + data.unread_list[i].description + " </li>");
var parent = $('#notification' + i).wrap("<a href='#'></a>").parent();
seen.push(slug);
$( document ).ready(function() {
$( document ).on("click", "#notification" + i, function() {
console.log("onclick " + slug);
removeNotification(parent[0], urlDelete);
});
});
}
}
}
function refreshNotifications() {
$.ajax({
url: "{% url 'notifications:live_unread_notification_list' %}",
type: 'get',
success: function(data) {
console.log("success");
insertNotifications(data);
},
failure: function(data) {
console.log('failure');
}
});
}
setInterval(refreshNotifications, 1000);
I really don't know what do you mean with parent[0] in
removeNotification(parent[0], urlDelete);
I think you can simply try $(this)
removeNotification($(this), urlDelete);
but to be honest I find to put
$( document ).ready(function() {
$( document ).on("click", "#notification" + i, function() {
console.log("onclick " + slug);
removeNotification(parent[0], urlDelete);
});
});
inside a loop .. its bad thing try to put it outside a function and use it like
$( document ).ready(function() {
setInterval(refreshNotifications, 1000);
$( document ).on("click", "[id^='notification']", function() {
console.log("onclick " + slug);
removeNotification($(this), urlDelete);
});
});
and try to find a way to pass a urlDelete which I think it will be just one url
What I want is to be notified when all images are loaded after DOM change. I know there is a jQuery plugin, but I'm wondering if there is any native method.
Example of code that does not work:
https://jsfiddle.net/wanpd5su/3/
// Real implementation will do an AJAX request to retrieve new
// document content. This one just sets a timeout instead.
$('#button').on('click', function doAjaxRequest() {
// This function changes the document content so that it
// contains new uncached images.
window.setTimeout(function changeContent() {
document.body.innerHTML = '<div id="div" style="background-image:url(\'http://lorempixel.com/800/600/abstract/?' + Math.random() + '\'); height:600px; width:800px;"></div>';
// This handler should run when new conent
// is ready and all images are loaded.
// BOT IT DOES NOT :(
$(window).on('load', function onLoad() {
alert('Document updated successfully.');
});
}, 1000);
});
I am attempting to add text from a jQuery array at a given point to my webpage. The page is set up so that when I click on a thumbnail, a larger image and caption data are to show on the page, however the caption text is not showing. $(caption[this.id]).text().appendTo('#images'); is where the error comes from, though if I do a simple DOM.write with the (caption[this.id]).text(), the words will show on the page.
// App variables
var filename = [];
var caption = [];
var id = [];
var counter = 0;
var thumbs = $([]);
var images = $([]);
//Make an AJAX call to load the XML file data
$.ajax({
url: 'gallery.xml',
dataType: 'xml',
success: function (data) {
$(data).find('gallery').each(function () {
// Gather the image filenames
$(data).find('image filename').each(function () {
counter++;
id.push(counter);
filename.push($(this).text());
});
//console.log(filename);
// Gather the image captions
$(data).find('image caption').each(function () {
caption.push($(this).text());
});
});
// Run the thumbnail loading procedure when the AJAX call has completed
loadThumbs();
loadImages();
},
error: function () {
// Failure alert if XML was not loaded
alert("XML file couldn't load...");
}
});
// Loop through filename list and create large image for each entry
var loadImages = function() {
$.each(filename, function (_, src) {
images = images.add(
$('<img />', {src: 'images/' + src, class: 'largeImage', height: '100px', width: '100px'})
);
});
// Add first image to default
$(images[0]).appendTo('#images')
};
// Do some shit when image is clicked...
$( document ).on( "click", "img", function() {
// Empty viewing DIV and create a new large-scale version of the image for viewing
$('#images').empty();
$(images[this.id]).appendTo('#images');
//THIS IS WHERE ERROR COMES FROM
// Add text to <span> to solve error?
$(caption[this.id]).text().appendTo('#images');
});
The error is specifically:
I can add all of the JS code if there is not enough here to understand. Thanks in advance.
You're passing the caption text to jQuery:
$(caption[this.id])
The library is trying to parse it as a CSS selector, and it can't so it throws the error.
You could do several things to make it work, and your suggestion in the comment is a good one:
$("<span/>", { text: caption[this.id] }).appendTo("#images");
In my plug-in I need to wrapp all sidebar's children in a div to let them overflow but if those elements are loaded dynamically the function does not work and I don't know either how to make it work.
The code is:
<div class="sidebar">
</div>
var $sidebar = $( '.sidebar' );
$sidebar.load( 'external-page.ext' );
$sidebar.MyPlugin();
$.fn.MyPlugin = function() {
this.wrapInner( '<div />' );
});
If those elements are not loaded dynamically there is no problem.
Firstly the code was:
$sidebar.wrapInner( '<div/>' );
and this just works fine if elemens are not loaded dynamically, so I tried this way:
var children = $sidebar.children();
$( document ).on( 'load', children, function() {
$( this ).wrapAll( '<div />' );
});
but, of course it does not work.
Can you please help me?
I thought that this rule would have worked this time too but it didn't. What did I mistake?
You can find the whole code here.
And a demo here
MORE DETAILS
I want to handle this issue from the inside, not from the outside! I don't know if users will load content dinamically or not. that's the point.
So there is a way to handle this issue inside the plugin and not outside?
From the manual
http://api.jquery.com/load/
Callback Function
If a "complete" callback is provided, it is executed after
post-processing and HTML insertion has been performed. The callback is
fired once for each element in the jQuery collection, and this is set
to each DOM element in turn.
Try the following code and see if this works:
$sidebar.load( 'external-page.ext', function() { $sidebar.MyPlugin(); } );
Thanks.
$.load() makes an ajax call to load the data ,
So there is a possibility that your this.wrapInner( '<div />' ) method has invoked before any data is loaded inside the div.sidebar.
Make sure this.wrapInner( '<div />' ) is called after all data has been loaded successfully using the complete callback.
$.load() trigger callback for each div ,call your plugin from callback
$sidebar.load('http://fiddle.jshell.net/vikrant47/ncagab2y/1/show/', function () {
$(this).MyPlugin();
}
});
DEMO
OR
If you are using $.load() only to load inside multiple elements then you could probably use one of the more powerful jQuery ajax methods (i.e., get() or post() or ajax()).
$.get('http://fiddle.jshell.net/vikrant47/ncagab2y/1/show/', {}, function(data) {
$sidebar.html(data).MyPlugin();
});
DEMO using $.get() Method
UPDATE-
Answer to the comment-
You should not have to worry about weather user gonna call your plugin like this $sidebar.load(...).MyPlugin().User must be aware enough about how to handle asynchronous methods.
You can not make your plugin work until there is some data inside div.slider
but ,you can add ajax loading functionality inside your plugin like -
$(document).ready(function () {
$.fn.MyPlugin = function (options) {
var $elem=this;
var init = function () {
options.load = $.extend({}, $.fn.MyPlugin.defaultOptions.load, options.load);
load();
}
//adding load method to load data dynamically
var load = function () {
if (!options.load.url) {
alert("url can not be empty");
} else {
$.ajax({
url: options.load.url,
type: options.load.type,
data: options.load.data,
success: function (response) {
options.load.success.call(this, response);
$elem.html(response).wrapInner('<div class="wrapper"/>');//wrap after data has been loaded successfully
},
error : function (jqXHR, textStatus, errorThrown) {
alert("error occured" + textStatus + " ," + errorThrown)
}
})
}
}
init();
}
$.fn.MyPlugin.defaultOptions = {
load: {
tye: "get",
data: {},
success: function () {}
}
};
Now use your plugin like-
var $sidebar = $('.sidebar');
$sidebar.MyPlugin({
load: {
url: 'http://fiddle.jshell.net/vikrant47/ncagab2y/1/show/'
}
});
});
DEMO with load
Try adding adding below piece to plugin . Added at lines 84 - 110 at gist .
var target = $sidebar.get(0);
// create an observer instance
var observer = new MutationObserver(function (mutations) {
mutations.forEach(function (mutation) {
// do stuff when
// `childList` modified
// i.e.g.,
$.each(mutation.addedNodes, function (k, v) {
$(v)
.wrapInner('<div data-'
+ dataName
+ '="sub-wrapper"></div>')
})
});
});
// configuration of the observer:
var _config = {
childList: true
};
// pass in the target node, as well as the observer options
observer.observe(target, _config);
jsfiddle http://jsfiddle.net/guest271314/s5wzptc8/
See MutationObserver
Apologies, a total newb here. How can I load other plugins, and let other separate scripts function after loading an ajax generated page? This is my curent code:
jQuery(document).ready(function($) {
var $mainContent = $("load-content"),
siteUrl = "http://" + top.location.host.toString(),
url = '';
$(document).delegate("a[href^='"+siteUrl+"']:not([href*='/wp-admin/']):not([href*='/wp-login.php']):not([href$='/feed/'])", "click", function() {
if($.browser.msie){
var myie="/"+this.pathname;
location.hash = myie;
//alert(location.hash);
}else{
location.hash = this.pathname;
}
return false;
});
$("#searchform").submit(function(e) {
$search = $("#s").val();
$search = $.trim($search);
$search = $search.replace(/\s+/g,'+');
location.hash = '?s='+$search;
e.preventDefault();
});
$(window).bind('hashchange', function(){
url = window.location.hash.substring(1);
if (!url) {
return;
}
url = url + " #content";
$('html, body, document').animate({scrollTop:0}, 'fast');
$mainContent.fadeOut(500, function(){$('#content').fadeOut(500, function(){
$("#loader").show();});}).load(url, function() {
$mainContent.fadeIn(500, function(){
$("#loader").hide(function(){ $('#content').fadeIn(500);});});});
});
$(window).trigger('hashchange');
});
How can embedded objects on pages retain their functionality? Mainly videos, slideshows and other media that use javascript like
video js (html5 video player)
vimeo
and
portfolio slideshow for wordpress
When you load ajax-generated markup it will not retain the functionality it had before. In your example above, you're initialising things when the DOM is ready to be acted upon. In order to make sure any plugins, etc, are running after you perform the ajax request you need to reinitialise them.
Given your code sample above, I'd recommend a little restructuring. For example, you could create a function called init which you could call to initialise certain plugins:
function init () {
$("#plugin-element").pluginName();
}
jQuery(document).ready(function () {
// Initialise the plugin when the DOM is ready to be acted upon
init();
});
And then following this, on the success callback of you ajax request, you can call it again which will reinitialise the plugins:
// inside jQuery(document).ready(...)
$.ajax({
type: 'GET',
url: 'page-to-request.html',
success: function (data, textStatus, jqXHR) {
// Do something with your requested markup (data)
$('#ajax-target').html(data);
// Reinitialise plugins:
init();
},
error: function (jqXHR, textStatus, errorThrown) {
// Callback for when the request fails
}
});