I am using this plugin.
However it seems to use global variables
$.blockUI();
$.unblockUI();
Is there away I can have different instances of this block.
$(document).ajaxStart(function (e)
{
$.blockUI(); //setup with a loading msg.
});
$(document).ajaxStop(function (e)
{
$.unblockUI();
})
var ajax = // ajax setup stuff
// 1.5 way of doing it
ajax .success(function (response)
{
var valid = checkIfValid(response); // check if valid
if(valid)
{
$.blockUI(); // setup with a save message
}
});
So that's sort of what I have. I put
$.blockUI();
to keep it simple with no options but in my real code I have messages and other options set.
So now the problem is this once the success is finished the ajax stop gets called and unblocks everything. I only want the one that was started in the ajax start to be cleared not the one in the valid.
So I need different instances.
You can accomplish what you're trying to do by calling block on a div that you create on the fly, and then simply removing that div from the DOM. For example:
$(document).ajaxStart(function (e) {
/* Create a <div> that will contain the blocking elements: */
$("<div id='ajax-block' style='position:fixed;width:100%;height:100%' />")
.appendTo("body").block()
});
$(document).ajaxStop(function (e) {
/* Remove the page block specific to the ajax request: */
$("#ajax-block").remove();
});
And do something similar for the other event you're blocking (just change the id attribute inside the dynamically appended div and the call to remove().
Related
We got a simple jQuery script on Drupal site that injects a div class with content:
(function($) {
Drupal.behaviors.myHelpText = {
attach: function (context, settings) {
//code starts
//change placeholder text
$('.form-item-quantity').append('<span class="help-block">For orders over 10 call for volume pricing</span>');
$('.help-block').css("flex-basis", "100%");
//code ends
}
};
})(jQuery);
The page has Drupal Commerce and various product attribute fields that gets processed by Ajax every time selecting an attribute. And when doing that our script injects same duplicate line each time on Ajax load/update.
How to avoid that? We just want jQuery code work once on page load.
Only add the element if it doesn't exist, otherwise do nothing.
(function($) {
Drupal.behaviors.myHelpText = {
attach: function (context, settings) {
if (!document.getElementById('help')) {
$('.form-item-quantity').append(
'<span id="help" class="help-block">For orders over 10 call for volume ricing</span>'
);
$('.help-block').css("flex-basis", "100%");
}
}
};
})(jQuery);
You have to understand that drupal.behaviors fire on page load and when ajax returns results. It is designed this way because you may want your code to run again on the ajax results, for example, if you are updating part of the page via ajax and it needs event listeners applied, or a class added.
The context variable is the key here.
on first page load, the context will be the whole window, but when ajax returns the result, the context will just be what is returned by the ajax.
Knowing this, you should be using context in your jquery selectors.
eg.
(function($) {
Drupal.behaviors.myHelpText = {
attach: function (context, settings) {
//code starts
//change placeholder text
$('.form-item-quantity', context).append('<span class="help-block">For orders over 10 call for volume pricing</span>');
$('.help-block', context).css("flex-basis", "100%");
//code ends
}
};
})(jQuery);
For added protection against something processing multiple times, you can use jquery once(), but this is usually not needed if using the context variable in the selector. jQuery once() separate library that must be loaded.
Why don't use jQuery once? My thought — it's a classic approach. A bunch of examples lives in docs on drupal.org
$('.form-item-quantity').once('help-appended').append('<span class="help-block">For orders over 10 call for volume pricing</span>');
And I'm not sure you need to apply styles via js. A css file is a better place for it. And jquery once should be available in your environment. That's it.
I have got a table of accounts and I want to be able to toggle them on/off using JQuery toggles. In the beginning I need to initialize the toggles each account (either they one account is set to on or off). I want to do this on page loading.
My Jade template part:
tbody
each account in accounts
tr
td
.col-sm-7.control-label
div(class='toggle toggle-success', onload='initToggle(#{account.IsActive}, this)')
| #{account.Id}
td #{account.Email}
My init toggle function:
script.
jQuery(document).ready(function () {
function initToggle(isActive, element)
{
if (isActive)
element.toggles({'on': true});
else
element.toggles({'on': false});
}
My problem:
If I use onload= for my function call I don't get an error at all. If I use the onclick=as function call, google chrome shows:
Uncaught ReferenceError: initToggle is not defined
How would I properly initialize my on/off toggles?
You get the error because the function is declared / scoped inside the "ready" callback.
To fix that, I would move the logic and let the javascript decides when init things:
Jade part
div(class='toggle toggle-success', data-is-active='#{account.IsActive}')
Javascript part
jQuery(document).ready(function ($) {
$(".toggle").each(function () {
var $this = $(this);
var isActive = $this.data("isActive") === "true";
// or .data("is-active") for jQuery 2, see https://api.jquery.com/data/
$this.toggles({'on': isActive});
});
});
The jade side uses a html data attribute to store the information and the js side uses it when the document is ready.
I have a file named index.php, which in I include another file named file1.php (in index.php I include all necessary files for jQuery, js etc.).
In file1.php I have a table with buttons which each opens a modal. the information in the modal is from an ajax call for file2.php. in file2.php I create a table. In the table I have the cell :
<button class='btn btn-default tooltip-default' data-toggle='tooltip' data-trigger='hover' data-placement='top' data-content='content' data-original-title='Twitter Bootstrap Popover'>AAA</button>
and, well, the tooltip doesn't work.
but, when I copy this and get it to file1.php, bellow the table, the tooltip does work.
Can anyone help me fix the tooltip ?
Thx.
Use selector on exist element like body
$('body').tooltip({selector: '[data-toggle="tooltip"]'});
I think you need to initialize the tooltip on the newly arrived data, e.g.
$('[data-toggle="tooltip"]').tooltip();
Place this code to your AJAX success handler, after the DOM manipulation.
You will have to put the tooltip initialization in Ajax callback function:
$.ajax({
method: "POST",
url: "some.php"
}).done(function( msg ) {
$('[data-toggle="tooltip"]').tooltip();
});
-OR-
instead of putting the initialization code in every Ajax callback function
you can implement it globally using the ajaxComplete event:
/* initializate the tooltips after ajax requests, if not already done */
$( document ).ajaxComplete(function( event, request, settings ) {
$('[data-toggle="tooltip"]').not( '[data-original-title]' ).tooltip();
});
This code will initialize the tooltip for every node which has the data-toggle="tooltip" attribute defined but do not have the attribute "data-original-title" (i.e tooltip not initialized).
I've tried everything and nothing worked for me.
So I took a closer look at tooltip when click* and found out that each time the shown.bs.tooltip is fired a aria-describedby property appears and its value changes every time.
So, my approach (and it works) is to change the content of this dynamic element.
I got this code:
$('body').on('shown.bs.tooltip', function(e) {
var $element = $(e.target);
var url = $element.data('url');
if (undefined === url || url.length === 0) {
return true;
}
var $describedByContent = $('#' + $element.attr('aria-describedby')).find('.tooltip-inner');
if ($element.attr('title').length > 1) {
$describedByContent.html($element.attr('title'));
return true;
}
$.ajax({
url: url,
method: 'GET',
beforeSend: function () {
$element.attr('title', 'Cargando... espere por favor.');
$describedByContent.html($element.attr('title'));
}
}).done(function (data) {
$element.attr('title', JSON.stringify(data));
$describedByContent.html($element.attr('title'));
});
return true;
});
In my case my tooltip has a data-url attribute to take the data for the title.
The original title is '-', and I don't want an ajax call every time I click* the element, just the first time.
To me it's not useful to make an ajax every time because I don't expect the data to change that fast.
The dynamic created element has an element with the class .tooltip-inner, so we just need to replace its content.
Hope this might help.
*click: I chose the click event because the default hover sometimes make the system turn crazy and the show.bs.tooltip was fired forever, switching its between the default and new value.
You can do this in one of these two ways:
you can write an ajaxComplete function so that every time after an ajax call completed it reinitialize the tooltip over and over again. This is useful when in most of your pages you have datatables and want to initialize the tooltip after every ajax datatable call:
$(document).ajaxComplete(function() {
$("[data-toggle=tooltip]").tooltip();
});
Or you can call tooltip function after ajax success callback:
function tool_tip() {
$('[data-toggle="tooltip"]').tooltip()
}
tool_tip(); // Call in document ready for elements already present
$.ajax({
success : function(data) {
tool_tip(); // Call function again for AJAX loaded content
}
})
I set up my tool tip by placement like so:
function setUpToolTipHelpers() {
$(".tip-top").tooltip({
placement: 'top'
});
$(".tip-right").tooltip({
placement: 'right'
});
$(".tip-bottom").tooltip({
placement: 'bottom'
});
$(".tip-left").tooltip({
placement: 'left'
});
}
initialize this with a document ready call:
$(document).ready(function () {
setUpToolTipHelpers();
});
This way I can determine the placement of the tool tip, and I only have to assign the tip with using a class and title:
<td class = "tip-top", title = "Some description">name</td>
Then I call, "setUpToolTipHelpers()" inside my success ajax function. Or you can call it on the complete function as well. This seems to work well for me.
run
$('#ding_me_tooltip').tooltip('dispose');
$('#ding_me_tooltip').tooltip();
after the ajax where #ding_me_tooltip is your selector
This may be a duplicate of this topic, but I must revive it as my issue seems to be a little deeper than this. I'm currently using ajaxForm() to submit a 4 question quiz to a PHP script, receive the result, and then populate it back into the DIV. The beforeSend function fires, sending the information to the ajax.php script. beforeSend also shows a loading graphic in the quiz container. Then the complete function fires properly as ajax.php returns the HTML to be populated back into the DOM. At that point, everything stops. The next line is a call to slideUp the loading div and then display the returned information in the quizContainer.
At this point if I put in a javascript alert it always fires, meaning that complete is at least firing when it should, but the jQuery reference to the loading div is completely ignored. Here's the code for the javascript file that handles the submission - the section handling this is "Handle the quiz submission":
$(document).ready(function () {
// Get rid of the message box after 15 seconds
setTimeout(function() {
$('#message').slideUp('fast');
}, 10000);
// Handle the Course List LIs
$('#courseList li').on('click', function () {
// Get the background color as it's set initially
var color = $(this).attr('oColor');
jQuery('div', this).toggle('slow', function () {
if ($(this).is(":hidden")) {
$(this).css('background-color', color);
}
});
// Change the background to be the same as the content background when it's expanded
if ($(this).is(":hidden")) {
$(this).css('background-color', '#33CC66');
} else {
$(this).removeAttr('style');
}
});
// Handle the quiz submission
jQuery.fn.exists = function(){return this.length>0;}
if ($('#quizForm').exists()) {
$('#quizForm').ajaxForm({
beforeSend: function() {
$('#quizContainer').slideUp('fast', function () {
$('#loading').show();
});
},
complete: function(xhr, theStatus) {
alert(theStatus);
$('#loading').slideUp('fast', function () {
$('#quizContainer').html(xhr.responseText);
$('#quizContainer').show();
});
}
});
}
});
If necessary I can provide more information and a temporary login to access this if anybody would like to see it in action. I'm currently using jQuery 1.8.1(.)
Thanks for any help!
Jon
I believe the first argument of the complete function is xhr.responseText rather than an xhr object which is actually the third argument. Try removing .responseText from your complete: function.
Strange situation:
I am building a menu bar using jQuery and CSS.
In my JavaScript file, I have an on-ready function like so:
$(document).ready(function(e) {
mark_active_menu();
}
and...
function mark_active_menu() {
var elementWidth = $("nav li").width();
alert(elementWidth);
}
For some reason, even BEFORE all the document finish loading, I'm getting the alert message with an incorrect width. Only when I release the message, the rest of the document loads and I'm getting the right width as it should be.
Why my function is being called BEFORE all the document finish loading?
Is there a way to load the function only AFTER a certain element done loading (Example: the nav element)?
You can use window.load, it will be triggered after all the resource have completed loading.
$(window).load(function(e) {
mark_active_menu();
});
The load event fires at the end of the document loading process. At
this point, all of the objects in the document are in the DOM, and all
the images and sub-frames have finished loading, Reference
All the current solutions are just treating symptoms of the main problem. If you want your handler to execute after all your ajax loads, then you may use a promise.
var ajax1 = $.ajax();
var ajax2 = $.ajax();
jQuery(function($) {
$.when.apply($, [ajax1, ajax2]).done(function() {
// your code here
});
});
Try on the window load event :
$(window).load(function() {
//Stuff here
});
To be sure, Try window load
$(window).load(function(e) {
mark_active_menu();
}
Before(sometimes, doesn't load absolutely at the beginning, a few milliseconds after(0-200ms about)):
$(document).ready(function(){
$('body').hide(0);
});
After:
$(window).load(function(){
$('body').delay(500).show(0);
});
In my situation of work with AJAX and HTML. I have the same problem with functions $(document).ready() and $(window).load(). I solved this problem by adding handler of my event (that should work at HTML DOC), to the jQuery function that runs right after AJAX reguest was finished. Read this: "
jQuery.post()" (third parameter in the function).
In my code it looks like this:
var RequestRootFolderContent = function(){
$.post(
'PHP/IncludeFiles/FolderContent.inc.php',
function(data){
$('[class~="folder-content"]').html(data);
//Here what you need
$('[class~="file"]').dblclick(function(){
alert("Double click");
});
}
)
}