I have a web application with a medium amount of ajax requests.
I load all jquery and jquery widgets on head then i load my base.js before close body tag.
function baseScripts() {
$(".open-dialog").click(function (event) {
event.preventDefault();
event.stopPropagation();
alert("Opening dialog");
href = $().buildUrl($(this).attr("href"), "&isAjax=true");
$().createDialog(href, "Window Title");
return false;
});
$("input:hidden.select").each(function () {
var element = $(this);
if (!($("#s2id_" + element.attr("id")).length)) {
$(element).select2({
// select2 properties...
});
}
});
}
}
SCRIPT BLOCK TO LOAD BASE SCRIPTS ON EVERY AJAX REQUEST
$(document).ajaxComplete(baseScripts);
The problem is after every ajax request the base scripts its called again and them opening dialog multiple times and attaching select2 multiples times too.
How i can detect if widget is already attached into element or class?
Execute scripts on every ajax request (like i did) its a bad pratice?
It doesn't make sense that you will want to re-bind the click event and select2 on ajaxComplete. They should be a one-time binding, in which case, you can just do:
$(document).ready(function(){
baseScripts();
function baseScripts() {
$(".open-dialog").click(function (event) {
event.preventDefault();
event.stopPropagation();
alert("Opening dialog");
href = $().buildUrl($(this).attr("href"), "&isAjax=true");
$().createDialog(href, "Window Title");
return false;
});
$("input:hidden.select").each(function () {
var element = $(this);
if (!($("#s2id_" + element.attr("id")).length)) {
$(element).select2({
// select2 properties...
});
}
});
}
});
Related
This question already has answers here:
Making jquery plugins work after an Ajax call
(3 answers)
Chosen not working on elements from AJAX call
(2 answers)
Closed 1 year ago.
So I have this Jquery functions that I've created using delegations and call each functions in the documeny.ready.
$(document).ready(function () {
getContent();
getQuoteButtton();
popupModal();
plugins();
});
function getQuoteButtton() {
// button quote
$("body").on("click", ".btn-quote", function (e) {
var $this = $(this);
$this.toggleClass('quote-selected');
if ($this.hasClass('quote-selected')) {
$this.text('Selected');
} else {
$this.text('Select This Quote');
}
});
}
function getContent() {
// fire on click
$("body").on("click", 'nav#sidebar.get-qoute-sidebar ul li a', function (e) {
// setting target from data attributes
var $this = $(this),
target = $this.attr('data-target'),
container = $('#get_content');
container.load('pages/' + target + '.php');
});
}
function popupModal() {
/*Toggle popup-modal class */
$("body").on("click", ".popup-modal-toggle", function (e) {
$('.popup-modal').fadeIn().show();
});
//close popup button
$("body").on("click", ".popup-close", function (e) {
$('.popup-modal').fadeOut().hide(300);
});
}
function plugins() {
// phone number plugin initialized singapore and malaysia only
$("#phone-num").intlTelInput({
initialCountry: "SG",
onlyCountries: ['SG', 'MY'],
utilsScript: './resources/vendors/intl-tel-input-master/js/utils.js'
});
// Select tags with search bar
$(".chzn-select").chosen();
}
The other functions is working fine but when I call the plugins function it doesn't seem to load after using the getContent.
The getContent function is where I handle my ajax call to load each pages in the section using the div element #get_content
I don't understand why my plugins function is not working. Does anybody know why? Do I have to call each functions in plugins to use delegations also? if so, what's the process? Thanks.
EDIT - Correct Answer
I have find out the solution, in the getContent function, I also added the plugins() function inside to fetch it after ajax. I don't know why this question was closed even though I have a different approach in coding.
function getContent() {
// fire on click
$("body").on("click", 'nav#sidebar.get-qoute-sidebar ul li a', function (e) {
// setting target from data attributes
var $this = $(this),
target = $this.attr('data-target'),
container = $('#get_content');
container.load('pages/' + target + '.php', function (response, status, xhr) {
// include the plugins function after the content loads -> if no initialization function won't load
plugins();
});;
});
}
<script>
$(document).ready(function(){
$("#register_link").click(function()
{
$("#login_or_register").empty();
$("#login_or_register").load("register_form.php");
});
$("#login_link").click(function()
{
$("#login_or_register").empty();
$("#login_or_register").load("login_form.php");
});
});
</script>
This is my jquery code for flipping between login and register forms.
Initially the page contains the login form and a link to load the register form. It works the first time to load the register form and a link to load the login form. But it doesn't work after that. It doesn't change from register to login form. How to rectify this?
This is because the listeners are only set on existing elements. When you load something using Ajax (jQuery.load()), there will be no listeners on those new elements. You can fix it by re-initializing the click listeners, after the new content is loaded, like this:
<script>
function listenToClick() {
$("#register_link").click(function() {
$("#login_or_register").empty();
$("#login_or_register").load("register_form.php", function() {
listenToClick();
});
});
$("#login_link").click(function() {
$("#login_or_register").empty();
$("#login_or_register").load("login_form.php", function() {
listenToClick();
});
});
}
$(document).ready(function(){
listenToClick();
});
</script>
An even better option would be to listen to the click event using the on function. The on function also listens to future elements (the elements created by jQuery.load()).
<script>
$(document).ready(function() {
$("#register_link").on('click', function() {
$("#login_or_register").empty();
$("#login_or_register").load("register_form.php");
});
$("#login_link").on('click', function() {
$("#login_or_register").empty();
$("#login_or_register").load("login_form.php");
});
});
</script>
You can use .on() to delegate the events like this:
$(document).ready(function(){
$(document).on('click', "#register_link, #login_link", function() {
$("#login_or_register")
.empty()
.load($(this).is('#register_link') ? "register_form.php" : "login_form.php");
});
});
Use event delegation to account for elements that don't exist at run time that may be added to the dom later:
$(document).on('click', '#register_link, #login_link').click(function () {
var url = $(this).is('#login_link') ? "login_form.php" :"register_form.php" ;
$("#login_or_register").empty().load(url);
});
I'am trying to pass a variable/ value from the fancybox iframe to the parent window without success.
Fancybox is launched from a link with
class="fancybox fancybox.iframe"
My code in the fancybox.iframe is:
$(document).ready(function(){
$('.insert_single').click(function(){
var test = $('.members_body').find('{row.U_USERNAME}');
setTimeout(function(){ parent.$.fancybox.close();},300);return true;
});
});
Where '{row.U_USERNAME}' is the username to find in the iframe.
Then, in the parent there's the following code:
$(document).ready(function(){
$('.fancybox').fancybox(
{
openEffect:'fade',
openSpeed:500,
afterClose: function(){
alert($(".fancybox-iframe").contents().find(test));
$('#form input[name=username]').val()(test);return false;
}
}
);
});
But when the fancybox is closed, there's no alert showing up with the variable "test", nor the variable is showing up as a value or as a text in the input field of the form.
I've read and tried various solutions found here on stackoverflow without success.
Thanks in advance for helping
EDIT
Here's an Example
When the fancybox is closed the iframe is removed from the document. So you must use beforeClose event instead of afterClose
$(document).ready(function() {
$('a.fancybox').fancybox({
openEffect:'fade',
openSpeed:500,
beforeClose: function() {
// working
var $iframe = $('.fancybox-iframe');
alert($('input', $iframe.contents()).val());
},
afterClose: function() {
// not working
var $iframe = $('.fancybox-iframe');
alert($('input', $iframe.contents()).val());
}
});
});
JSFiddle: http://jsfiddle.net/NXY7Y/1/
EDIT:
I edited your jsfiddle (http://jsfiddle.net/NXY7Y/9/). Update is in this link
http://jsfiddle.net/NXY7Y/13/
Main page javscript:
$(document).ready(function() {
$('a.fancybox').fancybox({
openEffect:'fade',
openSpeed:500//,
//beforeClose: function() {
// // working
// var $iframe = $('.fancybox-iframe');
// alert($('input', $iframe.contents()).val());
//},
//afterClose: function() {
// // not working
// var $iframe = $('.fancybox-iframe');
// alert($('input', $iframe.contents()).val());
//}
});
});
function setSelectedUser(userText) {
$('#username').val(userText);
}
No need to use afterClose or beforeClose events. Just access the parent function setSelectedUser from the iframe on link click event like this:
$(document).ready(function() {
$('a.insert_single').click(function() {
parent.setSelectedUser($(this).text());
parent.$.fancybox.close();
});
});
Some clarifications :
You should use .find() to find elements by selector (you are trying to find a variable .find(test), which is not a valid format).
You should use .val() to get the contents of an input field or .val(new_value) to set the contents of an input field
You should use .html() or .text() to get the contents of any element other than input,
example: having this html code
<p class="test">hola</p>
... and this jQuery code
var temp = $(".test").html();
... temp will return hola.
On the other hand, if you have control over the iframed page and it's under the same domain than the parent page, then you may not need to set any jQuery in the child page.
so, having this html in the child (iframed) page for instance
<div class="members_body">
<p>GOOGLE</p>
<p>JSFIDDLE</p>
<p>STACKOVERFLOW</p>
</div>
You could set this jQuery in your parent page to get the contents of any clicked element in your child page :
var _tmpvar; // the var to use through the callbacks
jQuery(document).ready(function ($) {
$(".fancybox").fancybox({
type: "iframe",
afterShow: function () {
var $iframe = $('.fancybox-iframe');
$iframe.contents().find(".members_body p").each(function (i) {
$(this).on("click", function () {
_tmpvar = $('.members_body p:eq(' + i + ')', $iframe.contents()).html();
$.fancybox.close();
}); // on click
}); // each
},
afterClose: function () {
$('#form input[name=username]').val(_tmpvar);
}
});
}); // ready
Notice that we declared the var _tmpvar globally so we can use it within different callbacks.
See JSFIDDLE
I've got this function:
$(document).ready(function() {
$('.post_button, .btn_favorite').click(function() {
//Fade in the Popup
$('.login_modal_message').fadeIn(500);
// Add the mask to body
$('body').append('<div class="overlay"></div>');
$('.overlay').fadeIn(300);
return false;
});
My page loads content with favourite buttons, but after Ajax call and generated additional new content the function doesn't work when you click new content's buttons. What could be not right?
That is because you are using dynamic content.
You need to change your click call to a delegated method like on
$('.post_button, .btn_favorite').on('click', function() {
or
$("body").on( "click", ".post_button, .btn_favorite", function( event ) {
Instead of this:
$('.post_button, .btn_favorite').click(function() {
do this:
$(document).on('click','.post_button, .btn_favorite', function() {
on will work with present elements and future ones that match the selector.
Cheers
class-of-element is the applied class of element. which is selector here.
$(document).on("click", ".class-of-element", function (){
alert("Success");
});
If you know the container for .post_button, .btn_favorite then use
$('#container_id').on('click', '.post_button, .btn_favorite', function () { });
so if '.post_button, .btn_favorite' are not found then it will bubble up to container_id
else if you don't know the container then delegate it to document
$(document).on('click', '.post_button, .btn_favorite', function () { });
Reference
I am not sure if I am getting your question right but you may want to try..
$.ajax({
url: "test.html"
}).done(function() {
$('.post_button, .btn_favorite').click(function() {
//Fade in the Popup
$('.login_modal_message').fadeIn(500);
// Add the mask to body
$('body').append('<div class="overlay"></div>');
$('.overlay').fadeIn(300);
return false;
});
Just try to paste your code inside done function.
Hope it helps :)
EDIT:
I also notice you are missing }); on your question.
The following worked for me
$(document).ready(function(){
$(document).bind('contextmenu', function(e) {
if( e.button == 2 && jQuery(e.target).is('img')) {
alert('These photos are copyrighted by the owner. \nAll rights reserved. \nUnauthorized use prohibited.');
return false;
}
});
});
You need to bind the jQuery click event once your ajax content is replaced old content
in AJAX success block you need to add code like here new response html content one a tag like
Click Me
So you can bind the new click event after change the content with following code
$("#new-tag").click(function(){
alert("hi");
return false;
});
Is there anyway to reload just the AJAX request, so that it updates the content pulled from the external site in the code below?
$(document).ready(function () {
var mySearch = $('input#id_search').quicksearch('#content table', { clearSearch: '#clearsearch', });
var container = $('#content');
function doAjax(url) {
if (url.match('^http')) {
$.getJSON("http://query.yahooapis.com/v1/public/yql?"+
"q=select%20*%20from%20html%20where%20url%3D%22"+
encodeURIComponent(url)+
"%22&format=xml'&callback=?",
function (data) {
if (data.results[0]) {
var fullResponse = $(filterData(data.results[0])),
justTable = fullResponse.find("table");
container.append(justTable);
mySearch.cache();
$('.loading').fadeOut();
} else {
var errormsg = '<p>Error: could not load the page.</p>';
container.html(errormsg);
}
});
} else {
$('#content').load(url);
}
}
function filterData(data) {
data = data.replace(/<?\/body[^>]*>/g, '');
data = data.replace(/[\r|\n]+/g, '');
data = data.replace(/<--[\S\s]*?-->/g, '');
data = data.replace(/<noscript[^>]*>[\S\s]*?<\/noscript>/g, '');
data = data.replace(/<script[^>]*>[\S\s]*?<\/script>/g, '');
data = data.replace(/<script.*\/>/, '');
data = data.replace(/<img[^>]*>/g, '');
return data;
}
doAjax('link');
});
Right now I have a button which reloads the entire page, but I just want to reload the AJAX request. Is this even possible?
Edit: I need to specify more. While it can easily call the AJAX again, can it also replace the info that is already there?
You just need to call the doAjax function again on button click...
$("#buttonID").on("click", function() {
doAjax("link");
});
Add that into the above document.ready code and set the button ID correspondingly.
Then change
container.append(justTable);
to
container.html(justTable);
In your doAjax function you append HTML onto an element. If you overwrite the element's HTML instead of appending to it then the HTML will be "refreshed" each time the doAjax function runs:
Simply change:
container.append(justTable);
To:
container.html(justTable);
And of-course you can bind a click event handler to a link (or any element) like the rest of the answers show. Make sure you bind the click event in the proper scope (inside the document.ready event handler) so the doAjax function will be accessible from the click event handler.