Applying jQuery to HTML elements loaded in by ajax - javascript

I am using the jQuery plugin DataTables to spruce up my generic html tables. I can use
<script>
$(document).ready(function() {
$('table.display').DataTable();
} );
</script>
To load the DataTables plugin for all pages on the page after it loaded, but it doesn't retroactively work on any tables added through AJAX (because the page has already been loaded at that point).
How do I make sure that the
$('table.display').DataTable();
Is run on the table added to the page as well?

You can try adding a ready() event listener in jQuery to act when each <table> is loaded (rather than when the document is loaded).
Just add another block, similar to what you have:
$('table.display').ready(function() {
$(this).DataTable();
});

You can add a listener for new DOM nodes, and call the .DataTable() function if the newly added node matches table.display:
$(document).on('DOMNodeInserted', 'table.display' function(e) {
$(this).DataTable();
});

Because the DataTable function must be called on an existing element, there doesn't seem to be a way for you to have all new table.display elements automatically get instantiated with by plugin. Try instantiating the new elements in your AJAX success callback:
$.ajax({
url: '/your/url',
type: 'POST',
success: function (data) { $('table.display').DataTable(); }
});

For what it's worth, I often have DataTables that are periodically refreshed using ajax. Here is how I instantiate my DataTables in my Ajax success handlers:
success: function (response) {
var $table = $('#user-table');
var $body = $('#user-table-body');
if ($.fn.DataTable.isDataTable($table)) { // if already init, destroy it
$table.dataTable().fnDestroy();
$body.empty(); // empty body of table
}
$body.html(response['users-table']) // set new data to body of table
$table.DataTable({ // init datatable
"order": [
[2, "desc"]
]
});
},

Related

Call event after script in external html loaded by Ajax

I have an Ajax Loaded Div in my page and, inside that div, a Jquery plugin load my Google Spreadsheet. I need to add some "event listening" to detect when that spreadsheet is loaded, but there is a problem with the unpredictable time to load and the fact that a event INSIDE my div (with external html content), as far as I know, can't be listened on my "parent" window. I've tried many ways to do that, by the way.
I'll post my code, but I don't think it can help. What can I say is: The height of my div change when the content is loaded. The Callback function can't work in this case 'cause my script (inside div) only get the spreadsheet after load the page.
index.html
$.ajax({
url : "test/index.html",
type : "get",
async: true,
success : function(result) {
$('.mailcontrol').html(result);
},
error: function() {
alert("Error");
}
});
test/index.html
<script type="text/javascript">
$('#dat').sheetrock({
url: 'https://docs.google.com/spreadsheets/ssid'});
</script>
Any ideia about some event listening in my case? Thanks!
EDIT:
jrummell answer gave me the ideia to ignore the external html file using the plugin inside the same page, so, I could use the callback function of "sheetrock", as suggested by Andre.
Thanks for the answers!!
New code:
$("#target2").click(function () {
var script = document.createElement( 'script' );
script.type = 'text/javascript';
script.src = 'sheetrock.min.js';
$("#dat").append(script);
$('#dat').sheetrock({
url: 'https://docs.google.com/spreadsheets',
callback: function() {
}
});
});
Try initializing your spreadsheet plugin after the content is loaded:
$.ajax({
url : "test/index.html",
type : "get",
async: true,
success : function(result) {
$('.mailcontrol').html(result);
$('#dat').sheetrock({
url: 'https://docs.google.com/spreadsheets/ssid'});
},
error: function() {
alert("Error");
}
});
You can use Jquery on() event listening, like this:
$('.mailcontrol').on('eventName', '#dat', callbackFunction);
The "selector" parameter is a selector string to filter the descendants of the selected elements that trigger the event. In your case "#dat". I suggest using "resize" as eventName.
Reference: http://api.jquery.com/on/
Have you tried the original sheetrock callback?
$('#dat').sheetrock({
url: 'https://docs.google.com/spreadsheets/ssid',
callback: function() {
//trigger event to be caught
}
});
Reference: https://github.com/chriszarate/sheetrock#callback

How to call a Jquery method on page load or page refresh in jquery

I have created a new JQuery widget for my project and I need to call that method on page load.
Here is the widget sample:
(function($){
$.widget("mywidget", {
options: {
},
_create: function(){
var self = this;
$.ajax({
url: "/api/1.0/getdata",
type: "GET",
contentType: "application/json",
success: function(arg) {
//will be inserting the details from the json call into the <div>
var data = arg;
},
error: function(resp){
}
});
}
});
})(jQuery);
Here is how I am trying to make the call to the widget:
$(document).ready(function(){
console.log("show my widget");
$("#div").mywidget();
});
Here is the HTML I am trying to load for my widget:
<div id="div">
<p>Welcome to the newly created JQuery widget</p>
</div>
But when I do this nothing gets called, neither is the URL called, from which I am trying to access the data to show in my message nor the <div>. Any idea how can i access the widget on page load?
Syntax errors aside, using the latest stable jQuery UI I had to include a namespace in my widget name. Here is a jsfiddle with your code working. Note that it will correctly output an error attempting to hit /api/1.0/getdata.
If this solution doesn't work in your setup, ensure that the widget initialization code is being run before attempting to use it.
It seems that your document ready is just missing brackets..
try -
$(document).ready(function(){
console.log("show my widget");
$("#div").mywidget();
});

JQuery hover state for appended elements

I am writing a page that once loaded will go off and make an ajax call, process the json respose data, and then append these elements into the dom as shown in a simplified way below:
$.ajax({
type: 'POST',
url: "http://mysite.dev:32769/getallnews",
success: function(data){
$container.append(item)
.isotope( 'appended', item );
}
});
It should also be noted I am using Metafizzy's Isotope library. http://isotope.metafizzy.co/
To demonstrate my issue I have a <div class="article-block"></div> both in the DOM at load time and one more appended once the ajax call finishes.
this jquery will only capture the first and not the second though!
$(".article-block").hover(function(){
//hover on
$(".article-block div").fadeIn();
},function(){
//hover off
$(".article-block div").fadeOut();
});
I've spent some time debugging this and found that when I type $('.article-block'); into the console. I get both correctly. However when I hover over my first one the fade works, and when I hover over the second, it doesn't.
Any ideas?
Order matters
You are registering your event handler for the initial div when the page loads which is good. Its important to note that if you add dom elements later you will need to apply handlers to the new items.
Try saving a reference to your handlers and applying it later.
function hoverOn() {
$(".article-block div").fadeIn();
}
function hoverOff() {
$(".article-block div").fadeOut();
}
// on page load
$('.article-block').hover(hoverOn, hoverOff);
// later in the ajax call
$.ajax({
type: 'POST',
url: "http://mysite.dev:32769/getallnews",
success: function (data) {
$(item).hover(hoverOn, hoverOff); // register your hover event to the
// new element
$container.append(item).isotope( 'appended', item );
}
});

the tooltip in bootstrap doesn't work after ajax

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

Multiple blocks in jquery ui blocker?

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().

Categories

Resources