On my web page, everything is okay.
My js is working very well but clicking on any page, page is loading with ajax but some function is not working for example my bootstrap carousel or my parallax.js plugin..
How do I do event management ?
I'm using youtube spf plugin
some js example on my page
if (!$(".scene").length) return false;
var q = document.getElementsByClassName("scene")[0];
var r = new Parallax(q, {
calibrateX: false,
calibrateY: true,
invertX: false,
invertY: true,
limitX: false,
frictionX: .2,
frictionY: 4,
originX: 0,
originY: 1
});
$('.img-area').cycle({
fx: 'fadeout',
speed: 950,
timeout: 100
}).cycle("pause");
$(".otel-history-list").on("click",function(){
var historyName = $(this).find(".history-current-name").text();
var historyDateIn = $(this).find(".history-current-datein").text();
var historyDateOut = $(this).find(".history-current-dateout").text();
var historyKisi = $(this).find(".history-current-kisi").text();
$(".input-form-ara input").val(historyName);
$(".otel-giris-cikis #checkin").val(historyDateIn);
$(".otel-giris-cikis #checkout").val(historyDateOut);
$(".kisi-sayi-otel-sec .kisi-count").text(historyKisi);
});
or something like these code
and my ajax code
$(function () {
spf.init();
NProgress.configure({ showSpinner: false });
$(document).on('spfrequest', function (event) {
NProgress.set(0.4);
});
$(document).on('spfprocess', function (event) {
NProgress.set(0.6);
NProgress.set(0.8);
});
$(document).on('spfdone', function (event) {
NProgress.set(1.0);
NProgress.done();
});
$(document).on('spfhistory', function (event) {
NProgress.set(0.7);
NProgress.set(0.9);
NProgress.set(1.0);
NProgress.done();
});
});
and I'm using bootstrap,parallax.js,cycle2.js,select2 plugin
I've answered a similar question in the past, so I'm restating it below:
I'm not sure what your full code set is, but based on what you posted, I'm guessing that several of your html elements (that have JQuery event handlers attached to them) are generated and re-generated using your ajax functions-- probably several times, after your original DOM is loaded.
This is the most likely reason why some of your events don't fire after your Ajax codes fire. The event handlers attached to your html elements (such as divs) get "detached" when these elements are programmatically (re)generated using Ajax.
As such, what you would want to do is to "attach" the event handler to a higher level in the DOM tree (highest being your html) that you are sure won't get 'programmatically' regenerated, then you'd want to check if the element in question, which is inside the DOM, exists. You then run your function when this element is found.
So as an example, you have this onclick function in your code:
$(".otel-history-list").on("click",function(){
//your actions
});
The element with the class "otel-history-list" is likely being generated or regenerated by your Ajax call after page load, and as such would get detached from your onclick event listener (See #1-#2 above).
So to rewrite your code following #3 above, you'd want to attach the event listener to something that won't be regenerated by your Ajax, then just look for the specific element inside it, which contains your class of interest:
$(document).on("click",".otel-history-list", function(){
//your actions
});
Hope this helps!
Related
I am working on a browser extension.
It has two parts:
popup - which contains checkboxes
content script - which contains the code to alter the CSS property
I am saving the states of checkboxes so that the next time I open the popup again the same checkboxes are marked as checked.
When I use the checkboxes they change the DOM as intended, however when I try to alter the DOM after the page is loaded, changes are not reflected. This is probably because the element on which I want to perform the operation is loaded slow and thus required operations fail.
I tried to use onload and ready but nothing worked
$('.question-list-table').on('load', function() {
browser.storage.local.get(["options"], modifyThenApplyChanges)
});
I also tried, but nothing changed.
$('body').on('load','.question-list-table', function() {
browser.storage.local.get(["options"], modifyThenApplyChanges)
});
Also, there is no visible error with the popup or content script as I test in both Google Chrome and Mozilla Firefox.
Update:
As suspected earlier, the target element is loaded slowly so I used setTimeout for 5 seconds and the script is working as intended.
Loading time is variable and I want to show my changes as early as possible everything in a consistent manner.
After going through MutationObserver as suggested by #charlietfl in the comment section, this is what I coded and works for me
// Mutation Observer
const observer = new MutationObserver(function (mutations) {
mutations.forEach(function(mutation) {
if(mutation.addedNodes.length) {
//do stuff
}
});
});
el = document.getElementsById('elementId');
if(el) {
observer.observe(el, {
childList: true // specify the kind of change you are looking for
});
}
I have a page where an image with a wrapping div gets loaded via ajax. I need to apply some code when that image is loaded. I cannot alter the ajax call so I cannot simply use on('success') on the ajax call.
After some time the image with the div gets reloaded the same way (it is a kind of rotation).
The structure is like this:
<div id="spot">
<div id="xyz">
<a href="http://someurl.com">
<img src="http://someimage.url" />
</a>
</div>
</div>
The "spot" div is fixed and everything inside of it gets loaded dynamically.
When I put in
$('#xyz img').on('load', myCallback);
It doesn't work, I think because when the image gets reloaded, the listener is also removed.
I tried with the delegated listener:
$('#spot').on('load', '#xyz img', myCallback);
but didn't work either, it doesn't get executed (I've put console.log inside to verify what happens).
When I type in console $('#spot #xyz > img') the console shows the correct object.
How can I run my myCallback function right after the dynamic content with the image is ready for some DOM scripting action?
If you can't get access to the AJAX request callback then your options are limited to a setInterval() timer which checks to see if the elements have been added, a MutationObserver or a load event on an img element - but be aware this will only fire after the src of the image has loaded so there will be a delay.
Here's how you can use the MutationObserver, but be aware this will only work for newer browsers:
var targetElement = document.querySelector('#container');
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
// perform the required actions here...
console.log(mutation.type);
});
});
observer.observe(targetElement, { attributes: true, childList: true, characterData: true });
Not the correct way but you can try this
var handle = setInterval(showImage, 500);
function showImage(e) {
var img = $('#spot').find("img");
if(img != undefined) {
if($(img).is(":visible")) {
clearInterval(handle);
handle = 0;
// your logic
}
}
}
I have tabs logic that load html templates inside a wrapper. That's works fine, but I included an animation that animate height of the tab wrapper when tab is switched.
The problem is the following: When a template contains <img src="/some-image.png"> the $('#tab-content').load('template-url', function() {...}) callback function sometimes is executed before the browser show the images. And my animation is not working correctly.
Code example (jsFiddle):
var currentHeight = $contentHolder.height();
$contentHolder.load(path, function() {
$contentHolder.stop();
function animateHeight() {
var loadedContentHeight = $contentHolder.css('height', 'auto').height();
$contentHolder.height(currentHeight);
$contentHolder.animate({
height: loadedContentHeight
}, 800, 'linear');
}
animateHeight();
});
I tried to set little timeout, but it's not working every time. If I set more that 300ms timeout, It feels like tabs are changed too slow.
I tried to execute the animation when $('img').load(function() {}) is fired, but with no luck.
This bug occurs most often when the web page is fully refreshed and each tab content loading for first time.
The image load event is kind of broken. To know when images are loaded you will have to observe the DOM for changes. Then on every change, you have to fetch all the new images and add the onload event to them from the callback. To prevent checking each element every time, once they've been loaded you could mark them as such by adding a data-loaded="true" property for instance.
One way to listen to DOM changes is the MutationObserver event. This is supported by all modern browsers and IE11.
A better supported solution (IE9 and up) can be found in this answer: Detect changes in the DOM. I will not repeat it here (but it's included in the demo below).
On every DOM change first you check for images without the data-loaded attribute that are already loaded anyway (this could happen when an image was still in the browser's cache) by checking element.complete. If so, fire the callback function and add the attribute to it.
If .complete is not the case, add an onload event to them that also fires the callback once it is loaded.
In your case you only want to fire your callback when all images are loaded, so I added a check if there's still images without the data-loaded attribute. If you remove that if-clause your callback would run after each image is loaded.
// Observe the DOM for changes
observeDOM(document.body, function(){
checkNewImages();
});
var checkNewImages = function() {
var images = $('img:not([data-loaded]').each(function() {
addImageLoadedEvent( this );
});
}
var addImageLoadedEvent = function(img) {
if (img.complete) {
onImageLoaded(img);
} else {
$(img).on('load', function() {
onImageLoaded(this);
});
}
}
// The callback that is fired once an element is loaded
var onImagesLoaded = function(img) {
$(img).attr('data-loaded', 'true');
if($('img:not([data-loaded])').length === 0) {
// YourCallbackHere();
}
}
DEMO: fire event on all images loaded
You can call your animateHeight function as each image in the loaded HTML is in turn loaded. You can expand this selection if you have other objects like videos.
// Call animateHeight as each image loads
var items = $('img', $contentHolder);
items.bind('load', function(){
animateHeight();
});
Updated demo: http://jsfiddle.net/jxxrhvvz/1/
I'm using classed links to change FlowPlayer content. Here is a working version: http://jsfiddle.net/r9fAj/
In my actual page using the same code the first link clicked works fine. The second one does not fire the click function at all. Even if I comment out everything but the console.log()...
$('.playerLink').click( function() {
audioPlayer.unload();
initAudioPlayer();
$('#player').css('display', 'block');
$('#player').animate({"height":"50px"}, 1000);
var newClip = {'url':$(this).attr('ajax-data'),'autoplay':true};
audioPlayer.play(newClip);
console.log('playing ' + $(this).attr('ajax-data'));
});
HTML like so
Listen
Listen
<a id="flowplayer" href="/audio/episodes/09_27_2013_Happy_Hour_88509726.mp3"></a>
And the player initialized like so:
var audioPlayer;
var initAudioPlayer = function () {
$f("flowplayer", "/player/flowplayer-3.2.16.swf", {
plugins: {
controls: {
fullscreen: false,
autoHide: false,
}
},
clip: {
autoPlay: false,
url: "",
}
});
audioPlayer = $f();
};
initAudioPlayer();
Since the jsFiddle works over and over I assume something else in my page is preventing the second click() from working but the console has no errors for me.
So my question is, short of posting the whole site's code how do I pursue debugging this?
So it sounds like your .click() event handler is only being fired for the first link you click and not for additional clicks. For general debugging, you could take your page that is not working and gradually comment out / remove other part of the JS and HTML until you are able to make it work correctly. Or start with the minimal amount that is working (the fiddle) and gradually add in the rest to see when it stops working.
So this is the first site I have done where content is delivered via AJAX and internal links are caught by
$("a:not([href^='http://'])").click( function(e) {
var url = $(this).attr("href");
var title = ($(this).attr("title")) ? ': ' + $(this).attr("title") : '';
e.preventDefault();
if(url!=window.location){
window.history.pushState({path:url},title,url);
$('#contentMain').load(url);
document.title = "It's New Orleans" + title;
}
});
For some reason it does work once to click a link with the class but the second time gets preventDefault()ed.
Listen
The fix was adding [href^='#'] to not() e.g.
$("a:not([href^='http://'],[href^='#'])").click( function(e) {
Im building a small application and I have some click events binded to some span tags that trigger AJAX requests to a PHP file which queries a MySQL database and spits out the results to populate the targeted area.
However, sometimes i will be clicking the buttons and I have conditionals in place to stop multiple clicking to prevent duplicate content being added numerous times.
I click on a button and firebug tells me that the ajax request had actioned more than once, sometimes it will multiply - so it will start by doing it 2 times or another time it will carry our the request 8 times on one click and obviously flood my content area with duplicate data.
Any ideas?
EDIT
Code for a button is as follows:
<span class="btn"><b>Material</b></span>
This would be enabled by
$('.btn').bind('click', matOption);
and this would be controlled by something like this
var matOption = function() {
$(this).addClass('active');
// remove colours if change of mind on materials
if($('#selectedColour').val() >= 1) {
$('.colour').slideUp(500).children().remove();
$('#selectedColour').val('');
$('.matColOpt .btn').html('<b>Material Colour</b>').removeClass('active').css('opacity', 0.55);
$('.btn').eq(2).unbind('click', colOption); // add click to colour
$('#stage h1 span').eq(2).fadeOut(500);
$('.paperOpt .btn').css('opacity', 0.55).unbind('click', selectPaper);
}
// ajax req for available materials
var cid = $('#selectedColour').val();
var target = $('#notebookOpts .matOpt ul');
$.ajax({
type: "GET",
url: ajaxFile+"?method=getMaterials",
beforeSend: function() {if($('.mats').children('li').size() >= 1) { return false; }},
success: function(data) {
target.append(data).slideDown(500);
$('.mats li').bind('click', matSelect);
},
error: function() {alert('An unexpected error has occurred! Please try again.');}
});
};
You're probably binding your matOption function more than once.
if(!window.matOptionBound){
$('.btn').bind('click', matOption);
window.matOptionBound = true;
}
If you have a code that binds an event handler to a DOM element repeatedly then that event handler does gets executed repeatedly on the event. so if your code such
$("span").click(myHandlerFunction)
gets executed thrice, then you have just told jQuery to fire myHandlerFunction thrice on every click of span. It would be good to make sure there is no such condition goign on in your code. If that is not true then please post your code so that I can help further.
PS: The safest way to do this will be as
$("span").unbind("click",myHandlerFunction).bind("click",myHandlerFunction)